kizniche / Mycodo

An environmental monitoring and regulation system
http://kylegabriel.com/projects/
GNU General Public License v3.0
2.99k stars 500 forks source link

[Suggestion] PWM for Led driver dimming #262

Closed leoneo closed 6 years ago

leoneo commented 7 years ago

Hello Kyle,

I would like to control the brightness of 3 led strips (red, blue, white) in the time. For example function 1 : day 1 = 10%; day 2 = 15%; day 3 = 20 % ... day 15 to day 30 = 100% function 2 : sunrise start at 6:30AM with 0% to 100% in 30min / sunset start at 8:30PM with 100% to 0% in 30min.

There are led drivers dimmable with 0-10Vc PWM input and with a 0-5V 0-10V PWM Converter Module it is theoretically possible with the Raspberry Pi to control the brightness. https://raspberrypi.stackexchange.com/questions/298/can-i-use-the-gpio-for-pulse-width-modulation-pwm http://www.meanwell.com/productPdf.aspx?i=300 http://www.uctronics.com/0-5v-0-10v-to-0-100-voltage-to-pwm-converter-module.html

Please can you add a PWM output function in Mycodo ?

Thanks Leo

kizniche commented 7 years ago

Good suggestion, How do you envision it being integrated into Mycodo? That is, what is your desired use? Such as x% at 8am, y% at 10am, etc.; response from sensors (conditional- if light sensor is x, set LED output to y, some sort of integration into the relay menu so relay actuation can somehow change brightness/color, or other?

leoneo commented 7 years ago

I use mycodo for the cultivation of microalgae. In the first stage the culture has a low density and requires little light. Excessive brightness inhibits growth. As cell density increases the luminous intensity must be increased. Then from day to day the luminous power increases. When cell density is at its maximum, microalgae are stressed with maximum intensity to make a red pigment.

I need a function that gradually increases the brightness during the first 15 days.

For an outdoor culture to have the ability to compensate for the loss of brightness by a cloud would be really very interesting to have a stable, climate-independent production.

I would like to use mycodo to a marine aquarium. For the coral it takes a function of sunrise and sunset every day. (And the cherry on the cake would be the simulation of the lunar cycle.)

The PWM output function can be integrated in the relay menu.

kizniche commented 7 years ago

Here is what I currently think would work best for the 15 day cycle:

  1. Create a method that gradually increases over the span of 15 days.
  2. Modify the timers to accept a method as an input and a [special] relay as an output. This special relay will be a PWM relay.
  3. When the timer is started, it will output according to the method.

For the sunrise/set, moon phase I could add a new type of controller that can calculate the sunrise/set and lunar phase for a given set of coordinates (and optional time offset to have a complete configuration), where there can be PWM output based on sunrise, midday, sunset, then switch to PWM for moon phase during night period. There could also be actions that can be taken at sunrise or sunset (or periods surrounding those using a time offset, such as "2 hours before sunrise" or "20 minutes after sunset", activate relay x to ON, set relay y PWM to 70% duty cycle, etc.)

leoneo commented 7 years ago

That will be great ;)

Do not forget the function of modifying the brightness of the LEDs according to the ambient brightness to maintain a constant luminosity in real time.

There is a lot of work.

kizniche commented 7 years ago

How are the LEDs duty cycle changed?

leoneo commented 7 years ago

I know that the frequency of pulsed light can have a beneficial effect on photosynthesis. This frequency depends on the color (wavelength). I have to do some research on the subject.

kizniche commented 7 years ago

I was asking how is the hardware (LEDs) modulated by the software. And what software or code is used for that? I need a starting point as I don't have any hardware for LED PWM control.

leoneo commented 7 years ago

I think we can have the information in the datasheet of the driver. I am in the bed, I can find tomorrow.

leoneo commented 7 years ago

driver datasheet : Applying additive 10V PWM signal (frequency range 100Hz ~ 3KH)

you can test mycodo with 1 led and 1 resistor like that : https://circuitdigest.com/microcontroller-projects/raspberry-pi-pwm-tutorial

wangine commented 7 years ago

