1

I'm a beginner in both Arduino and Python, and I have an idea but I can't get it to work. Basically, when in Arduino a button is pressed, it sends "4" through the serial port. What I want in Python is as soon as it reads a 4, it should do something. This is what I got so far:

import serial
ser = serial.Serial('/dev/tty.usbserial-A900frF6', 9600)
var = 1
while var == 1:
    if ser.inWaiting() > 0:
    ser.readline(1)
    print "hello"

But obviously this prints hello no matter what. What I would need is something like this:

import serial
ser = serial.Serial('/dev/tty.usbserial-A900frF6', 9600)
var = 1
while var == 1:
    if ser.inWaiting() > 0:
    ser.readline(1)
    if last.read == "4":
    print "hello"

But how can I define last.read?

HankSmackHood
  • 4,673
  • 7
  • 29
  • 30

2 Answers2

1

I don't know a good way of synchronising the comms with readLine since it's not a blocking call. You can use ser.read(numBytes) which is a blocking call. You will need to know how many bytes Arduino is sending though to decode the byte stream correctly. Here is a simple example that reads 8 bytes and unpacks them into 2 unsigned shorts and a long (the <HHL part) in Python

try:
  data = [struct.unpack('<HHL', handle.read(8)) for i in range(PACKETS_PER_TRANSMIT)]
except OSError:
  self.emit(SIGNAL("connectionLost()"))
  self.connected = False

Here's a reference to the struct.unpack()

The Arduino code that goes with that. It reads two analog sensor values and the micro timestamp and sends them over the serial.

unsigned int SensA, SensB;
byte out_buffer[64];
unsigned int buffer_head = 0;
unsigned int buffer_size = 64;

SensA = analogRead(SENSOR_A);
SensB = analogRead(SENSOR_B);
micr = micros();
out_buffer[buffer_head++] = (SensA & 0xFF);
out_buffer[buffer_head++] = (SensA >> 8) & 0xFF;

out_buffer[buffer_head++] = (SensB & 0xFF);
out_buffer[buffer_head++] = (SensB >> 8) & 0xFF;

out_buffer[buffer_head++] = (micr & 0xFF);
out_buffer[buffer_head++] = (micr >> 8) & 0xFF;
out_buffer[buffer_head++] = (micr >> 16) & 0xFF;
out_buffer[buffer_head++] = (micr >> 24) & 0xFF;

Serial.write(out_buffer, buffer_size);

The Arduino playground and Processing Forums are good places to look around for this sort of code as well.

UPDATE I think I might have misled you with readLine not blocking. Either way, the above code should work. I also found this other thread on SO regarding the same subject.

UPDATE You don't need to use the analog sensors, that's just what the project I did happened to be using, you are of course free to pass what ever values over the serial. So what the Arduino code is doing is it has a buffer of type byte where the output is being stored before being sent. The sensor values and micros are then written to the buffer and the buffer sent over the serial. The (SensA & 0xFF) is a bit mask operator that takes the bit pattern of the SensA value and masks it with the bit pattern of 0xFF or 255 in decimal. Essetianlly this takes the first 8 bits from the 16 bit value of SensA which is an Arduino short. the next line does the same thing but shifts the bits right by 8 positions, thus taking the last 8 bits.

You'll need to understand bit patterns, bit masking and bit shifting for this. Then the buffer is written to the serial.

The Python code in turn does reads the bits from the serial port 8 bits at a time. Have a look at the struct.unpack docs. The for comprehension is just there to allow sending more than one set of values. Because the Arduino board and the Python code are running out of sync I added that to be able to send more than one "lines" per transmit. You can just replace that with struct.unpack('<HHL',handle.read(8)). Remember that the ´handle.read()´ takes a number of bytes where as the Arduino send code is dealing with bits.

Community
  • 1
  • 1
Matti Lyra
  • 12,828
  • 8
  • 49
  • 67
  • Could you explain this is a bit more? And why would I need to use the analog sensors? Sorry, newbie here :) I saw the other thread, but it didn't really seem to solve my problem. – HankSmackHood Jan 23 '11 at 11:52
0

I think it might work with this modifications:

import serial
ser = serial.Serial('/dev/tty.usbserial-A900frF6', 9600)
var = 1
while var == 1:
    if (ser.inWaiting() > 0):
     ser.readline(1)
     print "hello"