Serial and execute on specific command received

Hi
I have a phone connected to an rpi which then sends commands on serial to my arduino which have a relay board that controls two blind motors, 4 push buttons(in case you dont want to use the phone) and 4 status led.

The blind motor are connected to NC for motor up and NO for motor down on the relay board and another relay cuts the power to the relay to turn the motor off.

The format I would like to use from the RPI is:
node-id;child-sensor-id;message-type;ack;sub-type;payload\n
where
My arduino node number is 2, (Never changing)
My sensor number is 0 for the relay connected to motorPinOnOff
My sensor number is 1 for the relay connected to motorPinSprit
My sensor number is 2 for the relay connected to motorPinVin

My message-type is 0 for incoming message
ack is 0
subtype= 3 for onOff relay and 5 for motors

and the payload is
0 for Motor Up.
1 for Motor Down.

0 for motor Off
1 for Motor On

So the message would look like this for enabling motors
2;0;0;0;3;1\n

and this for turning motor for wine up
2;2;0;0;5;0\n

But my question is how can I get this implemented in my code below, currently i am just sending a singel integer, and can i somehow reduce number of if sentences? And what should i set my delays to?

// constants won't change. They're used here to
// set pin numbers:
const int buttonPinSpritOpp = 9;     // the number of the pushbutton pin
const int buttonPinSpritNed = 12;     // the number of the pushbutton pin
const int buttonPinVinOpp = 10;     // the number of the pushbutton pin
const int buttonPinVinNed = 11;     // the number of the pushbutton pin

const int ledPinSpritOpp = 7;     // the number of the pushbutton pin
const int ledPinSpritNed = 6;     // the number of the pushbutton pin
const int ledPinVinOpp = 4;     // the number of the pushbutton pin
const int ledPinVinNed = 3;     // the number of the pushbutton pin

const int motorPinVin =  A2;      // the number of the motor pin
const int motorPinOnOff = A3;    // the number of pin to turn motors completly off
const int motorPinSprit =  A0;      // the number of the motor pin


int intCode =-1;

long startTime = 0;
void setup() {
  // initialize the LED pin as an output:
 
  pinMode(motorPinSprit, OUTPUT);
  pinMode(motorPinVin, OUTPUT);
  pinMode(motorPinOnOff, OUTPUT);

  // initialize the pushbutton pin as an input:
  pinMode(buttonPinSpritOpp, INPUT_PULLUP);
  pinMode(buttonPinSpritNed, INPUT_PULLUP);
  pinMode(buttonPinVinOpp, INPUT_PULLUP);
  pinMode(buttonPinVinNed, INPUT_PULLUP);
  
  

  digitalWrite(motorPinSprit,HIGH);
  digitalWrite(motorPinVin,HIGH);
  digitalWrite(motorPinOnOff, HIGH);

  Serial.begin(9600);
  Serial.println("starting now...");
  
  
}