@kizniche Is the same thing i ask you last year if you can integrate a PWM output function in PID control . Can be 2 main forms of controll PID output (relays and PWM). Relays can do a good job for normal control ,but for fast changes below 1 second , relays just simply cant. I can handle with C but unfortunately my programming skills in Phyton and Flask are very low. (I'm hardware engineer) , software are just a passion. Here's a simple function for a PWM software (for processors without harware PWM module like Raspberry ) http://www.ccsinfo.com/forum/viewtopic.php?t=54585 . Also the same function can be used in alternating power sources (~) not only on linear power sources (+-) like @leoneo need .

kizniche commented 7 years ago

The RPI.GPIO module has PWM and I think it would be somewhat easy to add it as a PID output (as the other use mentioned in this thread appears more difficult), now that I have a bit more experience with Python and the framework is more logical and accessible. What would be any additional PID options or changes needed to use PWM as an output? I'd assume I would essentially need to convert the PID output to a percentage, for use in defining the duty cycle. Any other suggestions would be appreciated, as I rarely work with PWM and don't currently have any devices that use it (though I can test the operation with my oscilloscope).

wangine commented 7 years ago

Yes Kyle , now i see, Pi is the same, software PWM (not hardware) and i assume can be selected as output any RPI pin. That would be great. Here is a tricky part. If controll is in one dirrection (raise or lower , usualy the temp) PWM output will be as percentage 0 - 100% and if the controll need to be in both dirrection can be in two ways : 1 : (the best one) with two RPI output pins , one for lower and one for raise . Raise between 0 - 100% and lower between 0 -100% . independently. Thats method is more easy to set the hardware without to much knowledge 2 : (need a complex hardware , specialy for alternating power source) . with one RPI pin . In that case raise will be between 50 - 100% and lower will be between 0 - 50% percentage. So the PID interface will be without the relays radio buttons , also without durrations max and min. We will need a 3 fields (radio buttons): 1: Field to select which method will use (relay or PWM) 2: Field to select the based PWM frequency (between 1Hz and 400kHz will be enoth for all aplications) 3: Field to specify the desired RPI pin (or pins in case of both dirrections).

wangine commented 7 years ago

@kizniche Also i can made a schematic for each one of the metods (2 pins or single RPI pin) and for the two power sources (alternating and countinuous ). You can fit into the help page after you finish. Also the advantage of PWM PID modulation control are double. 1: (example for temperature control ) The heat source dont need to be double as necesarry like in relay modulation type, because 100% duty cycle mean the heat will be turned on completly on entire period . 2: The 30% or more of the power source will be saved with PWM controll. Relays controll give a hudge lost in electromagnetic energy when is turned on. Also the delay is big.

kizniche commented 7 years ago

Sounds great. I can understand the 0-100% PID for a single relays (one 0-100% up, one 0- - 100 down), or just up or just down. However, I'm not fully understanding the other method you suggest. Schematics and descriptions would help. Thanks. I'm out right now, but plan to do some research when I get home later.

wangine commented 7 years ago

We can use the solid state relays instead of classic coil relay. That for heat sources load . Actualy is not to much difference between techniques of relays use. Classic relay can modulate in on and off (they can"t open or close only 30% or 66%) and solid state relays can work with PWM modulation . Thats mean if the power source wil be 120v AC , and relay is comanded with 50% duty cycle at 1kHz based frequency , the heat source will get 60v AC . Some tips about how they work http://www.idc-online.com/technical_references/pdfs/electrical_engineering/The_Solid_State_Relay_Static_Relay_Overview.pdf and here some relays i"ve used long time ago on my old regulation system with dsPIC and PWM output controller http://www.farnell.com/datasheets/1754070.pdf?_ga=2.34697575.719620540.1500236779-1343759042.1500236779

Ryobidelacroix commented 7 years ago

What about a PWM IC? I found two examples. They can be controlled by either I2C or SPI.

https://www.adafruit.com/product/815

https://www.adafruit.com/product/1429

wangine commented 7 years ago

@Ryobidelacroix That's IC are specialised only for LED PWM , If the code will be made like @kizniche suggestion http://raspi.tv/2013/rpi-gpio-0-5-2a-now-has-software-pwm-how-to-use-it the aplication will be general purpose , not only for LED. The native RPi pin"s can be used on any application.

Ryobidelacroix commented 7 years ago

Ah, even better!

kizniche commented 7 years ago

I completed about 75% of the PWM implementation last night, including the web interface and the PWM controller. Last is to test the operation and enable it as a new PID option. Then we can get into more complex uses.

wangine commented 7 years ago

I made a simple swap PWM code to simulate the output of PID on RPi . Schematics are for AC and DC load. Unfortunately my PC cant handle with record screen of 720p and ISIS simulate in real time, but is enough to someone understand. When you will finish i will test and made the schematic for any type on configuration (AC, DC , inductive , resistive load. ... ) https://www.youtube.com/watch?v=RPcaKuM9QoE

kizniche commented 7 years ago

I pushed the latest commit for what appears to be a working implementation of PWM. I say appears because everything responds as though it's working but I haven't actually tested the pin output. I'll check with my oscilloscope tomorrow. There may very well be issues with this PWM_support branch, as I haven't tested if current relay/PID functionality has been affected.

This commit only brings in the ability to add and configure a PWM output on the output's page (previously "relay" page), and turn on/off PWM. PID output will come next once I confirm there is indeed a PWM being output and normal relay/PID functionality hasn't been broken.

wangine commented 7 years ago

Ok. I put here some pictures with basical principle (the best and cheap way) . You are free to put in help page if you want. Simulate the AC resistive load with PWM and 1% dyty cycle pwm 1 duty Simulate the AC resistive load with PWM and 50% dyty cycle pwm 50 duty Simulate the AC resistive load with PWM and 99% dyty cycle pwm 99 duty This is a basic principle , not a full point schematic, just to users to get the ideea how it works. Is the best way to controll the AC (most used) loads with PWM. It"s work with bipolar, MOSFET and IGBT transistors as well. Can controll any resistive load with less than 40% inductive .

kizniche commented 7 years ago

Great! I'll add them to the manual. I've never really used PWM besides simple uses with microcontrollers, so this is all relatively new to me.

wangine commented 7 years ago

Is just the principle , if you have a osciloscope is easy to fully understand how it's works and the hudge advantage than relays. With PID and PWM , dont stress the relays , the loads . Is almost linear . After you will finish the PWM code , i will upload the full real schematics (ISIS can't simulate the complex hardware, to much math for him), but only after i will test on my rPI . I use that for years on my old dsPIC MCU"s before discover your software.

kizniche commented 7 years ago

That last commit should have all parts of the system working with PWM, including PID output. I have my oscilloscope with me so I can test when I get home.

wangine commented 7 years ago

Ok. The first complete schematics with bipolar transistors, to controll with PWM and isolated output . The normal circuit in phase with PWM , the most stable with bipolar transistor pwm 50 duty bipolar isolated no inverting phase And inverted phase than PWM , pwm 50 duty bipolar isolated 1 Are tested only on resistive loads . Not on motors (fully inductive)

kizniche commented 7 years ago

Just tested turning on a 100 Hz PWM through the output page (previously "relay" page), at 50% and 10% duty cycles, respectively.

newfile1

newfile2

wangine commented 7 years ago

That's perfect. I dont know which it is the limit of RPi , to generate PWM for everything to be fluid. To modulate AC sinusoidal, 50-60Hz , 100Hz isn't enough. Even for LED's we need more than 600Hz , to dont be visible. For AC is good 1kHz , but if is possible can be increased to avoid ressonance noise. If you can test on 22kHz and if you get that perfect square , that will be great and suitable for all aplications. Also need to be possible to put (like a variable) the desired frequvency and the PID will controll only the duty cycle 0 - 100. The PID dont need to controll the frequvency , that will be chosed by the user (depend of application) .That why i work on that schematic , to avoid RPi to deal with "zero cross reference" . Will be less work for you.

kizniche commented 7 years ago

I currently have the frequency set on the outputs configuration and, yes the PID only controls the duty cycle. I'm testing PID right now. I'll see about 22kHz and report back.

kizniche commented 7 years ago

I tested with 1kHz, 5kH, and 20kHz, below. Doesn't look great.

1 kHz

newfile4

5 kHz

newfile6

20 kHz

newfile7

kizniche commented 7 years ago

Strange, because I've found multiple sources that state RPi.GPIO should be able to output up to 70 kHz.

kizniche commented 7 years ago

This script gives me a clean 200 kHz square wave on my scope:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO

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

while True:
    GPIO.output(23, True)
    GPIO.output(23, False)
kizniche commented 7 years ago

Yet this, like the code currently being used with Mycodo, when 20000 Hz is set, my scope only detects ~ 5 kHz.

#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import RPi.GPIO as GPIO

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

pwm = GPIO.PWM(23, 20000)
pwm.start(50)
time.sleep(60)
pwm.stop()
GPIO.cleanup()
kizniche commented 7 years ago

Using the hardware PWM pin 18, and pigpio, I was able to get a nice looking 250 kHz wave, and even was able to go up to into MHz.

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Use hardware PWM pin 18 (BCM numbering)
import pigpio

frequency = 250000
duty_cycle = 50

pi = pigpio.pi()
pi.hardware_PWM(18, frequency, duty_cycle * 10000)

Edit: The documentation states "Frequencies above 30MHz are unlikely to work" which explains the weird wave when I went up to high MHz.

newfile10

kizniche commented 7 years ago

I was able to get up to 40 kHz on a regular pin (non-hardware PWM pin), by restarting pigpiod with a sample rate of 1 μs (sudo pigpiod -s 1) and running this code.

#!/usr/bin/python
# -*- coding: utf-8 -*-
import pigpio
import time

pin = 23  # Pin using BCM numbering
frequency = 40000
duty_cycle = 50

pi = pigpio.pi()

pi.set_PWM_frequency(pin, frequency)
calc_frequency = int((duty_cycle / 100.0) * 256)
pi.set_PWM_dutycycle(pin, calc_frequency) # 50%
time.sleep(60)
pi.stop()

See here for a table of available frequencies based on the selected sample rate when starting pigpiod. At 1 μs, available frequencies are: 40000 20000 10000 8000 5000 4000 2500 2000 1600 1250 1000 800 500 400 250 200 100 50

newfile9

kizniche commented 7 years ago

So, I could provide the option of using either the hardware PWN pins (which would use the pigpio hardware_PWM() function), or a regular pin (which would use pigpio's set_PWM_frequency() and set_PWM_dutycycle()).

There are a couple ways to do this. This could be in the form of a dropdown with two options, 1) hardware PWM pin and 2) regular pin. Then, if hardware pin i selected, the user could be presented with a list of available frequencies. If regular pin is selected, then the user can use any frequency they wish, up to 40 kHz (if the sample rate of pigpiod is changed to 1, which can be made default in the next release).

