Simple control via serial port.

Hello,

I'm new to this forum and arduino at all, but got some experience in general. I successful make my home automated, can switch relays from my phone, schedule them to turn on/off on specific time, or sensor triggered ... etc. For that purpose I use some PI computers. Until some day I got a task to control led sign (make animation). It was simple task at all and I do not want to waste a PI computer for that purpose, so I look at arduino (much cheaper and simple way) and that is the way it started. Arduino is great for low level control of any kind of devices, it have analog inputs - something that most of PI computers do not have. So after I complete my led sign project I decided to find a way to use PI and Arduino together. In general what am I showing below can be used to control arduino via any PC using serial port and linux.

Here is the idea, i made a little sketch (preconfigured) that listen on serial port and when receive a proper command it do whatever had to do - write analow/digital value to pin or read it and send back the result.

(sketch in separate post, due to post limitations)

I used that code on Arduino UNO R3
command format is:

:ping;

that gonna return message "pong"
that is to check if connection is up and arduino is responding.

commands should begin with : and end with ;

take a look at the sketch to see all of them.
here is the example of turning preconfigured digital pin to high:

:dwrite.1.1;

answer must be "done" if command is accepted.

now, here is the tricky part, doing that from linux in a secure and releable way.

I'm using arduino USB cable to connect it to Orange PI running on ARMBIAN. Bad part is that on every serial initialization arduino restarts. To avoid that I created a little bash script handling it:

#!/bin/bash

echo "Initializing COM port as FD"
stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts
exec 99<>/dev/ttyACM0
sleep 1
echo "Waiting for commands writen in /cmd, result gonna be writen in /answer"
while true
do

if [ -e /cmd ]
    then
        command=`cat /cmd`
        rm /cmd
        read -u 99 -t 0.01 -r qssgpio
        status=$?
        while [ $status -eq 0 ]  ; do
        qssgpio=""
        read -u 99 -t 0.01 -r qssgpio
        status=$?
        done
        echo $command >&99
        read -t 1 -u 99 answer
        echo $answer > /answer
fi

sleep 0.1

Script must be run in a backgroud process, it monitor for existance of /cmd file, if found it send it via serial, delete it, and output answer in /answer file.

here is usage example:

root@orangepione:/#
root@orangepione:/#
root@orangepione:/# /arduinoserial >/dev/null &
[1] 19627
root@orangepione:/# echo ":ping;" > /cmd
root@orangepione:/# cat /answer
pong
root@orangepione:/# echo ":dwrite.3.1;" > /cmd
root@orangepione:/# cat /answer
done
root@orangepione:/# echo ":aread.1;" > /cmd
root@orangepione:/# cat /answer
222
root@orangepione:/#
String command="";
int gpio=-1;
int value=0;

const byte dout[17]={13,12,11,10,9,8,7,6,5,4,3,2,A0,A1,A2,A3,A5};  // specify pin numbers to be used as digital outputs
const byte doutlenght=17; // 
const byte din[0]={};             // digital inputs without pullup
const byte dinlenght=0;
const byte dinp[0]={};              // digital inputs with pullup resistor
const byte dinplenght=0;
const byte aout[0]={};              // digital inputs with pullup resistor
const byte aoutlenght=0;
const byte ain[1]={A4};             // analog inputs without pullup
const byte ainlenght=1;

