Serial.read() help

This eludes me so I need some direction.

I am trying to send numerical values to the Arduino, for example the number 123. The Serial.read() receives it as separate ASCII values of 49, 50, and 51.

How do I turn this back into a int value of 123?

Do a search on this site for 'atoi' , that's a to (eye) , this question has cropped up before.

Thats what I need, but where do I find the lib stdlib.h?

On a Linux system it is part of the avr-libc package but I don't know about Windows.

Never mind, it is included.

yeah i'm working with a similar program.... sending values to another arduino and setting pwm accordingly

#include <math.h>
#include "Wire.h"
#include "WiiChuck.h"
//#include "nunchuck_funcs.h"

#define MAXANGLE 90
#define MINANGLE -90


WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;

void setup() {
  //nunchuck_init();
  Serial.begin(1200);
  chuck.begin();
  chuck.update();
  chuck.calibrateJoy();
}


void loop() {
  delay(500);
  chuck.update(); 

   // Serial.print(",jx ");  
    Serial.print((int)chuck.readJoyX()*-1+100); 
   // Serial.print(",jy ");  
    Serial.println((int)chuck.readJoyY()*-1+100); 
}

this program simply reads joystick x y on wii nunchuck controller, makes it positive, and adds 100 to each (so that it's always 6 characters long)

example output: 233230

I searched the forum for atoi and found this example program

#include <stdlib.h>     // needed for [shighlight]atoi[/shighlight]
char buffer[4];
int received;
int ledPin = 9;
void setup()
{
    Serial.begin(9600);
    received = 0;
    buffer[received] = '\0';
}
void loop()
{
    if (Serial.available())
    {
        buffer[received++] = Serial.read();
        buffer[received] = '\0';
        if (received >= (sizeof(buffer)-1))
        {
            Serial.print(buffer);
int myInt = [shighlight]atoi[/shighlight](buffer);
    analogWrite(ledPin, myInt);
            received = 0;
        }
    }
}   }
}

when i did syntax check i had error:

In function 'void loop()':
error: expected primary-expression before '[' token At global scope:

i don't have the library #include <stdlib.h>? where would i find this?

It compiles,

The issue is this line here,

int myInt = [shighlight]atoi[/shighlight](buffer);

Note the [ shighlight] and the [ /shighlight] these are inserted into the code block to Highlight the word you are searching for, "atoi", Take that out and get rid of the 2 extra }} at the bottom and it should compile.

The lib should already be there.

that's good because i read it and thought "what is that???
i'll try again and see what happens

could i get a pointer in the right direction?
i'm trying to send variables in one long serial message:

#include <math.h>
#include "Wire.h"
#include "WiiChuck.h"
//#include "nunchuck_funcs.h"

#define MAXANGLE 90
#define MINANGLE -90


WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;

void setup() {
  //nunchuck_init();
  Serial.begin(57600);
  chuck.begin();
  chuck.update();
  chuck.calibrateJoy();
}


void loop() {
  delay(1000);
  chuck.update(); 


   //Serial.print((int)9); 
   // Serial.print(",jx ");  
    Serial.print((int)chuck.readJoyX()*-1+100); 
   // Serial.print(",jy ");  
    Serial.println((int)chuck.readJoyY()*-1+100); 
}

this sends for example 222232 (222 = joyX, 232=joyY)

how would i isolate the variables and be able to work with them in the program below?

#include <stdlib.h>     // needed for [shighlight]atoi[/shighlight]
char buffer[9];
int received;

void setup()
{
    Serial.begin(57600);
    received = 0;
    buffer[received] = '\0';
    Serial.print("setup");
}
void loop()
{
    if (Serial.available())
    {
        buffer[received++] = Serial.read();
        buffer[received] = '\0';
        if (received >= (sizeof(buffer)-1))
        {
      int myInt = atoi(buffer);       
Serial.println(buffer);

Serial.print("1: ");
Serial.println(myInt/10);
Serial.print("2: ");
Serial.println(myInt/100);
Serial.print("3: ");
Serial.println(myInt%10);
Serial.print("4: ");
Serial.println(myInt%100);
received = 0;
  }
 }
}

