fanshim-python icon indicating copy to clipboard operation
fanshim-python copied to clipboard

Support PWM to control speed?

Open jcoetzee opened this issue 4 years ago • 19 comments

I was looking at the RPi.GPIO package and I noticed that it supports software-based PWM. I was wondering if that would be an idea to add support for that to get more control over fan output than just off and on? Would that be applicable in this case? Not sure what the overhead would be. I don't have a Fan SHIM to play with (not available in my country yet) but could look at bashing around with the idea when I do get one. Unless something else makes it a non-starter.

jcoetzee avatar Jul 24 '19 08:07 jcoetzee

Could even go a step further and delegate control logic to a PID controller (e.g. simple-pid) allowing smooth ramping up and down of fan speed.

jcoetzee avatar Jul 24 '19 08:07 jcoetzee

I intend to try implementing PWM and I wondered what effect would be on the fan. I would think if the right PWM frequency and control algorithm is chosen (any suggestions?) then the Fan might last longer than with the usual "bang bang" on off control. To start with how about a PWM frequency of (say) 20Hz and a target temperature of 58 and control range below 62. So 100% speed at 62C 0% speed at 54C. Then of course there is the simple-pid mentioned above which would provide an interesting exercise in its use. As an exercise in more advanced Control Engineering one could even use a model to improve accuracy by using CPU frequency and load as inputs to a model. (That is what is done nowadays in advanced control systems). You then compare the actual temperature with the predicted model output to update the model.

grayerbeard avatar Aug 10 '19 10:08 grayerbeard

On 10/08/2019 11:14, David Torrens wrote:

I intend to try implementing PWM and I wondered what effect would be on the fan. I would think if the right PWM frequency and control algorithm is chosen (any suggestions?) then the Fan might last longer than with the usual "bang bang" on off control.

You probably will have to always "bang on" at a 100% duty cycle, just to get the fan going. If you stop it with your finger it takes a second to start up even at 100%. Once its going you can try reducing the duty cycle until you find its stall point, and stay well above that.

Too start how about a PWM frequency of (say) 20Hz and a target temperature of 58 and control range below 62. So 100% speed at 62C 0% speed at 54C. Then of course there is the simple-pid mentioned above which would provide an interesting exercise in its use.

A PID controller is ideal for temperature control, which is very laggy and needs a lot of dampening.

From my days in Control Engineering one could even use a model to improve accuracy by looking at CPU frequency and load and adding them in as inputs to the model. (That is one is done nowadays with advanced control systems).

The CPU frequency does tend to flick a lot between the two states even when idling, so you'd need to read it at several times a second and produce an average. Otherwise reading at the temperature measurement interval you might think its running flat out when it isn't.

This is a good idea, as I prefer to see a nice stable temperature on my CPU temperature graphs, rather than it cycling between high and low values, so I tend to set the fans to run all the time at low speed.

Cheers ---David

druck13 avatar Aug 10 '19 23:08 druck13

I have PWM working OK but I had to play around quite a bit with the pwm frequency and the algorithm. With that arrangement I have not had to put fan full on for a period to get it going (although that is an alternative to what I have done).

Ref:

This is a good idea, as I prefer to see a nice stable temperature on my CPU temperature graphs, rather than it cycling between high and low values, so I tend to set the fans to run all the time at low speed.

One could have a very slow control that looked for the right constant speed speed.

I tested with finding the maximum frequency for each range of pwm speeds that always gets the fan going continuously (see below). For lower pwm % you need a lower frequency for the fan to spin at all but not too low so that its running intermittently. Very low speed values are not really worth bothering with (little cooling effect) so I start at 20%.

Its a rather nice result with the Fan spinning nice and calmly most of the time and never intermittently. The speed is updated at a very slow rate (about every minute and a half) normally but a check is made every 5 sec in case temperature is above a threshold and then for as long as temp is high speed is updated every 5 seconds.

On a full load CPU test it settles at around 60% speed and about 65C. For long periods the fan does not run at all.

