Serial control/conversion

Hi all, I am using the serial port to control my arduino. I am using the serial port to control and I want to send a control like g1234. The arduino would then use the motor shield to move a motor to position 1234 which is based on a potentiometer output. I am having a hard time figuring out how to get the 1234 value as an integer. Basically I have used the following code, but I am kinda lost at this point.

char bytes[6];

int bytesToRead = 0;  // number of bytes available to read

bytesToRead = Serial.available();

  if(bytesToRead > 0)
  {
    for(int i = 0; i < bytesToRead; i++)
    {
      bytes[i] = Serial.read();
    }
    Serial.println(atoi(bytes));
    ch = bytes[0];
  }

ch is used in a switch statement. Any thoughts?

Many thanks

Any thoughts?

I think that you haven't posted all your code.

If the control strings are all in the form cnnnn, where c is a single letter, and n is a single digit, you don't need to store the input in an array at all.

int bytesToRead = 0;  // number of bytes available to read
void loop()
{
   char cmd;
   int nnnn = 0;
   
   if(bytesToRead > 0)
   {
      cmd = Serial.read();
      if(cmd >= 'a' && cmd <= 'z')
      {
         for(int i = 0; i < bytesToRead; i++)
         {
            nnnn *= 10;
            nnnn += Serial.read() - '0';
         }
      }
   }

   // Create a switch statement using cmd
   switch(cmd)
   {
       case 'g':
          // Use nnnn to do something
          break;
       // Other cases for other commands
          break; // After each case
   }
}

Completely untested but something like this:-

int val;
byte digit;

bytesToRead = Serial.available();

  if(bytesToRead > 0)
  {
   if(Serial.read() == 'g')
     {
    val = 0;
    for(int i = 0; i < bytesToRead-1; i++)
    {
      digit = Serial.read();
      if((digit >= '0') && (dig <= '9')) val = val*10 + (digit & 0xf);
    }
  }
    Serial.println(val);
  }

However, try and make sure you have send all the digits before trying to read them otherwise it could go wrong.

PaulS, I'm not sure I understand "nnnn += Serial.read() - '0';"

What does this do? Why the -'0'? I get -49 as the value for nnnn no matter what I input.

Thanks

The data being sent to the Arduino is character data, in the ASCII character set. A '0' has an ASCII value of 48.

No data available, from Serial.read(), results in a return value of -1.

-1 - 48 = -49.

Post your code, so we can see if you (or I) typed something wrong.

if(bytesToRead > 0)
   {
      cmd = Serial.read();
      if(cmd >= 'a' && cmd <= 'z')
      {
         for(int i = 0; i < bytesToRead; i++)
         {
            nnnn *= 10;
            nnnn += Serial.read() - '0';
         }
      }
   }

needs a dash more "bytesToRead = Serial.available ();"

Sure this is the chunk I've just put in:

  bytesToRead = Serial.available();

  int nnnn = 0;

  if(bytesToRead > 0)
  {
    ch = Serial.read();
    if(ch >= 'a' && ch <= 'z')
    {

      for(int i = 0; i < bytesToRead; i++)
      {
        nnnn *= 10;
        nnnn += Serial.read() - '0';
      }
      Serial.print("nnnn: ");
      Serial.println(nnnn);
      Serial.print("ch: ");
      Serial.println(ch);
    }
  }

There have been several threads lately, involving Serial.read without a delay. It works for some people, but not for others. You might try adding a small delay after each Serial.read statement (something like 10 milliseconds seems to work).

What does your output look like?

The delay() statements helped, but I also noticed that I forgot to subtract 1 in my for loop.

Thanks everyone!

A delay should not be required if just reading a single character after testing if Serial.available() is true. If it's true the complete character has already been read in and is in a buffer location ready to be read in a single instruction. If however you try and read more then a single character without checking how many characters have been received and buffered or don't do a Serial.available() check before each character is read in you might have a problem that appears to be solved by adding a delay. Delay in this case is masking the real problem most likely, in handling of the serial data stream.

Lefty

Alright, here's all my code. Have a poke at it if you desire. Please note a lot of the code is just me playing to see what happens, etc.

#include <AFMotor.h>