I only know enough to be dangerous, but I'll give it a go.

I assume you mean to send the data "222232" from one to the other?

Maybe something like this

#include <stdlib.h>     
char X_buffer[3];
char Y_buffer[3];
int received;
int i=0;
int X_pos=0;
int Y_pos=0;

void setup()
{
    Serial.begin(57600);
    received = 0;
    X_buffer[received] = '\0';
    Y_buffer[received] = '\0';
    Serial.print("setup");
}
void loop()
{
    if (Serial.available())
    {
      // Get x cord
        for(i=0; i<3; i++)
          {
          X_buffer[i] = Serial.read();
          }
        // Get y cord
        for(i=0; i<3; i++)
          {
          Y_buffer[i] = Serial.read();
          }
      X_pos = atoi(X_buffer);
      Y_pos = atoi(Y_buffer);
    }
/*    
Serial.println(buffer);
Serial.print("1: ");
Serial.println(myInt/10);
Serial.print("2: ");
Serial.println(myInt/100);
Serial.print("3: ");
Serial.println(myInt%10);
Serial.print("4: ");
Serial.println(myInt%100);
received = 0;

  }
 }*/
}

I've been manipulating and rewriting both programs to no avail. In the first program i used i just don't understand why the serial read is "232230", but after atoi it's some oddball negative number.

I tried using this program

#include <stdlib.h>    
char X_buffer[3];
char Y_buffer[3];
int received;
int i=0;
int X_pos=0;
int Y_pos=0;

void setup()
{
    Serial.begin(57600);
    received = 0;
    X_buffer[received] = '\0';
    Y_buffer[received] = '\0';
    Serial.println("setup");
}
void loop()
{
    if (Serial.available())
    {
      // Get x cord
        for(i=0; i<3; i++)
          {
          X_buffer[i] = Serial.read();
          }
        // Get y cord
        for(i=0; i<3; i++)
          {
          Y_buffer[i] = Serial.read();
          }
      X_pos = atoi(X_buffer);
      Y_pos = atoi(Y_buffer);



  Serial.print("x:");
  Serial.print(X_pos);
  Serial.print("y:");
  Serial.print(Y_pos);
  Serial.println();

 }
}

with output

setup

x:2y:0

x:32230y:30

x:2y:0

x:-32306y:30

x:2y:0

x:32230y:30

x:2y:0

x:32230y:30

correct output should have been "232230"

i'm sending the data by:

    Serial.print((int)chuck.readJoyX()*-1+100); //make is positive and always 3 digits long
   // Serial.print(",jy ");  
    Serial.print((int)chuck.readJoyY()*-1+100); //make is positive and always 3 digits long

i've tried taking out the (int) makes no difference. I'm sending it as integer ascii?

here's the original program output

setup

*232230*-29914*

*233230*-28914*

*232230*-29914*

*232230*-29914*

it's getting the right 232230... after atoi it's unusable

If anyone is having the same problems, or wondering if the noob will ever shutup: I found a very good example program from http://rob.faludi.com/itp/clock_decode_with_debug.pde
Here 'rob' is decoding a serial message the same way i wanted to

// this program decodes a clock string sent via XBee radio
// the end result is six integer variables that hold the current year, month, day, hour, minute and second
//
// the time string is in the following format:
// *20061003143227
// where the year is 2006, month is October, day is the 3rd, hour is 14 (2 p.m.), minute is 32 and second is 27
//
// by Rob Faludi
// http://www.faludi.com

////// DEBUG OUTPUT IS HANDY, BUT NOT NECESSARY FOR CLOCK DECODING ///////
#include <SoftwareSerial.h>
int rx=6, tx=7; // pins 6 and 7 will have a debug output
SoftwareSerial softSerial(rx, tx); // creates SoftwareSerial on pins 6 and 7
///////////////////////////////////////////////////////////////