void loop() {

  
  if ( Serial.available()) // Check to see if at least one character is available
  {
    startTime = millis();
    char ch = Serial.read();
    if( isDigit(ch) ) // is this an ascii digit between 0 and 9?
    {
       intCode = (ch - '0');      // ASCII value converted to numeric value
    }
  }

  if (millis() -startTime> 2000 ){
    intCode=-1;
}
  
  if ((digitalRead(buttonPinSpritOpp) == HIGH && digitalRead(buttonPinSpritNed) == LOW) || intCode==1) {
    
    digitalWrite(motorPinSprit,HIGH);
    digitalWrite(motorPinOnOff,LOW);
    
    digitalWrite(ledPinSpritOpp,HIGH);
    digitalWrite(ledPinSpritNed,LOW);
    
    Serial.println("Sprit opp");
  }
 
  
  else if ((digitalRead(buttonPinSpritOpp) == LOW && digitalRead(buttonPinSpritNed) == HIGH)|| intCode==2) {    
    digitalWrite(motorPinSprit,LOW);
    digitalWrite(motorPinOnOff,LOW);
    digitalWrite(ledPinSpritNed,HIGH);
    digitalWrite(ledPinSpritOpp,LOW);
    Serial.println("Sprit ned");
  }

  else{
    digitalWrite(motorPinSprit,HIGH); 
    digitalWrite(motorPinOnOff,HIGH);  
    digitalWrite(ledPinSpritOpp,LOW);
    digitalWrite(ledPinSpritNed,LOW);
  }

  if ((digitalRead(buttonPinVinOpp) == HIGH && digitalRead(buttonPinVinNed) == LOW) || intCode==3) {
    
    digitalWrite(motorPinVin,HIGH);
    digitalWrite(motorPinOnOff,LOW);
    
    digitalWrite(ledPinSpritOpp,HIGH);
    digitalWrite(ledPinSpritNed,LOW);
    
    Serial.println("Vin opp");
  }
 
  
  else if ((digitalRead(buttonPinVinOpp) == LOW && digitalRead(buttonPinVinNed) == HIGH)|| intCode==4) {
    
    digitalWrite(motorPinVin,LOW);
    digitalWrite(motorPinOnOff,LOW);
    digitalWrite(ledPinSpritNed,HIGH);
    digitalWrite(ledPinSpritOpp,LOW);
    Serial.println("Vin ned");
  }
  else if (intCode==0){
    digitalWrite(motorPinOnOff,HIGH);  
    digitalWrite(ledPinSpritOpp,LOW);
    digitalWrite(ledPinSpritNed,LOW);
    Serial.println("Shutting off");
  }
  else{
    
    digitalWrite(motorPinVin,HIGH); 
    digitalWrite(motorPinOnOff,HIGH);  
    digitalWrite(ledPinSpritOpp,LOW);
    digitalWrite(ledPinSpritNed,LOW);
  }
   delay(400);
 
}

Is there a question?

how can I get this implemented in my code below

Read the serial input into an array of chars until you reach the end of message marker then parse the array and execute the commands it contains.

This may help Serial input basics

An example of capturing serial data and extracting desired information from it.

//zoomkat 11-12-13 String capture and parsing  
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data 

String readString; //main captured String 
String angle; //data String
String fuel;
String speed1;
String altidude;

int ind1; // , locations
int ind2;
int ind3;
int ind4;
 
void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 90,low,15.6,125*
  //or 130,hi,7.2,389*

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '*') {
      //do stuff
      
      Serial.println();
      Serial.print("captured String is : "); 
      Serial.println(readString); //prints string to serial port out
      
      ind1 = readString.indexOf(',');  //finds location of first ,
      angle = readString.substring(0, ind1);   //captures first data String
      ind2 = readString.indexOf(',', ind1+1 );   //finds location of second ,
      fuel = readString.substring(ind1+1, ind2+1);   //captures second data String
      ind3 = readString.indexOf(',', ind2+1 );
      speed1 = readString.substring(ind2+1, ind3+1);
      ind4 = readString.indexOf(',', ind3+1 );
      altidude = readString.substring(ind3+1); //captures remain part of data after last ,

      Serial.print("angle = ");
      Serial.println(angle); 
      Serial.print("fuel = ");
      Serial.println(fuel);
      Serial.print("speed = ");
      Serial.println(speed1);
      Serial.print("altidude = ");
      Serial.println(altidude);
      Serial.println();
      Serial.println();
      
      readString=""; //clears variable for new input
      angle="";
      fuel="";
      speed1="";
      altidude="";
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

A more compact example of capturing serial data and extracting desired information from it, avoiding the use of the String class, using roughly half the program memory of zoomkat's example.

(compiled, but not exhaustively tested)

const int MAX_LEN = 80;
const char lineEnding = '\n'; // whatever marks the end of your input.
char inputSentence [MAX_LEN + 1];
int inputIndex;
bool newInput;

const byte MAX_TOKENS = 4;
const char* delimiters = ", "; // whatever characters delimit your input string
char* tokens [MAX_TOKENS + 1];
enum indexName {angle, fuel, speed, altitude};
#define PRINT_ITEM(x) printItem (x, #x)

void setup ()
{
  Serial.begin (115200);
}

void loop ()
{
  while (Serial.available() )
  {
    char readChar = Serial.read ();
    if (readChar == lineEnding)
    {
      newInput = true;
    }
    else
    {
      if (inputIndex < MAX_LEN)
      {
        inputSentence [inputIndex++] = readChar;
        inputSentence [inputIndex] = '\0';
      }
    }
  }

  if (newInput && strlen (inputSentence))
  {
    int tokenIndex = 0;
    Serial.println (inputSentence); // tell 'em what you've got
    tokens [tokenIndex] = strtok (inputSentence, delimiters);
    while ((tokenIndex < MAX_TOKENS - 1) && tokens [tokenIndex])
    {
      tokenIndex++;
      tokens [tokenIndex] = strtok (NULL, delimiters);
    }
   
    PRINT_ITEM (angle);
    PRINT_ITEM (fuel);
    PRINT_ITEM (speed);
    PRINT_ITEM (altitude);

    // reset things for the next lot.
    newInput = false;
    inputIndex = 0;
    inputSentence [0] = '\0';
 }
}

void printItem (int index, char* name)
{
 Serial.print (name);
 Serial.print (F(" "));
 Serial.println (tokens [index]);
}

So update guys:) I burned the 10A relay, and finally new relay from china arrived, this time 32A relay. And now it works, hardware at least.