See ([https://www.smalle.uk/r-pi-4-blog]) speed calc is speed = 20 + 80 * (cpu.temp - min_temp)/(max_temp - min_temp) where min_temp is 62 and max_temp is 68. The PWM frequency is set .... 2Hz for Speed of 20% to 26% 3Hz for speed of 26% to 32% 4Hz for speed of 32% to 45% 6Hz for speed of 45% to 100%

I have not progressed to PID but I have my doubts its worth it from your comments above and observing what I have so far.

I have used a similar algorithm to control a Sauna Heater and its much easier to get a good result in situations when the load and conditions are constantly changing and super accuracy is not needed.

Whether its worth the trouble or not is debatable but its a nice exercise in Python and control methods.

grayerbeard avatar Aug 17 '19 14:08 grayerbeard

@grayerbeard are you going to publish the code somewhere?

AndreaCCIE avatar Sep 02 '19 16:09 AndreaCCIE

I really don't understand the approach you guys are suggesting.

Linux includes a facility for fan control by way of device tree overlays and GPIO. Why are you pursuing software control of fan speed when it should be the kernel dealing with it, that is, if you want maximum robustness?

adicarlo avatar Sep 19 '19 22:09 adicarlo

That's because RPi.GPIO (the package used by the library) only supports software PWM (hardware based is in the pipeline apparently). Obviously hardware-based would be preferable and there are python libraries that do claim support, but they come with their own complications and would involve rewriting the project to use them. I opened this mostly to gauge interest and prove the concept. If viable it may be beneficial to look into different python package although I have no visibility into why this package was chosen in the first place.

jcoetzee avatar Sep 20 '19 07:09 jcoetzee

@grayerbeard I would be also interested in the working pwm code.

polojoe avatar Sep 20 '19 08:09 polojoe

@grayerbeard Yeah show us the goods.

joaomoreno avatar Sep 24 '19 21:09 joaomoreno

First of all apologies for not answering earlier as I have been traveling. I do have a set of PWM code that works and its fairly Modularized so not hard to extract from it a simpler version. The problem I found was that the FanShim does not like short on times so there is only a range of frequencies/PWM rates that work Once I have got over jet lag etc and will put the latest version on my website at My Pi Blog Where you can see the result.

I am happy with the result as it can be set up to hardly use the fan at all if the Pi is not busy and yet can manage the temperature well when there is a burst of activity.

grayerbeard avatar Oct 14 '19 10:10 grayerbeard

Scripts now uploaded to https://www.smalle.uk/r-pi-4-blog where you can see the results of the code running live as of now. (1400hrs Oct 17th) and you can download the python etc. It will be some time before I get to a tidy version but you should be able to extract the essential parts to make a PWM control of your own. Much of the time the fan runs nice and peacefully at 70% speed or less, much more peaceful than when it runs at full speed.

grayerbeard avatar Oct 17 '19 13:10 grayerbeard

I set aside some time a few months ago to experiment with PWM on Fan SHIM and ran into the same set of problems, ultimately abandoning it in favour of simple on/off since it's easier to reason about and support- it would be interesting to see your code and perhaps try to work it into a re-written version of automatic.py.

I think most people expect Fan SHIM to be running constantly at low speed, rather than just kicking in to avoid an overheat condition.

Gadgetoid avatar Nov 06 '19 13:11 Gadgetoid

Have now reached a settled state with my PWM control of the Fanshim and have made sure all my install instructions are sorted.

To try this yourself either go to my Blog or direct the the branch of my gitHub repository.

https://github.com/grayerbeard/R_Pi_4_Fanshim_PWM

grayerbeard avatar Nov 29 '19 10:11 grayerbeard

Have now done version on Pimorini Software so operates as per their version but instead of running at 100% runs at (say) 70% so nice and quiet. This followed some testing to check how the cooling effect of the fan varied with speed. Turned out there is little point in varying the speed, the effect changes very little and as long as some cool air is moved in next to the CPU it still get cooled fine. See https://github.com/grayerbeard/fanshim-python.

Tests done using the "algorithm_test_cooling.py" algorithm in the pwm_fanshim branch of my RPi4_Python_FanshimPWM_Temperature_Control_with_logging repository. That produces a separate html and csv file showing the temperature drops produced by the fan running at a range of speeds.

grayerbeard avatar Dec 06 '19 13:12 grayerbeard

For pimorii software with a tiny mod so fan run quiet at 70 % see https://github.com/grayerbeard/fanshim-python from which you can clone the working version.

Although the cooling effect is around 30 to 40% less its actually enough to cool the CPU when running a 100% load stress test down to around 62 C depending on the ambient temperature.

All I did was alter the GPIO commands in fanshim-python/library/fanshim/__init__.py so they are based on the following in the appropriate places.

     GPIO.setwarnings(False)
     GPIO.setmode(GPIO.BCM)
     GPIO.setup(self._pin_fancontrol, GPIO.OUT)
     self.pwm_out = GPIO.PWM(self._pin_fancontrol,1)
     self.pwm_out.start(0)
     self.pwm_out.ChangeFrequency(self.pwm_freq)
     self.pwm_out.ChangeDutyCycle(self.pwm_speed)
     if fan_state:
         self.pwm_out.ChangeDutyCycle(self.pwm_on_speed)
         self.fan_state = True
     else:
         self.pwm_out.ChangeDutyCycle(0)
         self.fan_state = False

instead of

        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self._pin_fancontrol, GPIO.OUT)
        GPIO.output(self._pin_fancontrol, True if fan_state else False)

grayerbeard avatar Dec 07 '19 08:12 grayerbeard

I find that running on 70%, the fan produces a noticeable regular clicking sound.

I tried altering the frequency and duty cycle, but found very few values which successfully drove the fan, even some of those above didn't work. I don't know why such a low frequency is needed, other PWM uses such as driving an LED can use hundreds of Hz, so what is up with the fan motor?

druck13 avatar May 18 '20 16:05 druck13

I was trying to make an Arch package of fanshim-python-pwn. Unfortunately it does not work. Problems in Python indentation, not only on a single line. Tried to fix init.py with autopep8 without success.

olm52 avatar Jun 23 '20 12:06 olm52

I got my Fanshim PWM code to work reliably although it was difficult to find Frequencies/Duty Cycles that worked reliably. BUT I left the R Pi 4 for several weeks in continuous use. When I checked up on it a week or two ago I found the fan had worn out to the point where no values could be found to get it to work.

So now I have removed the Fanshim and fitted the large Pimorini Heatsink. For what I use my R Pi 4 this is more than adequate and I have no intention of ever using the Fanshim again.

If I purchase another R Pi 4 I think I would consider buying one of the many passive heat sink solutions that have emerged in recent months by which I mean those ones where the whole case is the heat sink but I might just use the simple solution mentioned above. To select a case I would start by watching this YouTube Video again on a selection of cases. Testing Raspberry Pi Cases with Stressberry & iPerf

If you have a fanshim and want to use it in an application where the Pi is used for long periods I would recommend setting the temperatures quite high so that the fan does not run very often. The Pi will be fine running in the 65C to 75C area.

grayerbeard avatar Jun 23 '20 14:06 grayerbeard

On 23/06/2020 15:23, David Torrens wrote:

I got my Fanshim PWM code to work reliably although it was difficult to find Frequencies/Duty Cycles that worked reliably. BUT I left the R Pi 4 for several weeks in continuous use. When I checked up on it a week or two ago I found the fan had worn out to the point where no values could be found to get it to work.

I think the main problem with the fanshim is the use of a tiny 30mm fan, they don't seem to be very durable, I'm on my 3rd one after just over a year. My 3B and 3B+ both have normal 40mm fans running continuously (on 3.3V) for far longer, and are showing now signs of wear.

If it was redesigned (along with the case) to use a 40mm fan with PWM as default (to run at the equivalent lower speed of using 3.3V) it would be much better.

So now I have removed the Fanshim and fitted the large Pimorini Heatsink https://shop.pimoroni.com/products/raspberry-pi-4-heatsink. For what I use my R Pi 4 this is more than adequate and I have no intention of ever using the Fanshim again.

I'm using that heatsink with my other Pi 4 and it works very well, idling at around 55C and only getting up in to the high 60s when web browsing. That one is running at the standard 1.5GHz, the one with the fanshim is overclocked to 2GHz, I checked see how well the heatsink worked when over clocked and it ran up to 10C warmer, which I feel is a bit too hot.

Cheers ---David

druck13 avatar Jun 25 '20 11:06 druck13