Go Down

Topic: Serial.read() help (Read 16546 times) previous topic - next topic

Jassper

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?

wiz

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

Jassper

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

wiz

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

Jassper

Never mind, it is included.

thefatmoop

#5
Jan 13, 2009, 03:25 am Last Edit: Jan 13, 2009, 03:50 am by thefatmoop Reason: 1
yeah i'm working with a similar program.... sending values to another arduino and setting pwm accordingly

Code: [Select]
#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
Code: [Select]
#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:
Code: [Select]
In function 'void loop()':
error: expected primary-expression before '[' token At global scope:
[/color]

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


Jassper

#6
Jan 13, 2009, 04:40 am Last Edit: Jan 13, 2009, 04:41 am by Jassper Reason: 1
It compiles,

The issue is this line here,
Code: [Select]

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.

thefatmoop

#7
Jan 13, 2009, 06:50 am Last Edit: Jan 13, 2009, 06:51 am by thefatmoop Reason: 1
that's good because i read it and thought "what is that???
i'll try again and see what happens

thefatmoop

could i get a pointer in the right direction?
i'm trying to send variables in one long serial message:
Code: [Select]
#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?

Code: [Select]
#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;
 }
}
}

Jassper

#9
Jan 13, 2009, 12:42 pm Last Edit: Jan 13, 2009, 12:43 pm by Jassper Reason: 1
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
Code: [Select]

#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;

 }
}*/
}


thefatmoop

#10
Jan 14, 2009, 12:45 am Last Edit: Jan 14, 2009, 12:47 am by thefatmoop Reason: 1
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
Code: [Select]
#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
Code: [Select]
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:
Code: [Select]
   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
Code: [Select]
setup

*232230*-29914*

*233230*-28914*

*232230*-29914*

*232230*-29914*


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

thefatmoop

#11
Jan 14, 2009, 03:10 am Last Edit: Jan 14, 2009, 03:11 am by thefatmoop Reason: 1
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
Code: [Select]
// 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

mikalhart

#12
Jan 14, 2009, 03:37 am Last Edit: Jan 14, 2009, 06:41 am by mikalhart Reason: 1
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

thefatmoop

thanks that does make sense and adds clarity

kg4wsv

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

-j


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy