My Digital Garden

JPNAS.NET / Digital Garden

🌳 EvergreenLast updated:

Microcontroller Communication

Exploring MCU, MPU, SoC semantics, Nextion displays, Arduino Cloud, eWeLink and your own MQTT / Home Assistant server.

Open in the interactive Digital Garden

Remember the disclaimer? Should you decide to act upon any information on this website, you do so at your own risk. Some parts below (the Sonoff Basic in Example 4 in particular) switch mains voltage, which can cause serious injury or death. Most countries restrict such work to qualified persons, so check the regulations in your country and consult a professional.

CPU (Central Processing Unit), MPU (Microprocessor Unit), MCU (Microcontroller Unit), and SoC (System on Chip) semantics differentiate integrated circuits based on their design or components. The boundaries are blurry, and in practice the terms overlap:

TermWhat it isTypical example
CPUThe processing core itself, the part that executes instructionsThe core inside every chip below
MPUA processor that needs external RAM, storage and peripherals, usually runs a full operating system such as LinuxRaspberry Pi (Linux board)
MCUCPU, RAM, flash and peripherals (GPIO, ADC, UART) in one chip, runs a single program without an operating systemRaspberry Pi Pico (RP2040), ATmega328 in the Arduino Uno
SoCEverything on one chip, often including radio; the term is used for MCUs with Wi-Fi as well as for complete application processorsESP8285 (ESP8266 with 1 MB flash inside)

For a few euros you can buy what Itead calls a Wi-Fi Switch module. It features an ESP8285 chip, which is an ESP8266 with the flash memory built into the package. According to Espressif Systems, with their development boards, you are able to develop your own IoT applications. These parts are so small that you need special tools to integrate them into a custom-designed system.

Raspberry Pi Pico, Arduino Nano 33 IoT, and many other variations make it easy to read sensors, drive displays and talk to the network from a few lines of code. The Nano 33 IoT combines a 3.3 V SAMD21 microcontroller with a separate Wi-Fi/Bluetooth module. Its pins are not 5 V tolerant, which matters as soon as you connect parts that were designed for the 5 V Arduino Uno. Communication with the Nextion Touch Display from Itead, who offers the Nextion Editor designed specifically for graphical user interfaces, takes the drawing of screens off the microcontroller: the display has its own processor, and the microcontroller only exchanges short messages with it over a serial line, instead of pushing binary pixel data. You place components visually and control them with ASCII text-based instructions, which is somewhat reminiscent of Microsoft Visual Basic.

You can pair a Nextion display with an Arduino Nano 33 IoT to display and manage various elements on the screen, a computer, or another smart device with network capabilities. The Arduino Cloud enables you to manage these elements over the internet without running your own server. That server does not disappear, however: it runs at Arduino, and the free plan is limited (at the time of writing two "Things", and the phone app counts as one of them, see the plans page for current limits). Thanks to the active Arduino community, numerous resources are available online.

Why would you need a server of your own? Temperature sensors and similar devices are often part of a larger collection. In terms of resource management, storing and processing data on each individual device separately makes little sense. A server collects the readings in one place, keeps the history, draws graphs, sends alerts and lets one device react to another. Whether that server belongs to someone else or to you decides who owns the data, whether the system keeps working without Internet access, and what happens when a vendor changes its plans:

eWeLink (Example 3)Arduino Cloud (Example 4)Own server (Example 5)
Who runs the serverIteadArduinoYou (Raspberry Pi, mini PC, VM)
Works without InternetPartly (LAN mode)NoYes
LimitsSupported devices onlyFree plan: few Things and variablesYour hardware
EffortLowestLowHighest (updates, backups, security are yours)

The own-server route (Mosquitto and Home Assistant) is described in more detail in the Network Door Opener note, Examples 4 and 5; here it is applied to a sensor.

Examples & Guides

Overview

#HardwareLinkServerUser interface
1Nano 33 IoT (or Uno) + LM60 + NextionUARTnoneNextion touch display
2Arduino + temperature sensorUSB serialnoneSerial Monitor / Plotter
3Sonoff switchWi-FieWeLink cloudeWeLink app
4Nano 33 IoT + Sonoff BasicWi-FiArduino CloudDashboard + IoT Remote app
5ESP8266 board + DS18B20Wi-Fi, MQTTOwn (Mosquitto + Home Assistant)Home Assistant dashboard

Example 1 – Temperature on a Nextion display

How it works:

  1. Wiring: display 5 V and GND to a supply that can deliver the display's current (see its datasheet, do not draw it from a weak pin), display TX to the microcontroller RX, display RX to the microcontroller TX, and all grounds together. Check in the datasheet of your Nextion model that its TX level is acceptable for a 3.3 V board.
  2. The LM60 outputs 424 mV at 0 °C plus 6.25 mV per °C, so the temperature is (V − 0.424) / 0.00625. Supply it with 3.3 V (it needs at least 2.7 V) and put a 100 nF capacitor close to the sensor.
  3. In the Nextion Editor add a text box named t0 on page 0. Its default speed is 9600 baud.
  4. Every Nextion command is ASCII text followed by three bytes of 0xFF, for example t0.txt="21.5 C". This is what nextionSend() below does.
// Arduino Nano 33 IoT: LM60 on A0, Nextion on Serial1 (D0 = RX, D1 = TX), 9600 baud
const int SENSOR_PIN = A0;

void nextionSend(const String &cmd) {
  Serial1.print(cmd);
  Serial1.write(0xFF);   // every Nextion command ends with three 0xFF bytes
  Serial1.write(0xFF);
  Serial1.write(0xFF);
}

float readTemperatureC() {
  long sum = 0;
  for (int i = 0; i < 16; i++) {          // average to reduce ADC noise
    sum += analogRead(SENSOR_PIN);
    delay(2);
  }
  float volts = (sum / 16.0f) * 3.3f / 4095.0f;   // 12-bit ADC, 3.3 V reference
  return (volts - 0.424f) / 0.00625f;             // LM60: 424 mV at 0 C, 6.25 mV per C
}

void setup() {
  Serial1.begin(9600);
  analogReadResolution(12);
  delay(500);                              // give the display time to start
  nextionSend("page 0");
}

void loop() {
  float t = readTemperatureC();
  nextionSend("t0.txt=\"" + String(t, 1) + " C\"");   // text box t0 on page 0
  delay(1000);
}

On an Uno use SoftwareSerial instead of Serial1 as in the tutorial, a 5.0 V reference and 1023 steps instead of 3.3 V and 4095. The averaging of 16 readings matters: a single reading of the analog pin jumps by a few tenths of a degree. The sensor tolerance (about ±2 °C according to the datasheet) is larger than the noise, so compare it with a reference thermometer before you trust it.

Example 2 – Temperature sensor without a display

The simplest setup: sensor on an analog pin, readings over USB to the Serial Monitor. This is the best way to test a sensor before you add a display or a network. Open Tools → Serial Plotter in the Arduino IDE to see a graph; it expects one number per line. The conversion depends on the sensor: an LM60 as in Example 1 has an offset of 424 mV, a sensor of the LM35 type gives 10 mV per °C without offset, so check the formula for the part you actually have.

const int SENSOR_PIN = A0;

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);               // Nano 33 IoT; on an Uno use 1023 and 5.0 V below
}

void loop() {
  long sum = 0;
  for (int i = 0; i < 16; i++) {
    sum += analogRead(SENSOR_PIN);
    delay(2);
  }
  float volts = (sum / 16.0f) * 3.3f / 4095.0f;
  float tempC = (volts - 0.424f) / 0.00625f;      // LM60; an LM35 would be volts * 100.0f
  Serial.println(tempC, 1);                        // one number per line: works with Serial Plotter
  delay(1000);
}

Example 3 – Sonoff switch with eWeLink

The module itself is the whole system: an ESP8285 that connects to your Wi-Fi, a relay, and firmware that talks to the eWeLink cloud. You need no programming and no server of your own.

  1. Power the RE5V1C with 5 V DC (it is a low-voltage module, specified for 0–40 °C) and connect only the load you want to switch to its dry-contact output.
  2. Your phone must be on a 2.4 GHz Wi-Fi network; the ESP8285 does not support 5 GHz. Put the module into pairing mode as described in the pairing guide and add it in the eWeLink app.
  3. Set the mode (toggle, inching with automatic switch-off, or self-locking) and optionally timers and scenes.
  4. Test it once with the Internet connection of your router unplugged. The module also supports LAN control without Internet access; if you want to control it only locally, the Sonoff DIY mode (offered by models sold as "DIY switch") and ESPHome (Example 5) are the alternatives.

Consequences of this convenience: the account and the data live at the vendor, the app only works as long as the service exists, and anyone who gets into your account can switch the relay. Use a long, unique password.

Example 4 – Arduino Nano 33 IoT, Arduino Cloud and a Sonoff Basic

The idea: the Nano reads the temperature and publishes it as a Cloud variable, the Cloud shows it in a dashboard on the web and in the IoT Remote app, and a switch on the dashboard controls the Sonoff Basic, which is registered as a second Thing. Create a Thing for the Nano, add the variable temperature (type Temperature Sensor, read only), connect the device, and let the Cloud generate thingProperties.h. The sketch is then short:

