first commit
This commit is contained in:
commit
2c599aaa51
39
CraterLab_base_giratoria/include/README
Normal file
39
CraterLab_base_giratoria/include/README
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
9
CraterLab_base_giratoria/include/constants.h
Normal file
9
CraterLab_base_giratoria/include/constants.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#define DEBUG_M4 false
|
||||||
|
#define DEBUG_M7 false
|
||||||
|
#define PULSE_REV 400
|
||||||
|
#define REDUCTION_XY 5
|
||||||
|
#define REDUCTION_A 60
|
||||||
|
const int EN[3] = {10, 7, 4};
|
||||||
|
const int DIRP[3] = {9, 6, 3};
|
||||||
|
const int PUL[3] = {8, 5, 2};
|
||||||
|
const int FC[3] = {51, 53, 49};
|
259
CraterLab_base_giratoria/include/interface.html
Normal file
259
CraterLab_base_giratoria/include/interface.html
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
// Plantilla HTML
|
||||||
|
const char *htmlTemplate = R"rawliteral(
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<style>
|
||||||
|
/* Tema oscuro básico */
|
||||||
|
body {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #ffffff;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #cccccc;
|
||||||
|
/* Gris claro */
|
||||||
|
font-size: 32px;
|
||||||
|
border-bottom: 2px solid #555555;
|
||||||
|
/* Un borde gris medio */
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #bbbbbb;
|
||||||
|
/* Gris medio-claro */
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px solid #444444;
|
||||||
|
/* Un borde gris oscuro */
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
color: #dddddd;
|
||||||
|
/* Blanco roto o gris muy claro */
|
||||||
|
font-size: 18px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos de los inputs */
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select {
|
||||||
|
width: 100px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px 0;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #555;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos del checkbox y radio */
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo de los sliders */
|
||||||
|
input[type="range"] {
|
||||||
|
width: 30%;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Botones */
|
||||||
|
button {
|
||||||
|
background-color: #1e88e5;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 20px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 10px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #1565c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Dark styling for select dropdown */
|
||||||
|
select {
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #555;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo para contenedores de secciones */
|
||||||
|
.section {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
padding: 20px;
|
||||||
|
padding-top: 0px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
/* Bordes más visibles */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo para centrar los formularios en la pantalla */
|
||||||
|
.form-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- Sección Dispositivo 360 -->
|
||||||
|
<!-- Subsección X0 -->
|
||||||
|
<h4>X0:</h4>
|
||||||
|
<label for='x0Degrees'>Grados:</label>
|
||||||
|
<input type='text' id='x0Degrees'>
|
||||||
|
<label for='x0Duration'>Duración (s):</label>
|
||||||
|
<input type='text' id='x0Duration'>
|
||||||
|
<input type='number' id='x0Read'>
|
||||||
|
<br>
|
||||||
|
<button onclick="moveMotor('test_360','x0')">Test</button>
|
||||||
|
<button onclick="moveMotor('save_360','x0')">Save</button>
|
||||||
|
<span id="x0Message" style="color: green; display: none;">Movimiento enviado correctamente</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<!-- Subsección X1 -->
|
||||||
|
<h4>X1:</h4>
|
||||||
|
<label for='x1Degrees'>Grados:</label>
|
||||||
|
<input type='text' id='x1Degrees'>
|
||||||
|
<label for='x1Duration'>Duración (s):</label>
|
||||||
|
<input type='text' id='x1Duration'>
|
||||||
|
<input type='number' id='x1Read'>
|
||||||
|
<br>
|
||||||
|
<button onclick="moveMotor('test_360','x1')">Test</button>
|
||||||
|
<button onclick="moveMotor('save_360','x1')">Save</button>
|
||||||
|
<span id="x1Message" style="color: green; display: none;">Movimiento enviado correctamente</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<!-- Subsección Y0 -->
|
||||||
|
<h4>Y0:</h4>
|
||||||
|
<label for='y0Degrees'>Grados:</label>
|
||||||
|
<input type='text' id='y0Degrees'>
|
||||||
|
<label for='y0Duration'>Duración (s):</label>
|
||||||
|
<input type='text' id='y0Duration'>
|
||||||
|
<input type='number' id='y0Read'>
|
||||||
|
<br>
|
||||||
|
<button onclick="moveMotor('test_360','y0')">Test</button>
|
||||||
|
<button onclick="moveMotor('save_360','y0')">Save</button>
|
||||||
|
<span id="y0Message" style="color: green; display: none;">Movimiento enviado correctamente</span>
|
||||||
|
<br><br>
|
||||||
|
<input type='checkbox' id='syncWithInterval360'> Sincronizar con Intervalómetro
|
||||||
|
<br><br>
|
||||||
|
<!-- Script para manejar las interacciones y enviar el JSON -->
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function sendHeight() {
|
||||||
|
const height = document.documentElement.scrollHeight || document.body.scrollHeight;
|
||||||
|
window.parent.postMessage(height, "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = sendHeight;
|
||||||
|
window.onresize = sendHeight;
|
||||||
|
setInterval(sendHeight, 500);
|
||||||
|
|
||||||
|
function showMessage(elementId) {
|
||||||
|
const messageElement = document.getElementById(elementId);
|
||||||
|
if (messageElement) {
|
||||||
|
messageElement.style.display = 'inline';
|
||||||
|
setTimeout(() => {
|
||||||
|
messageElement.style.display = 'none';
|
||||||
|
}, 3000); // Mostrar el mensaje durante 3 segundos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveMotor(type_mode, motor) {
|
||||||
|
const degrees = document.getElementById(`${motor}Degrees`).value;
|
||||||
|
const duration = document.getElementById(`${motor}Duration`).value;
|
||||||
|
const syncWithInterval = document.getElementById('syncWithInterval360').checked;
|
||||||
|
|
||||||
|
const motorData = {
|
||||||
|
type: type_mode,
|
||||||
|
motor: motor,
|
||||||
|
degrees: degrees,
|
||||||
|
duration: duration,
|
||||||
|
syncWithInterval: syncWithInterval
|
||||||
|
};
|
||||||
|
fetch('/moveMotor360', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(motorData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage(`${motor}Message`))
|
||||||
|
.catch(error => console.error('Motor Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatex0Position() {
|
||||||
|
fetch('/x0Read')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('x0Read').value = data.x0Read;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener x0:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatex1Position() {
|
||||||
|
fetch('/x1Read')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('x1Read').value = data.x1Read;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener x1:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatey0Position() {
|
||||||
|
fetch('/y0Read')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('y0Read').value = data.y0Read;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener y0:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSensors() {
|
||||||
|
fetch('/sensors')
|
||||||
|
.then(response => response.json()) // Parsear la respuesta como JSON
|
||||||
|
.then(data => {
|
||||||
|
if (data.sensors && Array.isArray(data.sensors)) {
|
||||||
|
const sensorValues = data.sensors;
|
||||||
|
// Asignar los valores a los elementos de la interfaz
|
||||||
|
if (sensorValues.length >= 1) {
|
||||||
|
document.getElementById('x0Read').value = sensorValues[0];
|
||||||
|
}
|
||||||
|
if (sensorValues.length >= 2) {
|
||||||
|
document.getElementById('x1Read').value = sensorValues[1];
|
||||||
|
}
|
||||||
|
if (sensorValues.length >= 3) {
|
||||||
|
document.getElementById('y0Read').value = sensorValues[2];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Estructura inesperada:', data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener sensores:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Llama a updateSensors cada 500ms
|
||||||
|
setInterval(updateSensors, 500);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
)rawliteral";
|
416
CraterLab_base_giratoria/include/main_m4.cpp
Normal file
416
CraterLab_base_giratoria/include/main_m4.cpp
Normal file
|
@ -0,0 +1,416 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <RPC.h>
|
||||||
|
#include <constants.h>
|
||||||
|
|
||||||
|
using namespace rtos;
|
||||||
|
|
||||||
|
Thread sensorThread;
|
||||||
|
|
||||||
|
#define x1_axis 0
|
||||||
|
#define y0_axis 1
|
||||||
|
#define x0_axis 2
|
||||||
|
|
||||||
|
#define RIGHT false
|
||||||
|
#define LEFT true
|
||||||
|
#define STOP 0
|
||||||
|
#define ZERO 1
|
||||||
|
#define CONTINUOUS 2
|
||||||
|
#define ANGLE_MODE 3
|
||||||
|
|
||||||
|
|
||||||
|
// Dispositivo 360
|
||||||
|
int x0Degrees = 0;
|
||||||
|
unsigned long x0Duration = 10000;
|
||||||
|
int x1Degrees = 0;
|
||||||
|
unsigned long x1Duration = 10000;
|
||||||
|
int y0Degrees = 0;
|
||||||
|
unsigned long y0Duration = 10000;
|
||||||
|
bool syncx0WithInterval360 = false;
|
||||||
|
bool syncx1WithInterval360 = false;
|
||||||
|
bool syncy0WithInterval360 = false;
|
||||||
|
bool isAction[3] = {false, false, false};
|
||||||
|
int mode = STOP;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ARDUINO_GIGA_M7)
|
||||||
|
#define debug Serial
|
||||||
|
#elif defined(ARDUINO_GIGA_M4)
|
||||||
|
#define debug RPC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIME_PULSE_XY 2500
|
||||||
|
#define TIME_PULSE_A 500
|
||||||
|
|
||||||
|
bool direction[3] = {RIGHT, RIGHT, RIGHT};
|
||||||
|
|
||||||
|
unsigned long time_fc_zero[3] = {millis(), millis(), millis()};
|
||||||
|
bool enable_zero[3] = {true, true, true};
|
||||||
|
|
||||||
|
void search_zero()
|
||||||
|
{
|
||||||
|
time_fc_zero[x1_axis] = millis();
|
||||||
|
while(digitalRead(FC[x1_axis])||((millis()-time_fc_zero[x1_axis])<10))
|
||||||
|
{
|
||||||
|
digitalWrite(PUL[x1_axis], HIGH);
|
||||||
|
delayMicroseconds(2000);
|
||||||
|
digitalWrite(PUL[x1_axis], LOW);
|
||||||
|
delayMicroseconds(2000);
|
||||||
|
if(digitalRead(FC[x1_axis])) time_fc_zero[x1_axis] = millis();
|
||||||
|
}
|
||||||
|
time_fc_zero[y0_axis] = millis();
|
||||||
|
while(digitalRead(FC[y0_axis])||((millis()-time_fc_zero[y0_axis])<10))
|
||||||
|
{
|
||||||
|
digitalWrite(PUL[y0_axis], HIGH);
|
||||||
|
delayMicroseconds(2000);
|
||||||
|
digitalWrite(PUL[y0_axis], LOW);
|
||||||
|
delayMicroseconds(2000);
|
||||||
|
if(digitalRead(FC[y0_axis])) time_fc_zero[y0_axis] = millis();
|
||||||
|
};
|
||||||
|
time_fc_zero[x0_axis] = millis();
|
||||||
|
while(digitalRead(FC[x0_axis])||((millis()-time_fc_zero[x0_axis])<10))
|
||||||
|
{
|
||||||
|
digitalWrite(PUL[x0_axis], HIGH);
|
||||||
|
delayMicroseconds(250);
|
||||||
|
digitalWrite(PUL[x0_axis], LOW);
|
||||||
|
delayMicroseconds(250);
|
||||||
|
if(digitalRead(FC[x0_axis])) time_fc_zero[x0_axis] = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int angle_pulses[3] = {0, 0, 0}; //Varaible temporal de pulsos
|
||||||
|
float axis_angle[3] = {0, 0, 0}; //Angulo actual
|
||||||
|
|
||||||
|
float angleRead(int axis)
|
||||||
|
{
|
||||||
|
int sensorReading = angle_pulses[axis];
|
||||||
|
float reduction = REDUCTION_XY;
|
||||||
|
if (axis==2) reduction = REDUCTION_A;
|
||||||
|
return (360*sensorReading/(reduction*PULSE_REV));
|
||||||
|
}
|
||||||
|
|
||||||
|
int axis_pulses[3] = {0, 0, 0}; //Pulsos necesarios para llegar al angulo indicado
|
||||||
|
int axis_direction[3] = {1, 1, 0}; //Direccion de giro
|
||||||
|
int angle_pulses_MAX[3] = {0, 0, 0}; //Pulsos necesarios para dar una vuelta completa
|
||||||
|
int angle_pulses_ant[3] = {0, 0, 0}; //Varaible temporal de pulsos
|
||||||
|
bool flag_search[3] = {false, false, false};
|
||||||
|
bool flag_equal[3] = {true, true, true};
|
||||||
|
bool flag_refresh[3] = {false, false, false};
|
||||||
|
|
||||||
|
unsigned long time_axis[3] = { millis(), millis(), millis()};
|
||||||
|
unsigned long time_parts[3] = {10, 10, 10};
|
||||||
|
unsigned long time_pulse[3] = {TIME_PULSE_XY, TIME_PULSE_XY, TIME_PULSE_A};
|
||||||
|
int ant_angle[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
void stop_all()
|
||||||
|
{
|
||||||
|
for(int i=0; i<3; i++) flag_refresh[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RESOLUTION_ANGLE 0.25
|
||||||
|
float axis_angle_ant[3] = {0,0,0};
|
||||||
|
|
||||||
|
void search_angle(int axis, int angle, unsigned long time_initial, unsigned long time_final)
|
||||||
|
{
|
||||||
|
if(isAction[axis])
|
||||||
|
{
|
||||||
|
axis_angle[axis] = angleRead(axis);
|
||||||
|
if((axis_angle[axis]>((float)angle+RESOLUTION_ANGLE))||(axis_angle[axis]<((float)angle-RESOLUTION_ANGLE)))
|
||||||
|
{
|
||||||
|
if (axis_angle_ant[axis]!=axis_angle[axis])
|
||||||
|
{
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print(axis_angle[axis]);
|
||||||
|
RPC.print(" ");
|
||||||
|
RPC.println(angle);
|
||||||
|
#endif
|
||||||
|
axis_angle_ant[axis] = axis_angle[axis];
|
||||||
|
}
|
||||||
|
if (flag_search[axis])
|
||||||
|
{
|
||||||
|
flag_search[axis] = false;
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print(axis_angle[axis]);
|
||||||
|
RPC.print(" ");
|
||||||
|
RPC.print(angle);
|
||||||
|
#endif
|
||||||
|
if (axis_angle[axis]<(angle + RESOLUTION_ANGLE)) direction[axis] = RIGHT;
|
||||||
|
else direction[axis] = LEFT;
|
||||||
|
if ((abs(axis_angle[axis])>360)||(abs(angle)>360))enable_zero[axis] = false;
|
||||||
|
else enable_zero[axis] = true;
|
||||||
|
if((axis==y0_axis)||(axis==x0_axis)) direction[axis]=!direction[axis];
|
||||||
|
digitalWrite(DIRP[axis], direction[axis]);
|
||||||
|
if (axis!=x0_axis) axis_pulses[axis] = map(abs(angle-axis_angle[axis]), 0, 359, 0, PULSE_REV*REDUCTION_XY);
|
||||||
|
else axis_pulses[axis] = map(abs(angle-axis_angle[axis]), 0, 359, 0, PULSE_REV*REDUCTION_A);
|
||||||
|
time_pulse[axis] = ((1000/2)*(time_final-time_initial)/axis_pulses[axis]); //1000 es conversion de milisegundos a microsegundos entre dos porque es tiempo de 0 a 1
|
||||||
|
if((time_pulse[axis]<TIME_PULSE_XY)&&(axis<=y0_axis)) time_pulse[axis]=TIME_PULSE_XY;
|
||||||
|
else if((time_pulse[axis]<TIME_PULSE_A)&&(axis==x0_axis)) time_pulse[axis]=TIME_PULSE_A;
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print(" ");
|
||||||
|
RPC.print(axis_pulses[axis]);
|
||||||
|
RPC.print(" ");
|
||||||
|
RPC.println(time_pulse[axis]);
|
||||||
|
#endif
|
||||||
|
flag_refresh[axis] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if((axis_angle[axis]<=((float)angle+RESOLUTION_ANGLE))&&(axis_angle[axis]>=((float)angle-RESOLUTION_ANGLE))) flag_refresh[axis] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long time_refresh_x = micros();
|
||||||
|
unsigned long time_refresh_y = micros();
|
||||||
|
unsigned long time_refresh_a = micros();
|
||||||
|
bool state_x = false;
|
||||||
|
bool state_y = false;
|
||||||
|
bool state_a = false;
|
||||||
|
void refresh_steppers()
|
||||||
|
{
|
||||||
|
if(((micros()-time_refresh_x)>=time_pulse[x1_axis])&&(flag_refresh[x1_axis]))
|
||||||
|
{
|
||||||
|
time_refresh_x = micros();
|
||||||
|
digitalWrite(PUL[x1_axis], state_x);
|
||||||
|
if(state_x)
|
||||||
|
{
|
||||||
|
if (direction[x1_axis]==RIGHT) angle_pulses[x1_axis]++;
|
||||||
|
else angle_pulses[x1_axis]--;
|
||||||
|
}
|
||||||
|
state_x = !state_x;
|
||||||
|
}
|
||||||
|
if(((micros()-time_refresh_y)>=time_pulse[y0_axis])&&(flag_refresh[y0_axis]))
|
||||||
|
{
|
||||||
|
time_refresh_y = micros();
|
||||||
|
digitalWrite(PUL[y0_axis], state_y);
|
||||||
|
if(state_y)
|
||||||
|
{
|
||||||
|
if (direction[y0_axis]==LEFT) angle_pulses[y0_axis]++;
|
||||||
|
else angle_pulses[y0_axis]--;
|
||||||
|
}
|
||||||
|
state_y = !state_y;
|
||||||
|
}
|
||||||
|
if(((micros()-time_refresh_a)>=time_pulse[x0_axis])&&(flag_refresh[x0_axis]))
|
||||||
|
{
|
||||||
|
time_refresh_a = micros();
|
||||||
|
digitalWrite(PUL[x0_axis], state_a);
|
||||||
|
if(state_a)
|
||||||
|
{
|
||||||
|
if (direction[x0_axis]==LEFT) angle_pulses[x0_axis]++;
|
||||||
|
else angle_pulses[x0_axis]--;
|
||||||
|
}
|
||||||
|
state_a = !state_a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long startTimex = 0;
|
||||||
|
long startTimey = 0;
|
||||||
|
long startTimea = 0;
|
||||||
|
const int timeThreshold = 500;
|
||||||
|
|
||||||
|
void f_x1_axis(){ //Funcion de paso por cero de la interrupcion del eje x
|
||||||
|
if (((millis() - startTimex) > timeThreshold)&&(enable_zero[x1_axis]))
|
||||||
|
{
|
||||||
|
if(angle_pulses[x1_axis]>0) angle_pulses_MAX[x1_axis] = angle_pulses[x1_axis]; //Varaible de pulsos maximos por vuelta
|
||||||
|
angle_pulses[x1_axis] = 0; //Varaible temporal de pulsos
|
||||||
|
startTimex = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void f_y0_axis(){ //Funcion de paso por cero de la interrupcion del eje y
|
||||||
|
if (((millis() - startTimey) > timeThreshold)&&(enable_zero[y0_axis]))
|
||||||
|
{
|
||||||
|
if(angle_pulses[y0_axis]>0) angle_pulses_MAX[y0_axis] = angle_pulses[y0_axis]; //Varaible de pulsos maximos por vuelta
|
||||||
|
angle_pulses[y0_axis] = 0; //Varaible temporal de pulsos
|
||||||
|
startTimey = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void f_x0_axis(){ //Funcion de paso por cero de la interrupcion del eje a
|
||||||
|
if (((millis() - startTimea) > timeThreshold)&&(enable_zero[x0_axis]))
|
||||||
|
{
|
||||||
|
if(angle_pulses[x0_axis]>0) angle_pulses_MAX[x0_axis] = angle_pulses[x0_axis]; //Varaible de pulsos maximos por vuelta
|
||||||
|
angle_pulses[x0_axis] = 0; //Varaible temporal de pulsos
|
||||||
|
startTimea = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Functions on the M4 that returns axis
|
||||||
|
*/
|
||||||
|
int AxisA_Read() {
|
||||||
|
int result = angle_pulses[x0_axis];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AxisX_Read() {
|
||||||
|
int result = angle_pulses[x1_axis];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AxisY_Read() {
|
||||||
|
int result = angle_pulses[y0_axis];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_value[10];
|
||||||
|
int* decode_values(String inputString_rpc, int num_dec)
|
||||||
|
{
|
||||||
|
String str = inputString_rpc.substring(inputString_rpc.lastIndexOf(":") + 1);
|
||||||
|
read_value[0] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
for(int i=1; i<num_dec; i++)
|
||||||
|
{
|
||||||
|
str = str.substring(str.indexOf(',')+1);
|
||||||
|
read_value[i] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
}
|
||||||
|
return read_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
char c_rpc;
|
||||||
|
String inputString_rpc;
|
||||||
|
void RPCRead()
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/////// RUTINA TRATAMIENTO DE STRINGS DEL UART ///////////
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
if (RPC.available())
|
||||||
|
{
|
||||||
|
c_rpc = RPC.read();
|
||||||
|
if ((c_rpc == '\r') || (c_rpc == '\n'))
|
||||||
|
{
|
||||||
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
|
if (inputString_rpc.startsWith("/axisA:")) //Interval Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 4);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido axis M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<4; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
x0Degrees = value[0];
|
||||||
|
x0Duration = value[1]*1000;
|
||||||
|
syncx0WithInterval360 = value[2];
|
||||||
|
mode = ANGLE_MODE;
|
||||||
|
if(!value[3]) //Save or test
|
||||||
|
{
|
||||||
|
isAction[x0_axis] = true;
|
||||||
|
flag_search[x0_axis] = true;
|
||||||
|
time_axis[x0_axis] = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/axisX:")) //Interval Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 4);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido axis M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<4; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
x1Degrees = value[0];
|
||||||
|
x1Duration = value[1]*1000;
|
||||||
|
syncx1WithInterval360 = value[2];
|
||||||
|
mode = ANGLE_MODE;
|
||||||
|
if(!value[3]) //Save or test
|
||||||
|
{
|
||||||
|
isAction[x1_axis] = true;
|
||||||
|
flag_search[x1_axis] = true;
|
||||||
|
time_axis[x1_axis] = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/axisY:")) //Interval Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 4);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido axis M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<4; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
y0Degrees = value[0];
|
||||||
|
y0Duration = value[1]*1000;
|
||||||
|
syncy0WithInterval360 = value[2];
|
||||||
|
mode = ANGLE_MODE;
|
||||||
|
if(!value[3]) //Save or test
|
||||||
|
{
|
||||||
|
isAction[y0_axis] = true;
|
||||||
|
flag_search[y0_axis] = true;
|
||||||
|
time_axis[y0_axis] = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/action:")) //Interval Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 1);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido action M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<1; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
if (value[0])
|
||||||
|
{
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
isAction[i] = true;
|
||||||
|
flag_search[i] = true;
|
||||||
|
time_axis[i] = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
isAction[i] = false;
|
||||||
|
flag_refresh[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputString_rpc = String();
|
||||||
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
inputString_rpc += c_rpc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void requestReading() {
|
||||||
|
while (true) {
|
||||||
|
//delay(100);
|
||||||
|
RPCRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
RPC.begin();
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
pinMode(EN[i], OUTPUT);
|
||||||
|
pinMode(DIRP[i], OUTPUT);
|
||||||
|
pinMode(PUL[i], OUTPUT);
|
||||||
|
digitalWrite(EN[i], LOW);
|
||||||
|
digitalWrite(DIRP[i], HIGH);
|
||||||
|
digitalWrite(PUL[i], HIGH);
|
||||||
|
}
|
||||||
|
for(int i=0; i<3; i++) pinMode(FC[i], INPUT_PULLUP);
|
||||||
|
search_zero();
|
||||||
|
//delay(10000);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(FC[x1_axis]), f_x1_axis, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(FC[y0_axis]), f_y0_axis, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(FC[x0_axis]), f_x0_axis, FALLING);
|
||||||
|
|
||||||
|
flag_refresh[y0_axis]=false;
|
||||||
|
flag_refresh[x1_axis]=false;
|
||||||
|
flag_refresh[x0_axis]=false;
|
||||||
|
|
||||||
|
//Bind the sensorRead() function on the M4
|
||||||
|
RPC.bind("AxisA", AxisA_Read);
|
||||||
|
RPC.bind("AxisX", AxisX_Read);
|
||||||
|
RPC.bind("AxisY", AxisY_Read);
|
||||||
|
/*
|
||||||
|
Starts a new thread that loops the requestReading() function
|
||||||
|
*/
|
||||||
|
//sensorThread.start(requestReading);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
search_angle(x0_axis, x0Degrees, 0, x0Duration);
|
||||||
|
search_angle(x1_axis, x1Degrees, 0, x1Duration);
|
||||||
|
search_angle(y0_axis, y0Degrees, 0, y0Duration);
|
||||||
|
refresh_steppers();
|
||||||
|
RPCRead();
|
||||||
|
}
|
315
CraterLab_base_giratoria/include/main_m7.cpp
Normal file
315
CraterLab_base_giratoria/include/main_m7.cpp
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <RPC.h>
|
||||||
|
#include "RPC.h"
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include "interface.html"
|
||||||
|
#include <constants.h>
|
||||||
|
|
||||||
|
#define AP_MODE false
|
||||||
|
|
||||||
|
// Inicializando RTOS
|
||||||
|
using namespace rtos;
|
||||||
|
Thread sensorThread;
|
||||||
|
|
||||||
|
#define WIFI true
|
||||||
|
|
||||||
|
#if WIFI
|
||||||
|
#include <WiFi.h>
|
||||||
|
char ssid[] = "Analogue_Hyperlapse_Camera"; // your network SSID (name)
|
||||||
|
char password[] = "CraterLab"; // your network password (use for WPA, or use as key for WEP)
|
||||||
|
IPAddress ip(192, 168, 8, 3);
|
||||||
|
IPAddress remote_ip(192, 168, 8, 4);
|
||||||
|
IPAddress gateway(192, 168, 8, 1);
|
||||||
|
IPAddress subnet(255, 255, 255, 0);
|
||||||
|
IPAddress dns(8, 8, 8, 8); //primaryDNS
|
||||||
|
// Crear el servidor en el puerto 80
|
||||||
|
WiFiServer server(80);
|
||||||
|
char packetBuffer[255]; //buffer to hold incoming packet
|
||||||
|
char ReplyBuffer[] = "acknowledged"; // a string to send back
|
||||||
|
WiFiUDP Udp;
|
||||||
|
unsigned int localPort = 2390; // local port to listen on
|
||||||
|
unsigned int remotePort = 2392; // local port to send
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define x1_axis 0
|
||||||
|
#define y0_axis 1
|
||||||
|
#define x0_axis 2
|
||||||
|
|
||||||
|
#define STOP 0
|
||||||
|
#define ZERO 1
|
||||||
|
#define CONTINUOUS 2
|
||||||
|
#define ANGLE_MODE 3
|
||||||
|
|
||||||
|
// Motor
|
||||||
|
int motorSpeedValue = 25;
|
||||||
|
bool motorIsSpeedActive = false;
|
||||||
|
int motorIntervalFrames = 1;
|
||||||
|
int motorIntervalSeconds = 1;
|
||||||
|
bool motorIsIntervalActive = false;
|
||||||
|
int motorDirection = 1;
|
||||||
|
|
||||||
|
// Shutter
|
||||||
|
int shutterFadePercent = 0;
|
||||||
|
int shutterFadeFrames = 50;
|
||||||
|
bool shutterSyncWithInterval = false;
|
||||||
|
bool shutterFadeInActive = false;
|
||||||
|
bool shutterFadeOutActive = false;
|
||||||
|
|
||||||
|
// Óptica
|
||||||
|
int zoomValue = 50;
|
||||||
|
int focusValue = 50;
|
||||||
|
float diaphragmValue = 1.8;
|
||||||
|
bool syncWithIntervalOptics = false;
|
||||||
|
|
||||||
|
// Dispositivo 360
|
||||||
|
int x0Degrees = 0;
|
||||||
|
int x0Duration = 0;
|
||||||
|
int x1Degrees = 0;
|
||||||
|
int x1Duration = 0;
|
||||||
|
int y0Degrees = 0;
|
||||||
|
int y0Duration = 0;
|
||||||
|
bool syncWithInterval360 = false;
|
||||||
|
|
||||||
|
//Sensores
|
||||||
|
float motorSpeedRead = 0;
|
||||||
|
float FadePercentRead = 0;
|
||||||
|
int zoomValueRead = 0;
|
||||||
|
int focusValueRead = 0;
|
||||||
|
float diaphragmValueRead = 0;
|
||||||
|
int x0DegreesRead = 0;
|
||||||
|
int x1DegreesRead = 0;
|
||||||
|
int y0DegreesRead = 0;
|
||||||
|
|
||||||
|
int mode = CONTINUOUS;
|
||||||
|
|
||||||
|
const char axis_c[] = {'x','y','a'};
|
||||||
|
|
||||||
|
float Motor_axis[3] = {0,0,0};
|
||||||
|
|
||||||
|
int read_value[10];
|
||||||
|
int* decode_values(String inputString, int num_dec)
|
||||||
|
{
|
||||||
|
String str = inputString.substring(inputString.lastIndexOf(":") + 1);
|
||||||
|
read_value[0] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
for(int i=1; i<num_dec; i++)
|
||||||
|
{
|
||||||
|
str = str.substring(str.indexOf(',')+1);
|
||||||
|
read_value[i] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
}
|
||||||
|
return read_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handlePostRequest(String body) {
|
||||||
|
// Parseamos el cuerpo del JSON
|
||||||
|
StaticJsonDocument<1000> doc;
|
||||||
|
deserializeJson(doc, body);
|
||||||
|
int save = true;
|
||||||
|
//DeserializationError error = deserializeJson(doc, body);
|
||||||
|
/*if (error) {
|
||||||
|
Serial.println("Error al parsear el JSON");
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
Serial.println("Procesando JSON...");
|
||||||
|
String type = doc["type"];
|
||||||
|
if((type=="test_360")||(type=="save_360"))
|
||||||
|
{
|
||||||
|
Serial.println(type);
|
||||||
|
if (type=="save_360") save = true;
|
||||||
|
else save = false;
|
||||||
|
String axis = doc["motor"];
|
||||||
|
if (axis=="x0")
|
||||||
|
{
|
||||||
|
x0Degrees = doc["degrees"];
|
||||||
|
x0Duration = doc["duration"];
|
||||||
|
syncWithInterval360 = doc["syncWithInterval"];
|
||||||
|
RPC.println("/axisA:" + String(x0Degrees) + "," + String(x0Duration) + "," + String(syncWithInterval360) + "," + String(save));
|
||||||
|
}
|
||||||
|
else if (axis=="x1")
|
||||||
|
{
|
||||||
|
x1Degrees = doc["degrees"];
|
||||||
|
x1Duration = doc["duration"];
|
||||||
|
syncWithInterval360 = doc["syncWithInterval"];
|
||||||
|
RPC.println("/axisX:" + String(x1Degrees) + "," + String(x1Duration) + "," + String(syncWithInterval360) + "," + String(save));
|
||||||
|
}
|
||||||
|
else if (axis=="y0")
|
||||||
|
{
|
||||||
|
y0Degrees = doc["degrees"];
|
||||||
|
y0Duration = doc["duration"];
|
||||||
|
syncWithInterval360 = doc["syncWithInterval"];
|
||||||
|
RPC.println("/axisY:" + String(y0Degrees) + "," + String(y0Duration) + "," + String(syncWithInterval360) + "," + String(save));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else Serial.println("No reconocido");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This thread calls the sensorThread() function remotely
|
||||||
|
every second. Result is printed to the RPC1 stream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void requestReading() {
|
||||||
|
while (true) {
|
||||||
|
delay(25);
|
||||||
|
Motor_axis[x1_axis] = RPC.call("AxisX").as<int>();
|
||||||
|
Motor_axis[y0_axis] = RPC.call("AxisY").as<int>();
|
||||||
|
Motor_axis[x0_axis] = RPC.call("AxisA").as<int>();
|
||||||
|
x0DegreesRead = 360*Motor_axis[x0_axis]/(REDUCTION_A*PULSE_REV);
|
||||||
|
y0DegreesRead = 360*Motor_axis[y0_axis]/(REDUCTION_XY*PULSE_REV);
|
||||||
|
x1DegreesRead = 360*Motor_axis[x1_axis]/(REDUCTION_XY*PULSE_REV);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mode_Read() {
|
||||||
|
int result = mode;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(1000000);
|
||||||
|
RPC.begin(); //boots M4
|
||||||
|
#if WIFI
|
||||||
|
#if AP_MODE
|
||||||
|
int status = WL_IDLE_STATUS;
|
||||||
|
// Create open network. Change this line if you want to create an WEP network:
|
||||||
|
WiFi.config(ip, dns, gateway, subnet);
|
||||||
|
status = WiFi.beginAP(ssid, password);
|
||||||
|
if (status != WL_AP_LISTENING) {
|
||||||
|
Serial.println("Creating access point failed");
|
||||||
|
// don't continue
|
||||||
|
while (true)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
WiFi.config(ip, dns, gateway, subnet);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
|
delay(1000);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Conectado a WiFi!");
|
||||||
|
Serial.print("Dirección IP: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
#endif
|
||||||
|
while (digitalRead(FC[x0_axis])||digitalRead(FC[x1_axis])||digitalRead(FC[y0_axis]));
|
||||||
|
// Enable Server
|
||||||
|
server.begin();
|
||||||
|
// Enable UDP
|
||||||
|
Udp.begin(localPort);
|
||||||
|
//Starts a new thread that loops the requestReading() function
|
||||||
|
sensorThread.start(requestReading);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readUDP()
|
||||||
|
{
|
||||||
|
int packetSize = Udp.parsePacket();
|
||||||
|
if (packetSize) {
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.print("Received packet of size ");
|
||||||
|
Serial.println(packetSize);
|
||||||
|
Serial.print("From ");
|
||||||
|
IPAddress remoteIp = Udp.remoteIP();
|
||||||
|
Serial.print(remoteIp);
|
||||||
|
Serial.print(", port ");
|
||||||
|
Serial.println(Udp.remotePort());
|
||||||
|
#endif
|
||||||
|
// read the packet into packetBufffer
|
||||||
|
int len = Udp.read(packetBuffer, 255);
|
||||||
|
if (len > 0) {
|
||||||
|
packetBuffer[len] = 0;
|
||||||
|
}
|
||||||
|
RPC.println(packetBuffer);
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Contents:");
|
||||||
|
Serial.println(packetBuffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
WiFiClient client = server.available();
|
||||||
|
if (client) {
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Nuevo cliente conectado");
|
||||||
|
#endif
|
||||||
|
String request = "";
|
||||||
|
bool isPostRequest = false;
|
||||||
|
|
||||||
|
while (client.connected()) {
|
||||||
|
if (client.available()) {
|
||||||
|
char c = client.read();
|
||||||
|
request += c;
|
||||||
|
|
||||||
|
// Identificar si es una solicitud POST
|
||||||
|
if (request.indexOf("POST") >= 0) {
|
||||||
|
isPostRequest = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si se encuentra el final de la solicitud
|
||||||
|
if (c == '\n' && request.endsWith("\r\n\r\n")) {
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Solicitud recibida:");
|
||||||
|
Serial.println(request);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (isPostRequest) {
|
||||||
|
String body = "";
|
||||||
|
while (client.available()) {
|
||||||
|
body += (char)client.read();
|
||||||
|
}
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Cuerpo del mensaje recibido:");
|
||||||
|
Serial.println(body);
|
||||||
|
#endif
|
||||||
|
// Llamamos a la función para procesar la petición POST
|
||||||
|
handlePostRequest(body);
|
||||||
|
// Respuesta al cliente
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-type:text/plain");
|
||||||
|
client.println();
|
||||||
|
client.println("Datos enviados correctamente");
|
||||||
|
} else if (request.indexOf("GET /sensors") >= 0) { // actualiza fps en interface
|
||||||
|
// Respuesta para la ruta /motorSpeed
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-Type: application/json");
|
||||||
|
client.println();
|
||||||
|
String response = "{\"sensors\":[" + String(x0DegreesRead) + "," + String(x1DegreesRead) + "," + String(y0DegreesRead) + "]}";
|
||||||
|
client.print(response);
|
||||||
|
} else {
|
||||||
|
// Respuesta para servir la interfaz HTML
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-type:text/html");
|
||||||
|
client.println();
|
||||||
|
client.print(htmlTemplate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.stop();
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Cliente desconectado");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
readUDP();
|
||||||
|
#if DEBUG_M7
|
||||||
|
String buffer = "";
|
||||||
|
|
||||||
|
while (RPC.available()) {
|
||||||
|
|
||||||
|
buffer += (char)RPC.read(); // Fill the buffer with characters
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.length() > 0) {
|
||||||
|
|
||||||
|
Serial.print(buffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
46
CraterLab_base_giratoria/lib/README
Normal file
46
CraterLab_base_giratoria/lib/README
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
30
CraterLab_base_giratoria/platformio.ini
Normal file
30
CraterLab_base_giratoria/platformio.ini
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:ARDUINO_GIGA_M7]
|
||||||
|
;platform = https://github.com/dberlin/platform-ststm32.git#develop
|
||||||
|
;platform = https://github.com/dberlin/platform-ststm32
|
||||||
|
platform = ststm32
|
||||||
|
board = giga_r1_m7
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 1000000
|
||||||
|
;upload_port = COM16
|
||||||
|
board_build.arduino.flash_layout = 75_25 ;50_50, 75_25, 100_0
|
||||||
|
lib_deps = bblanchon/ArduinoJson@^7.2.0
|
||||||
|
|
||||||
|
[env:ARDUINO_GIGA_M4]
|
||||||
|
;platform = https://github.com/dberlin/platform-ststm32.git#develop
|
||||||
|
platform = ststm32
|
||||||
|
board = giga_r1_m4
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 1000000
|
||||||
|
;upload_port = COM16
|
||||||
|
board_build.arduino.flash_layout = 75_25 ;50_50, 75_25, 100_0
|
||||||
|
;board_build.arduino.flash_layout = 100_0 ;50_50, 75_25, 100_0
|
5
CraterLab_base_giratoria/src/main.cpp
Normal file
5
CraterLab_base_giratoria/src/main.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#if defined(ARDUINO_GIGA_M7)
|
||||||
|
#include<main_m7.cpp>
|
||||||
|
#elif defined(ARDUINO_GIGA_M4)
|
||||||
|
#include<main_m4.cpp>
|
||||||
|
#endif
|
11
CraterLab_base_giratoria/test/README
Normal file
11
CraterLab_base_giratoria/test/README
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
This directory is intended for PlatformIO Test Runner and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PlatformIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
39
CraterLab_camera/include/README
Normal file
39
CraterLab_camera/include/README
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
42
CraterLab_camera/include/constants.h
Normal file
42
CraterLab_camera/include/constants.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#define FORWARD 0
|
||||||
|
#define BACKWARD 1
|
||||||
|
#define STOP 0
|
||||||
|
#define IN 1
|
||||||
|
#define OUT 2
|
||||||
|
#define IN_OUT 3
|
||||||
|
#define FPS_MOTOR 4
|
||||||
|
|
||||||
|
//Definicion de los pines del shift register
|
||||||
|
#define Data_pin 8
|
||||||
|
#define Clock_pin 4
|
||||||
|
#define Latch_pin 12
|
||||||
|
#define Enable 7
|
||||||
|
|
||||||
|
//Definicion de los Motores 0,1,2,3 en el shift register
|
||||||
|
#define M2A 0
|
||||||
|
#define M1A 1
|
||||||
|
#define M0A 2
|
||||||
|
#define M0B 3
|
||||||
|
#define M1B 4
|
||||||
|
#define M3A 5
|
||||||
|
#define M2B 6
|
||||||
|
#define M3B 7
|
||||||
|
|
||||||
|
//Definicion de los enable (PWM) de los Motores 0,1,2,3 en las gpio del Arduino
|
||||||
|
#define EN0 11
|
||||||
|
#define EN1 3
|
||||||
|
#define EN2 5
|
||||||
|
#define EN3 6
|
||||||
|
|
||||||
|
//Definicion del Motor 4
|
||||||
|
#define EN_M4 33
|
||||||
|
#define R_M4 10
|
||||||
|
#define L_M4 9
|
||||||
|
|
||||||
|
//Definicion de los pines de los sensores
|
||||||
|
#define sensor_fps 20
|
||||||
|
#define sensor_lineal_motor A0
|
||||||
|
|
||||||
|
//Definicion de los limites del sensor lineal
|
||||||
|
#define LINEAL_MAX 478
|
||||||
|
#define LINEAL_MIN 0
|
452
CraterLab_camera/include/interface.html
Normal file
452
CraterLab_camera/include/interface.html
Normal file
|
@ -0,0 +1,452 @@
|
||||||
|
// Plantilla HTML
|
||||||
|
const char *htmlTemplate = R"rawliteral(
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<style>
|
||||||
|
/* Tema oscuro básico */
|
||||||
|
body {
|
||||||
|
background-color: #121212;
|
||||||
|
color: #ffffff;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #cccccc;
|
||||||
|
/* Gris claro */
|
||||||
|
font-size: 32px;
|
||||||
|
border-bottom: 2px solid #555555;
|
||||||
|
/* Un borde gris medio */
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #bbbbbb;
|
||||||
|
/* Gris medio-claro */
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px solid #444444;
|
||||||
|
/* Un borde gris oscuro */
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
color: #dddddd;
|
||||||
|
/* Blanco roto o gris muy claro */
|
||||||
|
font-size: 18px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos de los inputs */
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select {
|
||||||
|
width: 100px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px 0;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #555;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos del checkbox y radio */
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo de los sliders */
|
||||||
|
input[type="range"] {
|
||||||
|
width: 30%;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Botones */
|
||||||
|
button {
|
||||||
|
background-color: #1e88e5;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 20px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 10px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #1565c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Dark styling for select dropdown */
|
||||||
|
select {
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #555;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo para contenedores de secciones */
|
||||||
|
.section {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
padding: 20px;
|
||||||
|
padding-top: 0px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
/* Bordes más visibles */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo para centrar los formularios en la pantalla */
|
||||||
|
.form-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100px;
|
||||||
|
/* Evita que sea muy pequeño al inicio */
|
||||||
|
overflow: hidden !important;
|
||||||
|
/* Asegura que no haya barras de desplazamiento */
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="form-container">
|
||||||
|
<h2>Control Bolex Paillard</h2>
|
||||||
|
<div class="section">
|
||||||
|
<!-- Sección Motor Cámara -->
|
||||||
|
<h3>Motor Cámara</h3>
|
||||||
|
|
||||||
|
<h4>Speed</h4>
|
||||||
|
<label for='fps'>FPS:</label>
|
||||||
|
<input type='range' min='0' max='48' value='24' id='speedSlider'>
|
||||||
|
<span id='speedValueDisplay'>24</span> fps
|
||||||
|
<input type='number' id='fps'>
|
||||||
|
<input type='checkbox' id='speedCheckbox'> Activar Speed
|
||||||
|
|
||||||
|
<h4>Intervalómetro:</h4>
|
||||||
|
<label for='intervalFrames'>Frames:</label>
|
||||||
|
<input type='number' id='intervalFrames' value='10' min='1'>
|
||||||
|
<label for='intervalSeconds'>Segundos:</label>
|
||||||
|
<input type='number' id='intervalSeconds' value='1' min='1'>
|
||||||
|
<input type='checkbox' id='intervalCheckbox'> Activar Intervalómetro
|
||||||
|
|
||||||
|
<h4>Dirección:</h4>
|
||||||
|
<input type='radio' id='forward' name='direction' value='forward' checked> Forward
|
||||||
|
<input type='radio' id='backward' name='direction' value='backward'> Backward
|
||||||
|
<br><br>
|
||||||
|
<button onclick="sendMotorCameraData('test_motor')">Test</button>
|
||||||
|
<button onclick="sendMotorCameraData('save_motor')">Save</button>
|
||||||
|
<button onclick="stop()">Stop</button>
|
||||||
|
<span id="motorCameraMessage" style="color: green; display: none;">Datos enviados correctamente</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<!-- Sección Shutter -->
|
||||||
|
<h3>Shutter</h3>
|
||||||
|
<h4>Fade In/Out Frames:</h4>
|
||||||
|
<p>% apertura inicial: <span id='fadePercentDisplay'>50</span></p>
|
||||||
|
<input type='range' min='0' max='100' value='50' id='fadePercentSlider'>
|
||||||
|
<input type='number' id='fade'>
|
||||||
|
<p>Número de frames: <span id='fadeFramesDisplay'>50</span></p>
|
||||||
|
<input type='range' min='0' max='100' value='50' id='fadeFramesSlider'>
|
||||||
|
|
||||||
|
<h4>Fade Activación:</h4>
|
||||||
|
<input type='checkbox' id='fadeInCheckbox'> Activar Fade In
|
||||||
|
<input type='checkbox' id='fadeOutCheckbox'> Activar Fade Out
|
||||||
|
<br><br>
|
||||||
|
<input type='checkbox' id='syncWithIntervalCheckbox'> Sincronizar con Intervalómetro
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<button onclick="sendShutterData('save_shutter')">Save</button>
|
||||||
|
<span id="shutterMessage" style="color: green; display: none;">Datos enviados correctamente</span>
|
||||||
|
</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">
|
||||||
|
<!-- Sección Óptica -->
|
||||||
|
<h3>Óptica</h3>
|
||||||
|
<h4>Zoom:</h4>
|
||||||
|
<p>Valor de zoom: <span id='zoomValueDisplay'>50</span></p>
|
||||||
|
<input type='range' min='0' max='100' value='50' id='zoomSlider'>
|
||||||
|
|
||||||
|
<h4>Foco:</h4>
|
||||||
|
<p>Valor de foco: <span id='focusValueDisplay'>50</span></p>
|
||||||
|
<input type='range' min='0' max='100' value='50' id='focusSlider'>
|
||||||
|
|
||||||
|
<h4>Diafragma:</h4>
|
||||||
|
<select id='diaphragmSelect'>
|
||||||
|
<option value='1.9'>1.9</option>
|
||||||
|
<option value='2.2'>2.2</option>
|
||||||
|
<option value='4'>4</option>
|
||||||
|
<option value='5.6'>5.6</option>
|
||||||
|
<option value='8'>8</option>
|
||||||
|
<option value='11'>11</option>
|
||||||
|
<option value='16'>16</option>
|
||||||
|
<option value='22'>22</option>
|
||||||
|
</select>
|
||||||
|
<br><br>
|
||||||
|
<input type='checkbox' id='syncWithIntervalOptics'> Sincronizar con Intervalómetro
|
||||||
|
<br><br>
|
||||||
|
<button onclick="sendOpticsData('test_optics')">Test</button>
|
||||||
|
<button onclick="sendOpticsData('save_optics')">Save</button>
|
||||||
|
<span id="opticsMessage" style="color: green; display: none;">Datos enviados correctamente</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<!-- Sección Dispositivo 360 -->
|
||||||
|
<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="iframe.html" width="100%" height="400px" style="border: none;"></iframe> -->
|
||||||
|
</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>
|
||||||
|
|
||||||
|
window.addEventListener("message", function (event) {
|
||||||
|
console.log("Mensaje recibido:", event.data); // Depuración
|
||||||
|
|
||||||
|
// Seleccionar el iframe específico por su ID
|
||||||
|
const targetIframe = document.getElementById("iframe360");
|
||||||
|
|
||||||
|
// Verificar que el mensaje contiene un número válido (altura)
|
||||||
|
if (targetIframe && typeof event.data === "number" && event.data > 0) {
|
||||||
|
targetIframe.style.height = event.data + "px";
|
||||||
|
console.log("Altura ajustada del iframe a:", event.data + "px"); // Depuración
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateDisplay() {
|
||||||
|
document.getElementById('speedValueDisplay').innerText = document.getElementById('speedSlider').value;
|
||||||
|
document.getElementById('fadePercentDisplay').innerText = document.getElementById('fadePercentSlider').value;
|
||||||
|
document.getElementById('fadeFramesDisplay').innerText = document.getElementById('fadeFramesSlider').value;
|
||||||
|
document.getElementById('zoomValueDisplay').innerText = document.getElementById('zoomSlider').value;
|
||||||
|
document.getElementById('focusValueDisplay').innerText = document.getElementById('focusSlider').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(elementId) {
|
||||||
|
const messageElement = document.getElementById(elementId);
|
||||||
|
if (messageElement) {
|
||||||
|
messageElement.style.display = 'inline';
|
||||||
|
setTimeout(() => {
|
||||||
|
messageElement.style.display = 'none';
|
||||||
|
}, 3000); // Mostrar el mensaje durante 3 segundos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMotorCameraData(type_mode) {
|
||||||
|
const motorData = {
|
||||||
|
type: type_mode,
|
||||||
|
/*speedValue: document.getElementById('speedSlider').value,
|
||||||
|
isSpeedActive: document.getElementById('speedCheckbox').checked,
|
||||||
|
intervalFrames: document.getElementById('intervalFrames').value,
|
||||||
|
intervalSeconds: document.getElementById('intervalSeconds').value,
|
||||||
|
isIntervalActive: document.getElementById('intervalCheckbox').checked,
|
||||||
|
direction: document.querySelector('input[name="direction"]:checked').value*/
|
||||||
|
0: document.getElementById('speedSlider').value,
|
||||||
|
1: document.getElementById('speedCheckbox').checked,
|
||||||
|
2: document.getElementById('intervalFrames').value,
|
||||||
|
3: document.getElementById('intervalSeconds').value,
|
||||||
|
4: document.getElementById('intervalCheckbox').checked,
|
||||||
|
5: document.querySelector('input[name="direction"]:checked').value
|
||||||
|
};
|
||||||
|
fetch('/updateMotorCamera', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(motorData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage('motorCameraMessage'))
|
||||||
|
.catch(error => console.error('Motor Camera Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
|
||||||
|
const accionData = {
|
||||||
|
type: 'stop',
|
||||||
|
};
|
||||||
|
fetch('/stop', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(accionData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage('motorCameraMessage'))
|
||||||
|
.catch(error => console.error('Stop Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendShutterData(type_mode) {
|
||||||
|
const shutterData = {
|
||||||
|
type: type_mode,
|
||||||
|
/*fadePercent: document.getElementById('fadePercentSlider').value,
|
||||||
|
fadeFrames: document.getElementById('fadeFramesSlider').value,
|
||||||
|
syncWithInterval: document.getElementById('syncWithIntervalCheckbox').checked,
|
||||||
|
fadeInActive: document.getElementById('fadeInCheckbox').checked,
|
||||||
|
fadeOutActive: document.getElementById('fadeOutCheckbox').checked*/
|
||||||
|
0: document.getElementById('fadePercentSlider').value,
|
||||||
|
1: document.getElementById('fadeFramesSlider').value,
|
||||||
|
2: document.getElementById('syncWithIntervalCheckbox').checked,
|
||||||
|
3: document.getElementById('fadeInCheckbox').checked,
|
||||||
|
4: document.getElementById('fadeOutCheckbox').checked
|
||||||
|
};
|
||||||
|
fetch('/updateShutter', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(shutterData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage('shutterMessage'))
|
||||||
|
.catch(error => console.error('Shutter Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendOpticsData(type_mode) {
|
||||||
|
const opticsData = {
|
||||||
|
type: type_mode,
|
||||||
|
zoomValue: document.getElementById('zoomSlider').value,
|
||||||
|
focusValue: document.getElementById('focusSlider').value,
|
||||||
|
diaphragmValue: document.getElementById('diaphragmSelect').value,
|
||||||
|
syncWithInterval: document.getElementById('syncWithIntervalOptics').checked
|
||||||
|
};
|
||||||
|
fetch('/updateOptics', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(opticsData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage('opticsMessage'))
|
||||||
|
.catch(error => console.error('Optics Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveMotor(type_mode, motor) {
|
||||||
|
const degrees = document.getElementById(`${motor}Degrees`).value;
|
||||||
|
const duration = document.getElementById(`${motor}Duration`).value;
|
||||||
|
const syncWithInterval = document.getElementById('syncWithInterval360').checked;
|
||||||
|
|
||||||
|
const motorData = {
|
||||||
|
type: type_mode,
|
||||||
|
motor: motor,
|
||||||
|
degrees: degrees,
|
||||||
|
duration: duration,
|
||||||
|
syncWithInterval: syncWithInterval
|
||||||
|
};
|
||||||
|
fetch('/moveMotor360', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(motorData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage(`${motor}Message`))
|
||||||
|
.catch(error => console.error('Motor Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function accion() {
|
||||||
|
|
||||||
|
const accionData = {
|
||||||
|
type: 'accion',
|
||||||
|
};
|
||||||
|
fetch('/accion', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(accionData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage('accionMessage'))
|
||||||
|
.catch(error => console.error('Accion Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function corten() {
|
||||||
|
|
||||||
|
const accionData = {
|
||||||
|
type: 'corten',
|
||||||
|
};
|
||||||
|
fetch('/corten', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(accionData),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(() => showMessage('accionMessage'))
|
||||||
|
.catch(error => console.error('Corten Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar la interfaz al cambiar los sliders
|
||||||
|
document.getElementById('speedSlider').addEventListener('input', updateDisplay);
|
||||||
|
document.getElementById('fadePercentSlider').addEventListener('input', updateDisplay);
|
||||||
|
document.getElementById('fadeFramesSlider').addEventListener('input', updateDisplay);
|
||||||
|
document.getElementById('zoomSlider').addEventListener('input', updateDisplay);
|
||||||
|
document.getElementById('focusSlider').addEventListener('input', updateDisplay);
|
||||||
|
|
||||||
|
// pide motorSpeed al M7
|
||||||
|
function updateMotorSpeed() {
|
||||||
|
fetch('/motorSpeed')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('fps').value = data.motorSpeedRead;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener motorSpeed:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatefadePosition() {
|
||||||
|
fetch('/fadePercent')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('fade').value = data.FadePercentRead;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener fadePercent:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSensors() {
|
||||||
|
fetch('/sensors')
|
||||||
|
.then(response => response.json()) // Parsear la respuesta como JSON
|
||||||
|
.then(data => {
|
||||||
|
if (data.sensors && Array.isArray(data.sensors)) {
|
||||||
|
const sensorValues = data.sensors;
|
||||||
|
// Asignar los valores a los elementos de la interfaz
|
||||||
|
if (sensorValues.length >= 1) {
|
||||||
|
document.getElementById('fps').value = sensorValues[0];
|
||||||
|
}
|
||||||
|
if (sensorValues.length >= 2) {
|
||||||
|
document.getElementById('fade').value = sensorValues[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Estructura inesperada:', data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error al obtener sensores:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Llama a updateSensors cada 500ms
|
||||||
|
setInterval(updateSensors, 500);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
)rawliteral";
|
539
CraterLab_camera/include/main_m4.cpp
Normal file
539
CraterLab_camera/include/main_m4.cpp
Normal file
|
@ -0,0 +1,539 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ShiftRegister74HC595.h>
|
||||||
|
//#include <PID_v1.h>
|
||||||
|
//#include <SPI.h>
|
||||||
|
#include <RPC.h>
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
#define DEBUG_M4 false
|
||||||
|
#define MIN_SPEED 55
|
||||||
|
|
||||||
|
// Motor
|
||||||
|
int motorSpeedValue = 24;
|
||||||
|
bool motorIsSpeedActive = false;
|
||||||
|
int motorIntervalFrames = 1;
|
||||||
|
int motorIntervalSeconds = 1;
|
||||||
|
bool motorIsIntervalActive = false;
|
||||||
|
bool motorDirection = 1;
|
||||||
|
|
||||||
|
// Shutter
|
||||||
|
int shutterFadePercent = 0;
|
||||||
|
int shutterFadeFrames = 50;
|
||||||
|
bool shutterSyncWithInterval = false;
|
||||||
|
bool shutterFadeInActive = false;
|
||||||
|
bool shutterFadeOutActive = false;
|
||||||
|
|
||||||
|
// Óptica
|
||||||
|
int zoomValue = 50;
|
||||||
|
int focusValue = 50;
|
||||||
|
float diaphragmValue = 1.8;
|
||||||
|
bool syncWithIntervalOptics = false;
|
||||||
|
|
||||||
|
bool closed=false;
|
||||||
|
bool isAction=false;
|
||||||
|
|
||||||
|
#if PID_ENABLE
|
||||||
|
// ************************************************ Variables PID *****************************************************************
|
||||||
|
double Setpoint = 0.0, Input = 0.0, Output = 0.0; // Setpoint=Posición designada; Input=Posición del motor; Output=Tensión de salida para el motor.
|
||||||
|
double kp = 0.0, ki = 0.0, kd = 0.0; // Constante proporcional, integral y derivativa.
|
||||||
|
double outMax = 0.0, outMin = 0.0; // Límites para no sobrepasar la resolución del PWM.
|
||||||
|
// **************************************************** Otras Variables ***********************************************************
|
||||||
|
volatile long contador = 0; // En esta variable se guardará los pulsos del encoder y que interpreremos como distancia (o ángulo si ese fuese el caso).
|
||||||
|
byte ant = 0, act = 0; // Sólo se utiliza los dos primeros bits de estas variables y servirán para decodificar el encoder. (ant=anterior, act=actual.)
|
||||||
|
byte cmd = 0; // Un byte que utilizamos para la comunicación serie. (cmd=comando.)
|
||||||
|
unsigned int tmp = 0; // Variable que utilizaremos para poner el tiempo de muestreo.
|
||||||
|
const byte ledok = 13; // El pin 13 de los Arduinos tienen un led que utilizo para mostrar que el motor ya ha llegado a la posición designada.
|
||||||
|
// ********************************************************************************************************************************
|
||||||
|
|
||||||
|
PID myPID(&Input, &Output, &Setpoint, 0.0, 0.0, 0.0, DIRECT); // Parámetros y configuración para invocar la librería.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// parameters: <number of shift registers> (data pin, clock pin, latch pin)
|
||||||
|
ShiftRegister74HC595<1> sr(Data_pin, Clock_pin, Latch_pin);
|
||||||
|
const int EN_MOTOR[4] = {EN0, EN1, EN2, EN3};
|
||||||
|
const int MA_MOTOR[4] = {M0A, M1A, M2A, M3A};
|
||||||
|
const int MB_MOTOR[4] = {M0B, M1B, M2B, M3B};
|
||||||
|
const long TIME_LINEAL_MAX[6] = {4150, 670, 4250, 6200, 4000, 4000 }; //ms
|
||||||
|
|
||||||
|
void backward(int motor, int SPEED)
|
||||||
|
{
|
||||||
|
if(motor<4)
|
||||||
|
{
|
||||||
|
sr.set(MA_MOTOR[motor], HIGH);
|
||||||
|
sr.set(MB_MOTOR[motor], LOW);
|
||||||
|
analogWrite(EN_MOTOR[motor], SPEED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
analogWrite(L_M4, SPEED);
|
||||||
|
analogWrite(R_M4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void forward(int motor, int SPEED)
|
||||||
|
{
|
||||||
|
if(motor<4)
|
||||||
|
{
|
||||||
|
sr.set(MA_MOTOR[motor], LOW);
|
||||||
|
sr.set(MB_MOTOR[motor], HIGH);
|
||||||
|
analogWrite(EN_MOTOR[motor], SPEED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
analogWrite(L_M4, 0);
|
||||||
|
analogWrite(R_M4, SPEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop(int motor)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(motor<4)
|
||||||
|
{
|
||||||
|
analogWrite(EN_MOTOR[motor], 0);
|
||||||
|
sr.set(MA_MOTOR[motor], LOW);
|
||||||
|
sr.set(MB_MOTOR[motor], LOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
analogWrite(L_M4, 0);
|
||||||
|
analogWrite(R_M4, 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()};
|
||||||
|
float position_motor[6] = { 0, 0, 0, 0, 0, 0};
|
||||||
|
float position_motor_objective[6] = { 0, 0, 0, 0, 0, 0};
|
||||||
|
bool moving_position_motor[6] = { false, false, false, false, false, false};
|
||||||
|
|
||||||
|
void config_position_motor(int motor, float position) //Configuracion posicion en % motor
|
||||||
|
{
|
||||||
|
if((position!=position_motor[motor])&&(!moving_position_motor[motor]))
|
||||||
|
{
|
||||||
|
if(motor==0)
|
||||||
|
{
|
||||||
|
if(position>position_motor[motor]) forward(motor,255);
|
||||||
|
else backward(motor,255);
|
||||||
|
position_motor_objective[motor] = position;
|
||||||
|
moving_position_motor[motor] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_move_for_move_position_motor[motor] = (abs(position_motor[motor]-position)*TIME_LINEAL_MAX[motor])/100.;
|
||||||
|
if(position>position_motor[motor]) forward(motor,255);
|
||||||
|
else backward(motor,255);
|
||||||
|
time_refresh_position_motor[motor] = millis();
|
||||||
|
position_motor_objective[motor] = position;
|
||||||
|
moving_position_motor[motor] = true;
|
||||||
|
//RPC.println("/debug:" + String(position_motor[motor]) + "," + String(position) + "," + String(millis()-time_refresh_position_motor[motor]) + "," + String(time_move_for_move_position_motor[motor]) + "," + "INI");
|
||||||
|
//Serial.println(time_move_for_move_position_motor[motor]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool state_smotor[6] = { false, false, false, false, false, false};
|
||||||
|
|
||||||
|
void config_speed_motor(int motor, int direction, int speed) //Configuracion velocidad motor
|
||||||
|
{
|
||||||
|
closed = false;
|
||||||
|
if(direction==FORWARD) forward(motor,speed);
|
||||||
|
else if(direction==BACKWARD) backward(motor,speed);
|
||||||
|
if(speed>0) state_smotor[motor] = true;
|
||||||
|
else state_smotor[motor] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
volatile float fps_read = 0;
|
||||||
|
volatile float fps_temp = 0;
|
||||||
|
unsigned long time_sec= millis();
|
||||||
|
unsigned long time_fps = micros();
|
||||||
|
|
||||||
|
static volatile unsigned long lastTimeDebounce = 0; //Tiempo del rebote
|
||||||
|
static volatile bool force_stop = false; //Tiempo del rebote
|
||||||
|
|
||||||
|
void fps_count_state() {
|
||||||
|
if((digitalRead(sensor_fps)&&(micros()-lastTimeDebounce>= 100))&&(!closed))
|
||||||
|
{
|
||||||
|
lastTimeDebounce = micros();
|
||||||
|
fps_temp = 1000000./(float)(micros()-time_fps);
|
||||||
|
if(fps_temp<70) fps_read = fps_temp;
|
||||||
|
time_fps = micros();
|
||||||
|
if((millis()-time_sec)>=1000)
|
||||||
|
{
|
||||||
|
//RPC.println(fps_read);
|
||||||
|
time_sec = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if((digitalRead(sensor_fps)&&(micros()-lastTimeDebounce >= 150))&&(closed))
|
||||||
|
{
|
||||||
|
lastTimeDebounce = micros();
|
||||||
|
closed = false;
|
||||||
|
force_stop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int interval_direction[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
int interval_frames[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
unsigned long interval_time[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
int frames_count[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
unsigned long time_interval_count[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
void config_interval_motor(int direction, int Frames, int Seconds) //Configuracion velocidad motor
|
||||||
|
{
|
||||||
|
closed = false;
|
||||||
|
interval_direction[FPS_MOTOR] = direction;
|
||||||
|
interval_frames[FPS_MOTOR] = Frames;
|
||||||
|
interval_time[FPS_MOTOR] = Seconds*1000;
|
||||||
|
frames_count[FPS_MOTOR] = 0;
|
||||||
|
time_interval_count[FPS_MOTOR] = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
float inc_position_fade = 0;
|
||||||
|
int fade_direction = 0;
|
||||||
|
void config_automatic_fade(int shutterFadeFrames, int shutterSyncWithInterval, int shutterFadeInActive, int shutterFadeOutActive) //Configuracion fade
|
||||||
|
{
|
||||||
|
|
||||||
|
if((shutterFadeInActive)&&(!shutterFadeOutActive))
|
||||||
|
{
|
||||||
|
fade_direction=IN;
|
||||||
|
inc_position_fade = (100-position_motor[0])/(float)shutterFadeFrames;
|
||||||
|
}
|
||||||
|
else if((!shutterFadeInActive)&&(shutterFadeOutActive))
|
||||||
|
{
|
||||||
|
fade_direction=OUT;
|
||||||
|
inc_position_fade = (position_motor[0])/(float)shutterFadeFrames;
|
||||||
|
}
|
||||||
|
else if((shutterFadeInActive)&&(shutterFadeOutActive))
|
||||||
|
{
|
||||||
|
fade_direction=IN_OUT;
|
||||||
|
inc_position_fade = (100)/(float)shutterFadeFrames;
|
||||||
|
}
|
||||||
|
else fade_direction=STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void config_optics(int zoomValue, int focusValue, int diaphragmValue, int syncWithIntervalOptics) //Configuracion de las opticas
|
||||||
|
{
|
||||||
|
config_position_motor(1, zoomValue);
|
||||||
|
config_position_motor(2, focusValue);
|
||||||
|
config_position_motor(3, map(int(diaphragmValue*10), 19, 220, 0, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
void secure_stop(int direction)
|
||||||
|
{
|
||||||
|
config_speed_motor(FPS_MOTOR, direction, 0);
|
||||||
|
delay(150);
|
||||||
|
if (!digitalRead(sensor_fps))
|
||||||
|
{
|
||||||
|
config_speed_motor(FPS_MOTOR, direction, MIN_SPEED);
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void next_frame(int direction)
|
||||||
|
{
|
||||||
|
config_speed_motor(FPS_MOTOR, motorDirection, MIN_SPEED);
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUM 20.
|
||||||
|
int read_lineal_motor()
|
||||||
|
{
|
||||||
|
int value = 0;
|
||||||
|
for (int i=0; i<10; i++) value += analogRead(sensor_lineal_motor);
|
||||||
|
return value/10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ini_motors()
|
||||||
|
{
|
||||||
|
//forward(0,255);
|
||||||
|
while (read_lineal_motor()>LINEAL_MAX) forward(0,255);
|
||||||
|
stop(0);
|
||||||
|
while (read_lineal_motor()<LINEAL_MAX) backward(0,255);
|
||||||
|
stop(0);
|
||||||
|
|
||||||
|
/*backward(1,255);
|
||||||
|
backward(2,255);
|
||||||
|
backward(3,255);
|
||||||
|
delay(TIME_LINEAL_MAX[3]);
|
||||||
|
stop(0);
|
||||||
|
stop(1);
|
||||||
|
stop(2);
|
||||||
|
stop(3);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh_position_motors()
|
||||||
|
{
|
||||||
|
position_motor[0] = map(read_lineal_motor(),LINEAL_MAX,LINEAL_MIN,0,100);
|
||||||
|
if((position_motor[0]==position_motor_objective[0])&&(moving_position_motor[0]))
|
||||||
|
{
|
||||||
|
stop(0);
|
||||||
|
moving_position_motor[0] = false;
|
||||||
|
}
|
||||||
|
for(int i=1; i<4; i++)
|
||||||
|
{
|
||||||
|
if(((millis()-time_refresh_position_motor[i])>(unsigned long)time_move_for_move_position_motor[i])&&(moving_position_motor[i]))
|
||||||
|
{
|
||||||
|
stop(i);
|
||||||
|
position_motor[i] = position_motor_objective[i];
|
||||||
|
moving_position_motor[i] = false;
|
||||||
|
//RPC.println("/debug:" + String(position_motor[i]) + "," + String(position_motor_objective[i]) + "," + String(millis()-time_refresh_position_motor[i]) + "," + String(time_move_for_move_position_motor[i]) + "," + "END");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int change_direction_inout = 1;
|
||||||
|
|
||||||
|
void refresh_interval_motors()
|
||||||
|
{
|
||||||
|
if((((millis()-time_interval_count[FPS_MOTOR])>=interval_time[FPS_MOTOR])&&(interval_frames[FPS_MOTOR]!=frames_count[FPS_MOTOR]))&&(isAction))
|
||||||
|
{
|
||||||
|
frames_count[FPS_MOTOR]++;
|
||||||
|
time_interval_count[FPS_MOTOR] = millis();
|
||||||
|
if(frames_count[FPS_MOTOR]>=interval_frames[FPS_MOTOR]) isAction=false;
|
||||||
|
if (shutterSyncWithInterval)
|
||||||
|
{
|
||||||
|
float value_position=0;
|
||||||
|
if(fade_direction==IN)
|
||||||
|
{
|
||||||
|
value_position = position_motor[0] + inc_position_fade;
|
||||||
|
if (value_position>100) value_position=100;
|
||||||
|
config_position_motor(0, value_position);
|
||||||
|
}
|
||||||
|
else if(fade_direction==OUT)
|
||||||
|
{
|
||||||
|
value_position = position_motor[0] - inc_position_fade;
|
||||||
|
if (value_position<0) value_position=0;
|
||||||
|
config_position_motor(0, value_position);
|
||||||
|
}
|
||||||
|
else if(fade_direction==IN_OUT)
|
||||||
|
{
|
||||||
|
if (((position_motor[0] + inc_position_fade)>100)&&(change_direction_inout==1)) change_direction_inout=-1;
|
||||||
|
else if (((position_motor[0] - inc_position_fade)<0)&&(change_direction_inout==-1)) change_direction_inout=1;
|
||||||
|
value_position = position_motor[0] + change_direction_inout*inc_position_fade;
|
||||||
|
RPC.println("/fade:" + String(position_motor[0]) + "," + String(change_direction_inout) + "," + String(inc_position_fade) + "," + String(0) + "," + String(shutterFadeOutActive));
|
||||||
|
config_position_motor(0, value_position);
|
||||||
|
}
|
||||||
|
//else value_position = position_motor[0];
|
||||||
|
|
||||||
|
}
|
||||||
|
next_frame(interval_direction[FPS_MOTOR]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float fps_request = 24;
|
||||||
|
uint8_t speed_request = 0;
|
||||||
|
unsigned long time_adjust = millis();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Functions on the M4 that returns FPS
|
||||||
|
*/
|
||||||
|
int fpsRead() {
|
||||||
|
int result = fps_read;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_value[10];
|
||||||
|
int* decode_values(String inputString_rpc, int num_dec)
|
||||||
|
{
|
||||||
|
String str = inputString_rpc.substring(inputString_rpc.lastIndexOf(":") + 1);
|
||||||
|
read_value[0] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
for(int i=1; i<num_dec; i++)
|
||||||
|
{
|
||||||
|
str = str.substring(str.indexOf(',')+1);
|
||||||
|
read_value[i] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
}
|
||||||
|
return read_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
char c_rpc;
|
||||||
|
String inputString_rpc;
|
||||||
|
unsigned long time_led = millis();
|
||||||
|
|
||||||
|
void RPCRead()
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/////// RUTINA TRATAMIENTO DE STRINGS DEL UART ///////////
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
if (RPC.available())
|
||||||
|
{
|
||||||
|
c_rpc = RPC.read();
|
||||||
|
if ((c_rpc == '\r') || (c_rpc == '\n'))
|
||||||
|
{
|
||||||
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
|
if (inputString_rpc.startsWith("/s_motor:")) //Speed Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 4);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido Speed M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<4; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
motorDirection = value[1];
|
||||||
|
motorSpeedValue = value[2];
|
||||||
|
motorIsSpeedActive = true;
|
||||||
|
motorIsIntervalActive = false;
|
||||||
|
//if (motorSpeedValue>0) motorSpeedValue = map(motorSpeedValue, 24, 48, 146, 192); //Fake fps
|
||||||
|
if (motorSpeedValue>0) motorSpeedValue = map(motorSpeedValue, 0, 48, 0, 255); //Fake fps
|
||||||
|
//if (motorSpeedValue>0) motorSpeedValue = 255;
|
||||||
|
if (value[3]==false) //Si es falso, se ejecuta, sino se guarda sin ejecutar
|
||||||
|
{
|
||||||
|
if (motorSpeedValue==0)
|
||||||
|
{
|
||||||
|
isAction = false;
|
||||||
|
secure_stop(motorDirection);
|
||||||
|
}
|
||||||
|
else config_speed_motor(value[0], motorDirection, motorSpeedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/i_motor:")) //Interval Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 5);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido Interval M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<5; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
motorDirection = value[1];
|
||||||
|
motorIntervalFrames = value[2];
|
||||||
|
motorIntervalSeconds = value[3];
|
||||||
|
motorIsIntervalActive = true;
|
||||||
|
motorIsSpeedActive = false;
|
||||||
|
if (value[4]==false) //Si es falso, se ejecuta, sino se guarda sin ejecutar
|
||||||
|
{
|
||||||
|
isAction = true;
|
||||||
|
config_interval_motor(motorDirection, motorIntervalFrames, motorIntervalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/fade:")) //Fade configuration
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 6);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido fade M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<6; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
shutterFadePercent = value[0];
|
||||||
|
shutterFadeFrames = value[1];
|
||||||
|
shutterSyncWithInterval = value[2];
|
||||||
|
shutterFadeInActive = value[3];
|
||||||
|
shutterFadeOutActive = value[4];
|
||||||
|
//RPC.println("/fade:" + String(shutterFadePercent) + "," + String(shutterFadeFrames) + "," + String(shutterSyncWithInterval) + "," + String(shutterFadeInActive) + "," + String(shutterFadeOutActive));
|
||||||
|
config_position_motor(0, shutterFadePercent);
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/optics:")) //Optics configuration
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 5);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido optics M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<5; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
zoomValue = value[0];
|
||||||
|
focusValue = value[1];
|
||||||
|
diaphragmValue = value[2];
|
||||||
|
syncWithIntervalOptics = value[3];
|
||||||
|
if (value[4]==false) //Si es falso, se ejecuta, sino se guarda sin ejecutar
|
||||||
|
{
|
||||||
|
config_optics(zoomValue, focusValue, diaphragmValue, syncWithIntervalOptics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/action:")) //Optics configuration
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 1);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido action M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<1; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
isAction=value[0];
|
||||||
|
if (isAction)
|
||||||
|
{
|
||||||
|
if (motorIsSpeedActive) config_speed_motor(4, motorDirection, motorSpeedValue);
|
||||||
|
else config_interval_motor(motorDirection, motorIntervalFrames, motorIntervalSeconds);
|
||||||
|
config_automatic_fade(shutterFadeFrames, shutterSyncWithInterval, shutterFadeInActive, shutterFadeOutActive);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
secure_stop(motorDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputString_rpc.startsWith("/sensors:")) //Optics configuration
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 1);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido fps M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<1; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
if(value[0])
|
||||||
|
RPC.println("/sensors:" + String(fps_read) + "," + String(analogRead(sensor_lineal_motor)) + "," + String(position_motor[1]) + "," + String(position_motor[2]) + "," + String(position_motor[3]));
|
||||||
|
//RPC.println("/sensors:" + String(fps_read) + "," + String(position_motor[0]) + "," + String(position_motor[1]) + "," + String(position_motor[2]) + "," + String(position_motor[3]));
|
||||||
|
//RPC.println(fps_read);
|
||||||
|
}
|
||||||
|
inputString_rpc = String();
|
||||||
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
inputString_rpc += c_rpc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
//SCB_CleanDCache();
|
||||||
|
RPC.begin();
|
||||||
|
//delay(5000);
|
||||||
|
pinMode(sensor_fps, INPUT_PULLUP);
|
||||||
|
pinMode(Enable, OUTPUT);
|
||||||
|
pinMode(EN_M4, OUTPUT);
|
||||||
|
digitalWrite(EN_M4, HIGH);
|
||||||
|
analogWriteResolution(8);
|
||||||
|
digitalWrite(Enable, LOW);
|
||||||
|
sr.setAllLow(); // set all pins LOW
|
||||||
|
ini_motors();
|
||||||
|
secure_stop(FORWARD);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(sensor_fps), fps_count_state, RISING);
|
||||||
|
|
||||||
|
#if PID_ENABLE
|
||||||
|
outMax = 255.0; // Límite máximo del controlador PID.
|
||||||
|
outMin = 128.0; // Límite mínimo del controlador PID.
|
||||||
|
|
||||||
|
tmp = 5; // Tiempo de muestreo en milisegundos.
|
||||||
|
|
||||||
|
kp = 10.0; // Constantes PID iniciales. Los valores son los adecuados para un encoder de 334 ppr,
|
||||||
|
ki = 3.5; // pero como el lector de encoder está diseñado como x4 equivale a uno de 1336 ppr. (ppr = pulsos por revolución.)
|
||||||
|
kd = 30.0;
|
||||||
|
|
||||||
|
myPID.SetSampleTime(tmp); // Envía a la librería el tiempo de muestreo.
|
||||||
|
myPID.SetOutputLimits(outMin, outMax);// Límites máximo y mínimo; corresponde a Max.: 0=0V hasta 255=5V (PWMA), y Min.: 0=0V hasta -255=5V (PWMB). Ambos PWM se convertirán a la salida en valores absolutos, nunca negativos.
|
||||||
|
myPID.SetTunings(kp, ki, kd); // Constantes de sintonización.
|
||||||
|
myPID.SetMode(AUTOMATIC); // Habilita el control PID (por defecto).
|
||||||
|
Setpoint = 24; // Para evitar que haga cosas extrañas al inciarse, igualamos los dos valores para que comience estando el motor parado.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.println("M4 Inicializado.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
#if PID_ENABLE
|
||||||
|
/*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())
|
||||||
|
analogWrite(EN_MOTOR[4], abs(Output)); // Por el primer pin sale la señal PWM.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
refresh_position_motors();
|
||||||
|
refresh_interval_motors();
|
||||||
|
RPCRead();
|
||||||
|
if(force_stop)
|
||||||
|
{
|
||||||
|
//config_speed_motor(FPS_MOTOR, !motorDirection, MIN_SPEED);
|
||||||
|
//delay(20);
|
||||||
|
stop(FPS_MOTOR);
|
||||||
|
force_stop = false;
|
||||||
|
}
|
||||||
|
}
|
348
CraterLab_camera/include/main_m7.cpp
Normal file
348
CraterLab_camera/include/main_m7.cpp
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
//#include <SPI.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include "interface.html"
|
||||||
|
#include "constants.h"
|
||||||
|
#include <RPC.h>
|
||||||
|
|
||||||
|
#define DEBUG_M7 false
|
||||||
|
#define AP_MODE false
|
||||||
|
|
||||||
|
// Inicializando RTOS
|
||||||
|
using namespace rtos;
|
||||||
|
Thread sensorThread;
|
||||||
|
|
||||||
|
// Configuración de red WiFi
|
||||||
|
const char *ssid = "Analogue_Hyperlapse_Camera";
|
||||||
|
const char *password = "CraterLab";
|
||||||
|
|
||||||
|
IPAddress ip(192, 168, 8, 4);
|
||||||
|
IPAddress remote_ip(192, 168, 8, 3);
|
||||||
|
IPAddress gateway(192, 168, 8, 1);
|
||||||
|
IPAddress subnet(255, 255, 255, 0);
|
||||||
|
IPAddress dns(192, 168, 8, 1); //primaryDNS
|
||||||
|
|
||||||
|
// Crear el servidor en el puerto 80
|
||||||
|
WiFiServer server(80);
|
||||||
|
// Crear conexion UDP para enviar datos
|
||||||
|
WiFiUDP Udp;
|
||||||
|
unsigned int remotePort = 2390; // local port to send
|
||||||
|
unsigned int localPort = 2392; // local port to read
|
||||||
|
char packetBuffer[255]; //buffer to hold incoming packet
|
||||||
|
char ReplyBuffer[] = "acknowledged"; // a string to send back
|
||||||
|
|
||||||
|
// Motor
|
||||||
|
int motorSpeedValue = 25;
|
||||||
|
bool motorIsSpeedActive = false;
|
||||||
|
int motorIntervalFrames = 1;
|
||||||
|
int motorIntervalSeconds = 1;
|
||||||
|
bool motorIsIntervalActive = false;
|
||||||
|
int motorDirection = 1;
|
||||||
|
|
||||||
|
// Shutter
|
||||||
|
int shutterFadePercent = 0;
|
||||||
|
int shutterFadeFrames = 50;
|
||||||
|
bool shutterSyncWithInterval = false;
|
||||||
|
bool shutterFadeInActive = false;
|
||||||
|
bool shutterFadeOutActive = false;
|
||||||
|
|
||||||
|
// Óptica
|
||||||
|
int zoomValue = 50;
|
||||||
|
int focusValue = 50;
|
||||||
|
float diaphragmValue = 1.8;
|
||||||
|
bool syncWithIntervalOptics = false;
|
||||||
|
|
||||||
|
// Dispositivo 360
|
||||||
|
int x0Degrees = 0;
|
||||||
|
int x0Duration = 0;
|
||||||
|
int x1Degrees = 0;
|
||||||
|
int x1Duration = 0;
|
||||||
|
int y0Degrees = 0;
|
||||||
|
int y0Duration = 0;
|
||||||
|
bool syncWithInterval360 = false;
|
||||||
|
|
||||||
|
//Sensores
|
||||||
|
float motorSpeedRead = 0;
|
||||||
|
float FadePercentRead = 0;
|
||||||
|
int zoomValueRead = 0;
|
||||||
|
int focusValueRead = 0;
|
||||||
|
float diaphragmValueRead = 0;
|
||||||
|
int x0DegreesRead = 0;
|
||||||
|
int x1DegreesRead = 0;
|
||||||
|
int y0DegreesRead = 0;
|
||||||
|
|
||||||
|
int read_value[10];
|
||||||
|
int* decode_values(String inputString, int num_dec)
|
||||||
|
{
|
||||||
|
String str = inputString.substring(inputString.lastIndexOf(":") + 1);
|
||||||
|
read_value[0] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
for(int i=1; i<num_dec; i++)
|
||||||
|
{
|
||||||
|
str = str.substring(str.indexOf(',')+1);
|
||||||
|
read_value[i] = str.substring(0, str.indexOf(',')).toInt();
|
||||||
|
}
|
||||||
|
return read_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
char c_rpc;
|
||||||
|
String inputString_rpc;
|
||||||
|
|
||||||
|
void RPCRead()
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/////// RUTINA TRATAMIENTO DE STRINGS DEL UART ///////////
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
if (RPC.available())
|
||||||
|
{
|
||||||
|
c_rpc = RPC.read();
|
||||||
|
if ((c_rpc == '\r') || (c_rpc == '\n'))
|
||||||
|
{
|
||||||
|
if (inputString_rpc.startsWith("/sensors:")) //Speed Motor
|
||||||
|
{
|
||||||
|
int* value = decode_values(inputString_rpc, 5);
|
||||||
|
#if DEBUG_M4
|
||||||
|
RPC.print("Recibido Speed M4: ");
|
||||||
|
RPC.println(inputString_rpc);
|
||||||
|
for(int i=0; i<5; i++) RPC.println(value[i]);
|
||||||
|
#endif
|
||||||
|
motorSpeedRead = value[0];
|
||||||
|
FadePercentRead = value[1];
|
||||||
|
zoomValueRead = value[2];
|
||||||
|
focusValueRead = value[3];
|
||||||
|
diaphragmValueRead = value[4];
|
||||||
|
}
|
||||||
|
else if(inputString_rpc.startsWith("/debug:"))
|
||||||
|
{
|
||||||
|
//int* value = decode_values(inputString_rpc, 5);
|
||||||
|
//#if DEBUG_M7
|
||||||
|
Serial.print("Recibido debug M4: ");
|
||||||
|
Serial.println(inputString_rpc);
|
||||||
|
//for(int i=0; i<5; i++) Serial.println(value[i]);
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
inputString_rpc = String();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
inputString_rpc += c_rpc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long time_refresh_sensors = millis();
|
||||||
|
|
||||||
|
void refresh_sensors()
|
||||||
|
{
|
||||||
|
if((millis()-time_refresh_sensors)>=500)
|
||||||
|
{
|
||||||
|
time_refresh_sensors = millis();
|
||||||
|
RPC.println("/sensors:1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(1000000);
|
||||||
|
RPC.begin(); //boots M4
|
||||||
|
#if AP_MODE
|
||||||
|
int status = WL_IDLE_STATUS;
|
||||||
|
// Create open network. Change this line if you want to create an WEP network:
|
||||||
|
WiFi.config(ip, dns, gateway, subnet);
|
||||||
|
status = WiFi.beginAP(ssid, password);
|
||||||
|
if (status != WL_AP_LISTENING) {
|
||||||
|
Serial.println("Creating access point failed");
|
||||||
|
// don't continue
|
||||||
|
while (true)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
WiFi.config(ip, dns, gateway, subnet);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
|
delay(1000);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Conectado a WiFi!");
|
||||||
|
Serial.print("Dirección IP: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
// Enable Server
|
||||||
|
server.begin();
|
||||||
|
// Enable UDP
|
||||||
|
Udp.begin(localPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool flag_send[10] = {false ,false ,false ,false ,false ,false ,false ,false ,false ,false};
|
||||||
|
|
||||||
|
void handlePostRequest(String body) {
|
||||||
|
// Parseamos el cuerpo del JSON
|
||||||
|
StaticJsonDocument<1000> doc;
|
||||||
|
deserializeJson(doc, body);
|
||||||
|
int save = true;
|
||||||
|
//DeserializationError error = deserializeJson(doc, body);
|
||||||
|
/*if (error) {
|
||||||
|
Serial.println("Error al parsear el JSON");
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
Serial.println("Procesando JSON...");
|
||||||
|
String type = doc["type"];
|
||||||
|
if ((type=="save_motor")||(type=="test_motor"))
|
||||||
|
{
|
||||||
|
Serial.println(type);
|
||||||
|
if (type=="save_motor") save = true;
|
||||||
|
else save = false;
|
||||||
|
|
||||||
|
/*motorSpeedValue = doc["speedValue"];
|
||||||
|
motorIsSpeedActive = doc["isSpeedActive"];
|
||||||
|
motorIntervalFrames = doc["intervalFrames"];
|
||||||
|
motorIntervalSeconds = doc["intervalSeconds"];
|
||||||
|
motorIsIntervalActive = doc["isIntervalActive"];
|
||||||
|
String Direction = doc["direction"];*/
|
||||||
|
motorSpeedValue = doc["0"];
|
||||||
|
motorIsSpeedActive = doc["1"];
|
||||||
|
motorIntervalFrames = doc["2"];
|
||||||
|
motorIntervalSeconds = doc["3"];
|
||||||
|
motorIsIntervalActive = doc["4"];
|
||||||
|
String Direction = doc["5"];
|
||||||
|
if (Direction=="forward") motorDirection = FORWARD;
|
||||||
|
else if (Direction=="backward") motorDirection = BACKWARD;
|
||||||
|
if(motorIsSpeedActive)
|
||||||
|
{
|
||||||
|
RPC.println("/s_motor:" + String(FPS_MOTOR) + "," + String(motorDirection) + "," + String(motorSpeedValue) + "," + String(save));
|
||||||
|
}
|
||||||
|
else if(motorIsIntervalActive)
|
||||||
|
{
|
||||||
|
RPC.println("/i_motor:" + String(FPS_MOTOR) + "," + String(motorDirection) + "," + String(motorIntervalFrames) + "," + String(motorIntervalSeconds) + "," + String(save));
|
||||||
|
}
|
||||||
|
/*Clave: type, Valor: motor
|
||||||
|
Clave: speedValue, Valor: )25
|
||||||
|
Clave: isSpeedActive, Valor: false
|
||||||
|
Clave: intervalFrames, Valor: 1
|
||||||
|
Clave: intervalSeconds, Valor: 1
|
||||||
|
Clave: isIntervalActive, Valor: false
|
||||||
|
Clave: direction, Valor: forward*/
|
||||||
|
}
|
||||||
|
else if ((type=="test_shutter")||(type=="save_shutter") )
|
||||||
|
{
|
||||||
|
Serial.println(type);
|
||||||
|
if (type=="save_shutter") save = true;
|
||||||
|
else save = false;
|
||||||
|
/*shutterFadePercent = doc["fadePercent"];
|
||||||
|
shutterFadeFrames = doc["fadeFrames"];
|
||||||
|
shutterSyncWithInterval = doc["syncWithInterval"];
|
||||||
|
shutterFadeInActive = doc["fadeInActive"];
|
||||||
|
shutterFadeOutActive = doc["fadeOutActive"];*/
|
||||||
|
shutterFadePercent = doc["0"];
|
||||||
|
shutterFadeFrames = doc["1"];
|
||||||
|
shutterSyncWithInterval = doc["2"];
|
||||||
|
shutterFadeInActive = doc["3"];
|
||||||
|
shutterFadeOutActive = doc["4"];
|
||||||
|
RPC.println("/fade:" + String(shutterFadePercent) + "," + String(shutterFadeFrames) + "," + String(shutterSyncWithInterval) + "," + String(shutterFadeInActive) + "," + String(shutterFadeOutActive) + "," + String(save));
|
||||||
|
}
|
||||||
|
else if ((type=="test_optics")||(type=="save_optics"))
|
||||||
|
{
|
||||||
|
Serial.println(type);
|
||||||
|
if (type=="save_optics") save = true;
|
||||||
|
else save = false;
|
||||||
|
zoomValue = doc["zoomValue"];
|
||||||
|
focusValue = doc["focusValue"];
|
||||||
|
diaphragmValue = doc["diaphragmValue"];
|
||||||
|
syncWithIntervalOptics = doc["syncWithInterval"];
|
||||||
|
RPC.println("/optics:" + String(zoomValue) + "," + String(focusValue) + "," + String(diaphragmValue) + "," + String(syncWithIntervalOptics) + "," + String(save));
|
||||||
|
}
|
||||||
|
else if (type=="accion")
|
||||||
|
{
|
||||||
|
Serial.println(type);
|
||||||
|
RPC.println("/action:" + String(1));
|
||||||
|
Udp.beginPacket(remote_ip, remotePort);
|
||||||
|
Udp.println("/action:" + String(1));
|
||||||
|
Udp.endPacket();
|
||||||
|
}
|
||||||
|
else if (type=="corten")
|
||||||
|
{
|
||||||
|
Serial.println(type);
|
||||||
|
RPC.println("/action:" + String(0));
|
||||||
|
Udp.beginPacket(remote_ip, remotePort);
|
||||||
|
Udp.println("/action:" + String(0));
|
||||||
|
Udp.endPacket();
|
||||||
|
}
|
||||||
|
else if (type=="stop") RPC.println("/s_motor:4," + String(motorDirection) + "," + String(0) + ", 0");
|
||||||
|
else Serial.println("No reconocido");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long time_blink=millis();
|
||||||
|
bool state = false;
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
WiFiClient client = server.available();
|
||||||
|
if (client) {
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Nuevo cliente conectado");
|
||||||
|
#endif
|
||||||
|
String request = "";
|
||||||
|
bool isPostRequest = false;
|
||||||
|
|
||||||
|
while (client.connected()) {
|
||||||
|
if (client.available()) {
|
||||||
|
char c = client.read();
|
||||||
|
request += c;
|
||||||
|
|
||||||
|
// Identificar si es una solicitud POST
|
||||||
|
if (request.indexOf("POST") >= 0) {
|
||||||
|
isPostRequest = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si se encuentra el final de la solicitud
|
||||||
|
if (c == '\n' && request.endsWith("\r\n\r\n")) {
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Solicitud recibida:");
|
||||||
|
Serial.println(request);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (isPostRequest) {
|
||||||
|
String body = "";
|
||||||
|
while (client.available()) {
|
||||||
|
body += (char)client.read();
|
||||||
|
}
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Cuerpo del mensaje recibido:");
|
||||||
|
Serial.println(body);
|
||||||
|
#endif
|
||||||
|
// Llamamos a la función para procesar la petición POST
|
||||||
|
handlePostRequest(body);
|
||||||
|
// Respuesta al cliente
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-type:text/plain");
|
||||||
|
client.println();
|
||||||
|
client.println("Datos enviados correctamente");
|
||||||
|
} else if (request.indexOf("GET /sensors") >= 0) { // actualiza fps en interface
|
||||||
|
// Respuesta para la ruta /motorSpeed
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-Type: application/json");
|
||||||
|
client.println();
|
||||||
|
String response = "{\"sensors\":[" + String(motorSpeedRead) + "," + String(FadePercentRead) + "]}";
|
||||||
|
client.print(response);
|
||||||
|
} else {
|
||||||
|
// Respuesta para servir la interfaz HTML
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-type:text/html");
|
||||||
|
client.println();
|
||||||
|
client.print(htmlTemplate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.stop();
|
||||||
|
#if DEBUG_M7
|
||||||
|
Serial.println("Cliente desconectado");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
//Enviar datos a M4
|
||||||
|
RPCRead();
|
||||||
|
refresh_sensors();
|
||||||
|
}
|
46
CraterLab_camera/lib/README
Normal file
46
CraterLab_camera/lib/README
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
33
CraterLab_camera/platformio.ini
Normal file
33
CraterLab_camera/platformio.ini
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:ARDUINO_GIGA_M7]
|
||||||
|
;platform = https://github.com/dberlin/platform-ststm32.git#develop
|
||||||
|
;platform = https://github.com/dberlin/platform-ststm32
|
||||||
|
platform = ststm32
|
||||||
|
board = giga_r1_m7
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 1000000
|
||||||
|
;upload_port = COM12
|
||||||
|
board_build.arduino.flash_layout = 75_25 ;50_50, 75_25, 100_0
|
||||||
|
lib_deps = https://github.com/br3ttb/Arduino-PID-Library
|
||||||
|
bblanchon/ArduinoJson@^7.2.0
|
||||||
|
|
||||||
|
|
||||||
|
[env:ARDUINO_GIGA_M4]
|
||||||
|
;platform = https://github.com/dberlin/platform-ststm32.git#develop
|
||||||
|
platform = ststm32
|
||||||
|
board = giga_r1_m4
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 1000000
|
||||||
|
;upload_port = COM12
|
||||||
|
board_build.arduino.flash_layout = 75_25 ;50_50, 75_25, 100_0
|
||||||
|
lib_deps = https://github.com/Simsso/ShiftRegister74HC595
|
||||||
|
https://github.com/br3ttb/Arduino-PID-Library
|
7
CraterLab_camera/src/main.cpp
Normal file
7
CraterLab_camera/src/main.cpp
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#if defined(ARDUINO_GIGA_M7)
|
||||||
|
#include<main_m7.cpp>
|
||||||
|
#elif defined(ARDUINO_GIGA_M4)
|
||||||
|
#include<main_m4.cpp>
|
||||||
|
#else
|
||||||
|
#include<main_m7.cpp>
|
||||||
|
#endif
|
11
CraterLab_camera/test/README
Normal file
11
CraterLab_camera/test/README
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
This directory is intended for PlatformIO Test Runner and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PlatformIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
Loading…
Reference in a new issue