Anyway, that's enough testing for tonight. Everything seems to be working fine, we just need to sort out what PWM code to use and how to configure it in the web UI.

wangine commented 7 years ago

Yea , i know python cant do a good job vs C , but is enough 20kHz. And look ok below 20kHz , anyway no one can't hear the armonics at 16kHz modulation. Also the digital scopes missunderstand the triggers level sometimes, can not fully trust, personaly i use mixed analog+dig scope. Why you say doesnt look great because i dont see the altered square . Just a little trigger lack on the end. I assume you use that lib. http://abyz.co.uk/rpi/pigpio/python.html#set_PWM_range http://abyz.co.uk/rpi/pigpio/cif.html

wangine commented 7 years ago

Yea looks great . For some reason , your last post didn't show when i write.

leoneo commented 7 years ago

Good new, thanks you very much. Now I need to find hardware and test it.

kizniche commented 7 years ago

I said "doesn't look great" because with RPi.GPIO, setting 1 kHz yielded an 869 Hz wave, 5 kHz yielded a 2.92 kHz wave, and 20 kHz yielded a 5.4 kHz wave.

I'll be changing the code to use pigpio, since, in my tests at least, it's proven to be more stable, accurate, and able to produce a higher frequency.

wangine commented 7 years ago

Yea , i did't look at freqvency , only at square form and the level voltage of RPi pin

