EP-0152

From 52Pi Wiki
Jump to navigation Jump to search

Raspberry Pi Fan Expansion Board Plus 0.91 OLED V1.0

Oledhat2.jpg

Description

This is a 40pin Raspberry Pi HAT type expansion board, which provides a 0.91 inch display screen connected to the I2C pin. The display information can be customized through the program.
It provides an ultra-thin 4007 silent fan to provide heat dissipation support. There are also 4 customizable LED lights on the back of the board. You can also control the lighting mode of the LED lights through simple programming. The previous HAT board design is used. The 40Pin GPIO can still be easily accessed by users. The new fixing method avoids the risk of short circuit caused by metal parts and provides a good appearance design.

 Raspberry Pi 4B does not include in the package.

Features

  • Speed Adjustable Fan
  • 0.91 Inch OLED Display
  • Programmable LED Indicator
  • High Performance Heat Dissipation
  • GPIO expandable interface
  • Hat Style
  • Compatible with Raspberry Pi 2B/3B/3B+/4B
  • Programmable Background light (Controlled by GPIO)

Gallery

  • Product Outlook
Oledhat2.jpg


  • Top view
Oledfan3.jpg


Package Includes

  • 1 x Raspberry Pi Fan Expansion Board Plus 0.91 OLED V1.0
OLEDFAN清单.jpg


How to assemble

  • Connect the Hat board to the GPIO pins of the Raspberry Pi.
  • Fix the hat with copper pillars and nuts.
  • Fix the hat to Raspberry Pi with screws.

Assemble Steps

Oledfan安装.jpg


How to enable Fan

For Raspberry Pi 5

  • Due to compatibility issues with the RPI.GPIO library on Raspberry Pi 5, it can lead to a RuntimeError: Cannot determine SOC peripheral base address, hence the choice to use the gpiozero library for LED control and fan speed control.
  • Install python3-gpiozero library
sudo apt update 
sudo apt upgrade -y 
sudo apt -y install python3-gpiozero 
  • Create python file to control LEDs, use thonny IDE or other editor, such as vim.tiny and nano editor.
 
vim.tiny demo_leds_blinking.py 

Copy and paste following code:

 
from gpiozero import LED
from time import sleep


led1 = LED(19)  # BCM Naming system, 19 means GPIO19 
led2 = LED(13)  
led3 = LED(6)
led4 = LED(5)

interval = 0.2   # delay 0.2 seconds

while True:
    led1.on()
    sleep(interval)
    led2.on()
    sleep(interval)
    led3.on()
    sleep(interval)
    led4.on()
    sleep(interval)
    led1.off()
    sleep(interval)
    led2.off()
    sleep(interval)
    led3.off()
    sleep(interval)
    led4.off()
    sleep(interval)

Save it and execute it by executing following command:

python3 demo_leds_blinking.py 
  • Fan speed control by using gpiozero library, create a python file named `fan_speed_control.py`, copy and paste following code:
from gpiozero import PWMLED
from time import sleep
import subprocess

# Create a PWMLED object for the fan, assuming it's connected to GPIO 14
fan = PWMLED(14)

# Function to get the CPU temperature
def get_cpu_temperature():
    try:
        # Use the vcgencmd command to get the CPU temperature
        output = subprocess.check_output(['vcgencmd', 'measure_temp']).decode('utf-8')
        # Extract the temperature value
        return float(output.replace('temp=', '').replace("'C\n", ''))
    except Exception as e:
        print(f"Error getting CPU temperature: {e}")
        return None

try:
    while True:
        # Get the CPU temperature
        temp = get_cpu_temperature()
        print(temp)
        if temp is not None:
            # Adjust the fan speed based on the temperature, 45 means CPU temperature is reached to 45 degree, you can modify as your wish. 
            if temp > 45:
                fan.value = 1.0  # Fan at full speed
            elif temp < 38:
                fan.value = 0.0  # Fan off
            else:
                fan.value = 0.5  # Fan at half speed

        # Sleep for a short period to avoid high CPU usage
        sleep(0.1)

