Skip to content

Instantly share code, notes, and snippets.

@SqyD
Last active November 23, 2022 07:30
Show Gist options
  • Select an option

  • Save SqyD/a927ab612df767a0cc892bcde23d025c to your computer and use it in GitHub Desktop.

Select an option

Save SqyD/a927ab612df767a0cc892bcde23d025c to your computer and use it in GitHub Desktop.
mqtt-pi-pwn-fan

MQTT client to control a PWM fan from a raspberry pi

A simple python script to control a fan from Home Assistant.

Note: I have replaced this Raspberry based solution with an Wemos/ESPHome based one you can find here:

https://gist.github.com/SqyD/38d10391c2e21988406d2bdaec24f031

  • Installing dependencies on a stock Raspbian install:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-pip python3-dev python3-gpiozero 
sudo pip3 install paho-mqtt
  • Create the python script as /home/pi/mqtt_fan.py
  • Create a systemd service definition file as /lib/systemd/system/mqtt_fan.service
  • Set permissions:
sudo chmod 644 /lib/systemd/system/mqtt_fan.service
  • Enable and test the service:
sudo systemctl daemon-reload
sudo systemctl enable mqtt_fan.service
sudo systemctl start mqtt_fan.service
# Snippet to add to a Home Assistant configuration yaml file
mqtt:
fan:
- platform: mqtt
name: "My Fan"
command_topic: "homeassistant/test_fan/on/set"
state_topic: "homeassistant/test_fan/on/state"
speed_command_topic: "homeassistant/test_fan/speed/set"
speed_state_topic: "homeassistant/test_fan/speed/state"
payload_low_speed: "low"
payload_medium_speed: "medium"
payload_high_speed: "high"
speeds:
- low
- medium
- high
#!/usr/bin/python3
import paho.mqtt.client as mqtt
from gpiozero import PWMOutputDevice
# MQTT configuration
broker = '127.0.0.1'
device_id = 'test_fan'
on_topic = 'homeassistant/' + device_id + '/on/set'
on_state_topic = 'homeassistant/' + device_id + '/on/state'
speed_topic = 'homeassistant/' + device_id + '/speed/set'
speed_state_topic = 'homeassistant/' + device_id + '/speed/state'
# gpio settings
gpio_pin = 18
pwm_freq = 5000
speeds = {'low': 0.05, 'medium': 0.4, 'high': 1}
class PwmFan:
on_state = 'OFF'
pwm = PWMOutputDevice(gpio_pin,frequency=pwm_freq)
speed_state = 'high'
def switch(self, onoff):
if onoff == 'ON':
if self.on_state == 'OFF':
self.on_state = 'ON'
self.set_speed(self.speed_state)
elif onoff == 'OFF':
if self.on_state == 'ON':
self.on_state = 'OFF'
self.pwm.off()
def set_speed(self,speed):
if speed in speeds:
if self.on_state == 'ON':
self.pwm.value=speeds[speed]
self.speed_state = speed
fan = PwmFan()
def on_message(client, userdata, message):
payload = str(message.payload.decode("utf-8"))
topic = message.topic
if topic == on_topic:
print("ON/OF command received")
if (payload == 'ON') or (payload == 'OFF'):
print("turning " + payload)
fan.switch(payload)
client.publish(on_state_topic, payload)
if payload == 'ON':
client.publish(speed_state_topic, fan.speed_state)
elif message.topic == speed_topic:
if payload in speeds:
print('Setting speed to ' + payload)
fan.set_speed(payload)
if fan.on_state == 'ON':
client.publish(speed_state_topic, fan.speed_state)
# Send messages in a loop
client = mqtt.Client("myfan")
client.on_message = on_message
# If your homeassistant is protected by as password, uncomment this next line:
# client.username_pw_set('homeassistant','yourpasswordhere')
client.connect(broker)
client.subscribe(on_topic)
client.subscribe(speed_topic)
client.loop_forever()
[Unit]
Description=MQTT Fan
After=multi-user.target
[Service]
Type=idle
ExecStart=/usr/bin/python3 /home/pi/mqtt_fan.py
[Install]
WantedBy=multi-user.target
@ReliableBob
Copy link
Copy Markdown

Hi.
Thanks for the great code.
Please tell me how to properly connect the fan to the GPIO? It needs to be connected directly or through a transistor.
Please give me the connection diagram.
Thank.

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 9, 2019