wangine commented 7 years ago

Sorry , maybe is not right place. How to update manual? I delete old system, i clone again , system remain the same . How to update that commit? Anyway i need to resolve my issue, daemon still stopping after several hours (that happen for days). I try to change sensors, RPi interface, power source , Even with new image and fresh Mycodo same issue. Tomorow i will reflash with the old stable version (working continuosly from last year without any isssue on other RPi) and i will see.

kizniche commented 7 years ago

Okay, I think everything related to PWM is working fine now. The only thing left to do is work on the graphs (which I have not touched and are probably broken). Here is what I have:

The output page allows a new selection dropdown "PWM output" to be selected.

The PWM output has the following options: Library ("Any Pin, <= 40 kHz" and "Hardware Pin, <= 30 MHz"), BCM Pin, Frequency (Hertz), Current Draw, all which can be set. Then there is a "Turn on" button and a Duty Cycle field to turn on the PWM from the Output Page, sort of how the relays can be turned on for a duration of seconds.

screenshot-192 168 0 5-2017-07-19-20-35-39

On the PID page, there is now a drop down selection for the PID type, which includes "Relay Output" and "PWM Output". The PWM PID includes the standard options like Input device, setpoint, PID gains, etc. But then only have "Output ID (Raise)" and "Output ID (Lower)" in place of the relay-specific options.

screenshot-192 168 0 5-2017-07-19-20-26-56

The specific code that converts the control variable to a duty cycle is this:

                        if self.control_variable > self.period:
                            self.raise_duty_cycle = 100.0
                        else:
                            self.raise_duty_cycle = float(
                                (self.control_variable / self.period) * 100)

I'm not sure if this is the best way to do this, but it was the first thing that came to mind and It seems to work fairly well. I'm open to other suggestions as to how to calculate the duty cycle. We can also have a dropdown to select different methods.