except KeyboardInterrupt:
    # When Ctrl+C is caught, turn off the fan and exit
    fan.off()
  • 0.91 inch OLED display please refer to instruction below, it is the same as it on Raspberry Pi 4B.

For Raspberry Pi 4 and old version OS

  • Fit for old Raspberry Pi OS: bullseye
  • Open a terminal and typing following command:

sudo raspi-config

  • Navigate to `4 Performance Options` -> `P4 Fan` -> `Yes` -> `14` -> `60` -> `OK` -> `OK` -> `Finish` -> `YES`.
  • Raspberry Pi will reboot and take effect.

How to control fan speed automatically by CPU temperature

  • Create a new python file, name it as "auto_fan.py"
  • Copy and paste following code into this file.
 #!/usr/bin/python3

import RPi.GPIO as GPIO
import time
import subprocess

GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.OUT)
pwm = GPIO.PWM(14,100)

print("\nPress Ctrl+C to quit \n")
dc = 0
pwm.start(dc)

try:
    while True:
        temp = subprocess.getoutput("vcgencmd measure_temp|sed 's/[^0-9.]//g'")
        if round(float(temp)) >= 45:
            dc = 100
            pwm.ChangeDutyCycle(dc)
            print("CPU Temp:",float(temp)," Fan duty cycle:",dc)
            time.sleep(180.0)
        if round(float(temp)) >= 40:
            dc = 85
            pwm.ChangeDutyCycle(dc)
            print("CPU Temp:",float(temp)," Fan duty cycle:",dc)
            time.sleep(120.0)
        else:
            dc = 70
            pwm.ChangeDutyCycle(dc)
            print("CPU Temp:",float(temp)," Fan duty cycle:",dc)
            time.sleep(60.00)

except KeyboardInterrupt:
    pwm.stop()
    GPIO.cleanup()
    print("Ctrl + C pressed -- Ending program")

  • Save it and execute it on terminal
python auto_fan.py  &

How to check if OLED dislay has been recognized?

  • Enable I2C interface
sudo raspi-config
  • Navigate to `Interface Options` -> `I2C` -> `Enable` -> `YES`.
  • Detect If OLED has been recognized.
i2cdetect -y 1
  • OLED default address: `0x3c`

How to lights up OLED Display?

  • Enabling The I2C Interface

The I2C interface may not be enabled by default on your SBC. To check if it is enabled:

$ dmesg | grep i2c
[    4.925554] bcm2708_i2c 20804000.i2c: BSC1 Controller at 0x20804000 (irq 79) (baudrate 100000)
[    4.929325] i2c /dev entries driver

or:

$ lsmod | grep i2c
i2c_dev                 5769  0
i2c_bcm2708             4943  0
regmap_i2c              1661  3 snd_soc_pcm512x,snd_soc_wm8804,snd_soc_core

If you have no kernel modules listed and nothing is showing using dmesg then this implies the kernel I2C driver is not loaded.

For Raspberry Pi OS, enable the I2C driver as follows:

  • Run sudo raspi-configUse the down arrow to select 5 Interfacing Options
  • Arrow down to P5 I2C
  • Select yes when it asks you to enable I2C
  • Also select yes when it asks about automatically loading the kernel module
  • Use the right arrow to select the <Finish> button
  • After rebooting re-check that the dmesg | grep i2c command shows whether I2C driver is loaded before proceeding. You can also enable I2C manually if the raspi-config utility is not available.
  • Then reboot.
  • Next, add your user to the i2c group and install i2c-tools:
$ sudo usermod -a -G i2c pi
$ sudo apt-get install i2c-tools

Logout and in again so that the group membership permissions take effect

Determining Address

Check that the device is communicating properly (if using a rev.1 board, use 0 for the bus, not 1) and determine its address using i2cdetect:

$ i2cdetect -y 1
       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  00:          -- -- -- -- -- -- -- -- -- -- -- -- --
  10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
  40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  70: -- -- -- -- -- -- -- --

