Pages: [1] 2   Go Down
Author Topic: Serial Arduino  (Read 1496 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello people...I am a newbie to arduino and I was just trying out the serial communication technique. The problem is that, the arduino accepts data as characters, not in numbers. So I couldn't send in a number like '15' to it, as it saw it as 1 followed by 5, i.e; two characters. I use Ubuntu. Arduino Deumilanove. What do I do about it i.e; how do i send two digit number?
Logged

Bristol, UK
Offline Offline
Edison Member
*
Karma: 1
Posts: 1197
Exhibitor at UK Maker Faire
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You'll have to accept characters into an array, and then stop when you get a delimiter of some sort (e.g. a return). Use 'atoi' to get the integer value of that character array:

Code:
int ival;
ival = atoi (str);
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void setup()
{
  Serial.begin(9600);
  pinMode(9,OUTPUT);
}

void loop()
{
  int i=0;
  int in;
  int input=0;
  if(Serial.available())
  {
      int j=Serial.read();
      while(j!=10)  //ASCII for Enter
      {   
      int in=j-'0';
      input+=in*pow(10,i);
      i++;
      j=Serial.read();  //Reading another character
      }
           
  }
 
  analogWrite(9,input);
  delay(3000);
  analogWrite(9,0);
 
}

This is supposed to change LED brightness according to the input I give. The LED seems to be On for as much as a millisecond(perhaps shorter?) and then switches off. Logically, doesn't this have to work?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, actually the LED doesn't switch on at all. Turns out it was the reflection from the Tx LED.   smiley-slim
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8477
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So I couldn't send in a number like '15' to it

You can send binary if you like

Serial.print (15, BYTE);

will send a single byte with a value of 15.

Apart from that your variables are local to loop() and will be initialized every time loop is called and there are other problems with the basic placement of the LED code, for example it's writing to the LED pin every time loop runs.

Try

Code:
void loop()
{
  static int input=0;
 
  if(Serial.available())
  {
      int j=Serial.read();
      if(j!=10)  //ASCII for Enter
{   
  input *= 10;
  input += j-'0';
} else {
  analogWrite(9,input);
  delay(3000);
  analogWrite(9,0);
  input = 0;
}
  }
}

______
Rob
« Last Edit: August 05, 2011, 11:41:25 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Solved! Thank you for the tipoff Anachrocomputer! Now I should type it like '015' instead if just '15' coz i need to include 3 digit ones as well. I could edit this further to include that as well, but, what the heck, it works!  smiley

Code:
void loop()
{
  int i=2,input=0;
  int j[3]={0};
 
  while(Serial.available())
  {
      j[i]=Serial.read()-'0';
      input+=j[i]*pow(10,i);
      i--;
      delay(5);
  }
 while(Serial.available()==0)
 analogWrite(9,input);
}
 
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48569
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
      input+=in*pow(10,i);
The pow() function takes two arguments, both floats, and returns a float. The float may not be exactly what you expect.

Since what you want to do is multiply input by 10 and add in, why not just do that.

If the string being received is 12846, for instance, input is initially 0.

When the 1 is received, input gets multiplied by 10 (still 0) and 1 gets added, so input is 1.
When the 2 is received, input gets multiplied by 10 (now 10) and 2 gets added, so input is 12.
When the 8 is received, input gets multiplied by 10 (now 120) and 8 gets added, so input is 128.
When the 4 is received, input gets multiplied by 10 (now 1280) and 4 gets added, so input is 1284.
When the 6 is received, input gets multiplied by 10 (now 12840) and 6 gets added, so input is 12846.

No pow() calls are needed.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Apart from that your variables are local to loop() and will be initialized every time loop is called
 

Yes, I actually want to them to be reset everytime loop is called. But, yeah I can set that right, that's not much of a problem is it?

Quote
it's writing to the LED pin every time loop runs.
I've fixed that in my new code. smiley

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Modified code according to advice given by PaulS and Greynomad! Thanks!

Code:
int input=0,i=2, j[3]={0};

void setup()
{
  Serial.begin(9600);
  pinMode(9,OUTPUT);
}

void loop()
{
  i=2;
  input=0;
  j[0]=j[1]=j[2]=0;
 
  while(Serial.available())
  {
      j[i]=Serial.read()-'0';
      input=input*10;
      input+=j[i];
      i--;
      delay(5);
  }
 
 while(Serial.available()==0)
 analogWrite(9,input);
}
 
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8477
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't need j or i if you have a delimiter (the LF), and I don't see how that works anyway but if it does it does smiley

_____
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48569
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't see how that works anyway
If a 3 digit value, 125 is sent, the values that are stored in the array will be 5, 2, and 1 (in
  • , [1], and [2]). The variable input will be set to 0, then 10*0 (0), then 0+1 (1), then 10*1 (10), then 10+2 (12), then 10*12 (120), and finally 120+5 (125).

There is, of course, no need to store the values in an array, especially backwards. Doing so limits the size of the number, as a string, that can be sent, to exactly 3 digits. The approach I defined allows for sending 1 digit, 3 digit, or 5 digit numbers (up to the limit if an int). Changing the type of input to long will allow for reading much larger number from the serial port.

There are some flaws in the code. It will happily try to process "ten" sent to the serial monitor, though the resulting value in input won't be anywhere near correct.

It also operates on the assumption that the 3 values will be received with 10 milliseconds, and takes all 10 milliseconds to read the values, even if they arrive much faster than that.

Finally, it assumes that only three values will be received. One could send 128765boo to the serial port, and that code would read all of the data, and try to process it.

Writing the same value to the PWM pin on every pass through loop doesn't hurt anything, but it isn't necessary, either. The check for serial data before writing to the PWM pin is silly, since the previous while loop did not terminate until there was no serial data available.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It will happily try to process "ten" sent to the serial monitor, though the resulting value in input won't be anywhere near correct.
Uh...i've sent 10,100 and it worked correctly.

Quote
There is, of course, no need to store the values in an array, especially backwards. Doing so limits the size of the number, as a string, that can be sent, to exactly 3 digits.
Well, they are actually stored forwards correctly. And I want my number to maximum 3 digits, in fact 255 is the max. In fact I also could have used constrain function to enforce that, but thats a bit trivial.

Quote
It also operates on the assumption that the 3 values will be received with 10 milliseconds, and takes all 10 milliseconds to read the values, even if they arrive much faster than that.
Well, any faster, or even that wouldn't make a difference to human eye, would it? I'll see if delay(1) works in any case. It should, perhaps.

Quote
One could send 128765boo to the serial port, and that code would read all of the data, and try to process it.
I'm pretty sure that a three digit array wont accept any more elements, and they'll simply be ignored, as in earlier versions of C.

Quote
Writing the same value to the PWM pin on every pass through loop doesn't hurt anything, but it isn't necessary, either. The check for serial data before writing to the PWM pin is silly, since the previous while loop did not terminate until there was no serial data available.
Yeah, thats right. I'd have to include another condition for while(), then.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8477
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm pretty sure that a three digit array wont accept any more elements, and they'll simply be ignored, as in earlier versions of C.
Only if that's how you write the code, C will happily trash the entire RAM no matter what size the array is. As it is if you get > 3 chars you start trashing memory.

But as we've said you don't need the array in the first place.

Using that delay() makes the code dependent on the bit rate of the serial line. Not good practice. If for some reason the characters come at a different rate or with some time between them you exit loop(). Then when you come back you reset i to 2 and start again, despite the fact that you may be half way through receiving your numbers.

______
Rob


Logged

Rob Gray aka the GRAYnomad www.robgray.com

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48569
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Uh...i've sent 10,100 and it worked correctly.
Might just be me, but I see a big difference between "10" and "ten".

Quote
Well, they are actually stored forwards correctly.
If you send "125", the first value received ('1') is stored in array position 2, the next value received ('2') is stored in array position 1, and the next value received ('5') is stored in array position 0. If that meets your definition of being stored "forwards" correctly, I'm happy for you.

Quote
I'm pretty sure that a three digit array wont accept any more elements, and they'll simply be ignored, as in earlier versions of C.
I don't live in the same fantasy world you inhabit, apparently.

Quote
Yeah, thats right. I'd have to include another condition for while(), then.
Why? If you are going to write to the pin on every pass through loop, why not just do that?


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Using that delay() makes the code dependent on the bit rate of the serial line. Not good practice.

I agree, but in fact it was the delay that made the whole thing work. If I sent '125' , it would otherwise output '1' , '2' , '5' one after the other so fast that you couldn't see anything but the resulting '5' output. It was too fast to receive the next character. Hence the delay.

Quote
Might just be me, but I see a big difference between "10" and "ten".
Oh. u meant 'ten'. smiley-razz

Quote
If that meets your definition of being stored "forwards" correctly, I'm happy for you.
Oh yeah, i missed that. :o

Quote
Why? If you are going to write to the pin on every pass through loop, why not just do that?
Not really. I'd want to reset the value of 'input' every time i send in a new number, which is on every pass to the loop. So i'd have to include a second loop, in this case 'while' , so as to compute 'input'.

Logged

Pages: [1] 2   Go Up
Jump to: