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):
    0_1580479911682_sender.png

    Receiver uiFlow (file):
    0_1580479928690_receiver.png

    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)