Raspberry Pi SCADA Part 1, Modbus Temperature Sensor.
One great thing about the Pi is that it is so cost effective in some SCADA applications. With several different languages to be able to present your data. In the many crazy off the wall things I will do in my series here I will start off with using pymodbus,the DS18b20, and a 4.7k resistor temperature probe to get building temperature. Now there are known security flaws with modbus since it is an open protocol, but with this example you can only read data from the addresses. This will be in holding the register 0x00 and will need to be scaled by 100 afterwords.
My total cost:
|
|
$25.00
| |
.05
| |
.20
| |
$10.00
| |
$3.00
| |
Total
|
$38.25
|
SETUP
get pymodbus and dependencies: sudo apt-get install python-pymodbus python-twisted-conch
from pymodbus.server.async import StartTcpServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer from twisted.internet.task import LoopingCall from threading import Thread from time import sleep import os os.system('modprobe w1-gpio') os.system('modprobe w1-therm') temperature =0 class Temp(Thread): """ A class for getting the current temp of a DS18B20 """ def __init__(self, fileName=''): Thread.__init__(self) self.tempDir = '/sys/bus/w1/devices/' list = os.listdir(self.tempDir) if(list[0][:2]=="28"): fileName=list[0] self.fileName = fileName self.currentTemp = -999 self.correctionFactor = 1; self.enabled = True def run(self): while True: if self.isEnabled(): try: f = open(self.tempDir + self.fileName + "/w1_slave", 'r') except IOError as e: print "Error: File " + self.tempDir + self.fileName + "/w1_slave" + " does$ return; lines=f.readlines() crcLine=lines[0] tempLine=lines[1] result_list = tempLine.split("=") temp = float(result_list[-1])/1000 # temp in Celcius temp = temp + self.correctionFactor # correction factor #if you want to convert to Celcius, comment this line temp = (9.0/5.0)*temp + 32 if crcLine.find("NO") > -1: temp = -999 self.currentTemp = temp #print "Current: " + str(self.currentTemp) + " " + str(self.fileName) sleep(1) #returns the current temp for the probe def getCurrentTemp(self): return self.currentTemp #setter to enable this probe def setEnabled(self, enabled): self.enabled = enabled #getter def isEnabled(self): return self.enabled def updating_writer(a): context = a[0] register = 3 slave_id = 0x00 address = 0x00 #print pi.getCurrentTemp(),str(int(pi.getCurrentTemp()*10)) values = [int(pi.getCurrentTemp()*100)] context[slave_id].setValues(register,address,values) store = ModbusSlaveContext( di = ModbusSequentialDataBlock(0, [0]*100), co = ModbusSequentialDataBlock(0, [0]*100), hr = ModbusSequentialDataBlock(0, [0]*100), ir = ModbusSequentialDataBlock(0, [0]*100)) context = ModbusServerContext(slaves=store, single=True) identity = ModbusDeviceIdentification() identity.VendorName = 'pymodbus' identity.ProductCode = 'PM' identity.VendorUrl = 'http://github.com/bashwork/pymodbus/' identity.ProductName = 'pymodbus Server' identity.ModelName = 'pymodbus Server' identity.MajorMinorRevision = '1.0' pi = Temp() pi.start() time = 5 # 5 seconds delaytime = 5 # 5 seconds delay loop = LoopingCall(f=updating_writer, a=(context,)) loop.start(time, now=False) # initially delay by time StartTcpServer(context, identity=identity, address=("localhost", 502)) #change localhost to your ip address.
Great I tried it and it worked!!
ReplyDeleteHow can 2 or more sensors be connected?
Thanks
Nice Blog. Thanks for sharing with us. Keep Sharing!!
ReplyDeleteDo you want to Buy LCD Photo Displays Online?
Buy LCD Photo Displays Online?