blog

Prototyyppien kehittäminen Modbusin avulla

Ohjelmoija koodaamassa Python-, JavaScript-, HTML-koodia tietokoneen näytöllä.
Alex Pohjanpelto
Alex Pohjanpelto
Published: 07. Syys 2021
Teollisuustuotanto ja -prosessit
Teollisuuden mittaukset
Life Science

Kehitätkö prototyyppejä tai etsitkö edullista tapaa mitata kosteutta ja lämpötilaa sovelluksessasi mittausten laatua vaarantamatta? Onko sinulla myös perustiedot jostakin ohjelmointikielestä, kuten Pythonista? Jos vastasit näihin kysymyksiin myöntävästi, toivon voivani näyttää sinulle, miten voit kirjata tietoja pitkiltäkin aikaväleiltä helposti itse. Tarvitset vain HMP110-mittapään, USB-huoltokaapelin (219690) sekä tietokoneen, jossa on asennettuna Python 3. Käyn läpi koodin eri osiot, mutta jos et halua selityksiä, voit hypätä suoraan alareunaan, josta voit ladata koko koodin. Haluaisin myös painottaa, että tämä on vain esimerkkikomentosarja, joka esittelee Modbus-tietoliikennettä.

Kirjastot

Ennen kuin siirrymme koodiin, haluan esitellä kirjastot, joita käytämme. Tärkein niistä on pymodbus. Tarvitsemme sitä viestimiseen mittapään kanssa Modbus RTU:n kautta, sillä tuomme ModbusSerialClient-luokan pymodbus.client.sync-moduulista. Käytämme struct-kirjastoa bittien muuttamiseen eri muuttujatyypeiksi, time-kirjastoa kyselyvälin muuttamiseen ja datetime-kirjastoa lukemien kellonaikojen ja päivämäärien noutamiseen. Lisäksi tuomme argparse-moduulin voidaksemme välittää argumentteja komentoriviltä koodiin.

from pymodbus.client.sync import ModbusSerialClient as ModbusClient
import struct
import time
import datetime
import argparse

Parametrit

Olen lisännyt joitakin argumentteja, jotka lisäävät koodiin joustavuutta. Niiden avulla voimme muuttaa muuttujien arvoja helposti komentoriviltä koodia muuttamatta. Hyödyllisiä argumentteja saattavat olla esimerkiksi sarjaportti, tietojen tallennukseen käytettävän tiedoston nimi, mittapään aliosoite, kyselyväli sekä tietojen tallennusajan pituus.

parser = argparse.ArgumentParser(
    description="Modbus-dataloggeri"
)
parser.add_argument('port', help="Sarjaportti, johon mittapää liitetään")
parser.add_argument('-f', '--file', help="Sen tiedoston nimi, johon tiedot tallennetaan (oletusarvo data.csv)", default="data.csv")
parser.add_argument('-a', '--address', help="Mittapään osoite (oletusarvo 240)", default=240, type=int)
parser.add_argument('-r', "--rate", help="Kyselyväli sekunteina (oletusarvo 1)", default=1, type=float)
parser.add_argument('-l', '--length', help="Tietojen tallennusajan pituus tunteina (oletusarvo 9999999)", type=float, default=9999999)
args = parser.parse_args()
 

Modbus-liitäntä

Ensin meidän täytyy alustaa uusi Modbus-sarja-asiakas, jolla on mittapään kannalta oikeat asetukset. Tämän esimerkin parametrijoukon täytyy sisältää tietoliikennemenetelmä, sarjaportti, vastauksen aikakatkaisu, baudinopeus, pysäytysbitit sekä pariteetti. Modbus RTU:n menetelmä on rtu. Portti määräytyy tietokoneen mukaan, ja alla olevassa osiossa selitän, miten tunnistat oikean portin. Muut parametrit määräytyvät mittapään asetusten mukaan, joten sinun täytyy tarkistaa sopivat arvot mittapään datalehdestä. Vaisalan mittapäiden tyypillinen baudinopeus on 19200, pysäytysbitit 2 ja pariteetti none.

probe = ModbusClient(method='rtu', port=args.port, timeout=1, baudrate=19200, stopbits=2, parity='N')

 

Pitorekisterien lukeminen

Luodaan nyt funktio, joka lukee mittapään pitorekisterit. Rekisterien lukua varten kutsumme edellisessä osiossa luomamme Modbus-asiakasinstanssin metodin read_holding_registers(). Meidän täytyy määrittää pitorekisterin aloitusosoite, rekisterien määrä sekä mittapään aliosoite. Vastaanotamme tiedot rekistereistä little-endian-muotoisina 16-bittisinä sanoina, jotka meidän täytyy sitten muuntaa 32-bittisiksi liukuluvuiksi. 

