_cyclops_
Posts: 6
Joined: Wed Dec 02, 2015 10:52 am

Controling output voltage with the PI

Wed Dec 02, 2015 11:01 am

Hi,

I've been searching quite a bit for this, but haven't found a solution yet.

I want to control a device based on voltage that i put into it. I know the GPIO's will only do 0v, 3.3v and 5v and that they are low power (amps), so those are not usable for me.

I want to control a fan's RPM, but also have a need to control a heating device (not sure what yet). I'm assuming (for now) that both devices are analog and "move volts" means "move power" and likely "more amps". In principle, i'm creating low heat oven that needs to stay at a certain temperature. I however want to have control on how quickly it heats up and also how much airflow will be used.

I've seen the DAC converters that would allow me to control the voltage, example here:https://www.adafruit.com/products/935
But, i believe that these are not high-amperage (unless somebody tells me they are, in which case i'm done :))
They also don't seem to have an external power source which means that all the power comes from the PI, which i want to avoid as the PI should just control the device.

Could anybody point me into a direction of doing this correctly?

sprinkmeier
Posts: 410
Joined: Mon Feb 04, 2013 10:48 am
Contact: Website

Re: Controling output voltage with the PI

Wed Dec 02, 2015 11:50 am

Chances are you want duty-cycle control rather than voltage control:
https://en.wikipedia.org/wiki/Pulse-wid ... r_delivery

without more info on the load you're trying to run (voltage, current etc.) it's difficult to know.

_cyclops_
Posts: 6
Joined: Wed Dec 02, 2015 10:52 am

Re: Controling output voltage with the PI

Wed Dec 02, 2015 12:02 pm

Thanks Sprinkmeier,

The PWM would work for the heat element, but (and i'm assuming here) would not work for the ventilator. The reason is that i need a constant stream of air, but want to be able to increase or decrease it based on some variables (temperature, moisture).
As i understand it, if i use PWM on a ventilator, it would turn on and off and on and off and on and off - or am i not understanding that correctly?

I also believe the PI only has one PWM pin, and i have two devices.

I understand it's difficult without the exact amps.I'm also still looking at which devices i'll likely use, but - it's also a bit depended on if i can control them with the voltage. So, i'm quite open to suggestions, at the moment this seems to me like the easiest approach.

User avatar
joan
Posts: 14936
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Controling output voltage with the PI

Wed Dec 02, 2015 12:36 pm

You may be better off detailing the specs of the things you want to control, i.e. voltage, current, and similar. There is a difference between controlling a 6V DC motor and a 240V AC engine.

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Controling output voltage with the PI

Wed Dec 02, 2015 12:38 pm

I'd agree with sprinkmeier, and I do something not unlike this for my day-job.

You'd want pulse-width modulation on the GPIO and some heavy and fast switching of the load. You don't need a DAC. So long as the PWM is fast enough, the devices will act as if you are feeding them a varying voltage. We are not talking about a rate of 1 or 2 Hz here, but somewhere around hundreds or even thousands of Hz.

I'm not an electrical engineer, but I believe you'll be wanting a MOSFET driver (provides sufficient voltage to switch and also isolation) and a power MOSFET.

The Pi may have only one PWM output controlled by the SoC, but any GPIO pins can be used for PWM; you just have to switch them on and off yourself. There are libraries available that allow you to control multiple PWM signals at the same time on different pins. For example pigpio.

_cyclops_
Posts: 6
Joined: Wed Dec 02, 2015 10:52 am

Re: Controling output voltage with the PI

Wed Dec 02, 2015 12:56 pm

Thanks for all the responses - to take this further, i need to select the devices, it seems.

For the Fan, a normal 5V computer case fan works. I'd like to be able to control 3 of those.
The input is 5v and MAX of 800mA.

The heating element is a bit more difficult. I can't really decide because i've simply got no clue on what will work well. Currently, there is just a 35W/230V incandescent lamp that is providing the warmth, but i want to replace that with something else. it could be 230V or just 5V as than i would keep everything on 5V, which makes it easier from a power supply point of view.
Now, 35W at 230V is around 0.15Amps, which means that at 5V it would be 7Amps. Now, i know that heating elements probably don't work like that, and i might need to look for other options here - but that's the difficult part. I don't know what is easy for the PI and what is an easy component to use.

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Controling output voltage with the PI

Wed Dec 02, 2015 4:44 pm

It looks like you don't need anything for the fan except a single transistor for each fan: https://en.wikipedia.org/wiki/Computer_ ... modulation

Rather than needing a 7A power supply, which would be large and difficult to source, my initial impulse would be to use the same, or suitably larger, mains light bulb. You can then use a small MOSFET driver and MOSFET to interface to it. If you did it at 5V you might be able to avoid using a MOSFET driver, or you may not. I would be happy using a pair of commercial products for that at mains voltage. If you don't feel safe doing that then your calculations are correct for using 5V, but 7A is not perfectly safe; you'll just burn the house down rather than electocute yourself. You will need beefy wires. Another way to do it would be to add 12V to the mix and use a car tail-light bulb. That's around the right power, IIRC.

For 5V a bulb may be hard to find. However you can just use a power resistor, or in fact a few of them. Four 2.2 ohm resistors in parallel will give you 0.55ohms and a power of (5x5)/0.55 = 45W. Mount those on a heatsink to get the heat out into the air as efficiently as possible. Make sure the resistors are rated for enough power. For example: http://uk.rs-online.com/web/p/panel-mou ... s/7027982/

If the current solution uses a 35W bulb and I assume it is not actively controlled to maintain temperature, using a slightly higher power, say 50W, would give you a faster response time so long as the control was working. If the control fails then everything either freezes or cooks.

_cyclops_
Posts: 6
Joined: Wed Dec 02, 2015 10:52 am

Re: Controling output voltage with the PI

Wed Dec 02, 2015 9:25 pm

Thanks rurwin,

I'll have a look at the computer fan and read the wiki article a bit better.

The reason i don't want to use the lightbulb anymore is threefold. It's inefficient, the lights are difficult to get nowadays and it produces light, which i don't want. As a heat source it does work, but since i'm moving away from just having a constant light to something that is controlled, i want to replace the heat element itself as well.
I've seen these things: http://www.ebay.co.uk/itm/Compact-5V-12 ... 1518988674
I guess i can control them using a relay or so, but i would love to be able to get a bit more control. I guess i just don't trust a lot in PWM because i haven't done it yet. I will have to play around with it :)

danjperron
Posts: 3502
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Controling output voltage with the PI

Wed Dec 02, 2015 10:04 pm

It is for an aquarium or a terrarium heat pad ?

A small relay will do but if you are using any AC heater, just use a SSR relay. They are optoisolated and won't have any contact problems.

If it is DC a simple power mosfet will do. I will put an optocoupler this way it is simple to drive the mosfet with 12V.

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Controling output voltage with the PI

Wed Dec 02, 2015 10:08 pm

There's no need to get fancy; just use resistors, they're 100% efficient and cheap. If you don't like using PWM for it you could even just switch them on and off and use a relay if you wanted to, although even at that rate it wouldn't last forever.

SSRs generally don't have sufficient frequency response to handle PWM but, as I said, it isn't strictly necessary here. It would just make the temperature control easier.

_cyclops_
Posts: 6
Joined: Wed Dec 02, 2015 10:52 am

Re: Controling output voltage with the PI

Thu Dec 03, 2015 11:52 am

Hi Danjperron, rurwin,

It's for a drying oven. the temp needs to be between 20 and 45 degrees C. I need to keep it there, with a slight breeze (fans..) for a long period of time. I want to be able to experiment with this a bit, higher temp (45) vs lower airflow and high airflow vs low temp (20).
Because of that, i want to be able to control it, and quite precise as well as i do want to see differences of 5 degrees C. more or less.

I've had a good look at PWM with computer fans. Now, i do wonder because the wiki article states that the control signal operates at 25kHz. Does that mean the raspberry has to switch on/off at 25kHz as well? I don't want to add extra CPU load for this, that seems like a flawed design. I've seen somebody talk about controlling PWM with this: https://www.adafruit.com/products/815
Would that work? Or, am i just not understanding the PWM thing correctly?

As for the heating element, i'm fine with a relay and "something" that creates heat. If it's a resistor or a specific heating element - i don't think it matters that much. i'll look at the SSR as well, lots to learn :)

