pH mérés (pH OEM Circuit pH-SM™) IC-vel

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-etamirő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.

envelop from US

A tartalma:

pH OEM Circuit pH-SM

A BNC csatlakozóst rész csináld magad módra tervezték, így kellett egy kis forrasztgatás:

pH circuit + csatlakozó

Aztán jött az összedrótozás, én Raspberry Pi 2 Model B 1GB használok, ennek a pin kiosztása:

raspberry_pi_circuit_note_fig2a

Ami a valóságban így néz ki:

raspberry és a pH áramkör

Nem a gyári pH szenzorral használom, hanem egy Jenway által gyártottal:

pH szenzor

Az összeszereléssel megvolnánk. Itt (http://www.atlas-scientific.com/product_pages/circuits/ezo_ph.html) megtalálható a mintakód (). 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:

mintakód futtatása

Enter command: Poll, 5

Ezzel elkezdtük az adatlekérdezést 5 másodpercenként:

adatgyűjtés

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:

i2cdetect

 

Ha bármilyen kérdésed van, akkor itt, vagy a fórumban felteheted.

 

 

Share This:

 
Loading Facebook Comments ...

Leave a Comment