def holding_registers_data():
    try:        
        registers = probe.read_holding_registers(address=0,count=10, unit=args.address).registers
            except Exception as e:
        print(e)
        return False, None, None, None
    try:
        rh = data_from_register(registers, 1)
        t = data_from_register(registers, 3)  
        dp = data_from_register(registers,9)   
       
    except Exception as e:
        print(e)
        return False, None, None, None
        return True, rh, t, dp
 

Rekisterien muuntaminen 32-bittisiksi arvoiksi

Rekisterit tallennetaan 16-bittisinä kokonaislukuina, ja meidän täytyy muuntaa ne 32-bittisiksi liukuluvuiksi. Laadin funktion, joka ottaa rekisterin arvot ja rekisterin indeksin ja palauttaa sitten indeksin tietojen 32-bittisen liukulukuarvon. Teemme tämän muunnoksen käyttämällä struct-moduulia.

def data_from_register(registers, i):
    return struct.unpack('!f', bytes.fromhex('{0:04x}'.format(registers[i]) + '{0:04x}'.format(registers[i-1])))[0]

 

Tietojen tallennus

Nyt, kun voimme lukea pitorekisterit ja muuntaa niiden arvot 32-bittisiksi liukulukuarvoiksi, meidän täytyy laatia funktio, joka tallentaa arvot .csv-tiedostoon. Tein tätä tarkoitusta varten funktion nimeltä data_logger(). Se kutsuu funktion holding_registers_data() ja liittää vastaanotetut tiedot tiedostoon muodossa päivämäärä–kellonaika, suhteellinen kosteus, lämpötila, kastepiste.

def data_logger():
    probe.connect()
    successful, rh, t, dp = holding_registers_data()
    if (successful):
        dt = datetime.datetime.now()
        
        try:
            with open(args.file, "a") as f:
                line = f"{dt},{rh},{t},{dp}\n"
                print(line)
                f.write(line)   
        except Exception as e:
            print(e)
        probe.close()
        time.sleep(args.rate)
        
    else:
        probe.close()
        time.sleep(0.5)
 

 

Mittapään sarjaportin määrittäminen

Varmista ensin, että mittapää on liitetty tietokoneeseen oikein. 
 

Windows
Windows-käyttöjärjestelmässä löydät laitteen sarjaportin Laitehallinta-kohdasta. Avaa Laitehallinta-ikkuna napsauttamalla näytön vasemmassa alakulmassa olevaa aloituspainiketta ja kirjoittamalla "Laitehallinta". Laitehallinta tulee näkyviin Paras vastaavuus ‑kohtaan ensimmäisenä vaihtoehtona. Avaa se napsauttamalla sen kuvaketta tai painamalla Enter-näppäintä. Laajenna portit napsauttamalla Portit (COM & LPT) ‑kohdan vieressä olevaa nuolta. Luettelossa pitäisi näkyä Vaisalan USB-laite, jonka vieressä näkyy sen sarjaportti, tässä tapauksessa COM6.

Image
Determining the communication port of the probe

Linux 
Linuxissa voit määrittää sarjaportin kirjoittamalla komentoriville komennon dmesg | grep tty. Sen pitäisi palauttaa muun muassa tämäntyyppinen lause: "cp210x converter now attached to ttyUSBn", missä ttyUSBn on haluamamme portti.

Koodin suorittaminen

Jotta voit suorittaa komentosarjan, kaikkien kirjastojen on oltava asennettuina. Voit tarvittaessa asentaa pymodbus-kirjaston pip-komennon 

pip3 install -U pymodbus 
avulla. Muiden kirjastojen pitäisi tulla python 3 ‑paketin mukana.
Jos haluat argumentteihin liittyviä ohjeita, siirry komentokehotteessa hakemistoon, johon Python-komentosarja on tallennettu, ja kirjoita 
    python Modbus_RTU -h 

Tämä palauttaa ohjetekstit, jotka näkyvät komentokehotteessa. Alla on näyttökuva tulosteesta.

Image
Terminal

 

 

 

 

 

Ainoa pakollinen parametri on sarjaportti. Muilla argumenteilla on oletusarvot, joita voit halutessasi muuttaa. Sarjaportin argumentti ei tarvitse tunnistetta, ja sen voi sijoittaa mihin tahansa tiedostonimen jälkeen. Muut, valinnaiset argumentit vaativat tunnisteen.
 Tässä on esimerkki tyypillisestä komennosta pitkässä ja lyhyessä muodossa:

    Python .\Modbus_RTU  --file datalog.csv --address 240 --rate 10 --length 48 COM6
    Python .\Modbus_RTU -f datalog.csv -a 240 -r 10 -l 48 COM6 
 

 

Lataa koko koodi ja katso Modbus 101 ‑webinaari.

 

Kirjoita kommentti