Table of Contents
In the last blog of HLW8012 energy metering IC, we have got an overview and understanding of HLW8012 IC. So now in continuation to that blog, in this blog, we are going to develop the Application driver for HLW8012. But before preceding with the Application Driver, we will see the hardware setup. At first, we are going to set up the hardware and connections that has to be made for reading the AC readings.
Hardware Setup and connections
To be honest this is one of the challenging parts which I faced when dealing with energy metering ICs. As being mainly into Firmware and software part, I was not well aware of the electrical and electronics-related terms, concepts and instruments. Though I am from the EEE branch interest since my graduation was more aligned with Firmware. But I also want to learn and understand the electronics and electrical part, in continuation to my Firmware skills. Thus, I thought of using the Energy Metering IC and make the Energy Meter project, as by that have to learn and understand the Electronics/electrical concepts.
Energy Metering IC\’s senses the AC voltage and Current, so input to these IC\’s are AC electrical signals. In comparison to other sensors/modules like temperature, Flash memory\’s, gyroscope sensors, display screens etc., in which input is either our environment or values given by us. But in Energy metering or current sensor ICs, for input we need AC load which will be powered by AC power supply. In addition to these we need multimeters, connecting wires and cables for electrical measurement and connections.
Hardware Setup
AC load
Their are 3 types of AC load: Resistive load, Capacitive load, and Inductive load.
There are electrical programmable AC loads, which are actually used in industry for testing and development of Energy Meters. These programmable AC loads can be configured for any type of load. But those are very expensive, to be afforded. So, I started looking for cheap alternatives for all 3 types of AC load.
We are going to use resistive load, which will be an AC bulb filament type.
AC Source
For powering the AC load, we need an AC power supply that will power it. Now while developing the Energy meter and driver for Energy metering IC, I need a variable AC power supply so that I can check the different readings of AC electrical parameters across my AC load. This is one of the first challenges that I faced, which electrical instrument to use, to have a regulated AC power supply. Because AC-regulated power supplies are also quite expensive in comparison to DC-regulated power supplies, which are not affordable to students.
Then I came to know about the Autotransformers that regulate AC power. One can take it analogous to potentiometers, on rotating the knob of them we get variable resistance. Same way in Autotransformers, there is a knob that maps from 0-270V. By rotating the knob, we can get variable AC voltage. Also, the AC signal from Autotransformer is quite stabilized and accurate, so these work great for such small and hobbyist projects.
Multimeters
Multimeters are electrical instruments that are used to measure electrical/electronics parameters. Multimeters can measure both AC/DC readings.
In this project multimeters would be used for measurement of AC voltage and AC current across our load. 2 multimeters would be used. One is the generic multimeter, which would be connected across the Autotransformer output pins to measure the voltage. Another is the Clamp meter, which would be connected across one of the wires of our AC load to measure the AC Current.
The readings which we will get from here would be used to cross verify and check the readings that would be decoded from HLW8012.
HOST MCU
In our case, I have used the STM32f103-Bluepill as HOST MCU.
Logic Analyzer
I will also be using the Logic analyzer, for debugging and seeing the PWM digital signals, that would be outputted by HLW8012.
STLINKV2 Debugger
STLINKV2 will be used as a debugger to program and flash the firmware into our HOST MCU.
Hardware Connections
Now coming to the connection parts, we can divide HLW8012 into 2 parts, one is the electronics connection that has to be connected with the HOST MCU. Another is an electrical connection that has to be made with AC load and AC supply.
At first, we will interface HLW8012 with our host MCU( which in this case is STM32F103-Blue pill). Viewers can refer to this part to understand how HLW8012 and host MCU communicate with each other. HLW8012 has mainly 3 pins CF(Blue), CF1(Green), and SEL(Yellow) pins that have to be connected with HOST MCU.
These pins can be connected to any GPIO pins, just have to make sure that those GPIO pins can be configured in TIMER INPUT CAPTURED MODE. The pins at which CF &CF1 pins will be connected are configured as INPUT and the pins at which the SEL pin would be connected are configured as OUTPUT.
In my case I have connected :
CF1 pin of hLW8012 –> PA8
CF pin of HLW8012 –> PB6
SEL pin of HLW8012 –> PB12
VCC pin of HLW8012 –> +5V pin of MCU
GND pin of HLW8012 –> GND pin of MCU
I have also connected the Logic analyzer for seeing the PWM signals digitally and the debugger STLINKv2 for flashing and debugging the code with my HOST MCU.
Coming to the electrical connection part, the HLW8012 module has 2 couple of green connectors on it.
One couple of connectors is connected to Power Supply, in our case power supply is coming from Autotransformer. So it will be connected to the Output terminals of Autotransformer. Generic Multimeter would be.
Another couple of connector is connected to the AC load, in our case, the AC load is AC bulb Filament type. Clamp multimeter would be connected across one of the wire of this connection to measure AC current.
That is all connection that has to be made and now let\’s move to the code part.
Configuration of HLW8012
HLW8012, has to be configured before we can get actual accurate readings. For that to understand, we have to understand that how does HLW8012 calculates AC readings.
their are concepts og Multiplixers
Application Driver
/** ****************************************************************************** * @file : main.c * @author : Auto-generated by STM32CubeIDE * @brief : Main program body ****************************************************************************** * @attention * ****************************************************************************** */ #include <stdint.h> #include \"gb_gpio.h\" #include \"gb_rcc.h\" #include \"GB_UART.h\" #include \"gb_t_delay.h\" #include \"GB_millis_systick.h\" #include \"stm32f1xx.h\" #include \"gb_timer_input_capture.h\" #include \"hlw8012_baremetal.h\" #include \"gb_ssd1306.h\" #define UPDATE_TIME 2000 #define DEMCR *((volatile uint32_t*) 0xE000EDFCU ) /* ITM register addresses */ #define ITM_STIMULUS_PORT0 *((volatile uint32_t*) 0xE0000000 ) #define ITM_TRACE_EN *((volatile uint32_t*) 0xE0000E00 ) int _write(int file, char *ptr, int len) { int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { //__io_putchar(*ptr++); ITM_SendChar(*ptr++); } return len; } #define CURRENT_RESISTOR 0.001 #define VOLTAGE_RESISTOR_UPSTREAM ( 5 * 470000 ) // Real: 2280k #define VOLTAGE_RESISTOR_DOWNSTREAM ( 1000 ) // Real 1.009k int main(void) { RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; systick_millis(32000); system_clk(); timer_initialise(); ssd1306_init(); ssd1306_clear(GB_SSD1306_COLOR_BLACK); ssd1306_update_data(); GB_uart_init1(); //terminal GB_printString1(\"Timer input capturen\"); gb_t4_input_capture(); gb_t1_input_capture(); __NVIC_SetPriority (TIM4_IRQn, 1); __NVIC_EnableIRQ(TIM4_IRQn); __NVIC_SetPriority (TIM1_CC_IRQn, 2); __NVIC_EnableIRQ(TIM1_CC_IRQn); hlw8012_config(); hlw8012_setResistors(CURRENT_RESISTOR, VOLTAGE_RESISTOR_UPSTREAM, VOLTAGE_RESISTOR_DOWNSTREAM); GB_printString1(\" Default Current Multiplier\"); GB_decimel1(hlw8012_getcurrent_multiplier()); GB_printString1(\" Default Voltage Multiplier\"); GB_decimel1(hlw8012_getvoltage_multiplier()); GB_printString1(\" Default Power Multiplier\"); GB_decimel1(hlw8012_getpower_multiplier()); hlw8012_calibrate(); while(1) { ssd1306_GotoXY(0, 0); ssd1306_print_string(\"Current:\", GB_SSD1306_COLOR_WHITE); ssd1306_float(hlw8012_getcurrent(),GB_SSD1306_COLOR_WHITE); ssd1306_print_string(\" A\", GB_SSD1306_COLOR_WHITE); ssd1306_update_data(); ssd1306_GotoXY(0, 15); ssd1306_print_string(\"Voltage:\", GB_SSD1306_COLOR_WHITE); ssd1306_float(hlw8012_getvoltage(),GB_SSD1306_COLOR_WHITE); ssd1306_print_string(\" V\", GB_SSD1306_COLOR_WHITE); ssd1306_update_data(); ssd1306_GotoXY(0, 24); ssd1306_print_string(\"Power:\", GB_SSD1306_COLOR_WHITE); ssd1306_float(hlw8012_getactivepower(),GB_SSD1306_COLOR_WHITE); ssd1306_print_string(\" W\", GB_SSD1306_COLOR_WHITE); ssd1306_update_data(); GB_printString1(\"Current in AMPS: \"); GB_float_value1(hlw8012_getcurrent()); GB_printString1(\"A\"); GB_uart_newline1(); GB_printString1(\"Voltage in Volts: \"); GB_float_value1(hlw8012_getvoltage()); GB_printString1(\"V\"); GB_uart_newline1(); } }
Header file(hlw8012.h)
/* hlw8012.h * * Created on: May 16, 2022 * Author: Gettobyte */ #ifndef HLW8012_BAREMETAL_H_ #define HLW8012_BAREMETAL_H_ void hlw8012_config(); void hlw8012_pins_config(); double hlw8012_getcurrent_multiplier(); double hlw8012_getvoltage_multiplier(); double hlw8012_getpower_multiplier(); void hlw8012_sel_low_volatge(); void hlw8012_sel_high_current(); void gb_unblockingDelay(uint32_t mseconds); void hlw8012_calibrate(); float hlw8012_getcurrent(); float pulseIN_current(); float hlw8012_getvoltage(); float pulseIN_voltage(); float hlw8012_getactivepower(); void hlw8012_setResistors( double current, double voltage_upstream, double voltage_downstream); void hlw8012_expected_ActiveCurrent( double value); #endif /* HLW8012_BAREMETAL_H_ */