A fermentáció pH értékének nyomon követésére kerestem egy eszközt, ami kellően pontos és könnyű vele a kommunikáció. Nemrég találtam rá az Atlas Scientific nevű cégre amely sokféle különböző modult gyárt, közöttük az EZO™ pH Circuit-et, amiről ma lesz szó.
Egy kb. 1,2∗2cm-es IC-ről van szó, amely bármely BNC csatlakozóval rendelkező pH elektróddal kompatibilis. Napjainkban általánosan használunk ún. kombinált elektródot, amely egybeépítve tartalmazza a mérő és az összehasonlító elektródot is (itt az üvegelektróddal össze van építve a referenciaelektród). A galvánelem (a két elektród között fellépő) elektromotoros erejéből a pH kiszámítható, amit az áramkörünk meg is tesz és I2C buszon keresztül továbbít (10-100kHz sebességgel) az adatfeldolgozó/regisztráló rendszerünk felé (pl. egy arduino vagy raspberry modulnak). Pontossága összevethető egy laboratóriumi pH mérővel, 0,001-14,000 pH tartományban mér ± 0,02 pontossággal.
A beüzemelés
Megrendeléstől számítva 4 napon belül Koppenhágában volt, de a helyi posta még egy hétig feltartotta, bár az értesítés napján kifizettem a vámot.
A tartalma:
A BNC csatlakozóst rész csináld magad módra tervezték, így kellett egy kis forrasztgatás:
Aztán jött az összedrótozás, én Raspberry Pi 2 Model B 1GB használok, ennek a pin kiosztása:
Ami a valóságban így néz ki:
Nem a gyári pH szenzorral használom, hanem egy Jenway által gyártottal:
Az összeszereléssel megvolnánk. Itt (http://www.atlas-scientific.com/product_pages/circuits/ezo_ph.html) megtalálható a mintakód (Raspberry Pi I2C Sample Code). Vagy itt:
#!/usr/bin/python import io # used to create file streams import fcntl # used to access I2C parameters like addresses import time # used for sleep delay and timestamps import string # helps parse strings class atlas_i2c: long_timeout = 1.5 # the timeout needed to query readings and calibrations short_timeout = .5 # timeout for regular commands default_bus = 1 # the default bus for I2C on the newer Raspberry Pis, certain older boards use bus 0 default_address = 99 # the default address for the pH sensor def __init__(self, address = default_address, bus = default_bus): # open two file streams, one for reading and one for writing # the specific I2C channel is selected with bus # it is usually 1, except for older revisions where its 0 # wb and rb indicate binary read and write self.file_read = io.open("/dev/i2c-"+str(bus), "rb", buffering = 0) self.file_write = io.open("/dev/i2c-"+str(bus), "wb", buffering = 0) # initializes I2C to either a user specified or default address self.set_i2c_address(address) def set_i2c_address(self, addr): # set the I2C communications to the slave specified by the address # The commands for I2C dev using the ioctl functions are specified in # the i2c-dev.h file from i2c-tools I2C_SLAVE = 0x703 fcntl.ioctl(self.file_read, I2C_SLAVE, addr) fcntl.ioctl(self.file_write, I2C_SLAVE, addr) def write(self, string): # appends the null character and sends the string over I2C string += "\00" self.file_write.write(string) def read(self, num_of_bytes = 31): # reads a specified number of bytes from I2C, then parses and displays the result res = self.file_read.read(num_of_bytes) # read from the board response = filter(lambda x: x != '\x00', res) # remove the null characters to get the response if(ord(response[0]) == 1): # if the response isnt an error char_list = map(lambda x: chr(ord(x) & ~0x80), list(response[1:])) # change MSB to 0 for all received characters except the first and get a list of characters # NOTE: having to change the MSB to 0 is a glitch in the raspberry pi, and you shouldn't have to do this! return "Command succeeded " + ''.join(char_list) # convert the char list to a string and returns it else: return "Error " + str(ord(response[0])) def query(self, string): # write a command to the board, wait the correct timeout, and read the response self.write(string) # the read and calibration commands require a longer timeout if((string.upper().startswith("R")) or (string.upper().startswith("CAL"))): time.sleep(self.long_timeout) elif((string.upper().startswith("SLEEP"))): return "sleep mode" else: time.sleep(self.short_timeout) return self.read() def close(self): self.file_read.close() self.file_write.close() def main(): device = atlas_i2c() # creates the I2C port object, specify the address or bus if necessary print(">> Atlas Scientific sample code") print(">> Any commands entered are passed to the board via I2C except:") print(">> Address,xx changes the I2C address the Raspberry Pi communicates with.") print(">> Poll,xx.x command continuously polls the board every xx.x seconds") print(" where xx.x is longer than the %0.2f second timeout." % atlas_i2c.long_timeout) print(" Pressing ctrl-c will stop the polling") # main loop while True: input = raw_input("Enter command: ") # address command lets you change which address the Raspberry Pi will poll if(input.upper().startswith("ADDRESS")): addr = int(string.split(input, ',')[1]) device.set_i2c_address(addr) print("I2C address set to " + str(addr)) # contiuous polling command automatically polls the board elif(input.upper().startswith("POLL")): delaytime = float(string.split(input, ',')[1]) # check for polling time being too short, change it to the minimum timeout if too short if(delaytime < atlas_i2c.long_timeout): print("Polling time is shorter than timeout, setting polling time to %0.2f" % atlas_i2c.long_timeout) delaytime = atlas_i2c.long_timeout # get the information of the board you're polling info = string.split(device.query("I"), ",")[1] print("Polling %s sensor every %0.2f seconds, press ctrl-c to stop polling" % (info, delaytime)) try: while True: print(device.query("R")) time.sleep(delaytime - atlas_i2c.long_timeout) 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: try: print(device.query(input)) except IOError: print("Query failed") if __name__ == '__main__': main()
Egy fontos dolog amit a kód futtatása előtt meg kell tenni, hogy az áramkört I2C módra állítjuk. Ezt kétféleképpen tehetjük meg, én a fizikai megoldást választottam. Áramtalanítjuk az áramkört, minden kábelt kihúzunk belőle. A PGND pint és TX-t pint rövidre zárjuk majd feszültség alá helyezzük az áramkört, amikor a led kéken világít megszüntetjük a rövidzárat a PGND és a TX között. Az áramkör most már I2C módban van
Az raspberry-mre RASPBIAN JESSIE-t telepítettem, ami már tartalmazta a python futtató környezetet. A letöltött kódot egyszerűen csak futtatni kellett. (ha nincs telepíteni kell a pythont)
sudo python rpi_i2c_sample_code.py
Ezt kell látnunk:
Enter command: Poll, 5
Ezzel elkezdtük az adatlekérdezést 5 másodpercenként:
Ha valami nem úgy működik, ahogy kellene, akkor érdemes installálni az I2C perifériák detektálására használható alkalmazást.
sudo apt-get install i2c-tools
Futtatás után
i2cdetect -y 1
ezt kell látnunk, vagy valami hasonlót:
Ha bármilyen kérdésed van, akkor itt, vagy a fórumban felteheted.