The address for your device will be needed when you initialize the interface. In the example above, the display address is 0x3c. Keep in mind that I2C buses can have more than one device attached. If more than one address is shown when you run i2cdetect, you will need to determine which one is associated with your display. Typically displays will only support a limited set of possible addresses (often just one). Checking the documentation can help determine which device is which.

Software settings

Before installing the library, create a virtual environment for your project using:

$ python3 -m venv ~/luma-env

This creates a virtual environment in the home directory called luma-env and a Python executable at ~/luma-env/bin/python.

  • Next, install the latest version of the library in the virtual environment directly with:
$ ~/luma-env/bin/python -m pip install --upgrade luma.oled --break-system-packages

This will normally retrieve all of the dependencies luma.oled requires and install them automatically.

Installing Dependencies

If pip is unable to automatically install its dependencies you will have to add them manually. To resolve the issues you will need to add the appropriate development packages to continue.

If you are using Raspberry Pi OS you should be able to use the following commands to add the required packages:

$ sudo apt-get update
$ sudo apt-get install python3 python3-pip python3-pil libjpeg-dev zlib1g-dev libfreetype6-dev liblcms2-dev libopenjp2-7 -y 

Permissions

luma.oled uses hardware interfaces that require permission to access. After you have successfully installed luma.oled you may want to add the user account that your luma.oled program will run as to the groups that grant access to these interfaces.:

$ sudo usermod -a -G gpio,i2c pi

Replace pi with the name of the account you will be using.

Clone repository of luma.examples

git clone https://github.com/rm-hull/luma.examples.git
cd luma.examples
sudo -H pip install -e . --break-system-packages 

Run the examples

cd examples/
python3 demo.py --help 

NOTE: This 0.91inch OLED display's resolution is 128x32 pixels

How to display system information on OLED display?

  • Display basic system information need psutil installed.
sudo -H pip install psutil --break-system-packages
sudo apt -y install python3-dev

According to the examples demo, you can just use "sys_info.py" to display the system information, but the fonts need to be changed so that it can display clearly. check the fonts file in luma.examples/examples/fonts folder, and select one of the fonts to replace the font settings in sys_info.py. For examples: replace 'C&C Red Alart [INET].ttf' in sys_info.py to 'DejaVuSansMono.ttf' find this line:

 font_path = str(Path(__file__).resolve().parent.joinpath('fonts', 'C&C Red Alert [INET].ttf'))

replace it to :

 font_path = str(Path(__file__).resolve().parent.joinpath('fonts', 'DejaVuSansMono.ttf'))

save it and execute this python script.

python3 sys_info.py

You will see the system information on OLED display.

How to customize your own system infor display?

  • According to demo.py of luma.examples, you can create your own system infor and display on OLED display.

For example, I want to display CPU temperature and IP address of Pi, and disk usage of my pi, I create a new python script as following:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import subprocess
from demo_opts import get_device
from luma.core.render import canvas


def system_infor(device, draw):
    # First define some constants to allow easy resizing of shapes
    # Move left to right keeping track of the current x position for drawing shapes
    x = 2

    # grap temperature of CPU
    temp =subprocess.getoutput("vcgencmd measure_temp | sed 's/[^0-9.*]//g'")
    # grap capacity of disk usage of /
    disk_usage = subprocess.getoutput("df -Th / | awk '{print $6}' | tail -n1")
    # grap memory infor
    free_mem = subprocess.getoutput("free -g |grep Mem | awk '{print $4}'")
    # Network Status
    IP = subprocess.getoutput("hostname -I | awk '{print $1}'")
    draw.rectangle((x, 0, 128, 32), fill="black")
    # draw.text((device.width - padding - w, top + 4), temp, fill="cyan")
    # draw.text((device.width - padding - w, top + 16), 'haha', fill="purple")
    draw.text((x, 0),'CPU TEMP:', fill="white")
    draw.text((56, 0), temp, fill="white")
    draw.text((82, 0), '°C', fill="white")
    draw.text((x, 8),'IP ADDR:', fill="white")
    draw.text((52, 8), IP, fill="white")
    draw.text((x, 16),'SD USAGE:', fill="white")
    draw.text((58, 16), disk_usage, fill="white")
    draw.text((78, 16), 'MEM:', fill="white")
    draw.text((100, 16), free_mem, fill="white")
    draw.text((104, 16), ' GB', fill="white")

    # Draw a rectangle of the same size of screen
    draw.rectangle(device.bounding_box, outline="white")