int ledPin = 13;
int year;
byte month, day, hour, minute, second;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode (rx,INPUT);
  pinMode (tx,OUTPUT); 
  // start up the serial connection with 9600-8-n-1-true (non-inverted):
  Serial.begin(9600); // start hardware serial process
  softSerial.begin(9600); // start software serial process
  // blink the status LED
  blinkLED(ledPin, 2, 200);

  softSerial.println();  // do a linefeed on the debug port
  delay(500);
  softSerial.println("starting..."); // show startup on the debug port
  setupXBee(); 
}


void loop() {
  Serial.flush(); // clear the serial buffer before reading new data
  char timeString[15]; // create a string to hold the time value when it's read
  memset(timeString,'\0',15); // initialize that string to all NULL characters
  boolean timeStringValid = false; // declare and initialize a variable to track whether the string has all valid characters
  Serial.print("GET");
  byte inByte = '\0'; // declare and initialize a byte to read in serial data
  long startTime = millis();//makes the start time = to now
  int timeout = 1000; // timeout after one second
  while(millis() - startTime < timeout && inByte != '*') {
    inByte = Serial.read(); // read data and wait for an asterisk character
  }

  if (inByte == '*') { // if we got the correct start character (instead of a timeout)
    timeStringValid = true; // declare and initialize a variable to track whether the string has all valid characters
    long startTime = millis();//makes the start time = to now
    int timeout = 1000; // timeout after one second
    while(millis() - startTime < timeout && Serial.available() < 14) {
      ; //wait for enough data to be available (14 characters of time string), while doing nothing else
    }
    for (int i=0; i < 14; i++) {
      timeString[i] = Serial.read(); // reach each time string character into a character array
      if(timeString[i] < '0' || timeString[i] > '9') {
        timeStringValid = false;  // if any character is bad then the whole string is bad
      }
    }
    softSerial.print("Time: ");
    softSerial.println(timeString);
  }

  if (timeStringValid == true) {
    char yearString[5];  // create a string to hold the year part of the string
    memset(yearString,'\0',5); // initialize that string to all NULL characters
    strncpy( yearString, timeString, 4); // copy the first four characters of timeString into the year string
    year = atoi(yearString); // convert ASCII year string to integer and store in the year integer variable
    softSerial.print("Year: ");
    softSerial.println(year, DEC);

    char monthString[3]; // create a string to hold the month part of the string
    memset(monthString,'\0',3); // initialize that string to all NULL characters
    strncpy( monthString, timeString+4, 2); // skip four characters, then copy the next two of timeString into the month string
    month = atoi(monthString);  // convert ASCII month string to integer and store in the month integer variable
    softSerial.print("Month: ");
    softSerial.println(month, DEC);

    char dayString[3];
    memset(dayString,'\0',3);
    strncpy( dayString, timeString+6, 2);
    day = atoi(dayString);
    softSerial.print("Day: ");
    softSerial.println(day, DEC);

    char hourString[3];
    memset(hourString,'\0',3);
    strncpy( hourString, timeString+8, 2);
    hour = atoi(hourString);
    softSerial.print("Hour: ");
    softSerial.println(hour, DEC);

    char minuteString[3];
    memset(minuteString,'\0',3);
    strncpy( minuteString, timeString+10, 2);
    minute = atoi(minuteString);
    softSerial.print("Minute: ");
    softSerial.println(minute, DEC);

    char secondString[3];
    memset(secondString,'\0',3);
    strncpy( secondString, timeString+12, 2);
    second = atoi(secondString);
    softSerial.print("Second: ");
    softSerial.println(second, DEC);
  }

  softSerial.println(""); // print a blank line

  delay(1000); // wait for a moment so that output is readable
}