danjperron
Posts: 3502
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Controling output voltage with the PI

Thu Dec 03, 2015 12:24 pm

At work I have to test some instruments for temperature.

I used a Raspberry Pi with a DS18B20 sensor and a relay.

The heating element is an electric domestic heater with a fan, protection removed and a higher temperature fuse added.

Since It is a slow process I just create a PID controller. (I didn't used the derivative parts).

The PWM in my case is irrelevant since the heater doesn't respond fast and I had 1 m² to heat up. Basically the duty cycle was in 60 seconds period.

at 30C it was ON for 1..2 sec each minutes.
at 40C it was ON for 16..17 sec each minutes.

The heater was set to 500W.

With the PID , when the target temperature rise I had a burst of 0.5 degree above the target at the beginning otherwise it was +/- 0.06 degree.

I will dig the source code.

I didn't care about the fan because it was with the heater. This gives me some problem at low temp since it was connected to the heater.

But for the fan you could use a PWM with an RC filter coupled to an power amplifier.

something like that , but with a power amplifier instead or just add a NPN transistor inside the amplifier loop, (TO220 type) to drive the fan.

viewtopic.php?p=819028#p819028

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Controling output voltage with the PI

Thu Dec 03, 2015 12:52 pm

25kHz is achievable for a computer with the power of the Pi. It does need to be done by a high-priority process though so it doesn't have to pause for the screen updates or USB events. The best way is probably using some library such as pigpio. In the worst case there is a single gpio pin that can be configured to produce PWM in hardware. It doesn't have to be too accurate -- a fan has a significant inertia and so long as the average speed is controllable you will still get good control with the right algorithm (PID probably, talk about that later.) It probably doesn't need to be 25kHz either. 3000rpm is 50 revolutions per second so at 25kHz you would be controlling the speed every 0.72 degrees of its revolution. That's excessive. A few hundred Hz is probably sufficient.

Ah. I've found the reason: "Switching the coils on and off generates some commutation noise. Driving the coils at rates greater than 20 kHz moves the noise outside of the audible range" -- http://www.analog.com/library/analogdia ... speed.html
So it's desirable, but not vital.

danjperron
Posts: 3502
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Controling output voltage with the PI

Thu Dec 03, 2015 5:39 pm

Code: Select all

Switching the coils on and off generates some commutation noise
Of course the copper wires vibrates !

30 years ago , on the pilot plan when I was working . I wasn't able to stay there for more than 1 minutes.

I said to my boss that the sound is way too loud and it hurts my hears!

I was the only one complaining, and of course the only one under 25.

So the health security guys came with a decibel meter et voila! It was 18.5Khz at 110db.

So we called the company which was manufacturing the induction heater and we simply increase the frequency to 25KHz.

And the loud high pitch noise disappeared including my headache at the end of the day.

danjperron
Posts: 3502
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Controling output voltage with the PI

Thu Dec 03, 2015 6:25 pm

ok I found my heater controller code.


it is in python with 2 scripts.

The first script LireTemperature.py read the sensor temperature and apply the PID on it.

The calculation returns an amount of time in seconds that the heater element will be ON.

It then it calls another script , in subprocess , to turn ON the heater. This subprocess prevent collision in case the script is start again by the crontab.

The script just do what it does and quit. All the variable are on text file inside a tmpfs folder (a ramdisk) called /ramdisk

This is the LireTemperature script

Code: Select all

#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import os
import sys
import datetime
import subprocess
import shlex
#import RPi.GPIO as GPIO
#lire la date courante
now = datetime.datetime.now()




TARGET = 20.0
PID = 15.0

if (os.path.isfile('/ramdisk/PID.txt')):
  f = open('/ramdisk/PID.txt','r')
  PID = float(f.readline().strip('\n'))
  f.close
else:
  if (os.path.isfile('/home/pi/PID.txt')):
    os.system('cp /home/pi/PID.txt /ramdisk/PID.txt')
    f = open('/ramdisk/PID.txt','r')
    PID = float(f.readline().strip('\n'))
    f.close


if (os.path.isfile('/ramdisk/TARGET.txt')):
  f = open('/ramdisk/TARGET.txt','r')
  TARGET = float(f.readline().strip('\n'))
  f.close
else:
  if (os.path.isfile('/home/pi/TARGET.txt')):
    os.system('cp /home/pi/TARGET.txt /ramdisk/TARGET.txt')
    f = open('/home/pi/TARGET.txt','r')
    TARGET = float(f.readline().strip('\n'))
    f.close


#GPIOHeater=23

#GPIO.setmode(GPIO.BCM)
#GPIO.setup(GPIOHeater,GPIO.OUT)





#definition de fonction pour creer un folder

def mkdirp(directory):
    if not os.path.isdir(directory):
        os.makedirs(directory)


#Fonction pour lire la Température CPU

def LireTarget():
   fichier = open("/ramdisk/Target.txt")
   texte = fichier.readline()
   fichier.close()
   return float(texte)

def LireCpu():
   fichier = open("/sys/class/thermal/thermal_zone0/temp","r")
   texte =  fichier.readline()
   fichier.close()
   return  (float(texte)/1000.0)

#Fonction pour lire les Capteurs DS18B20
#P.S. Le crc est vérifier pour être certain
#     que la température est valide
#     Si après 5 essais non valide,
#     la valeur None sera retourné indiquant une erreur

def LireDS18B20( CapteurId):
   if CapteurId == None:
     return None
   Compteur=0
   while(1):
     try:
       fichier = open( "/sys/bus/w1/devices/" + CapteurId + "/w1_slave")
       texte = fichier.read()
       fichier.close()
       ligne1 = texte.split("\n")[0]
       crc    = ligne1.split("crc=")[1]
       if crc.find("YES")>=0:
        break;
     except:
        #ok une erreur, bouclons
        pass

     Compteur = Compteur + 1
     if Compteur >= 5 :
       return None

   #ok nous avons une température valide
   ligne2 = texte.split("\n")[1]
   texte_temp = ligne2.split(" ")[9]
   return (float(texte_temp[2:])/1000.0)






Capteur1_ID= '28-000004575f0a'
th_t1  = LireDS18B20(Capteur1_ID)
th_target = TARGET


###################// PID here
if th_t1 != None:

  Flag = 1
  if th_t1 < th_target :
#    GPIO.output(GPIOHeater,1)
    print("Heater ON")
  else:
#    GPIO.output(GPIOHeater,1)
    Flag=0
    print("Heater OFF")


  P = (th_target  - th_t1) * 10.0


  if(P > 40.0):
   PID=0


  PID = PID + (( th_target - th_t1) * 2.0)

  if(PID > 55.0):
    PID = 55.0

  if(PID < 0.2):
    PID = 0.2;

  PPID = PID +  P

  if(PPID > 55.0):
     PPID = 55.0

  if(PPID < 0.0):
     PPID = 0.0

#  if Flag == 1:
  subprocess.Popen(['sudo','/usr/bin/python','/home/pi/RelayDuration.py',str(PPID)])

  lcnow = time.localtime()

  FileTemp = "/home/pi/CtrlTemp_" + time.strftime('%d%b%Y',lcnow) + ".txt"

  nfile = open(FileTemp,'a')
  if nfile != None:
    nfile.write(time.strftime('%H:%M:%S') + "\t" + "{:.2f}".format(th_t1) + "\t{:.1f}".format(th_target)  + "\t{}".format(PPID) + "\n")
    nfile.close()

  print("PID={}".format(PID))


  f = open("/ramdisk/PID.txt","w")
  f.write("{}\n".format(PID))
  f.close()



#affichons les valeurs
#petite fonction pour intercepter la valeur None
def TempS(valeur):
  if valeur == None :
    return "---"
  return "{0:.1f}".format(valeur)

print "Temperature Sensor 1: {0}'C  Target: {1}'C".format(TempS(th_t1), TempS(th_target))


#ok enregistrons la valeur dans un fichier temporaire pour
#incrustation ultérieur dans le time lapse
#le fichier sera dans le ramdisk folder /temp/temperature.txt

try:
   fichier = open("/ramdisk/temperature.txt","w")
   fichier.write("{0}\t{1}\t{2}\n".format(now.strftime("%H:%M"),TempS(th_t1), TempS(th_target)))
   fichier.close()
except:
   pass


#créons le répertoire /media/usbkey/Pi_Temperature
#juste au cas il nâest pas la

FichierRecord = "/home/pi"

mkdirp(FichierRecord)

#Créons le fichier avec la date comme nom

NomTemperature = FichierRecord + "/Temp_" + now.strftime("%Y_%m_%d") + ".txt"

#ouvre fichier en mode append
try:
   fichier = open(NomTemperature, "a")
   fichier.write("{0}\t{1}\t{2}\n".format(now.strftime("%H:%M"),TempS(th_t1), TempS(th_target)))
   fichier.close()
except:
  pass



#Créons la page web  dynamique

mkdirp("/ramdisk/www")

WebTemperature = "/ramdisk/www/CurrentTemperature.html"

try:
   fichier = open(WebTemperature,"w")
   fichier.write("<html><head><title>Rpi Temperature</title>")
   fichier.write("<meta http-equiv=""refresh"" content=""20"" >")
   fichier.write("<style>#cssTable td {text-align:center; vertical-align:middle;padding:10px}</style>")
   fichier.write("</head><body>")
   fichier.write("<table><tr><td><center><h2>Temperature</h2></td><td width=60></td><td>")
   fichier.write("<table border=""2"" id=""cssTable""><tr><td>Sensor</td><td>Target</td></tr>")
   fichier.write("<tr><td>{0}&deg;C</td><td>{1}&deg;C</td></tr></table>".format(TempS(th_t1),TempS(th_target)))
   fichier.write("</td></tr></table></body></html>")
   fichier.close()
except:
   pass


#updatons rrdtool

#definissons une fonction
# pour tenir compte d'une valeur invalide

def ValideValeur(valeur):
  if valeur == None:
     return ":U"
  else:
     return ":{0:.1f}".format(valeur)


texte= "N" + ValideValeur(th_t1) + ValideValeur(th_target)

#insérons dans le fichier de data rrdtool

fichierRrdtool = "/home/pi/temperatures.rrd"

subprocess.Popen(["/usr/bin/rrdtool","update",fichierRrdtool,texte])

#creons une fonction pour extraire l'information
def rrdExport(debut , step , sortieXML):
  texte = "rrdtool xport -s {0} -e now --step {1} ".format(debut, step)
  texte += "DEF:a={0}:th_t1:AVERAGE ".format(fichierRrdtool)
  texte += "DEF:b={0}:th_target:AVERAGE ".format(fichierRrdtool)
  texte += "XPORT:a:""Sensor1"" "
  texte += "XPORT:b:""Target"" "

  sortie = open("/ramdisk/www/{0}".format(sortieXML),"w")
  args = shlex.split(texte)
  subprocess.Popen(args, stdout=sortie)
  sortie.close()


#ok Extractons les donnés pour 3 heures
rrdExport("now-3h",60, "temperature3h.xml")

#ok Extractons les donnés pour 24 heures
rrdExport("now-24h",180, "temperature24h.xml")

#ok Extractons les donnés pour 48 heures
rrdExport("now-48h",360, "temperature48h.xml")

#ok Extractons les donnés pour 1 semaine
rrdExport("now-8d",7200, "temperature1w.xml")

#ok Extractons les donnés pour 1 mois
rrdExport("now-1month",2880, "temperature1m.xml")

#ok Extractons les donnés pour 3 mois
rrdExport("now-3month",5760, "temperature3m.xml")

#ok Extractons les donnés pour 1 an
rrdExport("now-1y",8640, "temperature1y.xml")

The script to turn the Relay ON. RelayDuration.py

Code: Select all

import sys
import RPi.GPIO as GPIO
import time

GPIOHeater=23

GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIOHeater,GPIO.OUT)