// Sketch tab of the Arduino Cloud Thing. thingProperties.h is generated by the Cloud
// and contains:  CloudTemperatureSensor temperature;   (variable "temperature", read only)
#include "thingProperties.h"

const int SENSOR_PIN = A0;

float readTemperatureC() {                 // same function as in Example 1
  long sum = 0;
  for (int i = 0; i < 16; i++) {
    sum += analogRead(SENSOR_PIN);
    delay(2);
  }
  float volts = (sum / 16.0f) * 3.3f / 4095.0f;
  return (volts - 0.424f) / 0.00625f;
}

void setup() {
  Serial.begin(9600);
  delay(1500);
  analogReadResolution(12);
  initProperties();
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();                   // keeps the connection alive, must run often
  static unsigned long last = 0;
  if (millis() - last >= 10000) {          // one reading every 10 s
    last = millis();
    temperature = readTemperatureC();
  }
}

Warning: the Sonoff Basic has no galvanic isolation between its circuit board and the mains. Never connect a serial adapter to it while it is connected to mains. Flash it on the bench, powered only by the 3.3 V of the adapter, and install it in a closed housing only when it is finished and by someone qualified. With two Things, the free plan is already used up; the IoT Remote app on a phone counts as a third one, so check the plan page before you rely on this.

Example 5 – Your own server: ESPHome, MQTT and Home Assistant

  • Server: Raspberry Pi, mini PC or virtual machine running Home Assistant with the Mosquitto broker (Home Assistant has it as an add-on)
  • ESP8266 board, for example a D1 mini (or the ESP32 of your choice)
  • DS18B20 temperature sensor (digital, 1-Wire) and a 4.7 kΩ resistor
  • ESPHome for the firmware

Here the roles from Example 4 are taken over by software that you control. A digital sensor replaces the analog LM60: it needs no ADC, is not disturbed by supply noise, and its reading is the same on a 3.3 V or a 5 V board. The device publishes its readings by MQTT, the broker passes them on, and Home Assistant stores them, draws the graphs and can send a message to your phone when a limit is crossed.

1. Broker (inside the home network, so plain port 1883 with a password is acceptable; never forward this port to the Internet):

# /etc/mosquitto/conf.d/lan.conf   (broker reachable only inside the home network)
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd

# sudo mosquitto_passwd -c /etc/mosquitto/passwd sensor_user
# sudo systemctl restart mosquitto
# test:  mosquitto_sub -h 192.168.1.10 -u sensor_user -P PASSWORD -t 'sensors/#' -v

2. Sensor firmware (ESPHome MQTT component). Check the sensor syntax for your ESPHome version, because the 1-Wire configuration has changed between releases:

# temp-sensor.yaml (ESPHome, ESP8266 board such as a D1 mini, DS18B20 on D2 = GPIO4)
esphome:
  name: temp-livingroom

esp8266:
  board: d1_mini

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

ota:
  - platform: esphome
    password: !secret ota_password

mqtt:
  broker: 192.168.1.10
  username: !secret mqtt_user
  password: !secret mqtt_pass
  topic_prefix: sensors/livingroom
  discovery: true                 # Home Assistant finds the sensor by itself

# 1-Wire bus; a 4.7 kOhm resistor between data and 3.3 V is required
one_wire:
  - platform: gpio
    pin: GPIO4

sensor:
  - platform: dallas_temp         # older ESPHome versions: "dallas:" hub + "platform: dallas"
    name: "Temperature"
    update_interval: 30s

3. Home Assistant: add the MQTT integration with the address and the account of the broker. The sensor appears by itself because of discovery: true. Put it on a dashboard and enable the history graph.

If the device is only used with Home Assistant, you can use the ESPHome native API instead of MQTT: remove the mqtt: block and add api: with an encryption key. MQTT is the better choice when other programs than Home Assistant should receive the data, or when you want to follow the same pattern as in the Network Door Opener note, including TLS and per-device accounts.

For all examples

  • Check the logic level before you connect anything: the Nano 33 IoT, ESP8266 and ESP32 are 3.3 V devices; 5 V on a pin can destroy them.
  • Ground of all parts must be common, and a sensor wire longer than a metre needs shielding or a digital sensor.
  • Use unique, long passwords for every cloud account, broker user and Wi-Fi network; one account per device lets you revoke a single device.
  • Keep the firmware and the server updated, and keep a backup of the server configuration.
  • Do not expose a broker or Home Assistant to the Internet without TLS and authentication. A VPN is the simplest way to reach them from outside.
  • Mains voltage belongs to qualified persons; use modules with low-voltage inputs wherever possible.

Some resources:

← All notes