Let me hear any thoughts if there should be any changes.

i clone again , system remain the same

This is because the code I'm pushing is on the PWM_support branch, so you'll have to checkout that branch before installing normally. I didn't want to push these edits to master yet, before we iron out all the issues.

git clone https://github.com/kizniche/Mycodo
cd Mycodo
git checkout PWM_support
cd install
sudo /bin/bash ./setup.sh

Then, if you want to update to the latest commit (if I push more), do this:

sudo service mycodo stop
sudo /etc/init.d/apache2 stop
cd Mycodo
git pull
sudo /bin/bash ./mycodo/scripts/upgrade_commands.sh initialize
sudo /bin/bash ./mycodo/scripts/upgrade_commands.sh restart-web-ui
sudo /bin/bash ./mycodo/scripts/upgrade_commands.sh restart-daemon

When I finally make the next version release to master, you can just to go the upgrade page and it will upgrade your install to the latest release.

daemon still stopping after several hours (that happen for days)

Does this happen on a freshly-installed system without anything added yet? Are there any errors in the daemon or HTTP logs?

wangine commented 7 years ago

Yes , thanks, i found the way."If you find yourself you never forget " // Yes that happen in last 3 weeks, i just assume is my router fault when i try to acces over home network , Linksys keep rejecting my RPi , i didn't take care because my tobacco wasn't ready to ferment, after i assume has something wrong with sensors. I change, RPi system (fresh lite and full also), new fresh mycodo install, i activate just one sensor , time by time and wait , i change sensors from other working RPi with very old and stable mycodo , same issue. I change power supply also. Dont worry , i will test tomorow with the old mycodo to see if is repeated. Now i wish to try PWM , is almost ready, i doit manualy with WinSCP . Testing..........

kizniche commented 7 years ago

I'll be constantly pushing commits to the branch (about to push one to fix a bug not turning the PWM signal off when the PID controller is stopped), so I'd recomment using the git clone method to be able to get the latest code.

wangine commented 7 years ago

Yes yes , now will be easy way , my network is faster . Daemon show randoms errors

2017-07-16 13:31:51,154 - mycodo - INFO - 42.192 MB ram in use
2017-07-16 13:31:51,411 - mycodo.influxdb - ERROR - No measurement available in the past 60 seconds.
2017-07-16 13:31:51,415 - mycodo.pid_1 - WARNING - No data returned from influxdb
2017-07-16 13:32:22,801 - mycodo.sensors.sht1x_7x - ERROR - SHT1x7xSensor raised an exception when taking a reading: (113L, 255)
2017-07-16 13:36:22,517 - mycodo.sensors.sht1x_7x - ERROR - SHT1x7xSensor raised an exception when taking a reading: (214L, 255)
2017-07-16 14:10:45,435 - mycodo - INFO - Received command to terminate daemon

and other one saved a short part

  File "/var/www/mycodo/env/local/lib/python2.7/site-packages/sqlalchemy/engine/strategies.py", line 97, in connect
  File "/var/www/mycodo/env/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 385, in connect
    return self.dbapi.connect(*cargs, **cparams)
OperationalError: (sqlite3.OperationalError) unable to open database file

2017-07-19 06:29:55,706 - mycodo.sensors.sht1x_7x - ERROR - SHT1x7xSensor raised an exception when taking a reading: (<functools.partial object at 0x640b3120>, 1.0)
2017-07-19 06:29:55,707 - mycodo.sensor_1 - ERROR - StopIteration raised. Possibly could not read sensor. Ensure it's connected properly and detected.
2017-07-19 06:30:10,786 - mycodo.sensors.sht1x_7x - ERROR - SHT1x7xSensor raised an exception when taking a reading: (<functools.partial object at 0x6608a390>, 1.0)
kizniche commented 7 years ago

Did you just copy your database over from another install?

wangine commented 7 years ago

No no . was a fresh one. Errors are from two RPi . One with lite and one with full image. On lite the install wasn't succesful , so i delete Mycodo in home and i reinstall again with

rm -r Mycodo git clone https://github.com/kizniche/Mycodo cd Mycodo/install sudo /bin/bash ./setup.sh

kizniche commented 7 years ago

Oh, I thought you were pasting logs with errors from the PWM_support branch install.

I don't have the SHT1x7x sensor, so I can't really debug the issue myself. The "unable to open database" error is strange.

kizniche commented 7 years ago

I would be careful about cloning master. It can at any time be in a non-working state. I would always only download releases using the install instructions. The releases are the only thing I really strive to have a working system with.