Dimmer example not working

Hi Folks,

I'm trying to get the "Dimmer" example to work but for some reason it doesn't work as expected. When I send the first number the LED lights up but subsequent numbers sent make no change to the LED??
Any ideas what could be happening?

Here's the code:

int ledPin = 9;

void setup()
{
// begin the serial communication
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}

void loop()
{
byte val;

// check if data has been sent from the computer
if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255)
val = Serial.read();
// set the brightness of the LED
analogWrite(ledPin, val);
}
}

Cheers

Jim H

Jim, I'm assuming you're using the Arduino console to send digits? Try the following modification to see if it helps:

if (Serial.available()) {
  // read the most recent byte (which will be from 0 to 255)
  val = Serial.read();
  if (val >= '0' && val <= '9') // ignore non-digits
  {
    val = 25 * (val - '0'); // scale to 0, 25, 50, 75, etc.
    // set the brightness of the LED
    analogWrite(ledPin, val);
  }
}

If that helps and you are curious why, reply back.

Mikal

Hmmm, I'm curious. It doesn't make any sense at all to me. It works yes but I can't figure out what's going on. I tried deleting the "(val - "0")" and just replaced it with 25 * val in the mistaken idea that taking "0" away from anything would make no difference to the result. However when I did this sending 1, 2 or 3 increases the brightness but sending 4 dips back down to dim again??

What's going on?

Thanks

Jim H

Slowly something is sinking in - it appears to be something to do with the last character sent - hence the '0' to '9'.

"Strings are represented as arrays of type char and are null-terminated."

So perhaps it's a string issue to do with Serial.read()?

I'm still pretty lost though.

Does this mean that I can't smoothly dim LEDs but have to use 25 * steps up to 215 instead?

Thanks

Jim H

You're on the right track, Jim.

In C, '0' and 0 are different things. 0 is 0, and '0' is another way to write the number 48, which is the ASCII encoding for the digit '0'.

When you read a digit from the serial port, you are reading ASCII-encoded values. If you type 0 on the serial console, what comes across the wire is the number 48. To convert it to a usable number, you have to subtract 48, hence the expression (val - '0'). The assignment

val = 25 * (val - '0')

was just an test to make sure the wiring was good. You can now use any expression you want to generate values for val between 0 and 255. You don't have to use 25* steps at all. Do whatever you want.

When you removed the -'0', you were effectively saying val = 25 * 48 or 1200. 1200 is obviously not between 0 and 255; hence the unpredictable results.

Mikal

That makes sense but unfortunately I'm still not able to get a response to anything other than the last character sent: so 222 is the same intensity as 2?

Thanks

Jim H

Consider what happens when you send the string "529". A "5" arrives and your code sets the LED to medium bright. But immediately afterward, the '2' and the '9' arrive, setting the LED to dim and then bright. It happens so fast that all your eye detects is the bright/last one.

I you want the LED to visibly go to different values, try putting a 500ms delay in write after the analogWrite:

delay(500);

If you are trying to type three-digit values, then you need to add some parsing code. I need to run now, but I can help with this later.

Mikal

Sorry Mikal,

I've been tinkering with the code in every way I can think of but I'm not getting anywhere. Yes, I'd like to be able to send numbers of more than 1 character so if parsing would help then that's what I need help to do.

What I can't understand is why it doesn't work in the first place - its an "Example" file after all!

Jim H

Ah, but the example is written to communicate with the Processing sketch (also provided) that is generating binary bytes, not with a human typing ASCII characters. A computer can send any value between 0 and 255. You can only (easily) type only a small percentage of these... characters 0-9, A-Z, etc.

What will your ultimate usage model be? I can help you write a routine that lets a human type three-digit numbers if that's ultimately what you want.

Mikal

I'm trying to create an interface between Runtime Revolution (a modern relative of Hypercard) and the Arduino. I'd like to be able to send 3 digit numbers so that I can fully control PWM from RunRev.

Jim H

Jim, I use Revolution/LiveCode and am trying to connect the Arduino Uno which uses a different method to register the serial port as a modem and does not use the FTDIUSBSerial driver. Did you get this working in Revolution? What version of Arduino are you using?

Thanks
Tom

Hi Tom,

Yes I got it to work pretty well. I was using the Duemillanova. I'm a bit rusty now because I haven't used it in a while but RunRev/Livecode works brilliantly with it.