Making an LED blink with Serial.read()

I’m trying to send some data to a board and make an LED blink a specific number of times based on the data sent. For example, if I send “4” then the led would blink four times. My code isn’t working. Is there something obvious I’m missing?

#include <LED.h>

LED led = LED(13);  // the pin that the LED is attached to
byte num = 0;        // a variable to read incoming serial data into

void setup() {
  Serial.begin(9600);}

void loop() {
  if (Serial.available() > 0)
     byte num = Serial.read(); {
     led.blink(num);} 
    }

Well I think I found a couple of things to change, others problems may still remain :wink:

#include <LED.h>

LED led = LED(13);  // the pin that the LED is attached to
byte num = 0;       [glow]// not needed, not used, as you have defined it   
                            // again as a local variable inside loop()[/glow]
void setup() {
  Serial.begin(9600);}

void loop() {
  if (Serial.available() > 0)  [glow]{  // move to here[/glow]
     byte num = Serial.read();   [glow]// { not here[/glow]
     led.blink(num);}
    }

Did you mean:

 if (Serial.available() > 0) {
     byte num = Serial.read(); 
     led.blink(num);}
    }

?

My code isn't working.

This isn't helpful - only you know what your definition of "working" is.
You need to explain the difference between what you expect to happen and what you observe happening.
My guess, based on your sketch, is that the LED once blinking, just carries on.

Also, another potential gotcha is that having entered '4', the LED proceeds to blink 52 times.
This is because the ASCII representation of '4' is not the same as the decimal digit 4.
To convert from ASCII to decimal digits, subtract 0x30 (or better still, '0') from the ASCII value.

To convert from ASCII to decimal digits, subtract 0x30 (or better still, '0') from the ASCII value.

I would prefer to AND it with a hex F:-

num &= 0xf;

Before sending it to the blink routine.

I would prefer to AND it with a hex F:-

num &= 0xf;

Before sending it to the blink routine.

Would you care to elaborate on what that does, and why you would prefer to do that?

Would you care to elaborate on what that does,

Amongst other things, it make SPACE == '0' == '@' == ''' == 'p'

Okay, I modified my code to read:

#include <LED.h>

LED led = LED(13);   // the pin that the LED is attached to

void setup() {
  Serial.begin(9600);} 

void loop() {
  if (Serial.available() > 0){
     byte num = Serial.read();
     num &= 0xf; 
     led.blink(400, num);}
   }

It works now, but only if my Arduino board is connected to my computer directly. I want to connect this board to a computer using two XBee modules, which appear to be communicating correctly. When I use the XBee modules, the LED blinks, but it always blinks 14 times no matter the number I send. Why would the XBee modules do this?

I should clarify, when I had the board running the PhysicalPixel sample sketch, it sent the “H” and “L” correctly. Why are numbers not making it through?

Each application that puts data on the serial port may put that data on the port differently. The application may write the data to the port, or it may print the data to the port. The difference is in whether the numbers are written as-is or converted to strings.

There is a big difference, when receiving the data, between getting 69 and getting '6', '9'.

In order to answer all of your questions, we need to know how data that this code receives is getting onto the serial port, and what code is on the sending and receiving XBee carriers.

The process of sending data from the PC to an Arduino with an XBee, and from there to another XBee on an Arduino is possible, as long as care is taken to ensure that the data is written and read the same way on both ends of the serial port.

In this case I have an Xbee connected via an Explorer board to a USB port on my computer. I then use the Arduino software's Serial Monitor to send the commands. The two Xbee modules were configured (one as the coordinator to send data and one as a node to receive it). The node Xbee module is connected to an Arduino board about 2 feet away.

When I use the PhysicalPixel program, it correctly sends an "H" and an "L" from the serial monitor to the remote Xbee/Arduino board. However, when I use the code above and send any numbers, my LED blinks 14 times, every time.

Well, since you've thown away (the most significant) half the character, it is going to be difficult to tell what's being sent.

Why not blink each nybble, with a delay between the two?

I'm not sure what you mean by blink each nybble. I'm trying to send a decimal integer and the Arduino correctly receives this, but when I add the Xbee shield, it converts everything to a "14." Is it possible the Xbee shield is converting things to some other type of number?

Again, here is my code:

#include <LED.h>

LED led = LED(9);

void setup() {
  Serial.begin(9600);}

void loop() {
  if (Serial.available() > 0){
     byte num = Serial.read();
     num &= 0xf; 
     led.blink(400, num);}
   }

I'm trying to send a decimal integer and the Arduino correctly receives this

Send a decimal integer from where?

, but when I add the Xbee shield, it converts everything to a "14."

What is "it" that is doing the conversion?

Is it possible the Xbee shield is converting things to some other type of number?

Absolutely not.

Post your sender code, too.

I'm sending a number from the serial monitor connected to another Xbee Explorer to a remote Xbee module running with an Arduino board.

I'm sending a number from the serial monitor connected

So, the data is being sent as strings.

Your code is not receiving strings. It expects to receive a single digit, then does something weird to the letter that it does receive.

I reversed the two Xbee modules, turned on the serial monitor and watched what was coming into the computer when I sent it from the Arduino. It received "þ" for every character, no matter what I sent. I'll try the string issue.

Okay, I'm solving the serial read to integer issue and I've found that I need to do the following:

int val = Serial.read() - '0';

This should turn any number read into an integer. But it doesn't. When I type in "4" it blinks forever (or so it seems, it is limited, but it's over 50 times). This seems like such a simple task, but I cannot get it to work! I was a lot closer when it blinked 14 times. I've probably spent three hours on this problem today alone, trying tons of different codes to convert serial data to integers. None have worked!

int val = Serial.read() - '0';

Did you check to see if there was something to read before you read it?
It’s difficult to tell from this snippet.
“read” returns -1 if there’s nothing in the buffer, so subtracting 0x30 from that may well cause you problems.

Yes, I checked to see if there was something to read, it just isn't in a format I know how to translate to an integer.

I've also tried this code, but it just blinks forever (or so it seems):

void loop()          
{
  int numMails = 0;
  delay(2000);
  
  switch (Serial.available()) {
    /* Serial.available() is the number of bytes waiting.  Convert from 
     * ASCII val to an int.  Intentional switch-case fall through below. */
    case 3:
      numMails = Serial.read();
      numMails -= 48;
      numMails *= 10;
    case 2:
      numMails += Serial.read();
      numMails -= 48;
      numMails *= 10;
    case 1:
      numMails += Serial.read();
      numMails -= 48;
      break;
    default:
      /* If >3 chars, just clear out the incoming buffer. */
      while (Serial.available())
        Serial.read();
      return;
  }
      led.blink(400, numMails);
}
switch (Serial.available()) {
    /* Serial.available() is the number of bytes waiting.  Convert from
     * ASCII val to an int.  Intentional switch-case fall through below. */
    case 3:

Serial isn't instantaneous.
Imagine your transmitter has sent "456".
At 9600 baud it takes over 3ms to transmit this, in which time, "loop" could have executed many many times.
Imagine now that Serial has just received the "4", but the other two characters are still to be transmitted.
"Serial.available" returns 1 because there is only one character in the receive buffer, so you read it, convert it to decimal (BTW, subtracting '0' is much easier to remember than subtracting 48), but you don't give it its correct decimal weight (it should be multiplied by 100).
Next time around, you receive a "5", and again, you don't weight it correctly.
Review your logic and post all your code.

Have you tried something like below to change the character to a number?

char numMails = Serial.read();

int n;
n = atoi(numMails); 

led.blink(400, n);