void setupXBee() {
  boolean success = false;
  int ctr = 0;
  while (success == false && ctr < 6) {
    // an arbitrary byte to wake up the XBee
    Serial.print("X");
    delay(1100);
    // put the XBee in command mode
    Serial.print("+++");
    delay(1100);
    Serial.flush(); // clear the serial buffer before sending and reading new data
    // set the PAN (personal area network) ID number
    Serial.print("ATIDC,");
    // set the MY (16 bit address)
    Serial.print("MY1,");
    // set the Destination High to 0x0
    Serial.print("DH0,");
    // set the Destination Low (16 bit address)
    Serial.print("DL0,");
    // exit command mode (note that we use Serial.printLN here to issue a linefeed that completes the command sequence)
    Serial.println("CN");

    if (checkFor("OK", 1000)) {
      // if an OK was received then continue 
      //     debugPrintln("setup done");
      softSerial.println("setup done");
      success = true;
    }
    else {
      //     debugPrintln("setup failed");
      softSerial.println("setup failed");
      success = false;
    }
    ctr++;
  }
}




///////////////////////////////// UTILITY FUNCTIONS //////////////////////////////////////////
// this function checks for a specific response on the serial port
// it accepts a string to look for and a timeout in milliseconds
int checkFor(char* desiredResponse, int timeout) {
  int result = 0;
  int length = 40;
  char incomingResponse[41];
  memset(incomingResponse,0,length); // initialize all incomingResponse string positions to null
  char inByte = NULL;
  long startTime = millis();//makes the start time = to now
  char* ptr_incomingResponse = incomingResponse;
  // while we haven't timed out or gotten back the string that we are looking for
  while (millis() - startTime < timeout && strstr(incomingResponse,desiredResponse) == NULL ) { //strstr compares strings
    if (Serial.available() > 0) { // if there are any bytes waiting to be read
      inByte = Serial.read();  // read one byte
      if (incomingResponse > ptr_incomingResponse-length) { // if we haven't read in 80 characters yet
        *ptr_incomingResponse = inByte;  // put the byte into the current position in the string
        ptr_incomingResponse++;  // advance to the next position in the string
      }
      else {
        //move the last char to be next to last, and so forth until we reach the end of the array.
        for (int i = 0; i < length; i++) {
          incomingResponse[i] = incomingResponse[i+1];  
        }
        incomingResponse[length-1] = inByte;  // put the byte into the current position in the string
      }
    }
  }
  softSerial.println(incomingResponse);
  if (strstr(incomingResponse,desiredResponse) != NULL ) { // if the desired string is found
    result = 1;
  }
  else { 
    result = 0; 
  }
  return result;
}



// this function blinks the an LED light as many times as requested
void blinkLED(int targetPin, int numBlinks, int blinkRate) {
  for (int i=0; i<numBlinks; i++) {
    digitalWrite(targetPin, HIGH);   // sets the LED on
    delay(blinkRate);                     // waits for a blinkRate milliseconds
    digitalWrite(targetPin, LOW);    // sets the LED off
    delay(blinkRate);
  }
}

thank you rob for the excessive commenting

thefatmoop--

The reason that atoi is returning such unexpected numbers for you is that it returns an int, which in Arduino-land is 16-bits and limited to a maximum value of 32767. If you use atol, which uses long instead, that may improve things.

Mikal

thanks that does make sense and adds clarity

Mikal, I think you meant -32768 to 32767 for an int (or 0 - 65535 for an unsigned int).

-j

Yipes! What am I thinking..?! Sorry: fixed. :smiley:

Thanks, j.

M

Hi,

I am also trying to connect two pc Arduino because I do not have outputs for connecting to the GLCD.

I need to send value from my nunchuck and temp sensor to another Arduino.
I've used the code here on the forum but what I can not handle is negative numbers.

I have negative numbers that I have to use in my other Arduino.
What I need is something like:
x = 50 or x = -50 can be positive or negative numbers
y = 50 or y = -50 can be positive or negative numbers and
temp = 25 or temp = -2

Desire is to send all this in a string such as for example
*- 50 79 25, all numbers can be a digit or more and could be negative.
or maybe something like this
*x=value y=value temp=value

Best regards (sorry my english)

I've used the code here on the forum but what I can not handle is negative numbers.

There have been more that 170, 000 posts. We could not begin to guess which of those posts contain the code you are using.

I have negative numbers that I have to use in my other Arduino.

