Using ultrasonic sensor with with arduino and pySerial

Hi all,
I'm having a hard time getting the distance measurements over to python. When I run my code in the serial monitor it looks just fine. However when I run it in python it has all sorts of random new lines and \r's thrown in there. What could be causing this?

Arduino code:

int trigPin=13; //Sensor Trig pin connected to Arduino pin 13
int echoPin=11;  //Sensor Echo pin connected to Arduino pin 11
float pingTime;  //time for ping to travel from sensor to target and return
float targetDistance; //Distance to Target in inches
float speedOfSound=776.5; //Speed of sound in miles per hour when temp is 77 degrees.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}
 
void loop() {
  // put your main code here, to run repeatedly:
  
  digitalWrite(trigPin, LOW); //Set trigger pin low
  delayMicroseconds(2000); //Let signal settle
  digitalWrite(trigPin, HIGH); //Set trigPin high
  delayMicroseconds(15); //Delay in high state
  digitalWrite(trigPin, LOW); //ping has now been sent
  delayMicroseconds(10); //Delay in low state
  
  pingTime = pulseIn(echoPin, HIGH);  //pingTime is presented in microceconds
  pingTime=pingTime/1000000; //convert pingTime to seconds by dividing by 1000000 (microseconds in a second)
  pingTime=pingTime/3600; //convert pingtime to hourse by dividing by 3600 (seconds in an hour)
  targetDistance= speedOfSound * pingTime;  //This will be in miles, since speed of sound was miles per hour
  targetDistance=targetDistance/2; //Remember ping travels to target and back from target, so you must divide by 2 for actual target distance.
  targetDistance= targetDistance*63360;    //Convert miles to inches by multipling by 63360 (inches per mile)
  
  Serial.println(targetDistance);
  
  delay(100); //delay tenth of a  second to slow things down a little.
}

Python Code

import serial

usbport = '/dev/tty.usbmodem1411' #usb from arduino


arduino = serial.Serial(usbport, 9600, timeout=0)


distances = []
while (True):
    if (arduino.inWaiting()>0):
        myData = arduino.readline()
        #distances.append(myData)
        print(myData)
        #print(distances)

Hi,
Serial.println() prints ASCII text to the serial port.
The type of the variable returned by serial.readline is string.
You should decode it in you python code.

Replace myData = arduino.readline()
by

myData = arduino.readline().decode('ascii')

I don't think the problem is with the data in ascii format - I think it is because your Python code is not taking full account of what the Arduino is sending.

Have a look at this Python - Arduino demo

...R

I'm not really sure how to implement your code on that thread. Could you elaborate?

Thank you.

Rahulbhardwaj488:
I'm not really sure how to implement your code on that thread. Could you elaborate?

I will try to help if you explain what part is causing you a problem.

Have you tried to run the programs? What happened?
Have you edited the reference to the serial port to suit your PC and operating system?

...R

I'm looking at your code "comArduino2.py" and I'm not sure what parts should come over to my code to get it to format correctly? Also what I should change to work with my serial ports.

Also I am getting all the same information into python that I get over the serial port. However for some reason the formatting is just off. It has a bunch of new lines and other things thrown in randomly.

Thank you,
Rahul

Rahulbhardwaj488:
I'm looking at your code "comArduino2.py" and I'm not sure what parts should come over to my code to get it to format correctly?

Maybe you could use the whole thing?

The most effective way to help you is if you make your best attempt and if it does not work post your code with a good description of what it actually does and what it should be. Examples of the actual and expected output would be good.

...R

Okay,
Here is what I tried:

from __future__ import (absolute_import, division, print_function, unicode_literals)

def sendToArduino(sendStr):
  ser.write(sendStr)


#======================================

def recvFromArduino():
  global startMarker, endMarker
  
  ck = ""
  x = "z" # any value that is not an end- or startMarker
  byteCount = -1 # to allow for the fact that the last increment will be one too many
  
  # wait for the start character
  while  ord(x) != startMarker: 
    x = ser.read()
  
  # save data until the end marker is found
  while ord(x) != endMarker:
    if ord(x) != startMarker:
      ck = ck + x 
      byteCount += 1
    x = ser.read()
  
  return(ck)


#============================

def waitForArduino():

   # wait until the Arduino sends 'Arduino Ready' - allows time for Arduino reset
   # it also ensures that any bytes left over from a previous message are discarded
   
    global startMarker, endMarker
    
    msg = ""
    while msg.find("Arduino is ready") == -1:

      while ser.inWaiting() == 0:
        pass
        
      msg = recvFromArduino()

      #print msg
      #print

import serial

usbport = '/dev/tty.usbmodem1411' #usb from arduino
#usbport = '/dev/tty.usbmodem14141' #usb with extension cable

arduino = serial.Serial(usbport, 9600, timeout=0)


distances = []
while (True):
    if (arduino.inWaiting()>0):
        myData = arduino.readline()
        #myData = arduino.readline().decode('ascii')
        distances.append(myData)
        #print(myData)
        print(distances)

what I got was this:

['1.']
['1.', '38\r\n']
['1.', '38\r\n', '1']
['1.', '38\r\n', '1', '.38\r']
['1.', '38\r\n', '1', '.38\r', '\n']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n', '1.3']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n', '1.3', '7\r\n']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n', '1.3', '7\r\n', '1.']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n', '1.3', '7\r\n', '1.', '38\r\n']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n', '1.3', '7\r\n', '1.', '38\r\n', '1']
['1.', '38\r\n', '1', '.38\r', '\n', '1.38', '\r\n', '1.3', '7\r\n', '1.3', '7\r\n', '1.', '38\r\n', '1', '.37\r']

It is ultrasonic data so it should all be ~1.38 and it's giving that value but the formatting is just off.

Any idea what's going on?

Rahulbhardwaj488:
Okay,
Here is what I tried:
..SNIP...

Any idea what's going on?

As far as I can see the essence of your program is

distances = []
while (True):
    if (arduino.inWaiting()>0):
        myData = arduino.readline()
        #myData = arduino.readline().decode('ascii')
        distances.append(myData)
        #print(myData)
        print(distances)

That is not using any of my functions.

Have a look at the function runTest() in my demo and adapt that to deal with your requirement.

Alternatively create your own version of my function recvFromArduino() and use that. You will note that it does not use readline()

...R