Thanks!

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 10, 2019

How can I use authentication for the mqtt client?

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 10, 2019

and when i start mqtt_fan.py :
gpiozero.exc.PinPWMUnsupported: PWM is not supported on pin GPIO18

@ReliableBob
Copy link
Copy Markdown

ReliableBob commented May 10, 2019

How can I use authentication for the mqtt client?

# If your homeassistant is protected by as password, uncomment this next line:
# client.username_pw_set('homeassistant','yourpasswordhere')

@ReliableBob
Copy link
Copy Markdown

and when i start mqtt_fan.py :
gpiozero.exc.PinPWMUnsupported: PWM is not supported on pin GPIO18

GPIO18 and there is a PWM

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 10, 2019

@ReliableBob
how could I not notice! Inattentive :) thanks. But I don’t understand why I get a error on pin18

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 10, 2019

@ReliableBob
root@osmc:/home/osmc/mqtt# sudo python3 mqtt_fan.py /usr/local/lib/python3.5/dist-packages/gpiozero/devices.py:279: PinFactoryFallba ck: Falling back from rpigpio: No module named 'RPi' 'Falling back from %s: %s' % (name, str(e)))) /usr/local/lib/python3.5/dist-packages/gpiozero/devices.py:279: PinFactoryFallba ck: Falling back from rpio: No module named 'RPIO' 'Falling back from %s: %s' % (name, str(e)))) /usr/local/lib/python3.5/dist-packages/gpiozero/devices.py:279: PinFactoryFallba ck: Falling back from pigpio: No module named 'pigpio' 'Falling back from %s: %s' % (name, str(e)))) Traceback (most recent call last): File "mqtt_fan.py", line 19, in <module> class PwmFan: File "mqtt_fan.py", line 21, in PwmFan pwm = PWMOutputDevice(gpio_pin,frequency=pwm_freq) File "/usr/local/lib/python3.5/dist-packages/gpiozero/devices.py", line 124, i n __call__ self = super(GPIOMeta, cls).__call__(*args, **kwargs) File "/usr/local/lib/python3.5/dist-packages/gpiozero/output_devices.py", line 418, in __init__ self.pin.frequency = frequency File "/usr/local/lib/python3.5/dist-packages/gpiozero/pins/__init__.py", line 358, in <lambda> lambda self, value: self._set_frequency(value), File "/usr/local/lib/python3.5/dist-packages/gpiozero/pins/__init__.py", line 354, in _set_frequency raise PinPWMUnsupported("PWM is not supported on pin %r" % self) gpiozero.exc.PinPWMUnsupported: PWM is not supported on pin GPIO18

@ReliableBob
Copy link
Copy Markdown

Strange things ... I did everything according to the instructions and it works for me without errors ...
Raspberry pi 3 B +

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 10, 2019

@ReliableBob
Really. But I have OSMС on pi2, not raspbian, can be because of this. And I did not manage to install python3-gpiozero via apt, I installed via pip. I will try on another system for the purity of the experiment.

@kvvoff
Copy link
Copy Markdown

kvvoff commented May 11, 2019

I needed a "wheel" setup for latest osmс

apt-get update
apt-get install python3-pip python3-dev gcc
apt-get install python3-setuptools
pip3 install wheel
pip3 install gpiozero

its working for me on my osmc, raspberry pi 2 model b

@SqyD
Copy link
Copy Markdown
Author

SqyD commented May 22, 2019

Please tell me how to properly connect the fan to the GPIO? It needs to be connected directly or through a transistor.
I used a cheap hardware PWM to 10V board since my ventilation unit has a 0-10V input. I don't have a diagram and my setup is likely different then yours. My ventilation unit has a 12V output and a 0-10V input. I used the PWM to 0-10V board to convert the GPIO PWM output to the variable voltage. I hope this clarifies things.

@ReliableBob
Copy link
Copy Markdown

Да, спасибо. Я всё понял.

Please tell me how to properly connect the fan to the GPIO? It needs to be connected directly or through a transistor.
I used a cheap hardware PWM to 10V board since my ventilation unit has a 0-10V input. I don't have a diagram and my setup is likely different then yours. My ventilation unit has a 12V output and a 0-10V input. I used the PWM to 0-10V board to convert the GPIO PWM output to the variable voltage. I hope this clarifies things.

Yes thank you. I got it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment