10

I am new to Arduino (and computer programming in general), so I apologize if this question looks silly.

Once I set up a basic arduino-LED connection, I have problems sending INTEGERS to arduino through the serial port. I can easily send characters such as 'm', 'o' and so on.. However if I send a number it looks like it simply does not get it.

Here is the Arduino code, ideally it should get a value from the usb port through python or the serial monitor and then adjust the brightness of the LED according to the value. (value must be in range [0,255]).

NOTE: I am using ARDUINO UNO and PYTHON 3

//--------------------------

int LED = 10;
int number;

void setup(){

pinMode(LED,OUTPUT);
Serial.begin(9600);
}

void loop(){

number = Serial.read();
Serial.print(number);
Serial.print('\n');
if(number == -1){
number = 0;
}

else if(number > 255){

number = 255;

}

else if(number < 0){

number = 0;
}

analogWrite(LED,number);
delay(1000);
}

However, when I input a value into the Serial port or through Python, for instance 0, it gives me 48 as answer (which, interestingly, is the ASCII code for 0!) and lights up the LED which is not what should happen since at 0 the LED should be off!! I am missing something but I cannot find what... Could you please tell me what is wrong?

Here is the code I use in Python:

import serial
import time
try:
    arduino = serial.Serial(port,speed)
    time.sleep(2)
    print("Connection to " + port + " established succesfully!\n")
except Exception as e:
    print(e)

#Note: for characters such as 'a' I set data = b'a' to convert the data in bytes
#However the same thing does not work with numbers...
data = 0
data = arduino.write(valueToWrite)
time.sleep(2)
arduino.close()

what am I doing wrong or misunderstanding? Thank you.

mickkk
  • 281
  • 3
  • 4
  • 9

2 Answers2

7

Parsing on the Arduino can be slow and time-consuming (which is bad if you use clock prescaling or have time-critical tasks), so let's do it in Python.

The problem is that you're sending the numbers as ASCII whereas you need to be sending them as raw binary. This is where struct comes in.

3>> import struct
3>> print(struct.pack('>B', 0))
b'\x00'
3>> print(struct.pack('>B', 255))
b'\xff'
3>> print(struct.pack('>2B', 255, 0))
b'\xff\x00'
3>> print(struct.pack('>H', 9000))
b'#('

So what you really want is:

data = arduino.write(struct.pack('>B', valueToWrite))

or something to that effect.

Ignacio Vazquez-Abrams
  • 17,733
  • 1
  • 28
  • 32
2

Serial.read() reads only ONE character from the serial port and returns its ASCII value, which explains the 48 you got.

To read a complete number, you have 2 options:

  1. Use Serial.parseInt() that reads as many characters as needed and performs the conversion before returning the read number as an int. Please further check the reference here.
  2. You read eachn character in a loop (with Serial.read()) until the last one, put each read charcater into a buffer (char array) then convert the resulting string to a number with the standard C function atoi.

Of course, the first option is the easiest one but it will return 0 if nothing is read after a 1s timeout (configurable with Serial.setTimeout()).

jfpoilpret
  • 9,162
  • 7
  • 38
  • 54