Saturday, December 12, 2020

0000 0000 0100 1101

Orange Pi temperature control

There is an Orange Pi Zero attached to my 3D printer running OctoPrint as per a previous post and YouTube video. On the assumption that it might run hot at times (introducing the possibility of a throttle or shutdown scenario) I connected a fan to the top of the printed enclosure which runs continuously off the 5V rail.


The fan is a bit noisy, although that doesn't matter as the unit is located downstairs in the garage/workshop, but also I was thinking that it may not be necessary to have the fan running all of the time. Maybe it only needs to cut in and out as the temperature of the board changes?

While the Orange Pi Zero is working well with the printer at the moment I don't want to hassle it too much, so to test a few ideas kicking around in my noggin I grabbed an Orange Pi PC as a guinea pig instead.

I loaded an SD card with the appropriate version of Armbian (choosing the "focal" version). Included with the OS is the command "armbianmonitor -m" which can check the temperature of the SOC directly. You can also find out the temperature via the command:

"cat /sys/class/thermal/thermal_zone0/temp"

...which will output something like 29200 if the temperature is 29.2°C.

The first (and most recommended) method of temperature mitigation for this board is to attach a heat sink to the SOC, in this case an ARM H3+.


Without doing extensive tests, this one simple modification did lower the temperature quite a bit - and I'm pretty sure from reading a few of the forums posts out there that this would be sufficient to keep the board cool. The only thing is that if the board does start to overheat, then performance is throttled and perhaps a a long print run might end up being interrupted and/or stopped - very sad!

Therefore, I 3D-printed a suitable enclosure that allowed for a fan to be installed directly over the SOC.

The fan works directly from either the 5V or the 3.3V rail as per the Orange Pi Zero version, but here I wanted to dive a little deeper and control the fan according to need. After reading about many options, I found this site which recommended a GPIO linked to a transistor as a switching mechanism (I've altered the circuit to suit as shown below).

Then, by controlling the GPIO status (HIGH or LOW), it should be possible to turn on and off the fan as required. Although many sites recommended a python-based solution for the control of the pin, I chose a bash script instead as per this github repository because I plan to have the script run at start-up (perhaps as a daemon) and this solution seemed the most likely to succeed.

I had to modify the script a bit (to include for instance hysteresis and address some scripting errors), but it ended up being as follows:

#!/bin/sh -e
#
#fantemp.sh
#
# see https://github.com/orangepi-xunlong/wiringOP for building wiringOP
#
# +------+-----+--------+OrangePiH3+-------+-----+------+
# | GPIO | wPi | Name	| Physical | Name  | wPi | GPIO |
# +------+-----+--------+----++----+-------+-----+------+
# |      |     |   3.3V |  1 || 2  | 5V	   | 	 |      |
# |   12 |   0 |  SDA.0 |  3 || 4  | 5V	   | 	 | 	|
# |   11 |   1 |  SCL.0 |  5 || 6  | GND   | 	 | 	|
# |    6 |   2 |    PA6 |  7 || 8  | TXD.3 | 3   | 13   |
# |      |     |    GND |  9 || 10 | RXD.3 | 4   | 14   |
# |    1 |   5 |  RXD.2 | 11 || 12 | PD14  | 6   | 110  |
# |    0 |   7 |  TXD.2 | 13 || 14 | GND   | 	 | 	|
# |    3 |   8 |  CTS.2 | 15 || 16 | PC04  | 9   | 68   |
# |      |     |   3.3V | 17 || 18 | PC07  | 10  | 71   |
# |   64 |  11 | MOSI.0 | 19 || 20 | GND   | 	 | 	|
# |   65 |  12 | MISO.0 | 21 || 22 | RTS.2 | 13  | 2    |
# |   66 |  14 | SCLK.0 | 23 || 24 | CE.0  | 15  | 67   |
# |      |     |    GND | 25 || 26 | PA21  | 16  | 21   |
# |   19 |  17 |  SDA.1 | 27 || 28 | SCL.1 | 18  | 18   |
# |    7 |  19 |   PA07 | 29 || 30 | GND   | 	 | 	|
# |    8 |  20 |   PA08 | 31 || 32 | RTS.1 | 21  | 200  |
# |    9 |  22 |   PA09 | 33 || 34 | GND   | 	 | 	|
# |   10 |  23 |   PA10 | 35 || 36 | CTS.1 | 24  | 201  |
# |   20 |  25 |   PA20 | 37 || 38 | TXD.1 | 26  | 198  |
# |      |     |    GND | 39 || 40 | RXD.1 | 27  | 199  |
# +------+-----+--------+----++----+-------+-----+------+
# | GPIO | wPi | Name	| Physical | Name  | wPi | GPIO |
# +------+-----+--------+OrangePiH3+-------+-----+------+
#

# see above table
PIN=6

# two temperatures for hysteresis
TEMP1=35000 # 35 degrees
TEMP2=45000 # 45 degrees

gpio mode $PIN out

while true; do
  if [ $(cat /sys/class/thermal/thermal_zone0/temp) -gt $TEMP1 ] \
  && [ $(cat /sys/class/thermal/thermal_zone0/temp) -gt $TEMP2 ]
  then
    gpio write $PIN 1
  elif [ $(cat /sys/class/thermal/thermal_zone0/temp) -lt $TEMP2 ] \
    && [ $(cat /sys/class/thermal/thermal_zone0/temp) -lt $TEMP1 ]
  then
    gpio write $PIN 0
  fi
  sleep 5
done

As part of testing, I dialed up a stress test as follows:

stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 45s

Monitoring of the CPU showed the temperature shooting up, and then the fan coming on and keeping everything cool - only to turn off when the "stress" is off. Very good result!

The final part was to solder up a board with the extra bits including the transistor to be placed inside the cooled housing, and make all the connections as per the breadboard test.

Now all I need to do is to retrofit this solution to the Orange Pi Zero attached to the printer and that will be mission accomplished!




2 comments:

  1. Nice blog and video, as usual. I think the script could be simplified. In the first 'it's you're saying "is the temperature greater than 35 and greater than 45" . That will only be true if the temperature is > 45, so you only need to test for that. Similarly for the 'elif', just text for < 35.

    ReplyDelete
  2. I think you are quite correct. I can only say that I was being a little too prescriptive in the hope of clarity!

    ReplyDelete