2

I'm using an Arduino Leonardo to interface with two pressure sensors and Python on my laptop, a MackBook Pro.

I'm using arduino IDE V. 1.5.4, Python V. 2.7.6, and OSX 10.8.5.

One pressure sensor is digital, using the Wire lib, and the other is analog.

My sketch compiles, runs, and works until I try to get the data in Python using pyserial.

If I try to grab a bunch of data using the readlines method in the scrip it will only return blank data or hang, depending on the serial object timeout settings. My python code sometimes works from the repl when I initialize the serial object and wait before reading from it. If I don't wait the serial object will only partially fill a list and then any future reads will return an empty string. This continues even after closing the serial object and reopening it in Python, or closing the serial object in Python and then opening the Serial Monitor in the Arduino IDE. Once the serial port stops sending, I have to reset the Leonardo in order to read new data.

I could be running into some kind of buffering problem, but if that were the case I would expect future calls to return data. Another option is that the Wire protocol is getting stuck and halting the program.

Here's my sketch

#include <Wire.h>

int ADDRESS = 0x28;//I2C address of sensor
int REQUEST = 4;//# of bytes to request from sensor
int BAUD = 19200;//serial rate
int PRESSURE_PIN = 1;

void setup()
{
  pinMode(A1, INPUT);
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(BAUD);  // start serial for output
}

void loop()
{
  Wire.requestFrom(ADDRESS, REQUEST);    // request 6 bytes from slave device #2

  Serial.print(analogRead(PRESSURE_PIN));
  Serial.print(',');

  while(Wire.available())    // slave may send less than requested
  { 
     Serial.print(((unsigned int)Wire.read() << 8) + Wire.read());
     Serial.print(',');
     Serial.println(((unsigned int)Wire.read()) << 3) + (Wire.read() >> 5);
  }

  delay(10);
}

and here is how I read it from python

import serial

serial_port = '/dev/tty.usbmodem1a1221'
ser = serial.Serial(serial_port, 19200, timeout=0)

vals = [val.split(',')[0:2] for val in ser.readlines(1001*14)]
  • Welcome to Arduino SE! First of all, try viewing output of the sketch using the Arduino IDE port. If it's not the sketch, I don't know how on-topic this question is. – Anonymous Penguin May 23 '14 at 20:33
  • As far as I can tell, the problem is arduino related, either software or hardware. I'm hoping it's just a stupid gotcha that I haven't realized – bob0the0mighty May 23 '14 at 22:20
  • did you work it out? – geometrikal May 24 '14 at 23:29
  • Yeah. There is some kind of USB communication problem I'm having with the Leonardo. I plugged in a Mega and everything works fine. I did notice that the tty and cu devices for the Leonardo would drop out of /dev when I had this issue. I don't know enough of the lower layer stuff to adequately explain why this is happening but it's not an issue with a Mega board. – bob0the0mighty May 28 '14 at 13:48
  • Writing custom clients on a Mac, you may find that you get better results using the /dev/cu.usbmodemXXX devices than the /dev/tty.usbmodemXXX ones. – Chris Stratton Jun 4 '14 at 20:16
0

The leonardo doesn't reset when the serial port is opened.

To check it isn't python, run your Arduino code, then open the terminal and run

screen /dev/tty.usbmodem1a1221 19200

NOTE: to exit the screen session type Ctrl-A Ctrl=\ (see here). If you just close the window it will stay connected and lock up the serial port until you recycle the power on the Arduino.

If the Arduino program spits out just fine to screen, then python is the problem. One thing that can happen is a python/java/whatever program can lock up the serial port driver, but recycling the Arduino power, not restarting the program, is required to reinitialise the driver. So the Arduino is not necessarily problem, as the serial port will stay locked up for ALL programs. So "I would expect future calls to return data" is actually wrong. If I stuff up the serial port code in my java interface programs the same kind of thing happens.

Other ideas:

  • Make the delay longer than 10ms.
  • Make sure hardware flow control is off in the python serial
  • Flash a LED in the Arduino loop to see if it is the main loop locked up or if that is running fine.
0

The Arduino forums talk the Arduino resetting when the serial port is opened. A solution as stated in the forums is to add a short delay. See if that works.
Source: http://forum.arduino.cc/index.php/topic,18371.0.html

  • My leonardo isn't resetting when the serial port is opened. I can close and open it several times in both python or the serial reader and it won't give data until I power cycle the leonardo. I'm beginning to lean more towards some race case in the wire library – bob0the0mighty May 23 '14 at 22:43
0

My eventual workaround for the Leonardo was to set up a call-response loop on the Leonardo. Here's the code:

#include <Wire.h>

int ADDRESS = 0x28;//I2C address of sensor
int REQUEST = 4;//# of bytes to request from sensor
int BAUD = 19200;//serial rate

void setup()
{
  pinMode(A1, INPUT);
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(BAUD);  // start serial for output
}

void loop()
{
  if (Serial.available() > 0) {
    Serial.read();
    Wire.requestFrom(ADDRESS, REQUEST);    // request 4 bytes from slave device at 0x28
    while(Wire.available())    // slave may send less than requested
    { 
       Serial.print(((unsigned int)Wire.read() << 8) + Wire.read());
       Serial.print(',');
       Serial.println(((unsigned int)Wire.read()) << 3) + (Wire.read() >> 5);
    }
  }
}

I was able to simplify a little.

There are two things to note:

  • There is no built in delay and requests made too quickly will result in either an empty response or old data from the sensor. Have to take into account in requesting program.

  • The sketch will respond a number of times equal to the number of bits sent. Use a single ASCII character for one response, 2 characters for 2 responses, etc... This is important if you use an API similiar to a write() and writeln() as the second sends extra characters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.