Showing posts with label Fan. Show all posts
Showing posts with label Fan. Show all posts

Monday, July 7, 2014

Raspberry Pi SCADA Part 2, Modbus TCP PWM Controller

Raspberr Pi SCADA Part 2, Modbus PWM Controller

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:

  1. Installing pymodbus and dependencies:
    • sudo apt-get install python-pymodbus python-twisted-conch
  2. Wire up your Fan, LED, or motor


  1. 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()

Sunday, September 8, 2013

Raspberry Pi PID/PWM 12V Fan Controller

Just for fun project.


So awhile back I purchased a Raspberry Pi.  I'm trying to stray away from the expensive industrial world in my home automation projects (namely the PLC).  I had many many project ideas for this neat little computer.... homemade digital picture frame, turtle habitat controller, light switches, weather station, thermostat, and on and on.  I purchased a PI weather board (found here) which gives you temperature, humidity, barometer , 4 high power dc outputs, and a couple external 1-wire sensors ports.
I had lots of fun with this little board and the PI. I didn't have to put it together which made it a good first project.  I put it in the fridge, on the ac vents, outside, and in the crawlspace to see what the temperatures were. I couldn't think of much more to do until I could get more funds and more parts for the projects I had in mind.

So after toying around for a bit with an LED and PWM I thought it'd be cool to get that working with the high power outputs the weather board has except with a computer fan :-). I found an old 12v 1000mA AC adapter plenty good enough for the fans.


Now that I got that working I wanted it to start cooling the weatherboard sensors and slow down to try and meet the desired set point. I found that in the industrial world there are nice little equations and formulas to help you achieve this. The PID loop (if you want to learn what that is (wiki link) gave me a value which I added to my dutycycle:
python pid code here ( i'll post my code later)

After recording that video the fans adjusted their speed to about 20-30% to maintain the setpoint. This could be a helpful addition to the cooling part of my turtle habitat project.