If you have negative numbers, you must not be using an unsigned type. That is not, then, the source of your problem.

Desire is to send all this in a string such as for example
*- 50 79 25, all numbers can be a digit or more and could be negative.
or maybe something like this
*x=value y=value temp=value

Either format is almost trivially simple. Using Serial.print(), the value specified is output as a string.

May I respectfully suggest that you use a closing delimiter, too. Send something like:

<-50 79 25>

This makes it much easier to determine when all the data for a packet has been received, and allows some level of checking for completeness. For example, there are two spaces in the string, so if you read '<', a number, a space, a number, a space, a number, and '>', you could be reasonably certain that there was no data loss.

If you have trouble sending or receiving and parsing the data, post your code. We'll be happy to help you get it working.

Writing it all for you, though, is not something we really want to do.

Hi again,

Thanks for your reply

The code I'm using is from this thread that is from Rob
What I'm doing right now is that I send my data from the Serial Monitor. I am writing myself in the serial monitor window and see what happens.
I have not tried to send data from my other Arduino. First I want to be sure that it works to receive and then I'll try to send from the correct source (Arduino)

Here is the code I have used where I send 7 characters * 252525 and it works but if I send *- 5-5-5 that is three negative numbers it does not work. I will use more characters later, but must first solve the problem.

void  loop(){   // run over and over again
    
    Serial.flush(); // clear the serial buffer before reading new data
  char timeString[7]; // create a string to hold the time value when it's read
  memset(timeString,'\0',7); // initialize that string to all NULL characters
  boolean timeStringValid = false; // declare and initialize a variable to track whether the string has all valid characters
  //Serial.print("GET");
  byte inByte = '\0'; // declare and initialize a byte to read in serial data
  long startTime = millis();//makes the start time = to now
  int timeout = 1000; // timeout after one second
  while(millis() - startTime < timeout && inByte != '*') {
    inByte = Serial.read(); // read data and wait for an asterisk character
  }

  if (inByte == '*') { // if we got the correct start character (instead of a timeout)
    timeStringValid = true; // declare and initialize a variable to track whether the string has all valid characters
    long startTime = millis();//makes the start time = to now
    int timeout = 1000; // timeout after one second
    while(millis() - startTime < timeout && Serial.available() < 6) {
      ; //wait for enough data to be available (14 characters of time string), while doing nothing else
    }
    for (int i=0; i < 6; i++) {
      timeString[i] = Serial.read(); // reach each time string character into a character array
      if(timeString[i] < '0' || timeString[i] > '9') {
        timeStringValid = false;  // if any character is bad then the whole string is bad
      }
    }
Serial.print("Results: ");
    Serial.println(timeString);
  }

  if (timeStringValid == true) {
    char yearString[3];  // create a string to hold the year part of the string
    memset(yearString,'\0',3); // initialize that string to all NULL characters
    strncpy( yearString, timeString, 2); // copy the first four characters of timeString into the year string
    Serial.print("X: ");
    Serial.println(yearString);
    
    char monthString[3]; // create a string to hold the month part of the string
    memset(monthString,'\0',3); // initialize that string to all NULL characters
    strncpy( monthString, timeString+2, 2); // skip four characters, then copy the next two of timeString into the month string
    Serial.print("Y: ");
    Serial.println(monthString);

    char dayString[3];
    memset(dayString,'\0',3);
    strncpy( dayString, timeString+4, 2);
    Serial.print("Temp: ");
   Serial.println(dayString);

 
  }

  Serial.println(""); // print a blank line

  delay(100); // wait for a moment so that output is readable
}

You have this code:

      if(timeString[i] < '0' || timeString[i] > '9') {
        timeStringValid = false;  // if any character is bad then the whole string is bad

When you send a '-' as part of the string, you are declaring that the whole string is invalid.

Try this:

      if([glow]([/glow]timeString[i] < '0' || timeString[i] > '9'[glow]) && 
                  timeString[i] != '-')[/glow] {
        timeStringValid = false;  // if any character is bad then the whole string is bad