device = get_device()

while True:
    with canvas(device) as draw:
        system_infor(device, draw)
        time.sleep(5)

  • Save it and execute it in a terminal:
python3 system_info.py --width 128 --height 32
  • You will see:
EP-0152-oled coustize 02.jpg


How can these executable Python scripts be turned into systemd-style background services?

There are three services you can create on your Raspberry Pi OS.

  • 1. Service of Fan control by CPU temperature
  • 2. Service of LEDs blinking patterm.
  • 3. Service of OLED display control

At the first, you need to create all of the demo code in your system. Following is the demo code:

  • Fan controlled by CPU's temperature, create a python script file named it autofan.py and place it to /home/pi/fan_test/ folder:
#!/usr/bin/python3

import RPi.GPIO as GPIO
import time
import subprocess

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

pwm = GPIO.PWM(14, 100)

# print("\nPress Ctrl+C to quit \n")

dc = 0

pwm.start(dc)

try:
    while True:
        temp = subprocess.getoutput("vcgencmd measure_temp|sed 's/[^0-9.]//g'")
        if round(float(temp)) >= 45:
            dc = 100
            pwm.ChangeDutyCycle(dc)
            time.sleep(180)

        if round(float(temp)) >= 40:
            dc = 85
            pwm.ChangeDutyCycle(dc)
            time.sleep(120)
        else:
            dc = 70
            pwm.ChangeDutyCycle(dc)
            time.sleep(60)

except KeyboardInterrupt:
    pwm.stop()
    GPIO.cleanup()
  • Save it and make sure it can execute in your terminal.
  • Next step is to create a systemd style file in location: '/etc/systemd/system/'
sudo vim.tiny /etc/systemd/system/52piFan.servicce 

And filling following lines:

[Unit]
Description=52Pi Pi fan expansion board Fan control service v1.0
After=multi-user.target

[Service]
Type=simple
RemainAfterExit=true
ExecStart=/usr/bin/python3 /home/pi/fan_test/autofan.py

[Install]
WantedBy=multi-user.target
  • Save it and reload the daemon and start service .
sudo systemctl daemon-reload
sudo systemctl enable 52piFan.service
sudo systemctl start 52piFan.service

And use the same method to create another services: For the LEDs, for examples, create a python file called: led_blinking.py in /home/pi location as following demo code.

import RPi.GPIO as GPIO
import time


LED1 = 19 # BCM naming system
LED2 = 13
LED3 = 6
LED4 = 5
interval = 0.2

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)

while True:
    for i in range(10):
        GPIO.output(LED1, GPIO.HIGH)
        time.sleep(interval)
        GPIO.output(LED2, GPIO.HIGH)
        time.sleep(interval)
        GPIO.output(LED3, GPIO.HIGH)
        time.sleep(interval)
        GPIO.output(LED4, GPIO.HIGH)
        time.sleep(interval)

    time.sleep(1)

    for i in range(10):
        GPIO.output(LED1, GPIO.LOW)
        time.sleep(interval)
        GPIO.output(LED2, GPIO.LOW)
        time.sleep(interval)
        GPIO.output(LED3, GPIO.LOW)
        time.sleep(interval)
        GPIO.output(LED4, GPIO.LOW)
        time.sleep(interval)

GPIO.cleanup()

and then create systemd file in /etc/systemd/system/lights.service

sudo vim.tiny /etc/systemd/system/lights.service

and filling with following lines:

[Unit]
Description=52Pi Raspberry Pi Fan Extansion board Plus 0.91 OLED v1.0
After=multi-user.target

[Service]
Type=simple
RemainAfterExit=true
ExecStart=/usr/bin/python3 /home/pi/led_blinking.py

