The Remote Control Demo showcases the integration of IoT technologies on the Nuvoton NuMaker-IIoT-NUC980G2 development board, leveraging an Embedded Linux OS environment built using Buildroot. This demo uses Python 3 and related modules. The board communicates with an external MQTT broker via Ethernet and MQTT protocol, to report system status, button states, and control an onboard LED.
Key Features
Prerequisite
Demo Environment
Software Setup and Firmware Build
$ git clone https://github.com/OpenNuvoton/buildroot_2024
$ cd buildroot_2024 $ make nuvoton_nuc980_iot_g2_defconfig
$ make menuconfig
Target packages => Interpreter language and scripting => [*] Python3
=> External python modules => [*] python-evdev [*] python-paho-mqtt [*] python-periphery
$ make linux-menuconfig
Device Drivers => Input device support => [*] Keyboards => [*] Nuvoton keys support
$ make
baudrate=115200 bootdelay=1 stderr=serial stdin=serial stdout=serial setspi=sf probe 0 30000000 loadkernel=sf read 0x7fc0 0x200000 0x1600000 loaddtb=sf read 0x1800000 0x1800000 0x20000 bootcmd=run setspi;run loadkernel;run loaddtb;bootm 0x7fc0 - 0x1800000
Burn Firmware to Board
Files | Type | Address |
u-boot-spl.bin | Loader | 0x200 |
u-boot.bin | Data | 0x100000 |
uImage | Data | 0x200000 |
nuc980-iot-g2-v1.0.dtb | Data | 0x1800000 |
env.txt | Environment | 0x80000 |
Boot the Board and Run Python Script
""" Remote Control Demo on Nuvoton NuMaker-IIoT-NUC980G2 Board This Python script is designed to run on the Nuvoton NuMaker-IIoT-NUC980G2 board with Embedded Linux. The script connects to an MQTT broker to report the board status, button status, and temperature reading. Additionally, it receives LED status from the MQTT broker and controls the onboard LED based on the received status. Features: 1. Reports board and button status to MQTT broker. 2. Periodically reads temperature from a MAX31875 sensor via I2C and reports it. 3. Receives LED status from MQTT broker and controls the onboard LED. 4. Implements thread-based monitoring for button events and temperature readings. License: MIT License, no warranty. Copyright (c) 2024 Nuvoton Technology Corp. """ import time, random, threading import paho.mqtt.client as mqtt from periphery import GPIO, I2C from evdev import InputDevice, categorize, ecodes # Constants for MQTT topics MQTT_BROKER = "test.mosquitto.org" CLIENT_ID = f'nuc980-mqtt-demo-{random.randint(0,1000)}' TOPIC_STATUS = "board/status" TOPIC_LED = "board/leds/1" TOPIC_BUTTON = "board/buttons/1" TOPIC_TEMPERATURE = "board/temperature/1" # GPIO pins configuration LED_PIN = GPIO("/dev/gpiochip0", 40, "out") # GPIO PB8 pin for the LED BUTTON_DEVICE_PATH = '/dev/input/event0' BUTTON_CODE = 108 # K1 button on board # I2C configuration I2C_BUS = "/dev/i2c-2" TEMP_SENSOR_ADDR = 0x48 # Address for MAX31875 CONFIG_REG = 0x01 # Configuration register address TEMP_REG = 0x00 # Temperature register address # Initialize the I2C device i2c = I2C(I2C_BUS) # MQTT events callbacks def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT broker!\n") # Subscribe to topics client.subscribe("board/leds/1") else: print("Failed to connect, return code is " + str(rc)) def on_message(client, userdata, msg): print(f"Received message on {msg.topic}: {msg.payload}") if msg.topic == "board/leds/1": if msg.payload.decode() == "off": LED_PIN.write(True) elif msg.payload.decode() == "on": LED_PIN.write(False) # Publish the board status to the broker def publish_status(client, status): print(f"Published status: {status}") client.publish("board/status", status) # Thread function to monitor the button status and publish it to the MQTT broker def monitor_button(client): button_device = InputDevice(BUTTON_DEVICE_PATH) for event in button_device.read_loop(): if event.type == ecodes.EV_KEY and event.code == BUTTON_CODE: key_event = categorize(event) if key_event.keystate == key_event.key_down: print("Button pressed") client.publish("board/buttons/1", "pressed") elif key_event.keystate == key_event.key_up: print("Button released") client.publish("board/buttons/1", "released") # Thread function to read the temperature and publish it to the MQTT broker def monitor_temperature(client): init_temperature_sensor(); while True: msgs = [I2C.Message([TEMP_REG]), I2C.Message([0x00, 0x00], read=True)] i2c.transfer(TEMP_SENSOR_ADDR, msgs) raw_temp = (msgs[1].data[0] << 8) | msgs[1].data[1] temp = (raw_temp >> 4) * 0.0625 print(f"Current Temperature: {temp:.2f} °C") client.publish("board/temperature/1", temp) time.sleep(2) # Function to initialize the MAX31875 def init_temperature_sensor(): config_value_high = 0x00 config_value_low = 0x60 msg = I2C.Message([CONFIG_REG, config_value_high, config_value_low]) # Send the I2C message i2c.transfer(TEMP_SENSOR_ADDR, [msg]) time.sleep(0.1) # Main Function def main(): client = mqtt.Client(CLIENT_ID) client.on_connect = on_connect client.on_message = on_message client.connect(MQTT_BROKER, 1883, 60) # Publish 'online' status publish_status(client, "online") client.loop_start() # Start button monitoring thread button_thread = threading.Thread(target=monitor_button, args=(client,)) button_thread.daemon = True button_thread.start() # Start temperature monitoring thread temperature_thread = threading.Thread(target=monitor_temperature, args=(client,)) temperature_thread.daemon = True temperature_thread.start() try: while True: time.sleep(1) # Keep the main thread alive except KeyboardInterrupt: pass finally: # Cleanup publish_status(client, "offline") client.loop_stop() client.disconnect() LED_PIN.close() i2c.close() if __name__ == "__main__": main()
Insert the MicroSD card to board.
Mount the MicroSD card
# mount –t vfat /dev/mmcblk0p1 /mnt
Activate Ethernet to get IP address via DHCP
# udhcpc
Run the Pyhton Script
# python /mnt/rcdemo.py
NUC980 board connects to MQTT broker, subscribe and publish status to MQTT broker.
Configure MQTT app
Files in the demo
The attached ZIP file contains precompiled firmware images, an env.txt, and a Python script files. These are provided for your convenience and easy use.
NUC980_RC_Demo_FW_and_Script.zip
Conclusion