So orginally I was aming for rpi serial to arduino, however I will change that approach because I couldn't get serial on GPIO on rpi to work with OpenHab and also that I realized that I needed Analog input for the rpi. So now I have added a second arduino connected on usb to RPI and then using software serial to send command to my arduino in the bar.

Question1:
My wire is 15meter(50 feet) long, should I use baudrate of 4800?

Question 2:
I would like to modify the code so whenever a button is pressed or int received the motor will run for 12 seconds.

  else if ((digitalRead(buttonPinVinOpp) == LOW && digitalRead(buttonPinVinNed) == HIGH)|| intCode==4) {
    
    digitalWrite(motorPinVin,HIGH);
    digitalWrite(motorPinOnVin,LOW);
    
    digitalWrite(ledPinVinNed,HIGH);
    digitalWrite(ledPinVinOpp,LOW);
    Serial.println("Vin ned");
	
	//Keep running for 12s
	delay(12000);
  }

However I need to have an emergency break, receiving 0 or buttonPinVinNed = HIGH and buttonPinSpritOpp=HIGH.

So while still executing the delay it needs to be able to listen for 0 or button commands.

Below is the full code for the bar arduino and for the one next to RPI for refereance

// constants won't change. They're used here to
// set pin numbers:
const int buttonPinSpritOpp = 9;     // the number of the pushbutton pin
const int buttonPinSpritNed = 12;     // the number of the pushbutton pin
const int buttonPinVinOpp = 10;     // the number of the pushbutton pin
const int buttonPinVinNed = 11;     // the number of the pushbutton pin

const int ledPinSpritOpp = 4;     // the number of the pushbutton pin
const int ledPinSpritNed = 8;     // the number of the pushbutton pin
const int ledPinVinOpp = 7;     // the number of the pushbutton pin
const int ledPinVinNed = 3;     // the number of the pushbutton pin

const int motorPinVin =  A3;      // the number of the motor pin
const int motorPinOnVin =A1;
const int motorPinOnSprit = A2;//
const int motorPinSprit =  A0;      // the number of the motor pin

//const int debugPin = A1;


int intCode =-1;

long startTime = 0;
void setup() {
  // initialize the LED pin as an output:
 
  pinMode(motorPinSprit, OUTPUT);
  pinMode(motorPinVin, OUTPUT);
  pinMode(motorPinOnSprit, OUTPUT);
  pinMode(motorPinOnVin, OUTPUT);
  
  //pinMode(debugPin, OUTPUT);

  // initialize the pushbutton pin as an input:
  pinMode(buttonPinSpritOpp, INPUT_PULLUP);
  pinMode(buttonPinSpritNed, INPUT_PULLUP);
  pinMode(buttonPinVinOpp, INPUT_PULLUP);
  pinMode(buttonPinVinNed, INPUT_PULLUP);
  
  

  digitalWrite(motorPinSprit,HIGH);
  digitalWrite(motorPinVin,HIGH);
  digitalWrite(motorPinOnSprit, HIGH);
  digitalWrite(motorPinOnVin, HIGH);

  //digitalWrite(debugPin, HIGH);
  
  Serial.begin(9600);
  Serial.println("starting now...");
  
  
}

