In this series, I design a programmable lab switch based on RP2040, that can turn a set of signals or supplies on or off. Over USB. SCPI compatible.
|
Implement the SCPI command
In this post, we'll finally have a working design. Because all of the preparation work is done in the previous posts (set up FreeRTOS, UART, SCPI parser), the last step is very simple.
This is the command we'll support:
DIGItal:OUTPut# TRUE|FALSE
Where:
- DIGItal:OUTPut (or DIGI:OUTP) is the command
- # is the output you want to control.
In this version there's one output with index 0: the on-board LED. See the Homework section later - TRUE|FALSE is the value. valid options are either 1|0 or ON|OFF
example:
DIGI:OUTP0 1
The command register:
/* custom commands for the switch */ {.pattern = "DIGItal:OUTPut#", .callback = SCPI_DigitalOutput,},
#include "hardware/gpio.h" // supported pins uint pins[] = {PICO_DEFAULT_LED_PIN};
The handler of the DIGI:OUTP command:
static scpi_result_t SCPI_DigitalOutput(scpi_t * context) { scpi_bool_t param1; int32_t numbers[1]; // retrieve the output index SCPI_CommandNumbers(context, numbers, 1, 0); if (! ((numbers[0] > -1) && (numbers[0] < sizeof(pins)/sizeof(pins[0])))) { SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SUFFIX); return SCPI_RES_ERR; } /* read first parameter if present */ if (!SCPI_ParamBool(context, ¶m1, TRUE)) { return SCPI_RES_ERR; } gpio_put(pins[numbers[0]], param1 ? 1 : 0); return SCPI_RES_OK; }
This one has three sections:
- parse parameter 1: the index, 0 based. With validation if it's in the array range
note: in SCPI lingo this is actually a command number, not a parameter. This is the way to indicate what channel to operate on. - parse parameter 2: the state, ON or OFF
- Set the GPIO pin that sits on that index to the state, using the Pico GPIO API
That is it. The parser lib makes it really easy to register and implement SCPI commands.
You can test this by sending the command DIGI:OUTP0 1 or DIGI:OUTP0 0 to the USB port. The led will turn on or off.
If you typed an error, you can always find that back: SYST:ERR:COUN? shows how many errors are stacked. SYST:ERR? pops the last error of the error stack.
Homework
These are easy-to-do improvements, that you can do yourself:
- very easy: extend the array of pins. Currently it's an array of 1 element (the LED), but you can define many. All GPIOs if you want.
The input validation will automatically adapt to the array size and only stack an error if you pass an index out of array range in the command
Don't forget to initialise these pins as outputs in the main() function - very easy: write code that initialises the pins automatically: loop over all array items and set them as outputs.
- still doable: write a command that returns the state of an output
hint: {.pattern = "DIGItal:OUTPut#?", .callback = SCPI_DigitalOutputQ,},
project sources (VSCode compatible):
freertos_scpi_switch_20221019.zip
binary (uf2, you can use this for drag-and-drop programming). There's one if you are using UART (pins 0 for TX, 1 for RX - the usual setup when a picoprobe is in use) and a version that uses the Pico's USB.