[NUC980] Remote Control demo (Use Python 3)

, Oct 11, 2024|
0
53
0

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

  • Platform: Nuvoton NuMaker-IIoT-NUC980G2 with Embedded Linux
  • Development: Buildroot-based environment tools
  • Communication: Real-time data exchange via MQTT protocol
  • Control Interface: IoT MQTT Panel on Android for user interaction

Prerequisite

  • A NuMaker-IIoT-NUC980G2.

  • A LAN cable.
  • Two USB (Type-C) cables.

  • A Wi-Fi Router with LAN
  • A MicroSD Card
  • A Thermo 6 Click board for the MAX31875 temperature sensor

  • A PC running Ubuntu. Ubuntu running in VM is fine.
  • Buildroot - https://github.com/OpenNuvoton/buildroot_2024 
  • Terminal Tool - Putty, Realterm, or TeraTerm, etc.
  • MQTT app - IoT MQTT Panel  on Google Play Or other MQTT client apps

Demo Environment

  • The NuMaker-IIoT-NUC980G2 board connects to test.mosquitto.org using the MQTT protocol.

  • Then it subscribes to the following topics:
    • board/status: The online or offline status of NuMaker board
    • board/leds/1: The status of the LED3 on board
    • board/buttons/1: The pressed or released status of K1 button on board
    • board/temperature/1: The temperature reported from MAX31875 sensor

Software Setup and Firmware Build

  • Buildroot Setup
    • In Ubuntu terminal
      • Clone the buildroot_2024 for NUC980
        $ git clone https://github.com/OpenNuvoton/buildroot_2024

      • Set default configuration for NuMaker-IIoT-NUC980G2 board
        $ cd buildroot_2024
        $ make nuvoton_nuc980_iot_g2_defconfig

      • Configure Buildroot to include related packages
        $ make menuconfig

      • Include Python 3
        Target packages => Interpreter language and scripting => [*] Python3

      • Go on adding more Python3 modules which are used in the demo
        => External python modules =>
        [*] python-evdev
        [*] python-paho-mqtt
        [*] python-periphery
        
      • Then <Save> configuration, <Exit> configuration
      • Configure Linux kernel to support NUC980 keyboard events
        $ make linux-menuconfig
        Device Drivers => Input device support => [*] Keyboards => [*] Nuvoton keys support
      • Then <Save> configuration, <Exit> Linux kernel configuration
      • Build the system image
        $ make
  • After make completed, get files from the following subdirectory in Buildroot
    • ./output/images/u-boot.bin
    • ./output/build/uboot-custom/spl/u-boot-spl.bin
    • ./output/images/nuc980-iot-g2-v1.0.dtb
    • ./output/images/uImage
  • Use a plain text editor to create the env.txt file with the following content
    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

  • Run any terminal tool on the PC/Laptop, such as TeraTerm, Putty, etc. to open a terminal for NUC980 VCOM, named “USB Serial Device”.
  • Select baud rate to 115200. Refer right diagram for other parameters.

  • Set NuMaker-IIoT-NUC980G2 board to boot from USB
    • Switch both No.1 and No.2 of SW1 to ON.
    • Press Reset (K3) button on board to boot from USB
  • Use the NuWriter to burn files with the following types and addresses.
    • Clone or Download from https://github.com/OpenNuvoton/NUC980_NuWriter
      • NuWriter Tool is in the ".\NuWriter\NuWriter\Release" directory
      • NuWriter Windows Driver is in the ".\NuWriter\Driver" directory
      • NuWriter Document is the PDF file in the ".\" directory
    • DDR parameter: NUC980DK71YC.ini
    • Choose Type: SPI NAND

      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

  • On PC, use a plain text editor to create the demo Python script - rcdemo.py
    """
    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()
    

  • Save the script to the MicroSD card.
  • Set NuMaker-IIoT-NUC980G2 board to boot from SPI Flash
    • Switch both No.1 and No.2 of SW1 to OFF.
    • Press Reset (K3) button to reboot the board from SPI Flash.
  • Use “root” as account to log in.

  • 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

  • Execute IoT MQTT Panel app on Android mobile phone
  • Add a new connection and enter the MQTT broker information
    • Connection name: Give this connection a name, such as NUC980-MQTT-Test
    • Client ID: Leave blank and it will be automatically generated.
    • Broker Web/IP address: Fill in test.mosquitto.org
    • Port1883
    • Network protocolTCP
    • Click + to add a dashboard, and assign a dashboard name, such as NUC980 Test Dashboard
    • Then tap CREATE
  • Back to app main screen, press Connection Name (i.e., NUC980-MQTT-Test in the demo) to add panels.
  • Add 4 panels for the connection.
  • Add the first panel
    • Select Text Log
    • Panel nameStatus
    • Topicboard/status
    • Checked Show last message only
    • Then tap CREATE
  • Add the second panel
    • Select Text Log
    • Panel nameButton
    • Topicboard/buttons/1
    • Checked Show last message only
    • Then tap CREATE

  • Add the third panel
    • Select Switch
    • Panel nameLED 1
    • Topicboard/leds/1
    • Payload onon
    • Payload offoff
    • Then tap CREATE
  • Add the fourth panel
    • Select Line Graph
    • Panel nameTemperature
    • Topicboard/temperature/1
    • Label for graph 1Temperature
    • Factor1
    • Graph color#ea1111
    • Checked Show plot areaShow points and tooltip, and Smooth curve
    • UnitCelsius
    • Max persistence10
    • Then tap CREATE

  • Make sure the connection is connected. If not, tap it to connect again. (The cloud icon)
  • NuMaker-IIoT-NUC980 board is running MQTT client demo and successfully connects to MQTT broker, so Board Status is online.
  • Now you can try to control…
    • Keep pressing K1 on board, and the Button status will appear pressed. Release K1, and released will appear.
    • Tap the LED 1 switch to control LED3 on board.
    • Temperature history shows on panel.

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

  • This demonstration highlights the use of the Nuvoton NuMaker-IIoT-NUC980G2 board running Embedded Linux, enabling remote control through MQTT protocol and a mobile IoT control panel app.
  • By leveraging Python 3 for coding, the demo effectively shows how to control on-board peripherals (like LEDs and buttons) and monitor environmental data (such as temperature) remotely.
  • This project demonstrates the seamless integration of hardware, software, and cloud services, offering a practical solution for IoT-based remote control applications.