Reading serial data from arduino -- invalid syntax error - python

I'm trying to write a python script to read values from the arduino's serial port and write it to a file so I can log the data.
The arduino code is long and complicated, but I'm using Serial.println() to print an integer to the serial port (located at /dev/ttyACM0)
import sys
import serial
import getpass
import datetime
import instrumentDriver
"""location of the arduino"""
location = '/dev/ttyACM0'
"""Connect to the arduino"""
arduino = instrumentDriver.serialDevice(location)
"""Successfully connected!"""
filename = str(sys.argv[1])
dataFile = open(filename+'.dat','w')
"""The main loop -- data is taken here and written to file"""
while True:
try:
datum = arduino.read()
print datum
dataFile.write(datetime.datetime.now().strftime("%Y-%m-%d"))
dataFile.write('\t')
dataFile.write(datum)
dataFile.write('\n')
except:
dataFile.close()
break
The instrumentDriver.py is just a wrapper for pySerial:
class serialDevice:
def __init__(self,location):
self.device = location
self.port = serial.Serial(location,9600)
def write(self,command):
self.port.write(command)
def read(self):
return self.port.readline()
I've used this block of code years ago and it worked fine, but it seems to be failing right now and I'm not entirely sure why. I get a SyntaxError on line 45:
scottnla#computer-1 ~/Documents/sensorTest $ python readSerial.py file
File "readSerial.py", line 45
print datum
^
SyntaxError: invalid syntax
I've tried changing the print statement, but no matter what I'm printing, I get a syntax error -- I speculate that the problem may actually be with the arduino.read() line.
Any advice would be greatly appreciated!

There is still an indentation issue; rewritten as below, it should run:
import sys
import datetime
class serialDevice:
def __init__(self,location):
self.device = location
self.port = sys.stdin # changed to run on terminal
def write(self,command):
self.port.write(command)
def read(self):
return self.port.readline()
"""location of the arduino"""
location = '/dev/ttyACM0'
"""Connect to the arduino"""
arduino = serialDevice(location)
"""Successfully connected!"""
filename = str(sys.argv[1])
dataFile = open(filename+'.dat','w')
"""The main loop -- data is taken here and written to file"""
while True:
try:
"""retrieve the raw analog number from the arduino's ADC"""
datum = arduino.read()
"""write it to file, along with a timestamp"""
print datum
dataFile.write(datetime.datetime.now().strftime("%Y-%m-%d"))
dataFile.write('\t')
dataFile.write(datum)
dataFile.write('\n')
except KeyboardInterrupt:
"""this allows for the user to CTRL-C out of the loop, and closes/saves the file we're writing to."""
dataFile.close()
break

Related

Running a Python script for k seconds

