I will use these last two blogs to only document the project I have done so far. Though I feel that there is still many things on which I could improve,
add more components and code but I am happy with what I was able to do in this challenge.
There are currently the following parts of the project.
- Raspberry Pi 4B
- Pimoroni Automation HaT
- Pimoroni Enviro HaT
- DPS310 Sensor
- ESP8266 + BME280 (MQTT Publishing)
- WemosD1R1 + BME280 (MQTT Publishing)
- Esp32 Pico V4 + RGB LED Strip (MQTT Subscribing)
Let me first explain what the project is doing. The RaspberryPi is controlling everything. There are sensors on Enviro-Hat and ESP's sending data over
MQTT and Automation Hat's LCD is used to display the data of the sensors.
I have kept publishing and subscribing ESPs separately. In the beginning, I wanted to use ESP8266 for subscribing + publishing the topics but I found some
issues are there with the libraries to do both subscription and publishing at the same time on ESPs. Hence, I decided to only do a subscription for controlling
LED Strips. The LED Strips are controlled in brightness. When an "ON" message is published on a topic by Raspberry Pi LED Strip will start with Lower brightness
and eventually, it will reach full brightness. It will take around 15 mins to blick the entire strip to full brightness.
The color of the strip is normally kept magenta pink as that is the wavelength required by the plants growing in space.
The following code is for controlling the LED strips over MQTT. There are two separate functions to Turn ON/OFF the strip. The topic is published by RaspberryPi.
The ESP32 will subscribe to that topic.
There is the possibility to Turn ON/OFF the LED strip at a specific time of the day.
now = datetime.now() c_t = now.strftime("%H:%M:%S") print("Current time = ", c_t) if(c_t > '05:16:12'): #Publish ON
//ESP32 Pico code #include <SPI.h> #include <MQTT.h> #include "WiFi.h" #include <FastLED.h> #define NUM_LEDS 120 #define DATA_PIN 15 String start = ""; CRGB leds[NUM_LEDS]; const char *ssid = "PiFi"; const char *Pass = "PSK"; const char *Lighttopic = "LEDStrip"; const char *mqtt_username = "ujjval"; const char *mqtt_pass = "PSK"; const char *client_ID = "IDOFCLIENT"; const char* mqtt_server = "192.168.43.71"; WiFiClient WiFiclient; MQTTClient cl1; void messageReceived(String &topic, String &payload){ Serial.println("incoming: " + topic + " - " + payload); if(payload=="ON" & start!="started"){ control_lights_on(); } else if(payload=="OFF"){ control_lights_off(); } } void setup() { // put your setup code here, to run once: delay(2000); FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(100); Serial.begin(9600); Serial.print("Connecting to the WiFi.."); Serial.print(ssid); WiFi.begin(ssid, Pass); while(WiFi.status() != WL_CONNECTED){ Serial.print(".."); delay(500); } cl1.begin(mqtt_server, 1883, WiFiclient); cl1.onMessage(messageReceived); if(!cl1.connect(client_ID, mqtt_username, mqtt_pass, false)){ Serial.print(".."); delay(500); } } void loop() { // put your main code here, to run repeatedly: cl1.loop(); delay(10); if(!cl1.connected()){ cl1.connect(client_ID, mqtt_username, mqtt_pass); delay(20); } Serial.println("Connected to LEDStrip"); cl1.subscribe("LEDStrip"); cl1.loop(); delay(10); delay(10); //LED Strip programming delay(10); } void control_lights_on(){ start="started"; for(int bright=10; bright<=150; bright++){ for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1){ // Turn our current led on to white, then show the leds leds[whiteLed] = CRGB::Purple; // Show the leds (only one of which is set to white, from above) FastLED.show(); FastLED.setBrightness(bright); // Wait a little bit delay(10); //leds[whiteLed] = CRGB::Black; delay(10); } delay(5000); } } void control_lights_off(){ for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) { leds[whiteLed] = CRGB::Black; FastLED.show(); delay(10); } start = ""; }
The ESP8266 and Wemos D1R1 with BME280 has almost a similar code running. They will gather the temperature/humidity data from the sensor and publish it on the respective topics.
//ESP8266 code #include <Wire.h> #include <PubSubClient.h> #include <Adafruit_BME280.h> #include "ESP8266WiFi.h" const char *ssid = "PiFi"; const char *Pass = ""; const char *Humiditytopic = "ESP8266_humy"; const char *Temperature "ESP8266_temp"; const char *mqtt_username = "ujjval"; const char *mqtt_pass = ""; const char *client_ID = ""; const char* mqtt_server = "192.168.43.71"; Adafruit_BME280 bme; float t,h,p; WiFiClient WiFiclient; PubSubClient client(mqtt_server, 1883, WiFiclient); void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.print("Connecting to the WiFi.."); Serial.print(ssid); WiFi.begin(ssid, Pass); while(WiFi.status() != WL_CONNECTED){ Serial.print(".."); delay(500); } Wire.begin(); if(client.connect(client_ID, mqtt_username, mqtt_pass)){ Serial.println("Connected to MQTT client.."); } else{ Serial.println("Connection to WifiClient failed."); } Serial.println("BME280 test"); bme.begin(0x76); } void loop() { // put your main code here, to run repeatedly: Serial.println("The weather data from the BME280 sensor.."); Serial.print("Temp = "); t = bme.readTemperature(); Serial.print(t); Serial.print(" *C"); Serial.println(); Serial.print("Humidity = "); h = bme.readHumidity(); Serial.print(h); Serial.print(" %"); Serial.println(); Serial.print("Pressure = "); Serial.print(bme.readPressure()); Serial.print(" hPa"); Serial.println(); Serial.println(); delay(50); if(client.publish(Temperature, String(t).c_str())){ Serial.println("Temprature is sent on MQTT"); } else{ Serial.print("Temprature failed to send, reconnecting and trying again"); Serial.println(); client.connect(client_ID, mqtt_username, mqtt_pass); delay(10); client.publish(Temperature, String(t).c_str()); delay(10); } if(client.publish(Humiditytopic, String(h).c_str())){ Serial.println("Humidity is sent on MQTT"); } else{ Serial.println(); Serial.print("Humidity failed to send, reconnecting and trying again"); client.connect(client_ID, mqtt_username, mqtt_pass); delay(10); client.publish(Humiditytopic, String(t).c_str()); } delay(1000); }
The Wemos D1 is running the following code
//Wemos D1 R1 code #include <Wire.h> #include <PubSubClient.h> #include <Adafruit_BME280.h> #include "ESP8266WiFi.h" const char *ssid = "PiFi"; const char *Pass = ""; const char *Humiditytopic = "/home/top/humidity"; const char *Temperature = "/home/top/temperature"; const char *Lighttopic = "LEDStrip"; const char *mqtt_username = "ujjval"; const char *mqtt_pass = ""; const char *client_ID = ""; const char* mqtt_server = "192.168.43.71"; byte* light; Adafruit_BME280 bme; float t,h,p; WiFiClient WiFiclient; PubSubClient client(mqtt_server, 1883, WiFiclient); //client->setCallback(callback); void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.print("Connecting to the WiFi.."); Serial.print(ssid); WiFi.begin(ssid, Pass); while(WiFi.status() != WL_CONNECTED){ Serial.print(".."); delay(500); } Wire.begin(); if(client.connect(client_ID, mqtt_username, mqtt_pass)){ Serial.println("Connected to MQTT client.."); } else{ Serial.println("Connection to WifiClient failed."); } Serial.println("BME280 test"); bme.begin(0x76); } void loop() { // put your main code here, to run repeatedly: Serial.println("The weather data from the BME280 sensor.."); Serial.print("Temp = "); t = bme.readTemperature(); Serial.print(t); Serial.print(" *C"); Serial.println(); Serial.print("Humidity = "); h = bme.readHumidity(); Serial.print(h); Serial.print(" %"); Serial.println(); Serial.print("Pressure = "); Serial.print(bme.readPressure()); Serial.print(" hPa"); Serial.println(); Serial.println(); delay(50); if(!client.connected()){ client.connect(client_ID, mqtt_username, mqtt_pass); } if(client.publish(Temperature, String(t).c_str())){ Serial.println("Temprature is sent on MQTT"); } else{ Serial.print("Temprature failed to send, reconnecting and trying again"); client.connect(client_ID, mqtt_username, mqtt_pass); delay(10); client.publish(Temperature, String(t).c_str()); delay(10); } if(client.publish(Humiditytopic, String(h).c_str())){ Serial.println("Humidity is sent on MQTT"); } else{ Serial.println(); Serial.print("Humidity failed to send, reconnecting and trying again"); client.connect(client_ID, mqtt_username, mqtt_pass); delay(10); client.publish(Humiditytopic, String(t).c_str()); } client.disconnect(); delay(100); Serial.println("Connected to LEDStrip"); }
The Raspberrypi has both the HaT's and programmed in Python to control everything automatically. The LCD on the Automation HaT will display data
from sensors connected over MQTT and data from Enviro as well.
#!/usr/bin/env python3 import os import sys import time import bme280 import smbus2 from ltr559 import LTR559 sys.path.append(os.path.abspath("/home/pi/1m3pi/MqTT.py")) sys.path.append(os.path.abspath("/home/pi/1m3pi/Disp.py")) from Disp import * import paho.mqtt.client as mqtt import paho.mqtt.subscribe as subscribe import paho.mqtt.publish as publish import DPS from struct import * from datetime import * dps310 = DPS.DPS() ser_add = '192.168.43.71' Wemos_temp = '/home/top/temperature' Wemos_humy = '/home/top/humidity' Esp_temp = 'ESP8266_temp' Esp_humy = 'ESP8266_humy' Lighttopic = 'LEDStrip' mqtt_user ='' mqtt_pass ='' ltr559 = LTR559() port = 1 address = 0x76 bus = smbus2.SMBus(port) cal_par = bme280.load_calibration_params(bus, address) def on_connect(wemos_client, userdata, flags, rc): #print('connected with code' + str(rc)) wemos_client.subscribe((Wemos_temp,0)) wemos_client.subscribe((Wemos_humy,0)) wemos_client.publish("LEDStrip","ON") sleep(0.5) def on_publish(wemos_client, userdata,mid): print ("This call is from the pblish callback\n" "Which means that your message was published") def on_connect1(esp_client, userdata, flags, rc): #print('connected with code' + str(rc)) esp_client.subscribe((Esp_temp,0)) esp_client.subscribe((Esp_humy,0)) def on_message(wemos_client, userdata, msg): payload = msg.payload print(msg.topic) global wemos_t, wemos_h if(msg.topic=='/home/top/temperature'): wemos_t = float(msg.payload) else: wemos_h = float(msg.payload) print(float(payload)) def on_message1(esp_client, userdata, msg): payload = msg.payload print(msg.topic) global esp_t, esp_h if(msg.topic=='ESP8266_temp'): esp_t = float(msg.payload) else: esp_h = float(msg.payload) print(float(payload)) def on_disconnect(self, wemos_client, userdata, rc): self.disconnected.set_result(rc) def on_disconnect1(self, esp_client, userdata, rc): self.disconnected.set_result(rc) def get_remote_temp(): wemos_client = mqtt.Client() wemos_client.username_pw_set(mqtt_user, mqtt_pass) wemos_client.on_connect = on_connect wemos_client.on_message = on_message wemos_client.on_publish = on_publish wemos_client.on_disconnect = on_disconnect wemos_client.loop_start() wemos_client.connect(ser_add, 1883) sleep(2) wemos_client.loop_stop() esp_client = mqtt.Client() esp_client.username_pw_set(mqtt_user, mqtt_pass) esp_client.on_connect = on_connect1 esp_client.on_message = on_message1 esp_client.on_disconnect =on_disconnect1 esp_client.loop_start() esp_client.connect(ser_add, 1883) sleep(2) esp_client.loop_stop() def main(): while True: global wemos_t, wemos_h,esp_t, esp_h wemos_t = 0.00 wemos_h = 0.00 esp_t = 0.00 esp_h = 0.00 data = bme280.sample(bus, address, cal_par) print("Temprature",data.temperature) print("Humidity", data.humidity) print("Now printing the LTR sensor data....") ltr559.update_sensor() lux = ltr559.get_lux() prox = ltr559.get_proximity() print("Lux ", lux, "Proximity ", prox) scaled_p = dps310.calcScaledPressure() scaled_t = dps310.calcScaledTemperature() p = dps310.calcCompPressure(scaled_p, scaled_t) t = dps310.calcCompTemperature(scaled_t) print("Temprature", t) print("Dsp_press", p) get_remote_temp() colour = (255, 181, 86) font = ImageFont.truetype(UserFont, 12) bar_height = disp1.height bar_width = disp1.width img=Image.new('RGB',(bar_width, bar_height), color=(0,0,0)) draw = ImageDraw.Draw(img) rect_color =(0,180,180) draw.rectangle((0,0,160,80), rect_color) font_size = 25 #font = ImageFont.truetype("fonts/Asap/Asap-Bold.ttf", font_size) colour=(255,255,255) temp="T1: {:.2f} *C".format(data.temperature) dsp_temp = "T2: {:.2f} *C".format(t) esp_temp ="T3: {:.2f} *C".format(esp_t) wemos_temp ="T3: {:.2f} *C".format(wemos_t) humy="H1: {:.2f} %".format(data.humidity) humy1="H2: {:2f} %".format(esp_h) humy3="H3: {:2f} %".format(wemos_h) lux = "Lux: {:.2f} ".format(lux) draw.text((0,0), temp, font=font, fill=colour) draw.text((0,10),dsp_temp, font=font, fill=colour) draw.text((0,20),esp_temp, font=font, fill=colour) draw.text((0,30),wemos_temp, font=font, fill=colour) draw.text((0,40),humy, font=font, fill=colour) draw.text((0,50),humy1, font=font, fill=colour) draw.text((0,60),humy3, font=font, fill=colour) draw.text((90,0),lux, font=font, fill=colour) disp.display(img) disp1.display(img) sleep(1) if __name__ == "__main__": main()
from time import sleep try: from PIL import Image, ImageFont, ImageDraw except ImportError: print("""This example requires PIL. Install with: sudo apt install python{v}-pil """.format(v="" if sys.version_info.major == 2 else sys.version_info.major)) sys.exit(1) import ST7735 as ST7735 try: from fonts.ttf import RobotoBlackItalic as UserFont except ImportError: print("""This example requires the Roboto font. Install with: sudo pip3 install fonts font-roboto """) sys.exit(1) disp = ST7735.ST7735( port=0, cs=1, dc=9, backlight=25, rotation=270, spi_speed_hz=4000000 ) disp1 = ST7735.ST7735( port=0, cs=0, dc=9, backlight=12, rotation=270, spi_speed_hz=4000000 ) # Initialise display. disp.begin() sleep(1) disp1.begin()
Let's first have a look at the photos