ESP-Now Project: Sender reporting temperature to Receiver
-
Here is an example of a project that utilizes ESP-Now for point-to-point communication between two M5Stack products. The M5StickC with ENV Unit is the Sender (transmitter) sending temperature and battery information to the M5Stack core (Receiver).
Features:
- Temperature reporting from the Sender with high temperature alarm beeps and visuals on the Receiver
- Battery voltage reporting on the Sender (voltage value and icon) with low battery alert on the Receiver
- Visual indicator on the Sender when data is being sent: The LED is on when sending data. Toggle button B on the M5StickC to turn the LED indicator on/off. When off, the temperature is displayed in red text to still give a visual indicator when the device is sending data.
- Audible indicator on the Receiver when the data is received: Volume +/- and Mute controls are available. Single beep tells the user the temperature is below the threshold (default is 160 degrees F). Triple beep tells the user the temperature is above the threshold.
- Visual indicator on the Receiver when the temperature is above the threshold: The temperature text is displayed red when the temperature is too high.
- Non-blocking code with the use of timers and callbacks instead of loops and waits
Sender uiFlow (file):
Receiver uiFlow (file):
Sender Python code:
from m5stack import * from m5ui import * from uiflow import * import espnow import wifiCfg import unit setScreenColor(0x000000) env0 = unit.get(unit.ENV, unit.PORTA) wifiCfg.wlan_ap.active(True) espnow.init() title0 = M5Title(title="Sender", x=3 , fgcolor=0xFFFFFF, bgcolor=0x0000FF) label0 = M5TextBox(5, 40, "--", lcd.FONT_DejaVu24,0xFFFFFF, rotate=0) rectangle4 = M5Rect(1, 117, 79, 25, 0x9d9d9d, 0x9d9d9d) label1 = M5TextBox(5, 83, "Battery (V):", lcd.FONT_DefaultSmall,0xFFFFFF, rotate=0) rectangle0 = M5Rect(3, 120, 15, 20, 0x33ff33, 0x33ff33) rectangle1 = M5Rect(23, 120, 15, 20, 0x33ff33, 0x33ff33) rectangle2 = M5Rect(43, 120, 15, 20, 0x33ff33, 0x33ff33) rectangle3 = M5Rect(63, 120, 15, 20, 0x33ff33, 0x33ff33) label2 = M5TextBox(5, 100, "--", lcd.FONT_DefaultSmall,0xFFFFFF, rotate=0) label3 = M5TextBox(38, 40, "O", lcd.FONT_DefaultSmall,0xFFFFFF, rotate=0) label4 = M5TextBox(47, 40, "F", lcd.FONT_DejaVu24,0xFFFFFF, rotate=0) import math senderFlag = None temperature = None batteryVoltage = None ledStatus = None highTempAlarm = None lowBatteryAlarm = None dataPayload = None def batteryIcon(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload if batteryVoltage >= 4.1: rectangle0.hide() rectangle0.setBgColor(0x33ff33) rectangle0.setBorderColor(0x33ff33) rectangle0.show() rectangle1.show() rectangle2.show() rectangle3.show() elif batteryVoltage < 4.1 and batteryVoltage >= 3.9: rectangle0.hide() rectangle0.setBgColor(0x33ff33) rectangle0.setBorderColor(0x33ff33) rectangle0.show() rectangle1.show() rectangle2.show() rectangle3.hide() elif batteryVoltage < 3.9 and batteryVoltage >= 3.7: rectangle0.hide() rectangle0.setBgColor(0x33ff33) rectangle0.setBorderColor(0x33ff33) rectangle0.show() rectangle1.show() rectangle2.hide() rectangle3.hide() elif batteryVoltage < 3.7 and batteryVoltage >= 3.5: rectangle0.hide() rectangle0.setBgColor(0x33ff33) rectangle0.setBorderColor(0x33ff33) rectangle0.show() rectangle1.hide() rectangle2.hide() rectangle3.hide() elif batteryVoltage < 3.5 and batteryVoltage >= 3.3: rectangle0.hide() rectangle0.setBgColor(0x33ff33) rectangle0.setBorderColor(0x33ff33) rectangle0.show() rectangle1.hide() rectangle2.hide() rectangle3.hide() else: rectangle0.hide() rectangle0.setBgColor(0xff0000) rectangle0.setBorderColor(0xff0000) rectangle0.show() rectangle1.hide() rectangle2.hide() rectangle3.hide() def highTempFunction(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload if temperature > 160: highTempAlarm = 1 label0.setColor(0xff0000) else: highTempAlarm = 0 label0.setColor(0xffffff) def lowBatteryFunction(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload if batteryVoltage < 3.3: lowBatteryAlarm = 1 label2.setColor(0xff0000) else: lowBatteryAlarm = 0 label2.setColor(0xffffff) def send_cb(flag): global senderFlag,temperature,batteryVoltage,ledStatus,highTempAlarm,lowBatteryAlarm,dataPayload senderFlag = flag if ledStatus == 1: M5Led.on() timerSch.run('ledOffTimer', 872, 0x01) else: label0.setColor(0xff0000) timerSch.run('ledOffTimer', 872, 0x01) pass espnow.send_cb(send_cb) def buttonB_wasPressed(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload if ledStatus == 1: ledStatus = 0 else: ledStatus = 1 pass btnB.wasPressed(buttonB_wasPressed) @timerSch.event('ledOffTimer') def tledOffTimer(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload M5Led.off() label0.setColor(0xffffff) pass @timerSch.event('sendData') def tsendData(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload temperature = round((env0.temperature) * 1.8 + 32) label0.setText(str(temperature)) highTempFunction() dataPayload = [temperature, highTempAlarm, lowBatteryAlarm] espnow.send(id=1, data=str(dataPayload)) pass @timerSch.event('checkBatteryTimer') def tcheckBatteryTimer(): global senderFlag, temperature, batteryVoltage, ledStatus, highTempAlarm, lowBatteryAlarm, dataPayload batteryVoltage = axp.getBatVoltage() label2.setText(str(batteryVoltage)) batteryIcon() lowBatteryFunction() pass batteryVoltage = axp.getBatVoltage() label2.setText(str(batteryVoltage)) batteryIcon() espnow.add_peer('30:ae:a4:49:cd:9d', id=1) ledStatus = 1 timerSch.run('checkBatteryTimer', 15000, 0x00) timerSch.run('sendData', 9999, 0x00)
Receiver Python code:
from m5stack import * from m5ui import * from uiflow import * import espnow import wifiCfg setScreenColor(0x000000) wifiCfg.wlan_ap.active(True) espnow.init() title0 = M5Title(title="Receiver", x=3 , fgcolor=0xFFFFFF, bgcolor=0x0000ff) label0 = M5TextBox(110, 85, "---", lcd.FONT_DejaVu56,0xFFFFFF, rotate=0) label6 = M5TextBox(85, 150, "HIGH TEMPERATURE!", lcd.FONT_Default,0xff0000, rotate=0) label7 = M5TextBox(90, 30, "Low battery on sender!", lcd.FONT_Default,0xff0000, rotate=0) rectangle0 = M5Rect(40, 194, 233, 18, 0x7e7c7c, 0x7e7c7c) label1 = M5TextBox(183, 85, "O", lcd.FONT_Default,0xFFFFFF, rotate=0) label10 = M5TextBox(7, 196, "Vol", lcd.FONT_Default,0xffffff, rotate=0) label2 = M5TextBox(194, 85, "F", lcd.FONT_DejaVu56,0xFFFFFF, rotate=0) rectangle1 = M5Rect(45, 198, 220, 10, 0xFFFFFF, 0xFFFFFF) label3 = M5TextBox(55, 220, "Vol-", lcd.FONT_Default,0xFFFFFF, rotate=0) label4 = M5TextBox(235, 220, "Vol+", lcd.FONT_Default,0xFFFFFF, rotate=0) label5 = M5TextBox(145, 220, "Mute", lcd.FONT_Default,0xFFFFFF, rotate=0) senderMacAddr = None messagePayload = None list2 = None volume = None temperature = None highTemperatureAlarm = None rectWidth = None lowBatteryAlarm = None def displayVolume(): global senderMacAddr, messagePayload, list2, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm if rectWidth > 220: rectangle1.setSize(width=220) elif rectWidth < 0: rectangle1.setSize(width=0) else: rectangle1.setSize(width=rectWidth) def displayTemperature(): global senderMacAddr, messagePayload, list2, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm if len(temperature) == 3: label0.setPosition(x=75) label0.setText(str(temperature)) else: label0.setPosition(x=110) label0.setText(str(temperature)) def highTemperatureCheck(): global senderMacAddr, messagePayload, list2, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm if highTemperatureAlarm == '1': label0.setColor(0xff0000) label6.show() speaker.tone(1200, 100) speaker.tone(1300, 200) speaker.tone(1200, 100) else: label0.setColor(0xffffff) label6.hide() speaker.tone(1000, 100) def lowBatteryCheck(): global senderMacAddr, messagePayload, list2, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm if lowBatteryAlarm == '1': label7.show() else: label7.hide() def recv_cb(_): global senderMacAddr,messagePayload,list,volume,temperature,highTemperatureAlarm,rectWidth,lowBatteryAlarm senderMacAddr, _, messagePayload = espnow.recv_data(encoder='str') list2 = messagePayload.split(',') temperature = list2[0].replace('[', '').strip() highTemperatureAlarm = list2[1].strip() lowBatteryAlarm = list2[2].replace(']', '').strip() displayTemperature() highTemperatureCheck() lowBatteryCheck() pass espnow.recv_cb(recv_cb) def buttonA_wasPressed(): global senderMacAddr, messagePayload, list, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm if volume < 0: label5.setColor(0xff0000) volume = 0 speaker.setVolume(volume) else: label5.setColor(0xffffff) volume = volume - 0.1 speaker.setVolume(volume) rectWidth = rectWidth - 22 displayVolume() pass btnA.wasPressed(buttonA_wasPressed) def buttonB_wasPressed(): global senderMacAddr, messagePayload, list, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm if volume > 0: label5.setColor(0xff0000) volume = 0 speaker.setVolume(volume) rectangle1.setSize(width=0) else: label5.setColor(0xffffff) volume = 0.5 speaker.setVolume(volume) rectangle1.setSize(width=110) pass btnB.wasPressed(buttonB_wasPressed) def buttonC_wasPressed(): global senderMacAddr, messagePayload, list, volume, temperature, highTemperatureAlarm, rectWidth, lowBatteryAlarm label5.setColor(0xffffff) if volume > 1: volume = 1 speaker.setVolume(volume) else: volume = volume + 0.1 speaker.setVolume(volume) rectWidth = rectWidth + 22 displayVolume() pass btnC.wasPressed(buttonC_wasPressed) volume = 0.5 speaker.setVolume(volume) label6.hide() label7.hide() rectWidth = 110 rectangle1.setSize(width=rectWidth) while True: wait_ms(2)