Control arduino with commands with multiple arguments sent over serial

Hey,

I need a bit of guidance on how to achieve my goal, if it is possible at all.

I have some WS2812B leds connected to an arduino nano using the FastLED library. The nano will be connected to a pc via usb all the time. I've written a programm with a GUI in C#, which is able to send data of different GUI elements, depending on their state, when buttons are clicked through the serial connection.
This way I want to change different things of the leds, like color, brightness and switch between pre-defined animations with commands like:

  • setRGB 255 255 255
  • setBrightness 255
  • setAnimation rainbow (doesn't need to be a name, numbers that represent each animation are also fine)

What would be the best way to interpret commands like that on the arduino side (some kind of acknowledgements would be nice for logging on the pc side, but not a must)?
The hardest part is propably switching between animations when the user wants to, because you can't loop through the animation pattern and receive serial data on the same time. It doesn't have to change in realtime, but a reaction time ~1sec would be nice.

I hope some of you can help a new arduino user like me :slight_smile: .

Probably best to develop a command format that is easy to decode, then send the command in that format. Below is some servo command code that decodes a value to send to the servo, and determines which servo is to get the command. The way the command is sent is that the value is first, followed by the servo identifier, followed by an end of packet marker. The data packet is captured, then evaluated for content.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control 
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

I agree with @zoomkat that you should design the format to be easy to decode. The simplest thing would be to use a single character for the command (e.g. C for colours, B for brightness) and it would also simplify the Arduino code if every caommand has the same number of elements - even if some are ignored.

I would suggest something like <C,255,255,255> or <B, 255,0,0>

The 3rd example in Serial Input Basics works with that system and the parse example uses COMMAs as separators.

...R

Thank yo both, that will already help quite a bit.

Any idea how to stop doing one animation when the user select another one from the gui? Can receiving serial data interrupt an ongoing function?

naphil:
Any idea how to stop doing one animation when the user select another one from the gui? Can receiving serial data interrupt an ongoing function?

You need to design the "ongoing function" so that it only does a little piece at a time. That will allow for it to be interrupted. Have a look at Several Things at a Time

...R