void loop() {

  
  if ( Serial.available()) // Check to see if at least one character is available
  {
    startTime = millis();
    char ch = Serial.read();
    if( isDigit(ch) ) // is this an ascii digit between 0 and 9?
    {
       intCode = (ch - '0');      // ASCII value converted to numeric value
    }
  }

  if (millis() -startTime> 2000 ){
    intCode=-1;
}
  
  if ((digitalRead(buttonPinSpritOpp) == HIGH && digitalRead(buttonPinSpritNed) == LOW) || intCode==1) {
    
    digitalWrite(motorPinSprit,LOW);
    digitalWrite(motorPinOnSprit,LOW);
    
    digitalWrite(ledPinSpritOpp,HIGH);
    digitalWrite(ledPinSpritNed,LOW);
    
    Serial.println("Sprit opp");
  }
 
  
  else if ((digitalRead(buttonPinSpritOpp) == LOW && digitalRead(buttonPinSpritNed) == HIGH)|| intCode==2) {    
    digitalWrite(motorPinSprit,HIGH);
    digitalWrite(motorPinOnSprit,LOW);
    digitalWrite(ledPinSpritNed,HIGH);
    digitalWrite(ledPinSpritOpp,LOW);
    Serial.println("Sprit ned");
  }

  else{
    digitalWrite(motorPinSprit,HIGH); 
    digitalWrite(motorPinOnSprit,HIGH);  
    digitalWrite(ledPinSpritOpp,LOW);
    digitalWrite(ledPinSpritNed,LOW);
  }

  if ((digitalRead(buttonPinVinOpp) == HIGH && digitalRead(buttonPinVinNed) == LOW) || intCode==3) {
    
    
    digitalWrite(motorPinOnVin,LOW);
    digitalWrite(motorPinVin,LOW);
    
    
    digitalWrite(ledPinVinOpp,HIGH);
    digitalWrite(ledPinVinNed,LOW);
    
    Serial.println("Vin opp");
  }
 
  
  else if ((digitalRead(buttonPinVinOpp) == LOW && digitalRead(buttonPinVinNed) == HIGH)|| intCode==4) {
    
    digitalWrite(motorPinVin,HIGH);
    digitalWrite(motorPinOnVin,LOW);
    
    digitalWrite(ledPinVinNed,HIGH);
    digitalWrite(ledPinVinOpp,LOW);
    Serial.println("Vin ned");
  }
  /*
  else if (intCode==0){
    digitalWrite(motorPinOnVin,HIGH); 
    digitalWrite(motorPinOnSprit,HIGH);  
    digitalWrite(ledPinSpritOpp,LOW);
    digitalWrite(ledPinSpritNed,LOW);
    digitalWrite(ledPinVinOpp,LOW);
    digitalWrite(ledPinVinNed,LOW);
    Serial.println("Shutting off");
  }
  */
  else{
    
    digitalWrite(motorPinVin,HIGH); 
   
    digitalWrite(motorPinOnVin,HIGH);  

    digitalWrite(ledPinVinOpp,LOW);
    digitalWrite(ledPinVinNed,LOW);
  }
  
   delay(400);
  
}

Command senter Arduino

 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX
int temp;
long myTimer = 0;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
 
}

void loop() // run over and over
{
    if (Serial.available()){
      temp = Serial.read();
    }
    
    if (temp !=0 && millis()- myTimer<12000 ){
      mySerial.write(temp);
      Serial.println(temp);
    }
    else{
      myTimer=millis();
      temp = 0;
    }
    
    
 
}

So while still executing the delay it needs to be able to listen for 0 or button commands.

While executing delay(), nothing happens. So, don't use delay(). It gets REALLY old pointing people to the blink without delay example.

skatun:
So while still executing the delay it needs to be able to listen for 0 or button commands.

Don't use the delay() function. See how millis() is used to manage timing without blocking in Several Things at a Time

...R

Yupp, I know.. But I was just unsure if I should put the delay(yes, millis... but lets call it delay as the physical meaning not the function) on the command arduino or the bar arduino. I will try to update the code tonight and give feedback to you guys tomorrow.

Seems like the bootloader died on my nano, so I can not burn new bootloader or upload new code.. So Maybe next week I will get a new nano and be up running again.

skatun:
but lets call it delay as the physical meaning not the function

It will be less confusing if you use the word "interval" and leave the word "delay" to mean the function.

...R