Actualizada interfaz web

This commit is contained in:
Miguel Angel de Heras 2025-03-13 18:26:32 +01:00
parent a7e45b6cb7
commit 9de20d7ede
5 changed files with 314 additions and 148 deletions
CraterLab_base_giratoria/include
CraterLab_camera/include

View file

@ -11,6 +11,7 @@ const char *htmlTemplate = R"rawliteral(
color: #ffffff; color: #ffffff;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 20px; margin: 20px;
font-size: 12px
} }
h2 { h2 {
@ -44,7 +45,7 @@ const char *htmlTemplate = R"rawliteral(
input[type="text"], input[type="text"],
input[type="number"], input[type="number"],
select { select {
width: 100px; width: 100%;
padding: 5px; padding: 5px;
margin: 5px 0; margin: 5px 0;
background-color: #333; background-color: #333;
@ -61,7 +62,7 @@ const char *htmlTemplate = R"rawliteral(
/* Estilo de los sliders */ /* Estilo de los sliders */
input[type="range"] { input[type="range"] {
width: 30%; width: 100%;
margin: 10px 0; margin: 10px 0;
} }
@ -102,7 +103,6 @@ const char *htmlTemplate = R"rawliteral(
border-radius: 10px; border-radius: 10px;
margin-bottom: 20px; margin-bottom: 20px;
border: 1px solid #333; border: 1px solid #333;
/* Bordes más visibles */
} }
/* Estilo para centrar los formularios en la pantalla */ /* Estilo para centrar los formularios en la pantalla */
@ -110,52 +110,77 @@ const char *htmlTemplate = R"rawliteral(
max-width: 600px; max-width: 600px;
margin: 0 auto; margin: 0 auto;
} }
.device-360-container {
display: flex;
justify-content: space-between;
gap: 20px;
/* Espaciado entre columnas */
}
.device-column {
flex: 1;
text-align: center;
}
.sync-checkbox {
text-align: center;
margin-top: 20px;
}
</style> </style>
</head> </head>
<body> <body>
<!-- Sección Dispositivo 360 --> <!-- Sección Dispositivo 360 -->
<!-- Subsección X0 --> <div class="device-360-container">
<!-- Columna X0 -->
<div class="device-column">
<h4>X0:</h4> <h4>X0:</h4>
<label for='x0Degrees'>Grados:</label> <label for='x0Degrees'>Grados:</label><br>
<input type='text' id='x0Degrees'> <input type='text' id='x0Degrees'><br><br>
<label for='x0Duration'>Duración (s):</label> <label for='x0Duration'>Duración (s):</label>
<input type='text' id='x0Duration'> <input type='text' id='x0Duration'>
<input type='number' id='x0Read'> <input type='number' id='x0Read'>
<br> <br><br>
<button onclick="moveMotor('test_360','x0')">Test</button> <button onclick="moveMotor('test_360','x0')">Test</button>
<button onclick="moveMotor('save_360','x0')">Save</button> <button onclick="moveMotor('save_360','x0')">Save</button>
<span id="x0Message" style="color: green; display: none;">Movimiento enviado correctamente</span> <span id="x0Message" style="color: green; display: none;">Movimiento enviado correctamente</span>
<br><br> </div>
<!-- Subsección X1 --> <!-- Columna X1 -->
<div class="device-column">
<h4>X1:</h4> <h4>X1:</h4>
<label for='x1Degrees'>Grados:</label> <label for='x1Degrees'>Grados:</label><br>
<input type='text' id='x1Degrees'> <input type='text' id='x1Degrees'><br><br>
<label for='x1Duration'>Duración (s):</label> <label for='x1Duration'>Duración (s):</label>
<input type='text' id='x1Duration'> <input type='text' id='x1Duration'>
<input type='number' id='x1Read'> <input type='number' id='x1Read'>
<br> <br><br>
<button onclick="moveMotor('test_360','x1')">Test</button> <button onclick="moveMotor('test_360','x1')">Test</button>
<button onclick="moveMotor('save_360','x1')">Save</button> <button onclick="moveMotor('save_360','x1')">Save</button>
<span id="x1Message" style="color: green; display: none;">Movimiento enviado correctamente</span> <span id="x1Message" style="color: green; display: none;">Movimiento enviado correctamente</span>
<br><br> </div>
<!-- Subsección Y0 --> <!-- Columna Y0 -->
<div class="device-column">
<h4>Y0:</h4> <h4>Y0:</h4>
<label for='y0Degrees'>Grados:</label> <label for='y0Degrees'>Grados:</label><br>
<input type='text' id='y0Degrees'> <input type='text' id='y0Degrees'><br><br>
<label for='y0Duration'>Duración (s):</label> <label for='y0Duration'>Duración (s):</label>
<input type='text' id='y0Duration'> <input type='text' id='y0Duration'>
<input type='number' id='y0Read'> <input type='number' id='y0Read'>
<br> <br><br>
<button onclick="moveMotor('test_360','y0')">Test</button> <button onclick="moveMotor('test_360','y0')">Test</button>
<button onclick="moveMotor('save_360','y0')">Save</button> <button onclick="moveMotor('save_360','y0')">Save</button>
<span id="y0Message" style="color: green; display: none;">Movimiento enviado correctamente</span> <span id="y0Message" style="color: green; display: none;">Movimiento enviado correctamente</span>
<br><br> </div>
</div>
<!-- Checkbox de sincronización debajo de las tres columnas -->
<div class="sync-checkbox">
<input type='checkbox' id='syncWithInterval360'> Sincronizar con Intervalómetro <input type='checkbox' id='syncWithInterval360'> Sincronizar con Intervalómetro
<br><br> </div>
<!-- Script para manejar las interacciones y enviar el JSON -->
<script> <script>
function sendHeight() { function sendHeight() {

View file

@ -1,9 +1,13 @@
#define FORWARD 0
#define BACKWARD 1
#define STOP 0 #define STOP 0
#define IN 1 #define FORWARD 1
#define OUT 2 #define BACKWARD 2
#define IN_OUT 3
#define IN 3
#define OUT 4
#define IN_OUT 5
//Posicion en la array del motor de fps
#define FPS_MOTOR 4 #define FPS_MOTOR 4
//Definicion de los pines del shift register //Definicion de los pines del shift register
@ -39,4 +43,4 @@
//Definicion de los limites del sensor lineal //Definicion de los limites del sensor lineal
#define LINEAL_MAX 4*478 #define LINEAL_MAX 4*478
#define LINEAL_MIN 0 #define LINEAL_MIN 4

View file

@ -11,6 +11,7 @@ const char *htmlTemplate = R"rawliteral(
color: #ffffff; color: #ffffff;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 20px; margin: 20px;
font-size: 12px
} }
h2 { h2 {
@ -40,29 +41,26 @@ const char *htmlTemplate = R"rawliteral(
margin-top: 20px; margin-top: 20px;
} }
/* Estilos de los inputs */
input[type="text"], .button-bar {
input[type="number"], display: flex;
select { justify-content: space-between;
width: 100px;
padding: 5px;
margin: 5px 0;
background-color: #333; background-color: #333;
border: 1px solid #555; padding: 10px;
color: #fff;
border-radius: 5px; border-radius: 5px;
margin-bottom: 20px;
} }
/* Estilos del checkbox y radio */ .button-bar button {
input[type="checkbox"], background-color: #1e88e5;
input[type="radio"] { border: none;
margin: 10px; color: white;
} padding: 10px 20px;
text-align: center;
/* Estilo de los sliders */ font-size: 16px;
input[type="range"] { cursor: pointer;
width: 30%; border-radius: 5px;
margin: 10px 0; transition: background-color 0.3s ease;
} }
/* Botones */ /* Botones */
@ -85,78 +83,220 @@ const char *htmlTemplate = R"rawliteral(
background-color: #1565c0; background-color: #1565c0;
} }
.button-bar button:hover {
/* Dark styling for select dropdown */ background-color: #1565c0;
select { }
background-color: #333;
color: white; .columns-container {
border: 1px solid #555; display: flex;
padding: 5px; justify-content: space-between;
width: 100%;
}
.section:nth-child(1) {
flex: 22%;
/* Primera columna */
}
.section:nth-child(2) {
flex: 15%;
/* Segunda columna */
}
.section:nth-child(3) {
flex: 15%;
/* Tercera columna */
}
.section:nth-child(4) {
flex: 45%;
/* Cuarta columna */
} }
/* Estilo para contenedores de secciones */
.section { .section {
background-color: #1e1e1e; background-color: #1e1e1e;
padding: 20px; padding: 20px;
padding-top: 0px;
border-radius: 10px; border-radius: 10px;
margin-bottom: 20px; margin-bottom: 20px;
border: 1px solid #333; margin: 5px;
/* Bordes más visibles */
} }
/* Estilo para centrar los formularios en la pantalla */ /* Estilos de los inputs */
.form-container { input[type="text"],
max-width: 600px; input[type="number"],
margin: 0 auto; select {
}
iframe {
display: block;
width: 100%; width: 100%;
min-height: 100px; padding: 5px;
/* Evita que sea muy pequeño al inicio */ margin: 5px 0;
overflow: hidden !important; background-color: #333;
/* Asegura que no haya barras de desplazamiento */ border: 1px solid #555;
color: #fff;
border-radius: 5px;
}
/* Estilos del checkbox y radio */
input[type="checkbox"],
input[type="radio"] {
margin: 10px;
vertical-align: middle;
margin-right: 5px;
/* Ajusta el espacio entre el input y el texto */
}
/* Estilo de los sliders */
/*input[type="range"] {
writing-mode: bt-lr;
transform: rotate(270deg);
width: auto;
height: 150px;
display: block;
}*/
input[type="range"] {
width: 100%;
margin: 10px 0;
}
/* Estilos de la capa flotante */
#monitorLayer {
display: none;
position: fixed;
top: 10%;
left: 50%;
transform: translate(-50%, 0);
background: rgba(0, 0, 0, 0.9);
padding: 20px;
border-radius: 10px;
z-index: 1000;
width: 80%;
max-width: 800px;
}
#monitorLayer iframe {
width: 100%;
height: 400px;
border: none;
}
#closeMonitor {
background: red;
border: none;
color: white;
padding: 10px;
font-size: 16px;
cursor: pointer;
margin-top: 10px;
}
.motor-camera {
display: flex;
flex-direction: column;
align-items: center;
}
.motor-columns {
display: flex;
justify-content: space-between;
width: 100%;
}
.motor-column {
flex: 1;
padding: 10px;
}
.motor-buttons {
text-align: center;
margin-top: 20px;
}
.speed-container {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin-bottom: 10px;
}
.speed-value {
display: flex;
align-items: center;
gap: 5px;
}
#iframe360 {
width: 100%;
height: 100%;
min-height: 400px;
/* Ajusta la altura mínima según sea necesario */
border: none; border: none;
} }
</style> </style>
</head> </head>
<body> <body>
<div class="form-container">
<h2>Control Bolex Paillard</h2> <div class="button-bar">
<button onclick="accion()">REC</button>
<button onclick="corten()">STOP</button>
<button onclick="toggleMonitor()">SCREEN</button>
</div>
<div id="monitorLayer">
<iframe src="http://192.168.8.5:8000"></iframe>
<button id="closeMonitor" onclick="toggleMonitor()">Cerrar</button>
</div>
<div class="columns-container">
<div class="section"> <div class="section">
<!-- Sección Motor Cámara -->
<h3>Motor Cámara</h3> <h3>Motor Cámara</h3>
<div class="motor-columns">
<!-- Columna 1: Counter y Speed -->
<div class="motor-column">
<h4>Counter</h4> <h4>Counter</h4>
<input type='number' id='frames'> <input type='number' id='frames'>
<h4>Speed</h4> <h4>Speed</h4>
<label for='fps'>FPS:</label> <label for='fps'>FPS:</label>
<div class="speed-container">
<input type='range' min='0' max='48' value='24' id='speedSlider'> <input type='range' min='0' max='48' value='24' id='speedSlider'>
<span id='speedValueDisplay'>24</span> fps <div class="speed-value">
<input type='number' id='fps'> <span id='speedValueDisplay'>24</span> <span>fps</span>
<input type='checkbox' id='speedCheckbox'> Activar Speed </div>
</div>
<input type='number' id='fps'><br><br>
<input type='checkbox' id='speedCheckbox'>Speed
</div>
<!-- Columna 2: Intervalómetro y Dirección -->
<div class="motor-column">
<h4>Intervalómetro:</h4> <h4>Intervalómetro:</h4>
<label for='intervalFrames'>Frames:</label> <label for='intervalFrames'>Frames:</label>
<input type='number' id='intervalFrames' value='10' min='1'> <input type='number' id='intervalFrames' value='10' min='1'><br><br>
<label for='intervalSeconds'>Segundos:</label> <label for='intervalSeconds'>Segundos:</label>
<input type='number' id='intervalSeconds' value='1' min='1'> <input type='number' id='intervalSeconds' value='1' min='1'><br><br>
<input type='checkbox' id='intervalCheckbox'> Activar Intervalómetro <input type='checkbox' id='intervalCheckbox'> Intervalómetro
<h4>Dirección:</h4> <h4>Dirección:</h4>
<input type='radio' id='forward' name='direction' value='forward' checked> Forward <input type='radio' id='forward' name='direction' value='forward' checked> Forward<br>
<input type='radio' id='backward' name='direction' value='backward'> Backward <input type='radio' id='backward' name='direction' value='backward'> Backward
<br><br> </div>
</div>
<!-- Botones centrados abajo -->
<div class="motor-buttons">
<button onclick="sendMotorCameraData('test_motor')">Test</button> <button onclick="sendMotorCameraData('test_motor')">Test</button>
<button onclick="sendMotorCameraData('save_motor')">Save</button> <button onclick="sendMotorCameraData('save_motor')">Save</button>
<button onclick="stop()">Stop</button> <button onclick="stop()">Stop</button>
<span id="motorCameraMessage" style="color: green; display: none;">Datos enviados correctamente</span> <span id="motorCameraMessage" style="color: green; display: none;">Datos enviados correctamente</span>
</div> </div>
</div>
<div class="section"> <div class="section">
<!-- Sección Shutter -->
<h3>Shutter</h3> <h3>Shutter</h3>
<h4>Fade In/Out Frames:</h4> <h4>Fade In/Out Frames:</h4>
<p>% apertura inicial: <span id='fadePercentDisplay'>0</span></p> <p>% apertura inicial: <span id='fadePercentDisplay'>0</span></p>
@ -166,22 +306,16 @@ const char *htmlTemplate = R"rawliteral(
<input type='range' min='0' max='100' value='10' id='fadeFramesSlider'> <input type='range' min='0' max='100' value='10' id='fadeFramesSlider'>
<h4>Fade Activación:</h4> <h4>Fade Activación:</h4>
<input type='checkbox' id='fadeInCheckbox'> Activar Fade In <input type='checkbox' id='fadeInCheckbox'> Fade In
<input type='checkbox' id='fadeOutCheckbox'> Activar Fade Out <input type='checkbox' id='fadeOutCheckbox'> Fade Out
<br><br> <br><br>
<input type='checkbox' id='syncWithIntervalCheckbox'> Sincronizar con Intervalómetro <input type='checkbox' id='syncWithIntervalCheckbox'> Sincronizar con Intervalómetro
<br><br> <br><br><br>
<button onclick="sendShutterData('save_shutter')">Save</button> <button onclick="sendShutterData('save_shutter')">Save</button>
<span id="shutterMessage" style="color: green; display: none;">Datos enviados correctamente</span> <span id="shutterMessage" style="color: green; display: none;">Datos enviados correctamente</span>
</div> </div>
<div class="section">
<!-- Sección Monitor de Cámara -->
<h3>Monitor de Cámara</h3>
<iframe src="http://192.168.8.5:8000" width="100%" height="400px" style="border: none;"></iframe>
</div>
<div class="section"> <div class="section">
<!-- Sección Óptica --> <!-- Sección Óptica -->
<h3>Óptica</h3> <h3>Óptica</h3>
@ -213,23 +347,17 @@ const char *htmlTemplate = R"rawliteral(
</div> </div>
<div class="section"> <div class="section">
<!-- Sección Dispositivo 360 -->
<h3>Dispositivo 360</h3> <h3>Dispositivo 360</h3>
<iframe id="iframe360" src="http://192.168.8.3" width="100%" height="400px" style="border: none;"></iframe> <iframe id="iframe360" src="http://192.168.8.3"></iframe>
<!-- <iframe id="iframe360" src="iframe.html" width="100%" height="400px" style="border: none;"></iframe> --> </div>
</div> </div>
<div class="section">
<!-- Sección Rodaje -->
<h3>Rodaje</h3>
<button onclick="accion()">ACCIÓN !!!</button>
<button onclick="corten()">CORTEN !!!</button>
<span id="accionMessage" style="color: green; display: none;">Mensaje enviado correctamente</span>
<br><br>
</div>
</div>
<!-- Script para manejar las interacciones y enviar el JSON --> <!-- Script para manejar las interacciones y enviar el JSON -->
<script> <script>
function toggleMonitor() {
let monitorLayer = document.getElementById('monitorLayer');
monitorLayer.style.display = (monitorLayer.style.display === 'none' || monitorLayer.style.display === '') ? 'block' : 'none';
}
window.addEventListener("message", function (event) { window.addEventListener("message", function (event) {
console.log("Mensaje recibido:", event.data); // Depuración console.log("Mensaje recibido:", event.data); // Depuración
@ -456,7 +584,7 @@ const char *htmlTemplate = R"rawliteral(
} }
// Llama a updateSensors cada 500ms // Llama a updateSensors cada 500ms
setInterval(updateSensors, 100); setInterval(updateSensors, 500);
</script> </script>
</body> </body>

View file

@ -15,7 +15,7 @@ bool motorIsSpeedActive = false;
int motorIntervalFrames = 1; int motorIntervalFrames = 1;
int motorIntervalSeconds = 1; int motorIntervalSeconds = 1;
bool motorIsIntervalActive = false; bool motorIsIntervalActive = false;
bool motorDirection = 1; bool motorDirection = STOP;
// Shutter // Shutter
int shutterFadePercent = 0; int shutterFadePercent = 0;
@ -116,6 +116,7 @@ void linear_motor_control(int motor, int SPEED)
else stop(motor); else stop(motor);
} }
unsigned long time_lineal_motor = millis();
float time_move_for_move_position_motor[6] = {0, 0, 0, 0, 0, 0}; float time_move_for_move_position_motor[6] = {0, 0, 0, 0, 0, 0};
unsigned long time_refresh_position_motor[6] = { millis(), millis(), millis(), millis(), millis(), millis()}; unsigned long time_refresh_position_motor[6] = { millis(), millis(), millis(), millis(), millis(), millis()};
float position_motor[6] = { 0, 0, 0, 0, 0, 0}; float position_motor[6] = { 0, 0, 0, 0, 0, 0};
@ -130,6 +131,7 @@ void config_position_motor(int motor, float position) //Configuracion posicion e
{ {
position_motor_objective[motor] = position; position_motor_objective[motor] = position;
Setpoint_Linear = position; Setpoint_Linear = position;
time_lineal_motor = millis();
} }
else else
{ {
@ -166,10 +168,10 @@ static volatile unsigned long lastTimeDebounce = 0; //Tiempo del rebote
static volatile bool force_stop = false; //Tiempo del rebote static volatile bool force_stop = false; //Tiempo del rebote
void fps_count_state() { void fps_count_state() {
if((digitalRead(sensor_fps)&&(micros()-lastTimeDebounce>= 100))&&(!closed)) if((digitalRead(sensor_fps)&&(micros()-lastTimeDebounce>=100))&&(!closed))
{ {
if(motorDirection==FORWARD) FramesCount++; if(motorDirection==FORWARD) FramesCount++;
else FramesCount--; else if(motorDirection==BACKWARD) FramesCount--;
lastTimeDebounce = micros(); lastTimeDebounce = micros();
fps_temp = 1000000./(float)(micros()-time_fps); fps_temp = 1000000./(float)(micros()-time_fps);
if(fps_temp<70) motorSpeedRead = fps_temp; if(fps_temp<70) motorSpeedRead = fps_temp;
@ -183,7 +185,7 @@ void fps_count_state() {
else if((digitalRead(sensor_fps)&&(micros()-lastTimeDebounce >= 150))&&(closed)) else if((digitalRead(sensor_fps)&&(micros()-lastTimeDebounce >= 150))&&(closed))
{ {
if(motorDirection==FORWARD) FramesCount++; if(motorDirection==FORWARD) FramesCount++;
else FramesCount--; else if(motorDirection==BACKWARD) FramesCount--;
lastTimeDebounce = micros(); lastTimeDebounce = micros();
closed = false; closed = false;
force_stop = true; force_stop = true;
@ -275,13 +277,20 @@ void ini_motors()
stop(3);*/ stop(3);*/
} }
void refresh_position_motors() void refresh_position_motors()
{ {
position_motor[0] = map(read_lineal_motor(),LINEAL_MAX,LINEAL_MIN,0,100000)/1000; position_motor[0] = map(read_lineal_motor(),LINEAL_MAX,LINEAL_MIN,0,100000)/1000;
#if PID_ENABLE #if PID_ENABLE
if ((position_motor[0]>=(Setpoint_Linear+1))||(position_motor[0]<=(Setpoint_Linear-1))) time_lineal_motor = millis();
if ((millis()-time_lineal_motor)<10)
{
Input_Linear = position_motor[0]; Input_Linear = position_motor[0];
PID_LINEAR.Compute(); PID_LINEAR.Compute();
linear_motor_control(0, Output_Linear); linear_motor_control(0, Output_Linear);
}
/*Input = (double)fps_temp; // Lectura del encoder óptico. El valor del contador se incrementa/decrementa a través de las interrupciones extrenas (pines 2 y 3). /*Input = (double)fps_temp; // Lectura del encoder óptico. El valor del contador se incrementa/decrementa a través de las interrupciones extrenas (pines 2 y 3).
if(myPID.Compute()) if(myPID.Compute())
analogWrite(EN_MOTOR[4], abs(Output)); // Por el primer pin sale la señal PWM. analogWrite(EN_MOTOR[4], abs(Output)); // Por el primer pin sale la señal PWM.