About This Project
Well first I did this project because I was looking for a new thing to do with my daughter .
The projects that work well right now for a father/daughter cooperation are small but still interesting for daddy while ideally using a lot of components daughter can play with. Also with a minimum of code because this daddy needs to do alone at night as it doesnât attract attention as much.
Use-case
Even for toy projects required to have a valid use-case and for this one it was for mommy too start the air conditioner in the bus while going home.
Step 1 - Carrier frequency
This AC is controller by an IR remote so we first had to get the carrier frequency which we managed to do here using an IR led in a received kinda mode.
You canât see it on the scope now but the received signal was not even above the noise level which was pretty high on the 20 seconds setup but we knew what we were looking for and we managed to find a pretty convincing 38 khz.
Step 2 - The circuit
Infrared transmitter
The plan was to use python as much as possible coupled with lirc.
I looked around and it seems that people are modulating in the kernel driver but I was pretty convinced to do a clean 38khz using a 555 so thatâs what we did. I must say Iâm not much of an analog guy but if a couple resistors can buy me a clean non jittery signal Iâm in.
So basically we go from pin 18 of the the raspberry pi to the reset pin of the 555. The output pin of the 555 controls a nice big n-channel mosfet which drives the ir led at just under 200 mA.
I then setup the lirc driver to disable carrier control.
I chose pin 18 because I though that if the 555 idea would fail me, I would use the raspberry pi hardware pwm instead.
In the end, that gave us a nice clean ir signal.
Infrared receiver
We kinda had to also have a receiver to allow us to spy on the remote.
To do this we hooked up a vishay ir receiver to pin 17 of the raspberry pi.
Lirc
So we used lirc userspace programs to record the on of the off commands.
We had to fall back to the raw mode as the remote is almost using the NEC protocol but also not. The raw mode did a good job of dealing with the non standard bits of the communication.
I canât remember but this shows either the on or the off command. You can see it uses 2 ir transmissions for a single button press.
We mapped ON to KEY_POWER and OFF to KEY_POWER2 and that is about it.
Step 3 - Code
Cayenne works really well for our father daughter projects as almost no code is required.
I take the time to wish you guys the best of luck. The idea behind the service is really good and even though we are not talking about appleâs like resources here, itâs working pretty well.
Note (Si7021)
We ended up adding an Si7021 as a second phase and youâll see that in the code
So the whole thing looks like this:
import cayenne.client
import time
import subprocess
import smbus2 as smbus
from enum import Enum
from si7021 import Si7021
MQTT_USERNAME = ""
MQTT_PASSWORD = ""
MQTT_CLIENT_ID = ""
def on_message(message):
global push_status
global ac_state
# print("message received: " + str(message))
if message.channel == 4:
if message.value == "1":
print("AC START")
subprocess.run(["irsend", "SEND_ONCE", "ac", "KEY_POWER"])
ac_state = State.on
elif message.value == "0":
print("AC STOP")
subprocess.run(["irsend", "SEND_ONCE", "ac", "KEY_POWER2"])
ac_state = State.off
push_status = True
client = cayenne.client.CayenneMQTTClient()
client.on_message = on_message
#client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
# For a secure connection use port 8883 when calling client.begin:
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID, port=8883)
State = Enum('State', 'on off')
push_status = False
ac_state = None
bus = smbus.SMBus(1)
sensor = Si7021(bus, hold_master_mode=False)
timestamp = 0
while True:
client.loop()
if push_status:
if ac_state == State.on:
# print("State ON")
client.virtualWrite(1, 1, "digital_sensor", "d")
elif ac_state == State.off:
# print("State OFF")
client.virtualWrite(1, 0, "digital_sensor", "d")
push_status = False
if (time.time() > timestamp + 30):
client.virtualWrite(2, sensor.temperature, "temp", "c")
client.virtualWrite(3, sensor.relative_humidity, "rel_hum", "p")
timestamp = time.time()
We control that with a fancy systemd service which ensures the network is operational before starting the script among other things.
Side note on the Si7021
Daddy had quite a bit of problem making the Si7021 work with the raspberry pi.
I didnât go to deep in the issue but it seems that the raspberry pi doesnât handle the i2c clock stretching too well and this is what this lib uses.
Iâm trying to have this upstream right now but to make it work I had to modify the Si7021 to also support getting the humidity level not using the mode which uses clock stretching.
To do this I also had to modify a bit the smbus library to handle the non smbus required transfer in a nice and loosely coupled way.
So I need this accepted first:
Then that:
Once this is done, the library should work with the raspberry pi out of the box with:
pip install smbus2
pip install Si7021
Video
It ended up working quite nicely and you can see the response time is really impressive. I must say itâs orders of magnitude above my expectations.
I goes from app to the server (websocket?), then MQTT to raspberry pi, then python spawns the lirc process, then kernel, then IR.
Just writing this I canât believe it work