[Install]
WantedBy=multi-user.target
  • save it and reload daemon as previous steps
sudo systemctl daemon-reload
sudo systemctl enable lights.service
sudo systemctl start lights.service
  • For the OLED display is the same.

For example, you have already create virtual env in your local system, the path of the venv location will be at /home/pi/luma-env/luma.examples/examples/, and I have create my own customized script named "system_infor.py". so the systemd file be like:

  • Create a systemd file named: oled.service
sudo vim.tiny /etc/systemd/system/oled.service
  • Filling the file with following lines:
[Unit]
Description=52Pi Pi Fan Expansion board plus OLED display service v1.0
After=multi-user.target

[Service]
Type=simple
RemainAfterExit=true
ExecStart=/usr/bin/python3 /home/pi/luma-env/luma.examples/examples/system_infor.py --width 128 --height 32

[Install]
WantedBy=multi-user.target
  • Save it and reload the daemon
sudo systemctl daemon-reload
sudo systemctl enable oled.service
sudo systemctl start oled.service
  • After that, even if you reboot your Raspberry Pi, it will bring up automatically.

Easy Install

  • Download the repository from github:
git clone https://github.com/geeekpi/RPiFEBP.git
cd RPiFEBP/
./install.sh 

More information please refer to README.md file.

How to Setup LED indicator

  • LED indicators Pin out

There are 4 LED under the PCB board.

- LED1 - nearby the GPIO pins and fan on left corner, connect to `GPIO 24` (BCM 19)
- LED2 - under LED1, connect to `GPIO 23` (BCM 13)
- LED3 - on the right of LED2, connect to `GPIO 22` (BCM 6) 
- LED4 - on the top of LED3, connect to `GPIO 21` (BCM 5) 
  • Create python script as following:
 
import RPi.GPIO as GPIO
import time 

LED1 = 19
LED2 = 13
LED3 = 6
LED4 = 5

GPIO.setmode(GPIO.BCM)
GPIO.setup(LED1,GPIO.OUT)
GPIO.setup(LED2,GPIO.OUT)
GPIO.setup(LED3,GPIO.OUT)
GPIO.setup(LED4,GPIO.OUT) 

while True:
    for i in range(10):
        GPIO.output(LED1, GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(LED2, GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(LED3, GPIO.HIGH)
        time.sleep(0.5)
         GPIO.output(LED4, GPIO.HIGH)
        time.sleep(0.5)
    time.sleep(1)
        for i in range(10):
            GPIO.output(LED1, GPIO.LOW)
            time.sleep(0.5)
            GPIO.output(LED2, GPIO.LOW)
            time.sleep(0.5)
            GPIO.output(LED3, GPIO.LOW)
            time.sleep(0.5)
            GPIO.output(LED4, GPIO.LOW)
            time.sleep(0.5)
 * Save it and execute it.
<pre>
python3 led_blink.py
  • Reinstall wiringPi library.(Deprecated)
sudo apt -y purge wiringpi
hash -r 
cd /tmp
wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb
gpio readall
  • Demo code in shell:
for i in `seq 21 24`
 do 
    gpio mode $i out
 done 

while true
do 
  for i in `seq 21 24`
  do
	gpio write $i 1 
  	sleep 0.01
  	gpio write $i 0
  done
done

Control LED on the bottom of expansion board by using RPi.GPIO library.

  • Demo code in Python:
import RPi.GPIO as GPIO
import time 


# BCM Number of LED indicators
leds = [5, 6, 13, 19]

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

for i in range(len(leds)):
    GPIO.setup(leds[i], GPIO.OUT)


try:
    while True:
	for led in leds:
       	    GPIO.output(led, GPIO.HIGH)
	    time.sleep(0.01)
            GPIO.output(led, GPIO.LOW)
except KeyboardInterrupt:
    GPIO.cleanup()
    print("BYE")

Keywords

  • Raspberry Pi Fan Expansion Board Plus 0.91 OLED V1.0, Fan expansion board, oled 0.91, raspberry Pi 4B, heat dissipation, hat board for raspberry Pi 4B