Closed leoneo closed 7 years ago
Do you have this sensor to perform testing with if I attempt to create a Mycodo sensor module?
Yes I have all ready to test.
Can you copy the output of their I2C script?
https://github.com/AtlasScientific/Raspberry-Pi-sample-code/blob/master/i2c.py
I'm expecting the output to be something like "Command succeeded X.XX" but I need to verify exactly what it is to be able to build a sensor module.
I have the V3.0 UART version https://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Biometric/pH_Stamp_3.0.pdf
I try this code :
#!/usr/bin/python
import serial
import sys
import time
import string
from serial import SerialException
def read_line():
"""
taken from the ftdi library and modified to
use the ezo line separator "\r"
"""
lsl = len('\r')
line_buffer = []
while True:
next_char = ser.read(1)
if next_char == '':
break
line_buffer.append(next_char)
if (len(line_buffer) >= lsl and
line_buffer[-lsl:] == list('\r')):
break
return ''.join(line_buffer)
def read_lines():
"""
also taken from ftdi lib to work with modified readline function
"""
lines = []
try:
while True:
line = read_line()
if not line:
break
ser.flush_input()
lines.append(line)
return lines
except SerialException as e:
print "Error, ", e
return None
def send_cmd(cmd):
"""
Send command to the Atlas Sensor.
Before sending, add Carriage Return at the end of the command.
:param cmd:
:return:
"""
buf = cmd + "\r" # add carriage return
try:
ser.write(buf)
return True
except SerialException as e:
print "Error, ", e
return None
if __name__ == "__main__":
print "\nWelcome to the Atlas Scientific Raspberry Pi UART example.\n"
print(" Any commands entered are passed to the board via UART except:")
print(" Poll,xx.x command continuously polls the board every xx.x seconds")
print(" Pressing ctrl-c will stop the polling\n")
print(" Press enter to receive all data in buffer (for continuous mode) \n")
# to get a list of ports use the command:
# python -m serial.tools.list_ports
# in the terminal
usbport = '/dev/tty1' # change to match your pi's setup
print "Opening serial port now..."
try:
ser = serial.Serial(usbport, 38400, timeout=0)
except serial.SerialException as e:
print "Error, ", e
sys.exit(0)
while True:
input_val = raw_input("Enter command: ")
# continuous polling command automatically polls the board
if input_val.upper().startswith("POLL"):
delaytime = float(string.split(input_val, ',')[1])
send_cmd("C,0") # turn off continuous mode
#clear all previous data
time.sleep(1)
ser.flush()
# get the information of the board you're polling
print("Polling sensor every %0.2f seconds, press ctrl-c to stop polling" % delaytime)
try:
while True:
send_cmd("R")
lines = read_lines()
for i in range(len(lines)):
# print lines[i]
if lines[i][0] != '*':
print "Response: " , lines[i]
time.sleep(delaytime)
except KeyboardInterrupt: # catches the ctrl-c command, which breaks the loop above
print("Continuous polling stopped")
# if not a special keyword, pass commands straight to board
else:
if len(input_val) == 0:
lines = read_lines()
for i in range(len(lines)):
print lines[i]
else:
send_cmd(input_val)
time.sleep(1.3)
lines = read_lines()
for i in range(len(lines)):
print lines[i]
connection work but no data
Have you been able to get a reading from the sensor by any method?
I am able to turn on/off the LED by l1/l0 commands but I have an error when aptent to read the pH by r command
pi@raspberrypi:~ $ sudo python /home/pi/Downloads/test3.py Welcome to the Atlas Scientific Raspberry Pi example. connected to: /dev/ttyAMA0 Enter your commands below. Insert "exit" to leave the application.
r Traceback (most recent call last): File "/home/pi/Downloads/test3.py", line 38, in
data = ser.read() File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 460, in read raise SerialException('device reports readiness to read but returned no data (device disconnected?)') serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected?)
The code :
import serial
import time
print "Welcome to the Atlas Scientific Raspberry Pi example."
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate=38400,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
#ser.open()
ser.close()
ser.open()
ser.isOpen()
print("connected to: " + ser.portstr)
print 'Enter your commands below.\r\nInsert "exit" to leave the application.'
input=1
while True:
input = raw_input(">> ")
# Python 3 users
# input = input(">> ")
if input == 'exit':
ser.close()
exit()
else:
ser.write(input + '\r')
line = ""
data = ""
time.sleep(1.3)
data = ser.read()
# if(data == "\r"):
# print ("Received from sensor:" + line)
# line = ""
#else:
# line = line + data
# print (line)
time.sleep(1.3)
print ("> >" + str(data))
I am noobs in python
I believe the command is "R", not "r"
Have take K30.py file and modified for pH, maybe it works
# coding=utf-8
from lockfile import LockFile
import logging
import serial
import time
import RPi.GPIO as GPIO
from .base_sensor import AbstractSensor
logger = logging.getLogger("mycodo.sensors.pHAtlas")
pHAtlas_LOCK_FILE = "/var/lock/sensor-pHAtlas"
class pHAtlasSensor(AbstractSensor):
""" A sensor support class that monitors the Atlas Scientifique's pH sensor """
def __init__(self):
super(pHAtlasSensor, self).__init__()
self._pH = 0
if GPIO.RPI_INFO['P1_REVISION'] == 3:
self.serial_device = "/dev/ttyS0"
else:
self.serial_device = "/dev/ttyAMA0"
def __repr__(self):
""" Representation of object """
return "<{cls}(pH={pH})>".format(
cls=type(self).__name__,
pH="{0:.2f}".format(self._pH))
def __str__(self):
""" Return pH information """
return "pH: {pH}".format(pH="{0:.2f}".format(self._pH))
def __iter__(self): # must return an iterator
""" pHAtlas iterates through live pH readings """
return self
def next(self):
""" Get next pH reading """
if self.read(): # raised an error
raise StopIteration # required
return dict(pH=float('{0:.2f}'.format(self._pH)))
def info(self):
conditions_measured = [
("pH", "pH", "float", "0.00", self._pH, self.pH)
]
return conditions_measured
@property
def pH(self):
""" pH measurement """
if not self._pH: # update if needed
self.read()
return self._pH
def get_measurement(self):
""" Gets the Atlas's pH measurement via UART"""
ser = serial.Serial(self.serial_device,
baudrate=38400,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1) # Wait 1 second for reply
ser.flushInput()
ser.flushOutput()
time.sleep(1)
ser.write("R\r")
time.sleep(.264)
resp = ser.read(8)
if len(resp) == 0:
pH = None
else:
pH = resp
return pH
def read(self):
"""
Takes a reading from the pHAtlas and updates the self._pH value
:returns: None on success or 1 on error
"""
lock = LockFile(pHAtlas_LOCK_FILE)
try:
# Acquire lock on pHAtlas to ensure more than one read isn't
# being attempted at once.
while not lock.i_am_locking():
try:
lock.acquire(timeout=60) # wait up to 60 seconds before breaking lock
except Exception as e:
logger.error("{cls} 60 second timeout, {lock} lock broken: "
"{err}".format(cls=type(self).__name__,
lock=pHAtlas_LOCK_FILE,
err=e))
lock.break_lock()
lock.acquire()
self._pH = self.get_measurement()
lock.release()
if self._pH is None:
return 1
return # success - no errors
except Exception as e:
logger.error("{cls} raised an exception when taking a reading: "
"{err}".format(cls=type(self).__name__, err=e))
lock.release()
return 1
Hello, My code works
import time
from datetime import datetime
import serial
ser = serial.Serial(port='/dev/ttyAMA0',
baudrate=38400,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
ser.close()
ser.open()
ser.isOpen()
ser.flushInput()
time.sleep(1)
while True:
input_val = raw_input("exit for quit Enter command: ")
if input_val == 'exit':
ser.close()
exit()
else:
ser.flushOutput
ser.write(input_val+'\r')
time.sleep(0.3)
bytesToRead = ser.inWaiting()
if bytesToRead != 0:
datapH = ser.read(bytesToRead)
print ">>" + datapH
ser.flushInput()
time.sleep(1)
I have follow the UART mode RPI config at https://github.com/AtlasScientific/Raspberry-Pi-sample-code
to read pH > input_val = r or R to correct pH in function of Temperatur > input_val = TT or TT.TT (ex = 25.00) it is all we need
Can you provide a little more information:
Thanks
Yes
1 it is my code 2 at page 10 : https://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Biometric/pH_Stamp_3.0.pdf
Thanks P.S: sorry for my english
Just a heads up. I noticed that your code is mixing upper and lower case letters in your names. You may want to fix these in your variables, methods, and functions. The code looks like a JavaScript style and not python. Python uses a different style guide.
Take a look at python's style guide called PEP8.
I guess most of that is from the serial package so nvm
It does look a bit odd. That was one of the things I most recently started becoming conscious of. Now, whenever I see it in code I previously write, I change it.
Doesn't proper calibration require a 4 pH medium and and 10 pH medium?
yes you need to put the sensor on the 4, 7 and 10 pH buffer solutions to make the calibration. So we need a text box with "Please put the sensor on the 4 pH buffer solution" sleep until user valid, read the value, ask to put sensor on 10 pH buffer, sleep... , read, ask to put on 7 pH buffer, sleep, read the last value and it is good
Yes, but it's still not clear to me how calibration is conducted, code-wise.
Okay, nevermind. I see the proper procedure.
simply add 3 click box on the pH sensor page calibration 4 pH buffer ->in the code -> input_val = f and make after an input_val = e calibration 7 pH buffer ->in the code -> input_val = s and make after an input_val = e calibration 10 pH buffer ->in the code -> input_val = t and make after an input_val = e
When the user is ready (he have put the sensor in the good buffer), he click on the corresponding buffer to make the calibration
Calibration must be performed in the order: pH 7, pH 4, pH 10, therefore a step-wise calibration page sequence will need to be created, with the first page instructing the user to place the probe in a pH 7 solution and clicking the submit button. A 2 minute countdown timer will present, preventing the user from continuing until the required period has elapsed, at which time the page will refresh (and calibration command sent), and the user will be further instructed to rinse and place the probe in the next solution, etc.
yes this will be very great !
I got the UI calibration pages working yesterday. I'll work on the sensor module tonight if I have time, and give you a way to test it before it goes live in the next release.
Do you have the calibration solutions with different pHs to test?
Thank you very much, It's been a long time since I wanted to ask you to add this sensor.
Yes I have the solutions
I just committed some code that should get the sensor working in the new_sensor_atlas_ph branch. Currently this should only be used to test if measurements can be read from the sensor. There is the calibration page under [More] -> [Calibrate pH Sensor] but this currently does not perform the calibration, it merely is there to demonstrate an experimental method to conduct the calibration. Once you can verify measurements can be read from the sensor, I'll go ahead and work on the calibration portion and we can continue testing from there. Here are the steps you can take to get this branch up and running in order to test adding the new sensor:
Stop the currently-running daemon and web server
sudo service mycodo stop
sudo /etc/init.d/apache2 stop
Move the current Mycodo directory
mv ~/Mycodo ~/Mycodo-old
Clone the Mycodo repo and checkout the branch
cd ~ &&
git clone https://github.com/kizniche/Mycodo &&
cd Mycodo &&
git checkout new_sensor_atlas_ph &&
sudo /bin/bash ~/Mycodo/install/setup.sh
This will install and start Mycodo that is updated with the new sensor code. You will be able to update from this version of Mycodo if I commit new code to this branch by doing the following:
sudo /etc/init.d/apache2 stop &&
sudo service mycodo stop &&
cd ~/Mycodo &&
sudo git pull &&
sudo /bin/bash ~/Mycodo/mycodo/scripts/upgrade_commands.sh initialize &&
sudo /etc/init.d/apache2 start &&
sudo service mycodo start
When I finally release the next version of Mycodo, you can use the upgrade menu of the Mycodo web UI to upgrade as you would if you were on a normal release, without having to reinstall.
Let me know if you have any issues with the commands above, or while testing the new sensor code.
I have this error when I click on Activate : Could not activate Sensor controller with ID 4: [Errno 2] could not open port /dev/ttyS0: [Errno 2] No such file or directory: '/dev/ttyS0'
Daemon log :
ready, cont_id)
File "/var/www/mycodo/mycodo/controller_sensor.py", line 260, in __init__
self.measure_sensor = AtlaspHUARTSensor()
File "/var/www/mycodo/mycodo/sensors/atlas_ph_uart.py", line 27, in __init__
bytesize=serial.EIGHTBITS)
File "/var/www/mycodo/env/local/lib/python2.7/site-packages/serial/serialutil.py", line 182, in __init__
self.open()
File "/var/www/mycodo/env/local/lib/python2.7/site-packages/serial/serialposix.py", line 245, in open
raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
SerialException: [Errno 2] could not open port /dev/ttyS0: [Errno 2] No such file or directory: '/dev/ttyS0'
2017-04-17 09:55:25,731 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
2017-04-17 09:56:10,908 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
2017-04-17 09:56:56,113 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
2017-04-17 09:57:29,141 - mycodo - WARNING - Sensor controller with ID 4 not found
2017-04-17 09:57:41,331 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
2017-04-17 09:57:43,241 - mycodo - ERROR - Could not activate Sensor controller with ID 4: [Errno 2] could not open port /dev/ttyS0: [Errno 2] No such file or directory: '/dev/ttyS0'
Traceback (most recent call last):
File "/var/www/mycodo/mycodo/mycodo_daemon.py", line 415, in controller_activate
ready, cont_id)
File "/var/www/mycodo/mycodo/controller_sensor.py", line 260, in __init__
self.measure_sensor = AtlaspHUARTSensor()
File "/var/www/mycodo/mycodo/sensors/atlas_ph_uart.py", line 27, in __init__
bytesize=serial.EIGHTBITS)
File "/var/www/mycodo/env/local/lib/python2.7/site-packages/serial/serialutil.py", line 182, in __init__
self.open()
File "/var/www/mycodo/env/local/lib/python2.7/site-packages/serial/serialposix.py", line 245, in open
raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
SerialException: [Errno 2] could not open port /dev/ttyS0: [Errno 2] No such file or directory: '/dev/ttyS0'
2017-04-17 09:58:26,558 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
2017-04-17 09:59:11,774 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
I have the raspberry Pi 2 normally the open port is ttyAMA0 and not ttyS0 ?
Are you sure you don't have a Pi 3? The code chat determines the device indicates you do:
if GPIO.RPI_INFO['P1_REVISION'] == 3:
self.serial_device = "/dev/ttyS0"
else:
self.serial_device = "/dev/ttyAMA0"
self.ser = serial.Serial(port=self.serial_device,
baudrate=38400,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
Can you go to the [Gear Icon] -> System Information page and copy the first output line from the "gpio readall" command?
Nevermind, my mistake, 3 would indicate a Pi2.
+-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----
Yes Pi 2
What was the procedure you used to set up the UART?
Did you follow the instructions provided by Mycodo?
the UART procedure : https://github.com/AtlasScientific/Raspberry-Pi-sample-code
Okay, let me review that
I have not use the instruction UART Mycodo
In the documentation you provided, the steps outline the same steps I linked to, which opens /dev/ttyS0 as your UART device.
maybe linux permission to access ttyAMA0 is not good
I need to use sudo command in Terminal to acces and read pH with my python code.
If I run my code directly with Python 2.7 I have error permission
Mycodo has root privileges to access devices, but what I'm wondering is how you got your UART device to be /dev/ttyAMA0 when the guide you linked to sets UART up on /dev/ttyS0
I have change atlas_ph_uart.py line by
if GPIO.RPI_INFO['P1_REVISION'] == 3:
self.serial_device = "/dev/ttyAMA0"
else:
and reboot
There are now no error and the light sensor indicate reading value every 15s
but in live page pH value still 0 pH no data last 30min
I have change atlas_ph_uart.py line by
Just be aware I don't intend to change this part of the code that selects the proper UART device, as it appears you deviated from the setup instructions at some point. This needs to remain standardized, and I'm going to keep it the same instructions for setting up UART for the K30 CO2 sensor.
With that being said, I'm going to update the code to put some logging lines in to see what's going on in the sensor module itself. Once I push the commit (watch for its mention in this thread), you can use the update instructions, above, to get the new code. Then you can activate the sensor and view the daemon log to see the new debug logging line that occurs at every sensor measurement.
I found an error in the module. The next commit (in a few minutes) should get the measurements turning up in Mycodo.
Can you try to get this code working again: https://github.com/AtlasScientific/Raspberry-Pi-sample-code/blob/master/uart.py
The working code you provided appears to have extraneous commands and I would like to clean it all up by using their version of the code.
Can you provide a photo of your pH circuit board?
Hi Kyle,
the code https://github.com/AtlasScientific/Raspberry-Pi-sample-code/blob/master/uart.py works well with changing bauderate 9600 by 38400.
In mycodo i still no receive pH data.
How can I put the photos here ?
There is now a debug line that should be printing in the daemon log upon every sensor read. Please paste the output if it's there.
Images can be dragged into the text input box to attach.
2017-04-19 19:01:45,954 - mycodo.sensors.atlas_ph - INFO - RETURNED VALUE: 6.77
6.77
2017-04-19 19:01:45,955 - mycodo.sensor_4 - ERROR - Error while attempting to read sensor: Unknown format code 'f' for object of type 'str'
Traceback (most recent call last):
File "/var/www/mycodo/mycodo/controller_sensor.py", line 709, in update_measure
measurements = self.measure_sensor.next()
File "/var/www/mycodo/mycodo/sensors/atlas_ph_uart.py", line 52, in next
return dict(ph=float('{0:.2f}'.format(self._ph)))
ValueError: Unknown format code 'f' for object of type 'str'
2017-04-19 19:02:00,993 - mycodo.sensors.atlas_ph - ERROR - AtlaspHUARTSensor raised an exception when taking a reading: argument of type 'NoneType' is not iterable
2017-04-19 19:02:00,994 - mycodo.sensor_4 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
Okay, that error can be fixed by enclosing self._ph on line 52 of ~/Mycodo/mycodo/sensors/atlas_ph_uart.py with float(). You can modify it to look like return dict(ph=float('{0:.2f}'.format(float(self._ph))))
to test if it fixes that issue.
I need to regulate the pH of medium with CO2. Can you please add the pH Atlas scientifique sensor with relay function, and calibration?
Thank you very much