Analogue_Hyperlapse_Camera/CraterLab_base_giratoria/include/main_m4.cpp
Miguel Angel de Heras 2c599aaa51 first commit
2025-02-26 10:33:31 +01:00

416 lines
13 KiB
C++

#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();
}