print("Argument={}".format(sys.argv[1]))

timeON = float(sys.argv[1])

if timeON >= 0.2 :
  GPIO.output(GPIOHeater,1)
  time.sleep(timeON)
  GPIO.output(GPIOHeater,0)
else:
  timeON = 0

file = open("/ramdisk/TimeON.txt","w")
file.write(str(timeON)+"\n")
file.close()

And it's use some text file in the ramdisk folder

/ramdisk/PID.txt => this hold the PID integration variable (this variable is in second).
/ramdisk/TARGET.txt => this is the Target temperature.

And of course I used rrdtool and HighCharts to display the result on the web page.


I did post the way to do it here (HighCharts on a web page).
viewtopic.php?p=672406#p672406


Now crontab.

On the root crontab, (sudo crontab -e), I call the LireTemperature every minutes.

Code: Select all

* * * * * /usr/bin/python /home/pi/LireTemperature.py
On the user crontab , (crontab -e) , I call the crontab when I want to change the target temperature

Code: Select all

30 10 * * * echo "30.0" >/ramdisk/TARGET.txt
00 13 * * * echo "40.0" >/ramdisk/TARGET.txt
00 16 * * * echo "20.0" >/ramdisk/TARGET.txt
BoxTemp.jpg
DS18B20_PID_control
BoxTemp.jpg (38.34 KiB) Viewed 7148 times

_cyclops_
Posts: 6
Joined: Wed Dec 02, 2015 10:52 am

Re: Controling output voltage with the PI

Thu Dec 03, 2015 7:12 pm

Hi All,

I'm going to move forward and order some parts, will be a while before i can get stuff to work. i might ask a question about a SSR for a heating element.

I really appreciate the help and the suggestions. This really is a great forum and great support!! Amazing!

Cheers,
ruben

danjperron
Posts: 3502
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Controling output voltage with the PI

Thu Dec 03, 2015 7:24 pm

Don't forget that SSR are solid state relay and normally they switch AC. Some could deal with DC.

The AC version will have a zero detection crossing detector to close circuit when the sinewave cross 0Volt.

Also high frequency PWM doesn't work very well because you are limited to 100/120Hz ( grid line frequency).

But a low frequency PWM with its resolution around 50ms with a full cycle of 10 seconds will do. Then it is software and not hardware PWM.

On my post my duty cycle full period was 1 minute with a floating value for the time ON. I did used a relay but a SSR will be better for a long term usage.

Return to “Beginners”