Since finding a cheap alternative to PLC whilst using an industrial protocol is a popular idea the Raspberry Pi has caught many eyes on doing this. I posted once on reading a temperature sensor and serving it up on the Pi using ModbusTCP. This time I expound on it and show you how to control something. In this case it will be a PC 12v fan.
Parts:
- 1 x Raspberry pi
- 1 x Darlington Transistor
- 1 x PC Fan (with about 500ma load)
- 1 x 12v DC Power Supply
Setup:
- Installing pymodbus and dependencies:
- sudo apt-get install python-pymodbus python-twisted-conch
- Wire up your Fan, LED, or motor
- View my code from Github.
Video of what I did:
Source Code:
from pymodbus.server.async import StartTcpServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer from twisted.internet.task import LoopingCall from threading import Thread import pid import threading from time import sleep import RPi.GPIO as GPIO import os os.system('modprobe w1-gpio') os.system('modprobe w1-therm') #set up Raspberry GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(25,GPIO.OUT) pwm = GPIO.PWM(25,60) pwmDutyCycle=100 pwm.start(pwmDutyCycle) temperaturePoll = None class Temp(Thread): """ A class for getting the current temp of a DS18B20 """ def __init__(self, fileName=''): Thread.__init__(self) super(Temp, self).__init__() self._stop = threading.Event() 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 self.Run=True def run(self): while 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 not exits" 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(.5) #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 global pwmDutyCycle,temp #uncomment to debug temperature print temp.getCurrentTemp() values = [int(pwmDutyCycle),temp.getCurrentTemp()*100] context[slave_id].setValues(register,address,values) def read_context(a): context = a[0] register = 3 slave_id = 0x00 address = 0x00 value = context[slave_id].getValues(register,address)[0] global pwmDutyCycle if(value!=pwmDutyCycle): print value pwmDutyCycle=value pwm.ChangeDutyCycle(pwmDutyCycle) def main(): 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/simplyautomationized' identity.ProductName = 'pymodbus Server' identity.ModelName = 'pymodbus Server' identity.MajorMinorRevision = '1.0' time = 5 # 5 seconds delaytime = 5 # 5 seconds delay writer = LoopingCall(read_context,a=(context,)) loop = LoopingCall(updating_writer, a=(context,)) loop.start(.5) # initially delay by time writer.start(.1) StartTcpServer(context, identity=identity)#, address=("localhost", 502)) #cleanup async tasks temp.setEnabled(False) loop.stop() writer.stop() GPIO.cleanup() if __name__ == "__main__": temp = Temp() temp.start() main()