satnogs-rotator-firmware
easycomm.h
Go to the documentation of this file.
1 
10 #ifndef LIBRARIES_EASYCOMM_H_
11 #define LIBRARIES_EASYCOMM_H_
12 
13 #include <Arduino.h>
14 #include <WString.h>
15 #include <avr/wdt.h>
16 #include "rs485.h"
17 #include "rotator_pins.h"
18 #include "globals.h"
19 
20 #define RS485_TX_TIME 9
21 #define BUFFER_SIZE 256
22 #define BAUDRATE 19200
23 
25 
26 /**************************************************************************/
30 /**************************************************************************/
31 class easycomm {
32 public:
33 
34  /**************************************************************************/
38  /**************************************************************************/
39  void easycomm_init() {
41  }
42 
43  /**************************************************************************/
47  /**************************************************************************/
48  void easycomm_proc() {
49  char buffer[BUFFER_SIZE];
50  char incomingByte;
51  char *Data = buffer;
52  char *rawData;
53  static uint16_t BufferCnt = 0;
54  char data[100];
55  String str1, str2, str3, str4, str5, str6;
56 
57  // Read from serial
58  while (rs485.available() > 0) {
59  incomingByte = rs485.read();
60 
61  // Read new data, '\n' means new pacakage
62  if (incomingByte == '\n') {
63  buffer[BufferCnt] = 0;
64  if (buffer[0] == 'A' && buffer[1] == 'Z') {
65  if (buffer[2] == ' ' && buffer[3] == 'E' &&
66  buffer[4] == 'L') {
67  // Send current absolute position in deg
68  str1 = String("AZ");
69  str2 = String(control_az.input, 1);
70  str3 = String(" EL");
71  str4 = String(control_el.input, 1);
72  str5 = String("\n");
73  rs485.print(str1 + str2 + str3 + str4 + str5);
74  } else {
75  // Get the absolute position in deg for azimuth
77  rawData = strtok_r(Data, " ", &Data);
78  strncpy(data, rawData + 2, 10);
79  if (isNumber(data)) {
80  control_az.setpoint = atof(data);
81  }
82  // Get the absolute position in deg for elevation
83  rawData = strtok_r(Data, " ", &Data);
84  if (rawData[0] == 'E' && rawData[1] == 'L') {
85  strncpy(data, rawData + 2, 10);
86  if (isNumber(data)) {
87  control_el.setpoint = atof(data);
88  }
89  }
90  }
91  } else if (buffer[0] == 'V' && buffer[1] == 'U') {
92  // Elevation increase speed in mdeg/s
94  strncpy(data, Data + 2, 10);
95  if (isNumber(data)) {
96  // Convert to deg/s
97  control_el.setpoint_speed = atof(data) / 1000;
98  }
99  } else if (buffer[0] == 'V' && buffer[1] == 'D') {
100  // Elevation decrease speed in mdeg/s
102  strncpy(data, Data + 2, 10);
103  if (isNumber(data)) {
104  // Convert to deg/s
105  control_el.setpoint_speed = - atof(data) / 1000;
106  }
107  } else if (buffer[0] == 'V' && buffer[1] == 'L') {
108  // Azimuth increase speed in mdeg/s
110  strncpy(data, Data + 2, 10);
111  if (isNumber(data)) {
112  // Convert to deg/s
113  control_az.setpoint_speed = atof(data) / 1000;
114  }
115  } else if (buffer[0] == 'V' && buffer[1] == 'R') {
116  // Azimuth decrease speed in mdeg/s
118  strncpy(data, Data + 2, 10);
119  if (isNumber(data)) {
120  // Convert to deg/s
121  control_az.setpoint_speed = - atof(data) / 1000;
122  }
123  } else if (buffer[0] == 'S' && buffer[1] == 'A' &&
124  buffer[2] == ' ' && buffer[3] == 'S' &&
125  buffer[4] == 'E') {
126  // Stop Moving
128  str1 = String("AZ");
129  str2 = String(control_az.input, 1);
130  str3 = String(" EL");
131  str4 = String(control_el.input, 1);
132  str5 = String("\n");
133  rs485.print(str1 + str2 + str3 + str4 + str5);
136  } else if (buffer[0] == 'R' && buffer[1] == 'E' &&
137  buffer[2] == 'S' && buffer[3] == 'E' &&
138  buffer[4] == 'T') {
139  // Reset the rotator, go to home position
140  str1 = String("AZ");
141  str2 = String(control_az.input, 1);
142  str3 = String(" EL");
143  str4 = String(control_el.input, 1);
144  str5 = String("\n");
145  rs485.print(str1 + str2 + str3 + str4 + str5);
146  rotator.homing_flag = false;
147  } else if (buffer[0] == 'P' && buffer[1] == 'A' &&
148  buffer[2] == 'R' && buffer[3] == 'K' ) {
149  // Park the rotator
151  str1 = String("AZ");
152  str2 = String(control_az.input, 1);
153  str3 = String(" EL");
154  str4 = String(control_el.input, 1);
155  str5 = String("\n");
156  rs485.print(str1 + str2 + str3 + str4 + str5);
159  } else if (buffer[0] == 'V' && buffer[1] == 'E') {
160  // Get the version if rotator controller
161  str1 = String("VE");
162  str2 = String("SatNOGS-v2.2");
163  str3 = String("\n");
164  rs485.print(str1 + str2 + str3);
165  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
166  buffer[2] == '0') {
167  // Get the inside temperature
168  str1 = String("IP0,");
169  str2 = String(rotator.inside_temperature, DEC);
170  str3 = String("\n");
171  rs485.print(str1 + str2 + str3);
172  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
173  buffer[2] == '1') {
174  // Get the status of end-stop, azimuth
175  str1 = String("IP1,");
176  str2 = String(rotator.switch_az, DEC);
177  str3 = String("\n");
178  rs485.print(str1 + str2 + str3);
179  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
180  buffer[2] == '2') {
181  // Get the status of end-stop, elevation
182  str1 = String("IP2,");
183  str2 = String(rotator.switch_el, DEC);
184  str3 = String("\n");
185  rs485.print(str1 + str2 + str3);
186  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
187  buffer[2] == '3') {
188  // Get the current position of azimuth in deg
189  str1 = String("IP3,");
190  str2 = String(control_az.input, 2);
191  str3 = String("\n");
192  rs485.print(str1 + str2 + str3);
193  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
194  buffer[2] == '4') {
195  // Get the current position of elevation in deg
196  str1 = String("IP4,");
197  str2 = String(control_el.input, 2);
198  str3 = String("\n");
199  rs485.print(str1 + str2 + str3);
200  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
201  buffer[2] == '5') {
202  // Get the load of azimuth, in range of 0-1023
203  str1 = String("IP5,");
204  str2 = String(control_az.load, DEC);
205  str3 = String("\n");
206  rs485.print(str1 + str2 + str3);
207  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
208  buffer[2] == '6') {
209  // Get the load of elevation, in range of 0-1023
210  str1 = String("IP6,");
211  str2 = String(control_el.load, DEC);
212  str3 = String("\n");
213  rs485.print(str1 + str2 + str3);
214  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
215  buffer[2] == '7') {
216  // Get the speed of azimuth in deg/s
217  str1 = String("IP7,");
218  str2 = String(control_az.speed, 2);
219  str3 = String("\n");
220  rs485.print(str1 + str2 + str3);
221  } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
222  buffer[2] == '8') {
223  // Get the speed of elevation in deg/s
224  str1 = String("IP8,");
225  str2 = String(control_el.speed, 2);
226  str3 = String("\n");
227  rs485.print(str1 + str2 + str3);
228  } else if (buffer[0] == 'G' && buffer[1] == 'S') {
229  // Get the status of rotator
230  str1 = String("GS");
231  str2 = String(rotator.rotator_status, DEC);
232  str3 = String("\n");
233  rs485.print(str1 + str2 + str3);
234  } else if (buffer[0] == 'G' && buffer[1] == 'E') {
235  // Get the error of rotator
236  str1 = String("GE");
237  str2 = String(rotator.rotator_error, DEC);
238  str3 = String("\n");
239  rs485.print(str1 + str2 + str3);
240  } else if(buffer[0] == 'C' && buffer[1] == 'R') {
241  // Get Configuration of rotator
242  if (buffer[3] == '1') {
243  // Get Kp Azimuth gain
244  str1 = String("1,");
245  str2 = String(control_az.p, 2);
246  str3 = String("\n");
247  rs485.print(str1 + str2 + str3);
248  } else if (buffer[3] == '2') {
249  // Get Ki Azimuth gain
250  str1 = String("2,");
251  str2 = String(control_az.i, 2);
252  str3 = String("\n");
253  rs485.print(str1 + str2 + str3);
254  } else if (buffer[3] == '3') {
255  // Get Kd Azimuth gain
256  str1 = String("3,");
257  str2 = String(control_az.d, 2);
258  str3 = String("\n");
259  rs485.print(str1 + str2 + str3);
260  } else if (buffer[3] == '4') {
261  // Get Kp Elevation gain
262  str1 = String("4,");
263  str2 = String(control_el.p, 2);
264  str3 = String("\n");
265  rs485.print(str1 + str2 + str3);
266  } else if (buffer[3] == '5') {
267  // Get Ki Elevation gain
268  str1 = String("5,");
269  str2 = String(control_el.i, 2);
270  str3 = String("\n");
271  rs485.print(str1 + str2 + str3);
272  } else if (buffer[3] == '6') {
273  // Get Kd Elevation gain
274  str1 = String("6,");
275  str2 = String(control_el.d, 2);
276  str3 = String("\n");
277  rs485.print(str1 + str2 + str3);
278  } else if (buffer[3] == '7') {
279  // Get Azimuth park position
280  str1 = String("7,");
281  str2 = String(rotator.park_az, 2);
282  str3 = String("\n");
283  rs485.print(str1 + str2 + str3);
284  } else if (buffer[3] == '8') {
285  // Get Elevation park position
286  str1 = String("8,");
287  str2 = String(rotator.park_el, 2);
288  str3 = String("\n");
289  rs485.print(str1 + str2 + str3);
290  } else if (buffer[3] == '9') {
291  // Get control mode
292  str1 = String("9,");
293  str2 = String(rotator.control_mode);
294  str3 = String("\n");
295  rs485.print(str1 + str2 + str3);
296  }
297  } else if (buffer[0] == 'C' && buffer[1] == 'W') {
298  // Set Config
299  if (buffer[2] == '1') {
300  // Set Kp Azimuth gain
301  rawData = strtok_r(Data, ",", &Data);
302  strncpy(data, rawData + 4, 10);
303  if (isNumber(data)) {
304  control_az.p = atof(data);
305  }
306  } else if (buffer[2] == '2') {
307  // Set Ki Azimuth gain
308  rawData = strtok_r(Data, ",", &Data);
309  strncpy(data, rawData + 4, 10);
310  if (isNumber(data)) {
311  control_az.i = atof(data);
312  }
313  } else if (buffer[2] == '3') {
314  // Set Kd Azimuth gain
315  rawData = strtok_r(Data, ",", &Data);
316  strncpy(data, rawData + 4, 10);
317  if (isNumber(data)) {
318  control_az.d = atof(data);
319  }
320  } else if (buffer[2] == '4') {
321  // Set Kp Elevation gain
322  rawData = strtok_r(Data, ",", &Data);
323  strncpy(data, rawData + 4, 10);
324  if (isNumber(data)) {
325  control_el.p = atof(data);
326  }
327  } else if (buffer[2] == '5') {
328  // Set Ki Elevation gain
329  rawData = strtok_r(Data, ",", &Data);
330  strncpy(data, rawData + 4, 10);
331  if (isNumber(data)) {
332  control_el.i = atof(data);
333  }
334  } else if (buffer[2] == '6') {
335  // Set Kd Elevation gain
336  rawData = strtok_r(Data, ",", &Data);
337  strncpy(data, rawData + 4, 10);
338  if (isNumber(data)) {
339  control_el.d = atof(data);
340  }
341  } else if (buffer[2] == '7') {
342  // Set the Azimuth park position
343  rawData = strtok_r(Data, ",", &Data);
344  strncpy(data, rawData + 4, 10);
345  if (isNumber(data)) {
346  rotator.park_az = atof(data);
347  }
348  } else if (buffer[2] == '8') {
349  // Set the Elevation park position
350  rawData = strtok_r(Data, ",", &Data);
351  strncpy(data, rawData + 4, 10);
352  if (isNumber(data)) {
353  rotator.park_el = atof(data);
354  }
355  }
356  } else if (buffer[0] == 'R' && buffer[1] == 'S'
357  && buffer[2] == 'T') {
358  // Custom command to test the watchdog timer routine
359  while(1)
360  ;
361  } else if (buffer[0] == 'R' && buffer[1] == 'B') {
362  // Custom command to reboot the uC
363  wdt_enable(WDTO_2S);
364  while(1);
365  }
366  // Reset the buffer an clean the serial buffer
367  BufferCnt = 0;
368  rs485.flush();
369  } else {
370  // Fill the buffer with incoming data
371  buffer[BufferCnt] = incomingByte;
372  BufferCnt++;
373  }
374  }
375  }
376 
377 private:
378  bool isNumber(char *input) {
379  for (uint16_t i = 0; input[i] != '\0'; i++) {
380  if (isalpha(input[i]))
381  return false;
382  }
383  return true;
384  }
385 };
386 
387 #endif /* LIBRARIES_EASYCOMM_H_ */
double input
Motor Position feedback in deg.
Definition: globals.h:30
void easycomm_proc()
Get the commands from RS485 and response to the client.
Definition: easycomm.h:48
double setpoint
Position set point in deg.
Definition: globals.h:33
Definition: globals.h:26
void begin(uint16_t baudrate)
Initialize the RS485 transceiver.
Definition: rs485.h:38
bool switch_az
Definition: globals.h:48
double p
Definition: globals.h:37
#define BAUDRATE
Set the Baudrate of easycomm 3 protocol.
Definition: easycomm.h:22
_control control_az
Definition: globals.h:51
#define RS485_DIR
Digital output, to set the direction of RS485 communication.
Definition: rotator_pins.h:28
_rotator rotator
Definition: globals.h:57
enum _rotator_status rotator_status
Rotator status.
Definition: globals.h:41
enum _rotator_error rotator_error
Rotator error.
Definition: globals.h:42
bool switch_el
End-stop vales.
Definition: globals.h:48
double park_el
Park position for both axis.
Definition: globals.h:46
double i
Definition: globals.h:37
uint8_t available(void)
The number of chars/uint8_t that are available in RS485 buffer.
Definition: rs485.h:73
int8_t inside_temperature
Inside Temperature.
Definition: globals.h:45
double d
Control gains.
Definition: globals.h:37
double speed
Motor Rotation speed in deg/s.
Definition: globals.h:32
uint8_t read()
Read a char/uint8_t from RS485 bus.
Definition: rs485.h:63
void easycomm_init()
Initialize the RS485 bus.
Definition: easycomm.h:39
double setpoint_speed
Speed set point in deg/s.
Definition: globals.h:34
double park_az
Definition: globals.h:46
bool homing_flag
Homing flag.
Definition: globals.h:44
enum _control_mode control_mode
Control mode.
Definition: globals.h:43
Class that functions for easycomm 3 implementation.
Definition: easycomm.h:31
void flush()
Waits for the transmission of outgoing serial data to complete.
Definition: rs485.h:82
void print(String str)
Print a string to RS485 bus.
Definition: rs485.h:50
#define RS485_TX_TIME
Delay "t"ms to write in serial for RS485 implementation.
Definition: easycomm.h:20
Class that functions for interacting with a RS485 transceiver.
Definition: rs485.h:23
uint16_t load
Motor Load in mA.
Definition: globals.h:35
#define BUFFER_SIZE
Set the size of serial buffer.
Definition: easycomm.h:21
_control control_el
Definition: globals.h:54
rs485 rs485(RS485_DIR, RS485_TX_TIME)
bool isNumber(char *input)
Definition: easycomm.h:378