398 lines
18 KiB
C++
398 lines
18 KiB
C++
/*!
|
|
* @file easycomm.h
|
|
*
|
|
* It is a driver for easycomm 3 protocol as referred, in Hamlib.
|
|
*
|
|
* Licensed under the GPLv3
|
|
*
|
|
*/
|
|
|
|
#ifndef LIBRARIES_EASYCOMM_H_
|
|
#define LIBRARIES_EASYCOMM_H_
|
|
|
|
#include <Arduino.h>
|
|
#include <WString.h>
|
|
#include <avr/wdt.h>
|
|
#include "rs485.h"
|
|
#include "rotator_pins.h"
|
|
#include "globals.h"
|
|
|
|
#define RS485_TX_TIME 9 ///< Delay "t"ms to write in serial for RS485 implementation
|
|
#define BUFFER_SIZE 256 ///< Set the size of serial buffer
|
|
#define BAUDRATE 19200 ///< Set the Baudrate of easycomm 3 protocol
|
|
|
|
rs485 rs485(RS485_DIR, RS485_TX_TIME);
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Class that functions for easycomm 3 implementation
|
|
*/
|
|
/**************************************************************************/
|
|
class easycomm {
|
|
public:
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Initialize the RS485 bus
|
|
*/
|
|
/**************************************************************************/
|
|
void easycomm_init() {
|
|
rs485.begin(BAUDRATE);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Get the commands from RS485 and response to the client
|
|
*/
|
|
/**************************************************************************/
|
|
void easycomm_proc() {
|
|
char buffer[BUFFER_SIZE];
|
|
char incomingByte;
|
|
char *Data = buffer;
|
|
char *rawData;
|
|
static uint16_t BufferCnt = 0;
|
|
char data[100];
|
|
String str1, str2, str3, str4, str5, str6;
|
|
|
|
// Read from serial
|
|
while (rs485.available() > 0) {
|
|
incomingByte = rs485.read();
|
|
|
|
// Read new data, '\n' means new pacakage
|
|
if (incomingByte == '\n' || incomingByte == '\r') {
|
|
buffer[BufferCnt] = 0;
|
|
if (buffer[0] == 'A' && buffer[1] == 'Z') {
|
|
if (buffer[2] == ' ' && buffer[3] == 'E' &&
|
|
buffer[4] == 'L') {
|
|
// Send current absolute position in deg
|
|
str1 = String("AZ");
|
|
str2 = String(control_az.input, 1);
|
|
str3 = String(" EL");
|
|
str4 = String(control_el.input, 1);
|
|
str5 = String("\n");
|
|
rs485.print(str1 + str2 + str3 + str4 + str5);
|
|
} else {
|
|
// Get the absolute position in deg for azimuth
|
|
rotator.control_mode = position;
|
|
rawData = strtok_r(Data, " ", &Data);
|
|
strncpy(data, rawData + 2, 10);
|
|
if (isNumber(data)) {
|
|
control_az.setpoint = atof(data);
|
|
}
|
|
// Get the absolute position in deg for elevation
|
|
rawData = strtok_r(Data, " ", &Data);
|
|
if (rawData[0] == 'E' && rawData[1] == 'L') {
|
|
strncpy(data, rawData + 2, 10);
|
|
if (isNumber(data)) {
|
|
control_el.setpoint = atof(data);
|
|
}
|
|
}
|
|
}
|
|
} else if (buffer[0] == 'E' && buffer[1] == 'L') {
|
|
// Get the absolute position in deg for elevation
|
|
rotator.control_mode = position;
|
|
rawData = strtok_r(Data, " ", &Data);
|
|
if (rawData[0] == 'E' && rawData[1] == 'L') {
|
|
strncpy(data, rawData + 2, 10);
|
|
if (isNumber(data)) {
|
|
control_el.setpoint = atof(data);
|
|
}
|
|
}
|
|
} else if (buffer[0] == 'V' && buffer[1] == 'U') {
|
|
// Elevation increase speed in mdeg/s
|
|
rotator.control_mode = speed;
|
|
strncpy(data, Data + 2, 10);
|
|
if (isNumber(data)) {
|
|
// Convert to deg/s
|
|
control_el.setpoint_speed = atof(data) / 1000;
|
|
}
|
|
} else if (buffer[0] == 'V' && buffer[1] == 'D') {
|
|
// Elevation decrease speed in mdeg/s
|
|
rotator.control_mode = speed;
|
|
strncpy(data, Data + 2, 10);
|
|
if (isNumber(data)) {
|
|
// Convert to deg/s
|
|
control_el.setpoint_speed = - atof(data) / 1000;
|
|
}
|
|
} else if (buffer[0] == 'V' && buffer[1] == 'L') {
|
|
// Azimuth increase speed in mdeg/s
|
|
rotator.control_mode = speed;
|
|
strncpy(data, Data + 2, 10);
|
|
if (isNumber(data)) {
|
|
// Convert to deg/s
|
|
control_az.setpoint_speed = atof(data) / 1000;
|
|
}
|
|
} else if (buffer[0] == 'V' && buffer[1] == 'R') {
|
|
// Azimuth decrease speed in mdeg/s
|
|
rotator.control_mode = speed;
|
|
strncpy(data, Data + 2, 10);
|
|
if (isNumber(data)) {
|
|
// Convert to deg/s
|
|
control_az.setpoint_speed = - atof(data) / 1000;
|
|
}
|
|
} else if (buffer[0] == 'S' && buffer[1] == 'A' &&
|
|
buffer[2] == ' ' && buffer[3] == 'S' &&
|
|
buffer[4] == 'E') {
|
|
// Stop Moving
|
|
rotator.control_mode = position;
|
|
str1 = String("AZ");
|
|
str2 = String(control_az.input, 1);
|
|
str3 = String(" EL");
|
|
str4 = String(control_el.input, 1);
|
|
str5 = String("\n");
|
|
rs485.print(str1 + str2 + str3 + str4 + str5);
|
|
control_az.setpoint = control_az.input;
|
|
control_el.setpoint = control_el.input;
|
|
} else if (buffer[0] == 'R' && buffer[1] == 'E' &&
|
|
buffer[2] == 'S' && buffer[3] == 'E' &&
|
|
buffer[4] == 'T') {
|
|
// Reset the rotator, go to home position
|
|
str1 = String("AZ");
|
|
str2 = String(control_az.input, 1);
|
|
str3 = String(" EL");
|
|
str4 = String(control_el.input, 1);
|
|
str5 = String("\n");
|
|
rs485.print(str1 + str2 + str3 + str4 + str5);
|
|
rotator.homing_flag = false;
|
|
} else if (buffer[0] == 'P' && buffer[1] == 'A' &&
|
|
buffer[2] == 'R' && buffer[3] == 'K' ) {
|
|
// Park the rotator
|
|
rotator.control_mode = position;
|
|
str1 = String("AZ");
|
|
str2 = String(control_az.input, 1);
|
|
str3 = String(" EL");
|
|
str4 = String(control_el.input, 1);
|
|
str5 = String("\n");
|
|
rs485.print(str1 + str2 + str3 + str4 + str5);
|
|
control_az.setpoint = rotator.park_az;
|
|
control_el.setpoint = rotator.park_el;
|
|
} else if (buffer[0] == 'V' && buffer[1] == 'E') {
|
|
// Get the version if rotator controller
|
|
str1 = String("VE");
|
|
str2 = String("SatNOGS-v2.2");
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '0') {
|
|
// Get the inside temperature
|
|
str1 = String("IP0,");
|
|
str2 = String(rotator.inside_temperature, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '1') {
|
|
// Get the status of end-stop, azimuth
|
|
str1 = String("IP1,");
|
|
str2 = String(rotator.switch_az, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '2') {
|
|
// Get the status of end-stop, elevation
|
|
str1 = String("IP2,");
|
|
str2 = String(rotator.switch_el, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '3') {
|
|
// Get the current position of azimuth in deg
|
|
str1 = String("IP3,");
|
|
str2 = String(control_az.input, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '4') {
|
|
// Get the current position of elevation in deg
|
|
str1 = String("IP4,");
|
|
str2 = String(control_el.input, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '5') {
|
|
// Get the load of azimuth, in range of 0-1023
|
|
str1 = String("IP5,");
|
|
str2 = String(control_az.load, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '6') {
|
|
// Get the load of elevation, in range of 0-1023
|
|
str1 = String("IP6,");
|
|
str2 = String(control_el.load, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '7') {
|
|
// Get the speed of azimuth in deg/s
|
|
str1 = String("IP7,");
|
|
str2 = String(control_az.speed, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'I' && buffer[1] == 'P' &&
|
|
buffer[2] == '8') {
|
|
// Get the speed of elevation in deg/s
|
|
str1 = String("IP8,");
|
|
str2 = String(control_el.speed, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'G' && buffer[1] == 'S') {
|
|
// Get the status of rotator
|
|
str1 = String("GS");
|
|
str2 = String(rotator.rotator_status, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[0] == 'G' && buffer[1] == 'E') {
|
|
// Get the error of rotator
|
|
str1 = String("GE");
|
|
str2 = String(rotator.rotator_error, DEC);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if(buffer[0] == 'C' && buffer[1] == 'R') {
|
|
// Get Configuration of rotator
|
|
if (buffer[3] == '1') {
|
|
// Get Kp Azimuth gain
|
|
str1 = String("1,");
|
|
str2 = String(control_az.p, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '2') {
|
|
// Get Ki Azimuth gain
|
|
str1 = String("2,");
|
|
str2 = String(control_az.i, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '3') {
|
|
// Get Kd Azimuth gain
|
|
str1 = String("3,");
|
|
str2 = String(control_az.d, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '4') {
|
|
// Get Kp Elevation gain
|
|
str1 = String("4,");
|
|
str2 = String(control_el.p, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '5') {
|
|
// Get Ki Elevation gain
|
|
str1 = String("5,");
|
|
str2 = String(control_el.i, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '6') {
|
|
// Get Kd Elevation gain
|
|
str1 = String("6,");
|
|
str2 = String(control_el.d, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '7') {
|
|
// Get Azimuth park position
|
|
str1 = String("7,");
|
|
str2 = String(rotator.park_az, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '8') {
|
|
// Get Elevation park position
|
|
str1 = String("8,");
|
|
str2 = String(rotator.park_el, 2);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
} else if (buffer[3] == '9') {
|
|
// Get control mode
|
|
str1 = String("9,");
|
|
str2 = String(rotator.control_mode);
|
|
str3 = String("\n");
|
|
rs485.print(str1 + str2 + str3);
|
|
}
|
|
} else if (buffer[0] == 'C' && buffer[1] == 'W') {
|
|
// Set Config
|
|
if (buffer[2] == '1') {
|
|
// Set Kp Azimuth gain
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
control_az.p = atof(data);
|
|
}
|
|
} else if (buffer[2] == '2') {
|
|
// Set Ki Azimuth gain
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
control_az.i = atof(data);
|
|
}
|
|
} else if (buffer[2] == '3') {
|
|
// Set Kd Azimuth gain
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
control_az.d = atof(data);
|
|
}
|
|
} else if (buffer[2] == '4') {
|
|
// Set Kp Elevation gain
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
control_el.p = atof(data);
|
|
}
|
|
} else if (buffer[2] == '5') {
|
|
// Set Ki Elevation gain
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
control_el.i = atof(data);
|
|
}
|
|
} else if (buffer[2] == '6') {
|
|
// Set Kd Elevation gain
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
control_el.d = atof(data);
|
|
}
|
|
} else if (buffer[2] == '7') {
|
|
// Set the Azimuth park position
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
rotator.park_az = atof(data);
|
|
}
|
|
} else if (buffer[2] == '8') {
|
|
// Set the Elevation park position
|
|
rawData = strtok_r(Data, ",", &Data);
|
|
strncpy(data, rawData + 4, 10);
|
|
if (isNumber(data)) {
|
|
rotator.park_el = atof(data);
|
|
}
|
|
}
|
|
} else if (buffer[0] == 'R' && buffer[1] == 'S'
|
|
&& buffer[2] == 'T') {
|
|
// Custom command to test the watchdog timer routine
|
|
while(1)
|
|
;
|
|
} else if (buffer[0] == 'R' && buffer[1] == 'B') {
|
|
// Custom command to reboot the uC
|
|
wdt_enable(WDTO_2S);
|
|
while(1);
|
|
}
|
|
// Reset the buffer an clean the serial buffer
|
|
BufferCnt = 0;
|
|
rs485.flush();
|
|
} else {
|
|
// Fill the buffer with incoming data
|
|
buffer[BufferCnt] = incomingByte;
|
|
BufferCnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
bool isNumber(char *input) {
|
|
for (uint16_t i = 0; input[i] != '\0'; i++) {
|
|
if (isalpha(input[i]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
#endif /* LIBRARIES_EASYCOMM_H_ */
|