char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
int clearToRead = 1; // 1 allow, 0 disallow

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++)
    {
      if(data.charAt(i)==separator || i==maxIndex)
        {
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}


void setup()
{
  for (int x = 0; x < doutlenght; x++)    //setting digital outputs
    {
    pinMode(dout[x], OUTPUT);
    digitalWrite(dout[x],LOW);       //set default state
    }
  for (int x = 0; x < aoutlenght; x++)    //setting analog outputs
    {
    pinMode(aout[x], OUTPUT);
    digitalWrite(aout[x],LOW);        //it is said no need to set pin to output, but I preder to do it, and write LOW state
    }
  for (int x = 0; x < dinlenght; x++)     //setting digital inputs
    {
    pinMode(din[x], INPUT);
    }
  for (int x = 0; x < dinplenght; x++)      //setting digital inputs with pullup
    {
    pinMode(dinp[x], INPUT_PULLUP);
    }
  for (int x = 0; x < ainlenght; x++)      //setting analog inputs
    {
    pinMode(ain[x], INPUT);
    }
  Serial.begin(9600);
  delay(200);
  Serial.println("\nPower On");
}




 //if(strcmp(inData,This)  == 0){


void loop()
{
  //while(Serial.available() > 0)
  while((Serial.available() > 0) && (clearToRead == 1)) // Don't read unless
   // there you know there is data
    {
    if(index < 19) // One less than the size of the array
      {
      inChar = Serial.read(); // Read a character
      inData[index] = inChar; // Store it
      if (inChar == 58) // end of string by separator
        {
        index = -1;
        }
      if (inChar == 59) // end of string by separator
        {
        inData[index] = '\0'; // Null terminate the string
        clearToRead=0;    // do not allow reading again
        index = 0;
        }
      else
        {
        index++; // Increment where to write next
        //Serial.println(index);
        }
      }
    else  // string is long, overflow the array
      {
      inData[index] = '\0'; 
      clearToRead=1;    // do not allow reading again, if we set that to 1 overflow string gonna be ignored
      index = 0;
      //Serial.flush();
      Serial.println("String oversized!");
      }
    }
 
  if (clearToRead == 0)
    {
      clearToRead = 1;
//      Serial.println(inData);  
      command=getValue(inData,'.',0);
      gpio=getValue(inData,'.',1).toInt();
      value=getValue(inData,'.',2).toInt();
  
    if (command == "ping")    // reply to ping to check if board is alive
      {
      Serial.println("pong");
      }
    else if ( command == "help")
      {
      Serial.println("You wish :)");
      }
    else if ( command == "config")
      {
//      Serial.println("Preconfigured pins list:");
      Serial.print("Digital outputs :");
      Serial.println(doutlenght);
      for (int x = 0; x < doutlenght; x++)
        {
        x++;
        Serial.print(x);
        x--;
        Serial.print(" - ");
        Serial.println(dout[x]);
        }
      Serial.print("Digital inputs :");
      Serial.println(dinlenght);
      for (int x = 0; x < dinlenght; x++)
        {
        x++;
        Serial.print(x);
        x--;
        Serial.print(" - ");
        Serial.println(din[x]);
        }
      Serial.print("Digital inputs with pullup :");
      Serial.println(dinplenght);
      for (int x = 0; x < dinplenght; x++)
        {
        x++;
        Serial.print(x);
        x--;
        Serial.print(" - ");
        Serial.println(dinp[x]);
        }
      Serial.print("Analog outputs :");
      Serial.println(aoutlenght);
      for (int x = 0; x < aoutlenght; x++)
        {
        x++;
        Serial.print(x);
        x--;
        Serial.print(" - ");
        Serial.println(aout[x]);
        }  
      Serial.print("Analog inputs :");
      Serial.println(ainlenght);
      for (int x = 0; x < ainlenght; x++)
        {
        x++;
        Serial.print(x);
        x--;
        Serial.print(" - ");
        Serial.println(ain[x]);
        } 
           
      }
    else if ( command == "dwrite")
      {
      if (gpio < 1)
        {
          Serial.println("number expected");
        }
      else if (gpio > doutlenght)
        {
        Serial.println("out of range");
        }
      else
        {
        gpio--;
        if (value > 0)
          {
          digitalWrite(dout[gpio], HIGH);
          }
        else
          {
          digitalWrite(dout[gpio], LOW);
          }
        Serial.println("done");
        }
      }
    else if ( command == "awrite")
      {
      if (gpio < 1)
        {
          Serial.println("number expected");
        }
      else if (gpio > doutlenght)
        {
        Serial.println("out of range");
        }
      else
        {
        gpio--;
        analogWrite(aout[gpio], value);
        Serial.println("done");
        }
      }
      else if ( command == "dread")
      {
      if (gpio < 1)
        {
          Serial.println("number expected");
        }
      else if (gpio > dinlenght)
        {
        Serial.println("out of range");
        }
      else
        {
        gpio--;
        Serial.println(digitalRead(din[gpio]));
        }
      }
      else if ( command == "dreadp")
      {
      if (gpio < 1)
        {
          Serial.println("number expected");
        }
      else if (gpio > dinplenght)
        {
        Serial.println("out of range");
        }
      else
        {
        gpio--;
        Serial.println(digitalRead(dinp[gpio]));
        }
      }
      else if ( command == "aread")
      {
      if (gpio < 1)
        {
          Serial.println("number expected");
        }
      else if (gpio > ainlenght)
        {
        Serial.println("out of range");
        }
      else
        {
        gpio--;
        Serial.println(analogRead(ain[gpio]));
        }        
      }
    else
      {
      Serial.println("Unrecognized command,\ntype \"help\" for command list");
      }
    }
 

}

Have a look at this Python - Arduino demo and at Serial Input Basics

...R

Yeah, I did not invent the hot water :), just done what I need using my ways. Decided to share with others.

nedoskiv:
Yeah, I did not invent the hot water :), just done what I need using my ways. Decided to share with others.

I thought you were looking for help in your Original Post :slight_smile:

...R