RF-Positioning-System V0.1
by Max Heinekamp
Loading...
Searching...
No Matches
scpi_commands.cpp
Go to the documentation of this file.
1
12
13#include "flash.h"
14#include "scpi.h"
15
16extern FLASH flash_memory;
17extern SCPI* scpi_instrument;
18extern STEPPER* stepper1;
19extern STEPPER* stepper2;
20
21void Identify(SCPI_C commands, SCPI_P parameters, Stream& interface) {
22 static char response[100]; // Buffer for formatted output
23 snprintf(response, sizeof(response), "%s, %s, V%s, #%s", DEVICE_MANUFACTURER, DEVICE_NAME, DEVICE_VERSION, DEVICE_SERIAL);
24 interface.print(response);
25 interface.write('\n');
26}
27
28void Reset(SCPI_C commands, SCPI_P parameters, Stream& interface) {
29 esp_restart();
30}
31
32void OPC(SCPI_C commands, SCPI_P parameters, Stream& interface) {
33 interface.print("1");
34 interface.write('\n');
35}
36
37void GetError(SCPI_C commands, SCPI_P parameters, Stream& interface) {
38 const char* response = scpi_instrument->getError();
39 interface.print(response);
40 interface.write('\n');
41}
42
43void GetHelp(SCPI_C commands, SCPI_P parameters, Stream& interface) {
44 scpi_instrument->printAllHeaders(interface);
45}
46
47void GetHelpSyntax(SCPI_C commands, SCPI_P parameters, Stream& interface) {
48 scpi_instrument->printHeaderSyntax(interface, parameters[0]);
49}
50
51void GetVersion(SCPI_C commands, SCPI_P parameters, Stream& interface) {
52 static char response[10]; // Buffer for formatted output
53 snprintf(response, sizeof(response), "V%s", DEVICE_VERSION);
54 interface.print(response);
55 interface.write('\n');
56}
57
58void GetDebug(SCPI_C commands, SCPI_P parameters, Stream& interface) {
59 scpi_instrument->PrintDebugInfo(interface);
60 interface.write('\n');
61}
62
63void Preset(SCPI_C commands, SCPI_P parameters, Stream& interface) {
64 // Reset the device to factory settings
65 flash_memory.preferences.clear();
66 esp_restart();
67}
68
69void SetPort(SCPI_C commands, SCPI_P parameters, Stream& interface) {
70 //Parse string from input
71 String portString = String(parameters[0]);
72 int port = portString.toInt();
73
74 //Check if the port is valid
75 if (port < 0 || port > 65535) {
76 scpi_instrument->logError(220, "Invalid port number");
77 return;
78 }
79 //Set the port number
80 flash_memory.preferences.putInt("SCPI-PORT", port);
81}
82
83void GetPort(SCPI_C commands, SCPI_P parameters, Stream& interface) {
84 //Retrieve the port number from flash memory
85 int port = scpi_instrument->getPort();
86 interface.print(port);
87 interface.write('\n');
88}
89
90void SetIP(SCPI_C commands, SCPI_P parameters, Stream &interface) {
91 //Parse string from input
92 String ipString = String(parameters[0]);
93
94 //Check if the string is a valid IP address
95 IPAddress ip;
96 if (!ip.fromString(ipString)) {
97 scpi_instrument->logError(220, "Invalid IP address");
98 return;
99 }
100 //Set the IP address
101 flash_memory.preferences.putString("IP-ADDRESS", ipString);
102
103}
104
105void GetIP(SCPI_C commands, SCPI_P parameters, Stream &interface) {
106 IPAddress myAddress = Ethernet.localIP();
107 interface.print(myAddress);
108 interface.write('\n');
109}
110
111void SetMAC(SCPI_C commands, SCPI_P parameters, Stream &interface) {
112 //Parse string from input
113 String macString = String(parameters[0]);
114 byte myAddress[6];
115 sscanf(macString.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &myAddress[0], &myAddress[1], &myAddress[2], &myAddress[3], &myAddress[4], &myAddress[5]);
116
117 //Set the MAC address
118 flash_memory.preferences.putBytes("MAC-ADDRESS", myAddress, sizeof(myAddress));
119}
120
121void GetMAC(SCPI_C commands, SCPI_P parameters, Stream &interface) {
122 byte myAddress[6];
123 Ethernet.MACAddress(myAddress);
124 for (byte octet = 0; octet < 6; octet++) {
125 interface.print(myAddress[octet], HEX);
126 if (octet < 5) {
127 interface.print(':');
128 }
129 }
130 interface.write('\n');
131}
132
133void GetGW(SCPI_C commands, SCPI_P parameters, Stream &interface) {
134 IPAddress myGateWay = Ethernet.gatewayIP();
135 interface.print(myGateWay);
136 interface.write('\n');
137}
138
139void Perpetual(SCPI_C commands, SCPI_P parameters, Stream &interface) {
140 while (true) {
141 // Perform perpetual motion until device is reset or powered off
142 stepper1->step();
143 stepper2->step();
144 delay(1); // Adjust delay as needed to control speed
145 }
146}
147
148void Step(SCPI_C commands, SCPI_P parameters, Stream &interface) {
149 //Get the numeric suffix/index (if any) from the commands
150 String header = String(commands.Last());
151 header.toUpperCase();
152 interface.print(header);
153 interface.write('\n');
154 int suffix = -1;
155 sscanf(header.c_str(),"%*[STEP]%u", &suffix);
156
157 //Check if the suffix is valid
158 if (suffix != 1 && suffix != 2) {
159 scpi_instrument->logError(131, "Invalid Suffix");
160 return;
161 }
162
163 if (suffix == 1) {
164 for (int i = 0; i < 3200; i++) {
165 stepper1->step();
166 }
167
168 interface.print(F("STEP1"));
169 interface.write('\n');
170 }
171
172 if (suffix == 2) {
173 for (int i = 0; i < 19200; i++) {
174 stepper2->step();
175 }
176
177 //stepper2->move(1000, 5000, 360, (STEPS_PER_REV * AXIS2_GEAR_RATIO * MICROSTEPS),stepper1, 6);
178 //stepper2.runStepperSCurve(2000, 500, 9600);
179
180 interface.print(F("STEP2"));
181 interface.write('\n');
182 }
183}
184
185void SetRelativePosition(SCPI_C commands, SCPI_P parameters, Stream &interface) {
186 //Parse string from input
187 String positionString = String(parameters[0]);
188 int position = positionString.toInt();
189
190 //Check if the position is valid
191 if (position < 0 || position > 360) {
192 scpi_instrument->logError(220, "Invalid position value");
193 return;
194 }
195
196 //Get the numeric suffix/index (if any) from the commands
197 String header = String(commands.Last());
198 header.toUpperCase();
199 int suffix = -1;
200 sscanf(header.c_str(),"%*[RELATIVE]%u", &suffix);
201
202 //Check if the suffix is valid
203 if (suffix != 1 && suffix != 2) {
204 char errorMessage[30];
205 sprintf(errorMessage, "Invalid Suffix: %d", suffix);
206 scpi_instrument->logError(131, errorMessage);
207 return;
208 }
209
210 //Get speed and acceleration from flash memory
211 int speed = flash_memory.preferences.getInt("SPEED", 1500);
212 int acceleration = flash_memory.preferences.getInt("ACCELERATION", 500);
213
214 if (suffix == 1) {
215 stepper1->move(speed, acceleration, position, (STEPS_PER_REV * AXIS1_GEAR_RATIO * MICROSTEPS));
216 }
217
218 if (suffix == 2) {
219 stepper2->move(speed, acceleration, position, (STEPS_PER_REV * AXIS2_GEAR_RATIO * MICROSTEPS), stepper1, 6);
220 }
221}
222
223void GetAbsolutePosition(SCPI_C commands, SCPI_P parameters, Stream &interface) {
224 //Get the numeric suffix/index (if any) from the commands
225 String header = String(commands.Last());
226 header.toUpperCase();
227 int suffix = -1;
228 sscanf(header.c_str(),"%*[ABSOLUTE]%u", &suffix);
229
230 //Check if the suffix is valid
231 if (suffix != 1 && suffix != 2) {
232 scpi_instrument->logError(131, "Invalid Suffix");
233 // A query must always produce a response, or the client is left waiting indefinitely.
234 interface.print(F("NaN"));
235 interface.write('\n');
236 return;
237 }
238
239 if (suffix == 1) {
240 float position = stepper1->getCurrentPosition();
241
242 interface.print(position);
243 interface.write('\n');
244 }
245
246 if (suffix == 2) {
247 float position = stepper2->getCurrentPosition();
248
249 interface.print(position);
250 interface.write('\n');
251 }
252}
253
254void SetAbsolutePosition(SCPI_C commands, SCPI_P parameters, Stream &interface) {
255 //Parse string from input
256 String positionString = String(parameters[0]);
257 int position = positionString.toInt();
258
259 //Check if the position is valid
260 if (position < 0 || position > 360) {
261 scpi_instrument->logError(220, "Invalid position value");
262 return;
263 }
264
265 //Get the numeric suffix/index (if any) from the commands
266 String header = String(commands.Last());
267 header.toUpperCase();
268 int suffix = -1;
269 sscanf(header.c_str(),"%*[ABSOLUTE]%u", &suffix);
270
271 //Check if the suffix is valid
272 if (suffix != 1 && suffix != 2) {
273 char errorMessage[30];
274 sprintf(errorMessage, "Invalid Suffix: %d", suffix);
275 scpi_instrument->logError(131, errorMessage);
276 return;
277 }
278
279 int speed = flash_memory.preferences.getInt("SPEED", 1500);
280 int acceleration = flash_memory.preferences.getInt("ACCELERATION", 500);
281
282 if (suffix == 1) {
283 stepper1->absoluteMove(speed, acceleration, position, (STEPS_PER_REV * AXIS1_GEAR_RATIO * MICROSTEPS));
284 }
285
286 if (suffix == 2) {
287 stepper2->absoluteMove(speed, acceleration, position, (STEPS_PER_REV * AXIS2_GEAR_RATIO * MICROSTEPS), stepper1, 6);
288 }
289}
290
291void SetDirection(SCPI_C commands, SCPI_P parameters, Stream &interface) {
292 //Get the numeric suffix/index (if any) from the commands
293 String header = String(commands.Last());
294 header.toUpperCase();
295 int suffix = -1;
296 sscanf(header.c_str(),"%*[DIRECTION]%u", &suffix);
297
298 //Check if the suffix is valid
299 if (suffix != 1 && suffix != 2) {
300 char errorMessage[30];
301 sprintf(errorMessage, "Invalid Suffix: %d", suffix);
302 scpi_instrument->logError(131, errorMessage);
303 return;
304 }
305
306 if(suffix == 1) {
307 if (String(parameters[0]) == "CW") {
308 stepper1->SetDirection(false);
309 }
310 else if (String(parameters[0]) == "CCW") {
311 stepper1->SetDirection(true);
312 }
313 else {
314 char errorMessage[30];
315 sprintf(errorMessage, "Illegal parameter value: %s", String(parameters[0]));
316 scpi_instrument->logError(224, errorMessage);
317 }
318 }
319 if(suffix == 2) {
320 String param = String(parameters[0]);
321 if (param == "CW" || param == "CCW") {
322 bool newDir = (param == "CCW"); // matches STEPPER::SetDirection convention: true=CCW, false=CW
323 bool oldDir = stepper2->GetDirection();
324 stepper2->SetDirection(newDir);
325
326 if (newDir != oldDir) {
327 // Drive the motor a little bit to adjust for play in the gears — only on an actual reversal
328 float cal_factor = flash_memory.preferences.getFloat("AXIS2-DIR-CHANGE-CAL-FACTOR", AXIS2_DIR_CHANGE_CAL_FACTOR);
329 int cal_steps = (int)(cal_factor * STEPS_PER_REV * AXIS2_GEAR_RATIO * MICROSTEPS / 360.0);
330 for (int i = 0; i < cal_steps; i++) {
331 stepper2->step();
332 delayMicroseconds(200);
333 }
334 }
335 }
336 else {
337 char errorMessage[30];
338 sprintf(errorMessage, "Illegal parameter value: %s", String(parameters[0]));
339 scpi_instrument->logError(224, errorMessage);
340 }
341 }
342}
343
344void GetDirection(SCPI_C commands, SCPI_P parameters, Stream &interface) {
345 //Get the numeric suffix/index (if any) from the commands
346 String header = String(commands.Last());
347 header.toUpperCase();
348 int suffix = -1;
349 sscanf(header.c_str(),"%*[DIRECTION]%u", &suffix);
350
351 //Check if the suffix is valid
352 if (suffix != 1 && suffix != 2) {
353 char errorMessage[30];
354 sprintf(errorMessage, "Invalid Suffix: %d", suffix);
355 scpi_instrument->logError(131, errorMessage);
356 // A query must always produce a response, or the client is left waiting indefinitely.
357 interface.print(F("ERR"));
358 interface.write('\n');
359 return;
360 }
361
362 if (suffix == 1) {
363 if (stepper1->GetDirection()) {
364 interface.print(F("CCW"));
365 interface.write('\n');
366 }
367 else {
368 interface.print(F("CW"));
369 interface.write('\n');
370 }
371 }
372
373 if (suffix == 2) {
374 if (stepper2->GetDirection()) {
375 interface.print(F("CCW"));
376 interface.write('\n');
377 }
378 else {
379 interface.print(F("CW"));
380 interface.write('\n');
381 }
382 }
383}
384
385void SetRMSCurrent(SCPI_C commands, SCPI_P parameters, Stream &interface) {
386 //Parse string from input
387 String rmsString = String(parameters[0]);
388 int rms = rmsString.toInt();
389
390 //Check if the RMS current is valid
391 if (rms < 0 || rms > 2400) {
392 scpi_instrument->logError(220, "Invalid RMS current value");
393 return;
394 }
395 //Set the RMS current
396 flash_memory.preferences.putInt("RMS-CURRENT", rms);
397
398 //Update the stepper driver with the new RMS current
399 stepper1->updateRMSCurrent();
400 stepper2->updateRMSCurrent();
401}
402
403void GetRMSCurrent(SCPI_C commands, SCPI_P parameters, Stream &interface) {
404 //Report the actual current applied by the driver (both axes are always driven identically)
405 interface.print(stepper1->getRMSCurrent());
406 interface.write('\n');
407}
408
409void SetHoldCurrent(SCPI_C commands, SCPI_P parameters, Stream &interface) {
410 //Parse string from input
411 String holdString = String(parameters[0]);
412 int hold = holdString.toInt();
413
414 //Check if the hold current is valid
415 if (hold < 0 || hold > 32) {
416 scpi_instrument->logError(220, "Invalid hold current value");
417 return;
418 }
419 //Set the hold current
420 flash_memory.preferences.putInt("HOLD-CURRENT", hold);
421
422 //Update the stepper driver with the new hold current
423 stepper1->updateHoldCurrent();
424 stepper2->updateHoldCurrent();
425}
426
427void GetHoldCurrent(SCPI_C commands, SCPI_P parameters, Stream &interface) {
428 //Report the actual hold current applied by the driver (both axes are always driven identically)
429 interface.print(stepper1->getHoldCurrent());
430 interface.write('\n');
431}
432
433void SetMicrosteps(SCPI_C commands, SCPI_P parameters, Stream &interface) {
434 //Parse string from input
435 String microstepsString = String(parameters[0]);
436 int microsteps = microstepsString.toInt();
437
438 //Check if the microsteps value is valid
439 if (microsteps < 1 || microsteps > 256) {
440 scpi_instrument->logError(220, "Invalid microsteps value");
441 return;
442 }
443 //Set the microsteps value
444 flash_memory.preferences.putInt("MICROSTEPS", microsteps);
445
446 //Update the stepper driver with the new microsteps value
447 stepper1->updateMicrosteps();
448 stepper2->updateMicrosteps();
449}
450
451void GetMicrosteps(SCPI_C commands, SCPI_P parameters, Stream &interface) {
452 //Retrieve the microsteps value from flash memory
453 int microsteps = flash_memory.preferences.getInt("MICROSTEPS", MICROSTEPS);
454 interface.print(microsteps);
455 interface.write('\n');
456}
457
458void SetSpeed(SCPI_C commands, SCPI_P parameters, Stream &interface) {
459 //Parse string from input
460 String speedString = String(parameters[0]);
461 int speed = speedString.toInt();
462
463 //Check if the speed value is valid
464 if (speed < 0 || speed > 100000) {
465 scpi_instrument->logError(220, "Invalid speed value");
466 return;
467 }
468 //Set the speed value
469 flash_memory.preferences.putInt("SPEED", speed);
470}
471
472void GetSpeed(SCPI_C commands, SCPI_P parameters, Stream &interface) {
473 //Retrieve the speed value from flash memory
474 int speed = flash_memory.preferences.getInt("SPEED", SPEED);
475 interface.print(speed);
476 interface.write('\n');
477}
478
479void SetAcceleration(SCPI_C commands, SCPI_P parameters, Stream &interface) {
480 //Parse string from input
481 String accelerationString = String(parameters[0]);
482 int acceleration = accelerationString.toInt();
483
484 //Check if the acceleration value is valid
485 if (acceleration < 0 || acceleration > 10000) {
486 scpi_instrument->logError(220, "Invalid acceleration value");
487 return;
488 }
489 //Set the acceleration value
490 flash_memory.preferences.putInt("ACCELERATION", acceleration);
491}
492
493void GetAcceleration(SCPI_C commands, SCPI_P parameters, Stream &interface) {
494 //Retrieve the acceleration value from flash memory
495 int acceleration = flash_memory.preferences.getInt("ACCELERATION", ACCELERATION);
496 interface.print(acceleration);
497 interface.write('\n');
498}
499
500void DebugMotorPins(SCPI_C commands, SCPI_P parameters, Stream &interface) {
501 int step_pin1 = flash_memory.preferences.getInt("MOTOR1-STEP-PIN", MOTOR1_STEP_PIN);
502 int enable_pin1 = flash_memory.preferences.getInt("MOTOR1-ENABLE-PIN", MOTOR1_ENABLE_PIN);
503 int step_pin2 = flash_memory.preferences.getInt("MOTOR2-STEP-PIN", MOTOR2_STEP_PIN);
504 int enable_pin2 = flash_memory.preferences.getInt("MOTOR2-ENABLE-PIN", MOTOR2_ENABLE_PIN);
505 interface.print("Motor 1 Step Pin: "); interface.print(step_pin1); interface.write('\n');
506 interface.print("Motor 1 Enable Pin: "); interface.print(enable_pin1); interface.write('\n');
507 interface.print("Motor 2 Step Pin: "); interface.print(step_pin2); interface.write('\n');
508 interface.print("Motor 2 Enable Pin: "); interface.print(enable_pin2); interface.write('\n');
509}
510
511void GetMotorDebug(SCPI_C commands, SCPI_P parameters, Stream &interface) {
512 MOTOR_SERIAL_PORT.flush(); // Clear any pending data
513 delay(20);
514
515 int status1 = stepper1->Debug();
516 delay(20); // Add delay between reads
517
518 int status2 = stepper2->Debug();
519
520 interface.print("Motor 1 Status: "); interface.print(status1, BIN); interface.write('\n');
521 interface.print("Motor 2 Status: "); interface.print(status2, BIN); interface.write('\n');
522}
523
524void ResetEthernet(SCPI_C commands, SCPI_P parameters, Stream &interface) {
525 int ethernet_reset_pin = flash_memory.preferences.getInt("ETHERNET-RESET-PIN", ETHERNET_RESET_PIN);
526
527 //Reset ethernet module
528 digitalWrite(ethernet_reset_pin, LOW);
529 delay(100);
530 digitalWrite(ethernet_reset_pin, HIGH);
531 delay(500);
532
533 //Re-initialize the Ethernet stack and drop any stale client sessions
534 scpi_instrument->reinitEthernet();
535
536 interface.print(ethernet_reset_pin);
537 interface.print(" Ethernet module reset");
538 interface.write('\n');
539}
540
541void GetSessionList(SCPI_C commands, SCPI_P parameters, Stream &interface) {
542 scpi_instrument->printSessionList(interface);
543}
544
545void GetSessionLog(SCPI_C commands, SCPI_P parameters, Stream &interface) {
546 scpi_instrument->printSessionLog(interface);
547}
548
549void GetSocketList(SCPI_C commands, SCPI_P parameters, Stream &interface) {
550 scpi_instrument->printSocketList(interface);
551}
552
553void GetDiagSystem(SCPI_C commands, SCPI_P parameters, Stream &interface) {
554 scpi_instrument->printSystemDiagnostics(interface);
555}
This class handles access to the flash memory of the ESP32. It is also used to initialize the flash m...
Definition flash.h:19
This class handles the SCPI communication with the instrument. It is responsible for parsing SCPI com...
Definition scpi.h:26
The STEPPER class is used to manage stepper motor instances. It provides methods to control the motor...
Definition stepper.h:20
Handles the flash memory for the ESP32.
This file contains the functions and classes related to SCPI communication.
void GetHelpSyntax(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends syntax help for a single command header, given as a parameter (e.g. SYSTem:HELP:SYNTax?...
void GetSocketList(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends the raw state of all W5500 hardware sockets over the given interface.
void GetSessionLog(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends the ring buffer of recent SCPI session closures (with reason) over the given interface.
void GetDebug(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends the debug information from Vrekrer-SCPI-Parser over the given interface.
void Preset(SCPI_C commands, SCPI_P parameters, Stream &interface)
Rewrites the parameters stored in flash memory with the defaults from the config.h file.
void OPC(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends a 1 over the given interface to indicate that the previous command has finished executing.
void Identify(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends an identification message over the given interface.
void GetSessionList(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends the live SCPI Ethernet session table over the given interface.
void GetVersion(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends the current firmware version of the device over the given interface.
void GetDiagSystem(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends system/reset health diagnostics (uptime, heap, reset reason, boot count) over the given interfa...
void GetHelp(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends a help message with all available SCPI commands over the given interface.
void Reset(SCPI_C commands, SCPI_P parameters, Stream &interface)
Triggers a full reset of the ESP32.
void GetError(SCPI_C commands, SCPI_P parameters, Stream &interface)
Sends the oldest error message over the given interface.