This project involves building an IoT modular electrical meter. It can be used to detect faults and abnormal high power consumption. Based around a current clamp design, it can be used to measure the current in a circuit without breaking the circuit. Hence it is modular and easily installable with minimal safety concerns from high voltage wiring.The system is deployed on an STM32U575 Nucleo Board running RT-Thread. RT-Thread allows for rapid development through the support of BSPs. The power waveform can be captured and the frequency components are analysed in the microcontroller.The real-time information is updated on the cloud and can be accessed remotely using a smartphone or computer dashboard.
This project is done as part of the RT-Thread IoT Contest 2023.Preparation of Hardware
In this project, the STM32U575 Nucleo Board (NUCLEO-U575ZI-Q) is attached with the RT-Thread RW007 Wifi Module. The Wifi module involves the SPI communication bus.
To perform power measurements, we use a current sensor. The SCT-013 consists of a current transformer. It must be clamped around only one wire of the AC cable (because the opposite current directions of the two wires will cancel out the magnetic field).
The current sensor consists of a current transformer with turns ratio of 2000. The AC current is large, but it will be stepped down by a factor of 2000 to become a very small current which can be handled by the microcontroller.
To read the current, we can use a shunt resistor R3 to allow the ADC to read in terms of voltage. As the current is an AC waveform, we bias it about the midpoint of the supply voltage using R1 and R2.
I soldered the circuit by repurposing an old PCB shield. After wiring everything it looks like this, attachable to the bottom of the Nucleo Board
Warning: The following involves AC wiring. Please ensure proper safety procedure. Turn off all power before proceeding.
This is the AC wiring for a 2-gang outlet.
Attach the current sensor to the Live wire of the AC appliance and connect it using the 3.5mm connector.
As written above, the system uses the following microcontroller peripherals:- ADC: SCT-013 Current Sensor- SPI & WIFI: RW007 Wifi Module
To summarize, the block diagram of the system is as follows:
This project focuses on the setup of RT-Thread on Linux Ubuntu. You may refer to many other tutorials for RT-Thread Studio on Windows.
Install STM32CubeMX:
Install STM32CubeProgrammer
Install SCons:
sudo apt install scons
Setup EnvironmentEnsure that you start your working folder without any spaces or special characters! The build scripts will throw an error if there are.
Download latest toolchain from the ARM website
I am running on x86_64 with Linux Ubuntu so I downloaded the following using the `wget` command.
$ wget https://developer.arm.com/-/media/Files/downloads/gnu/12.2.mpacbti-rel1/binrel/arm-gnu-toolchain-12.2.mpacbti-rel1-x86_64-arm-none-eabi.tar.xz?rev=71e595a1f2b6457bab9242bc4a40db90&hash=37B0C59767BAE297AEB8967E7C54705BAE9A4B95
Extract it and move it into a folder called `toolchain`:
tar xf arm-gnu-toolchain-12.2.mpacbti-rel1-x86_64-arm-none-eabi.tar.xz
mv arm-gnu-toolchain-12.2.mpacbti-rel1-x86_64-arm-none-eabi toolchain
Clone the main repo of RT-Thread. Take note that about 1GB of data is downloaded and after extraction it is almost 3GB.
git clone https://github.com/RT-Thread/rt-thread.git
You should have the two folders in your root folder now.
---
Before we continue, let us define this as the working directory using these commands:
export WORKING_DIR=$(pwd)
echo $WORKING_DIR
Please make sure there are no spaces or special characters in this directory. If not the compilation scripts will throw errors.
We also define environment variables needed by RT-Thread compilation:
export RTT_CC="gcc"
export RTT_ROOT="$WORKING_DIR/rt-thread"
export RTT_EXEC_PATH="$WORKING_DIR/toolchain/bin"
Go to the BSP for the STM32U575 Nucleo Board and make a distribution. (A distribution will export all necessary BSPs filed into a single folder):
cd ./rt-thread/bsp/stm32/stm32u575-st-nucleo
scons --dist
You will see the project distribution in the dist folder.
I will move the folder back into our working directory for convenience. I chose the name `my-iot-project`.
mv ./dist/project/ $WORKING_DIR/my-iot-project/
Your working directory should look like this
Run this command to compile it. A file will be generated as `rtthread.bin`.
scons
To program the board, Launch STM32CubeProgrammer and do the following :
- 1. Click on ST-LINK > Connect
- 2. Open > (choose file) > rtthread.bin
- 3. Download
After programming, the board restarts and the Red LED is blinking. As seen under `applications/main.c`, the template project toggles the pin PG2.
To access the serial terminal, you can use `screen` with the baud rate of 115200:
screen /dev/serial/by-id/usb-STMicroelectronics_STLINK-V3_002E00343331510D34333834-if02 115200
Now we know our environment has been setup properly since we got the blinking LED working.
Setup STM32 HAL Drivers (if needed)As mentioned in "Preparation of Hardware", we require the use of ADC and SPI under STM32CubeMX.
Note that in the latest version of the RT-Thread repo (v5.0.0), ADC1 and SPI1 has been initialized for us already. If you are using other versions, please check the following:
- Launch CubeMX and open `
/board/CubeMX_Config/CubeMX_Config.ioc
`. - - ADC1: Enable (leave everything else as default)
- - SPI1: Choose
Mode: Full-Duplex Master
, and setSPI1_SCK: PA5
Once you check that the above are correct, click on `Generate Code`.
Setup RT-Thread ConfigurationTo launch the RT-Thread menu, we run scons --menuconfig
which has a terminal interface (TUI). Alternatively, there exists a graphical interface (GUI) as well using scons --pyconfig
.
Open configuration window
scons --pyconfig
Enable the ADC and SPI packages
- RT-Thread Components > Device Drivers > Using ADC device drivers
- RT-Thread Components > Device Drivers > Using SPI Bus/Device device drivers
- Hardware Drivers Config > On-chip Peripheral Drivers > Enable ADC
- Hardware Drivers Config > On-chip Peripheral Drivers > Enable SPI BUS > Enable SPI1 Bus
Enable Wifi using RW007 module. The options for the pin connections to the Nucleo board are as follows:
- RT-Thread Online Packages > IoT - internet of things > rw007: SPI WIFI rw007 driver
- ------> RW007 BUS NAME: spi1
- ------> (62) CS pin index
- ------> (5) BOOTO pin index (same as spi clk pin)
- ------> (62) BOOTl pin index (same as spi cs pin)
- ------> (63) INT/BUSY pin index
- ------> (92) RESET pin index
Finally, as I will be uploading the sensor values to the cloud, I will make use of the WebClient package to access the website service.
- RT-Thread Online Packages > IoT - internet of things > WebClient
Click on Save. Close the window.
After using scons --menuconfig
, the Env tool will be installed and initialized, and a ".env" folder will be generated under your home directory.
Use the Env update command. It will download new packages from the Github server.
source ~/.env/env.sh
pkgs --update
Modify the code in packages/rw007-v2.0.1/example/rw007_stm32_port.c
. Replace the content of the wifi_spi_device_init(void)
with the following code:
int wifi_spi_device_init(void) {
char sn_version[32];
rw007_gpio_init();
rt_hw_spi_device_attach(RW007_SPI_BUS_NAME, "wspi", RW007_CS_PIN);
rt_hw_wifi_init("wspi");
rt_wlan_set_mode(RT_WLAN_DEVICE_STA_NAME, RT_WLAN_STATION);
rt_wlan_set_mode(RT_WLAN_DEVICE_AP_NAME, RT_WLAN_AP);
rw007_sn_get(sn_version);
rt_kprintf("\nrw007 sn: [%s]\n", sn_version);
rw007_version_get(sn_version);
rt_kprintf("rw007 ver: [%s]\n\n", sn_version);
return 0;
}
Next, under `packages/rw007-v2.0.1/inc/spi_wifi_rw007.h
` add the following to the first line of the file.
#define ALIGN(n) __attribute__((aligned(n)))
Now, we can build the project and program using STM32CubeProgrammer
scons
In the serial terminal, you will see new functions using the wifi
command. There will be a lot of timeout errors, but the Wifi is still working fine.
The timeout errors are documented on the official RT-Thread repo and it is to be fixed in future versions.
You can connect to a Wifi network and obtain an IP address.
Here, I can also ping websites.
For my application, I will be referencing some Arduino code from another open-source project. To make things simple, we can incorporate the Arduino code directly using the RTduino package.
Open configuration window again
scons --pyconfig
Enable RTduino
- Hardware Drivers Config > Onboard Peripheral Drivers > Compatible with Arduino Ecosystem (RTduino)
- RT-Thread online packages > Arduino libraries > RTduino: Arduino Ecological Compatibility Layer
Use the Env update command. It will download new packages from the Github server.
source ~/.env/env.sh
pkgs --update
Take note that the `pref_counter
` is included by RTduino. As of writing, it unfortunately throws an error during compilation.
To fix this, go to ./packages/perf_counter-latest/SConscript.
Remove this portion from CPPDEFINES:
'__PERF_COUNT_PLATFORM_SPECIFIC_HEADER__=<rtthread.h>'
You will be left with the following:
CPPDEFINES = ['__perf_counter_printf__=rt_kprintf']
Now everything can be compiled, we can write a test code to read the ADC analog voltages. The ADC will be used later on for the current sensor. Go to ./applications/arduino_main.cpp
and use the following code:
#include <Arduino.h>
void setup(void) {
/* put your setup code here, to run once: */
Serial.begin();
}
void loop(void) {
Serial.print("## A0:"); Serial.print(analogRead(A0));
Serial.print(" | A1:"); Serial.print(analogRead(A1));
Serial.print(" | A2:"); Serial.print(analogRead(A2));
Serial.print(" | A3:"); Serial.print(analogRead(A3));
Serial.print(" | A4:"); Serial.print(analogRead(A4));
Serial.print(" | A5:"); Serial.println(analogRead(A5));
delay(2000);
}
Take note, when I did this project, the BSP libraries were not updated to support ADC on the STM32U575. Hence, the ADC values were all zeros.
I have raised this issue to the RT-Thread repo and it has been merged for the next version. If the changes are not present for you, please add it the updated driver code ./libraries/HAL_Driver/drv_adc.c
as per my pull request: https://github.com/RT-Thread/rt-thread/pull/7680
If ADC works properly, you will expect the values to show up.
Creating Adafruit.io DashboardGo to Adafruit IO. You should see your dashboards in your account.
Click on "Newdashboard" and enter the name for this project.
The new dashboard will reflect on the page, let's click on it to set it up. You will see an empty dashboard. Click on "Create new block".
I chose the line chart and created a "current-sensor" feed to be selected for the line-chart.
You can change the parameters of the line chart, I simply filled in the title and left the rest at default.
Your dashboard will look like this now
As the code is very long, I have published it on my Github repo: https://github.com/zst123/rtt_iot_project-2023
I will explain how my application code works:
For the current sensor, I used this Web Serial Plotter to view the values I am printing. In this screenshot, I switched on my laptop charger, and you can see the raw current waveforms (blue) and the calculated power consumption (orange).
For IoT connectivity, the WebClient package is used to connect to Adafruit.io. The data is uploaded to the cloud and can be seen remotely from the live website.
This is the end of the project explanation. I hope this has been useful for you!
Comments