I have written a Python script that reads the serial monitor in order to get sensor readings from an Arduino. I've been trying to solve the following problem: I want my script to run exactly for one minute in order to get the data and process it offline. For instance, if I execute the following script, it should be running for a minute and then stop. I have tried using the time module or the sleep function but my script keeps getting data and does not stop. I'm not sure how to break the while loop. Until now I managed to stop the execution by pressing CTRL+C, but it's necessary for the script to stop on its own. Here's my code(I'm also posting the get_readings function):
python
# -*- coding: utf-8 -*-
import chair_functions as cf
import os
if __name__ == '__main__':
file_extension = '.txt'
rec_file = 'chair_'+cf.get_date()+file_extension
raw_data = cf.create_directories()
rec_file = os.path.join(raw_data,rec_file)
cf.get_readings(rec_file)
# -*- coding: utf-8 -*-
from serial import Serial
import pandas as pd
import collections
import logging
import serial
import time
import sys
import csv
import os
def get_readings(output_file):
"""Read the data stream coming from the serial monitor
in order to get the sensor readings
Parameters
----------
output_file : str
The file name, where the data stream will be stored
"""
serial_port = "/dev/ttyACM0"
baud_rate = 9600
ser = serial.Serial(serial_port,baud_rate)
logging.basicConfig(filename=output_file,level=logging.DEBUG,format="%(asctime)s %(message)s")
flag = False
while True:
try:
serial_data = str(ser.readline().decode().strip('\r\n'))
time.sleep(0.2)
tmp = serial_data.split(' ')[0] #Getting Sensor Id
if(tmp == 'A0'):
flag = True
if (flag and tmp != 'A4'):
#print(serial_data)
logging.info(serial_data)
if(flag and tmp == 'A4'):
flag = False
#print(serial_data)
logging.info(serial_data)
except (UnicodeDecodeError, KeyboardInterrupt) as err:
print(err)
print(err.args)
sys.exit(0)
It is the time module itself that does not work. Therefore, instead of using True for the while condition, set start = timer.time(), then while time.time() - start < 60: as below:
start = time.time()
while time.time() - start < 60:
...

Python logger inserting null (^#) control characters into file

I am reading some data from gpsd and writing it using using Python's logging module. I am fairly confident that only one process writes to this file, although I read from it using tail while this logger is running. Every once in a while I am seeing some log entries that look like the image below. I am hoping that somebody can shed some light on what would cause (presumably Python) to insert null control characters into my log file.
The code I am using is:
"""
Read the GPS continuously
"""
import logging
from logging.handlers import RotatingFileHandler
import sys
import gps
LOG = '/sensor_logs/COUNT.csv'
def main():
log_formatter = logging.Formatter('%(asctime)s,%(message)s', "%Y-%m-%d %H:%M:%S")
my_handler = RotatingFileHandler(LOG, mode='a', maxBytes=1024*1024,
backupCount=1, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)
app_log = logging.getLogger('root')
app_log.setLevel(logging.INFO)
app_log.addHandler(my_handler)
session = gps.gps("localhost", "2947")
session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
while True:
try:
report = session.next()
if hasattr(report, 'gdop'):
satcount = 0
for s in report['satellites']:
if s['used'] == True:
satcount+=1
data = "{}".format(str(satcount))
app_log.info(data)
except KeyError:
pass
except KeyboardInterrupt:
quit()
except StopIteration:
session = None
if __name__ == "__main__":
main()
This ended up being a result of failing hardware. Thank you for your help, #RobertB.

How to import variable (sensor input) & update it from one python script to another?

I'm currently setting up a some sensors with my raspberry pi in python. Total python newbie here.
Each sensor has it's own script to read the sensor and there is another script that drives an LCD display and displays the imported variable from the sensor script.
I've gotten so far with working scripts that run the sensors and generate output, however, I cannot seem to import the variables (temperature & pH) into the LCD display script. Also, once I have imported the variables, how do I instruct the LCD script to "refresh" the and fetch the updated variable?
Here's a trimmed down version of what I have so far, I've omitted the sensor and data logging parts of each script. For simplicity, script_display is the LCD driver, and pH_script is for pH and temp_script is for temperature.
Here's a simplified version of the scripts:
script_display.py
import sys
sys.path.insert(0, '/home/pi/Raspberry-Pi-sample-code')
import pH_script
import temp_script
from ph_script import ph_main
from temp_script import get_temp
import time
while True:
print PH.ph_main(ph_output)
print get_temp(temp)
time.sleep(1)
temp_script.py
from w1thermsensor import W1ThermSensor
import time
#Get Temperature
def get_temp():
global temp
sensor = W1ThermSensor(W1ThermSensor.THERM_SENSOR_DS18B20, "031683a0a4ff")
activate_temp = sensor.get_temperature()
temp = str(activate_temp)
return temp
#Read Temp Frequency
def read():
threading.Timer(0.5, read).start()
get_temp()
time.sleep(1)
try:
while True:
read()
get_temp()
print get_temp()
except KeyboardInterrupt:
print("Program Ended By User")
pH_script.py
def ph_main():
lots and lots of code to activate the PH probe, and other variables, but the variable ph_output returns as a string, ph_output
try:
while True:
global ph_output
dev.send_cmd("R")
lines = dev.read_lines()
for i in range(len(lines)):
print lines[i]
if lines[i][0] != '*':
print lines[i]
ph_output = str(lines[i])
return ph_output
time.sleep(delaytime)
try:
while True:
ph_main()
except KeyboardInterrupt:
print("Continuous polling stopped")
so, again, first question, how to pass the global variables back to the display script? and two, how to instruct the display script to 'refresh' the variables?
the error I am currently getting is:
Traceback (most recent call last):
File "script_display.py", line 8, in <module>
print PH.ph_main(ph_output)
NameError: name 'ph_output' is not defined
looking forward to any input and thanks for your time + help!

Using Scanner to print lines from file

Im trying to read a file using a scanner then have my program print the first line of the file then looping over each other individual line throughout the file and printing them as well. This issue is I cant even get it to print a single line from the first file. And I'm not receiving an error so I cant figure out the issue
import sys
import scanner
def main():
log1 = (sys.argv[1])
log2 = (sys.argv[2])
def readRecords(s):
s = Scanner("log1")
print (log1)
main()
I will go out on a limb here and suggest something like:
import sys
import scanner
def readRecords(log):
s = scanner.Scanner(log)
print s.SomeAttribute
def main():
log1 = (sys.argv[1])
log2 = (sys.argv[2])
readRecords(log1)
readRecords(log2)
main()
Your original code has numerous problems though, least of which you are never calling your readRecords function. You are also never defining/importing Scanner, and you are doing nothing with the s variable that you are assigning to (unless merely creating a Scanner object has the desired side-effect).

How to consistently print data from serial in python

I'm trying to print the data that comes across the serial from an Arduino but I am unable to do so. My attempted code is this:
import serial
import time
s = serial.Serial('/dev/tty.usbmodemfd141',9600)
while 1:
if s.inWaiting():
val = s.readline(s.inWaiting())
print val
Yet after about 30 lines or so are spit out I get the following error message:
Traceback (most recent call last):
File "py_test.py", line 7, in <module>
val = s.readline(s.inWaiting())
File "build/bdist.macosx-10.8-intel/egg/serial/serialposix.py", line 460, in read
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected?)
I imagine I am using inWaiting incorrectly, but I do not see how to use it any other way.
Have you tried wrapping the readline in a try/except SerialException block? You could then just pass on the SerialException. It could be an issue with the serial driver reporting data in the receive buffer when there is not any, in which case your code will just keep running. Not a great fix, but it may lead you to the correct solution.
try:
s.read(s.inWaiting())
except serial.serialutil.SerialException:
pass # or maybe print s.inWaiting() to identify out how many chars the driver thinks there is
I believe you want to use function read(), not readline(). You are retrieving the number of characters in the buffer, they don't necessarily end with a new-line
Your loop becomes:
while 1:
if s.inWaiting():
val = s.read(s.inWaiting())
print val
if you want to simply print the data coming out of the serially connected device.you can
simply do it by using readline().
first open the port by using open() then you need to use the readline().
note:/dev/ttyUSB0 is a port number for linux and com0 is windows
here is the code
import serial
BAUDRATE = 115200
device_name = "ttyUSB0"
tty = device_name
s = serial.Serial("/dev/" + tty, baudrate=BAUDRATE)
s.open()
print s
try:
while True:
line = s.readline() //after this you can give the sleep time also as time.sleep(1) before that import time module.
print line
finally:
s.close()

Categories

Resources