#define ACTUATORPOSITIONPIN 0  // pin used to get value of the actuator pot

AF_DCMotor motor(3); // create motor #3, 1KHz pwm

int newActuatorPosition = 0;  // pin that analog input from actuator is hooked to
int prevActuatorPosition = 0;  // pin that analog input from actuator is hooked to

int longLimit = 0;  // extreme limit the actuator will go to
int shortLimit = 0;  // shortest limit for actuator
int homePosition = 0;  // the position calculated to be home (middle of extremes)

char bytes[4];

void GetActuatorPosition();  // find position of actuator
void CopyActuatorPosition();  // copy newActuatorPosition to prevActuatorPosition

void GetLongLimit();  // extend atuator all the way out
void GetShortLimit();  // extend atuator all the way out

void GoTo(int ch);  // go to a certain position

char ch = 't';  // used for incoming command on serial port
int bytesToRead = 0;  // number of bytes available to read


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps

  motor.setSpeed(200);     // set the speed to 200/255
}

void loop()
{
  bytesToRead = Serial.available();
  delay(200);
  int nnnn = 0;

  if(bytesToRead > 0)
  {
    ch = Serial.read();
    delay(100);
    if(ch >= 'a' && ch <= 'z')
    {
      for(int i = 0; i < bytesToRead - 1; i++)
      {
        nnnn *= 10;
        nnnn += Serial.read() - '0';
        delay(100);
      }
      Serial.print("ch: ");
      Serial.println(ch);
      Serial.print("nnnn: ");
      Serial.println(nnnn);
    }
  }

  switch(ch)
  {
  case 'g':
    GoTo(int(nnnn));
    break;
  case 'h':
    HomeActuator();
    break;
  case 'l':
    GetLongLimit();
    break;
  case 's':
    GetShortLimit();
    break;
  case 'f':
    motor.run(FORWARD);
    break;
  case 'z':
    motor.run(RELEASE);
    Serial.println("Stopped");
    break;
  case 'r':
    motor.run(BACKWARD);
    break;
  default:
    break;
  }
  ch = 't';
}

void GoTo(int pos)
{
  GetActuatorPosition();

  if(newActuatorPosition < pos)
  {
    motor.run(FORWARD);
    while(newActuatorPosition != pos)
    {
      GetActuatorPosition();
      if(newActuatorPosition == pos)
      {
        motor.run(RELEASE);
      }
    }
  }
  else if(newActuatorPosition > pos)
  {
    motor.run(BACKWARD);
    while(newActuatorPosition != pos)
    {
      GetActuatorPosition();
      if(newActuatorPosition == pos)
      {
        motor.run(RELEASE);
      }
    }
  }
  Serial.print("Pos: ");
  Serial.println(newActuatorPosition);
}

void HomeActuator()
{
  GetLongLimit();
  GetShortLimit();
  homePosition = (longLimit - shortLimit)/2 + shortLimit;
  Serial.print("Long Limit: ");
  Serial.println(longLimit);
  Serial.print("Short Limit: ");
  Serial.println(shortLimit);
  Serial.print("Home Position: ");
  Serial.println(homePosition);
  GoTo(homePosition);
  GetActuatorPosition();
  Serial.print("Position: ");
  Serial.println(newActuatorPosition);
}

void GetLongLimit()
{
  motor.run(FORWARD);
  GetActuatorPosition();
  while(prevActuatorPosition != newActuatorPosition)
  {
    CopyActuatorPosition();
    delay(300);
    GetActuatorPosition();
  }
  motor.run(RELEASE);
  longLimit = newActuatorPosition;
  CopyActuatorPosition();
}

void GetShortLimit()
{
  motor.run(BACKWARD);
  GetActuatorPosition();
  while(prevActuatorPosition != newActuatorPosition)
  {
    CopyActuatorPosition();
    delay(300);
    GetActuatorPosition();
  }
  motor.run(RELEASE);
  shortLimit = newActuatorPosition;
  CopyActuatorPosition();
}

void GetActuatorPosition()
{
  newActuatorPosition = analogRead(ACTUATORPOSITIONPIN); 
}

void CopyActuatorPosition()
{
  prevActuatorPosition = newActuatorPosition; 
}

Thanks again!