Arduino开发实例-DIY电能表

DIY电能表

在本文中,将展示如何制作一个基于 Arduino 的功率和电能表。应用使用 INA219 电流传感器测量电流、功率和能耗,并将其显示在 OLED 显示屏上。 可以在 OLED 显示屏上查看您的电压、电流、功率和能量数据。

1、INA219介绍

INA219 电流传感器是一款支持 I2C 的基于接口的零漂移和双向电流/功率监控模块。 它可以测量电路的电流、电压和功率。 我们可以很容易地使用 INA219 电流传感器和 Arduino 来测量电流和功率,它还可以检测分流电压。 该传感器模块配备 0.1 欧姆和 1% 的分流电阻,以满足电流测量的要求。 它可以测量高达+26V的直流电压。

在这里插入图片描述

INA219 的工作电压在 3V 和 5.5V 之间。 传感器值通过 INA219 模块和微控制器之间的 I2C 通信协议传输。

1)INA219工作原理

在我们开始使用 INA219 传感器之前,我们必须了解该传感器的工作原理。

在这里插入图片描述

INA219 传感器有一个 2端子,串联到测量的高端,能够测量高达 26V 的电压。 螺纹项与一个 0.1Ω 1% 检测分流电阻并联。 INA219 在高端测量两个不同的电压:

  • V_shunt 是分流电阻器上的电压降。
  • V_bus 是来自负极相对于地的电压。

然后将两个电压转发到可编程增益放大器 (PGA) 以提高测量的灵敏度。 INA219 将满量程范围提高了 2、4 或 8 倍 (320mV)。 此外,总线电压测量有两个范围:16V 和 32V。

在提高电压测量的灵敏度后,计算电流和功率。 下图显示了如何根据分流器和母线电压进行计算。

在这里插入图片描述

通过将分流电压乘以分流电阻器的校准电阻来计算测量高端上的电流。 由于分流电阻为 0.1Ω,8 档的最大分流电压为 320mV,因此可测量的最大电流为 320mV / 0.1Ω = 3.2A。

然后用这个电流乘以总线电压来计算功率。 基于 3.2A 的最大电流和 26V 的最大总线电压,INA219 可以测量高达 3.2A * 26V = 83W 的功率。

因此,INA219 能够提供四种不同的测量:

  • 分流电压:分流电阻上的电压降
  • 总线电压:被测电路看到的总电压。 (电源电压 - 分流电压)。
  • 电流:通过欧姆定律从测得的分流电压得出
  • 功率:电流乘以母线电压

每个测量和计算都存储在连接到 I2C 接口的寄存器中,以将值转发到 Arduino 或 ESP 微控制器。

2、硬件接线

本次应用使用到的硬件配件如下:

序号 配件名称 数量
1 Arduino Nano 1
2 0.96” I2C OLED 显示屏 1
3 INA219 电流传感器 1
4 杜邦线 20

本次硬件接线如下:

在这里插入图片描述

关于SSD1306 OLED驱动请参考:

3、驱动实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <Wire.h>
#include <Adafruit\_INA219.h>
#include <Adafruit\_SSD1306.h>

#define SCREEN\_WIDTH 128 // OLED display width, in pixels
#define SCREEN\_HEIGHT 32 // OLED display height, in pixels
#define OLED\_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN\_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_INA219 ina219;

unsigned long previousMillis = 0;
unsigned long interval = 100;
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
float energy = 0;

void setup(void)
{
Serial.begin(115200);
while (!Serial) {
// will pause Zero, Leonardo, etc until serial console opens
delay(1);
}

uint32\_t currentFrequency;

Serial.println("Hello!");
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();

// Initialize the INA219.
// By default the initialization will use the largest range (32V, 2A). However
// you can call a setCalibration function to change this range (see comments).
if (! ina219.begin()) {
Serial.println("Failed to find INA219 chip");
while (1) { delay(10); }
}
// To use a slightly lower 32V, 1A range (higher precision on amps):
//ina219.setCalibration\_32V\_1A();
// Or to use a lower 16V, 400mA range (higher precision on volts and amps):
//ina219.setCalibration\_16V\_400mA();

Serial.println("Measuring voltage and current with INA219 ...");
}

void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
ina219values();
displaydata();
}
}


void ina219values() {

shuntvoltage = ina219.getShuntVoltage\_mV();
busvoltage = ina219.getBusVoltage\_V();
current_mA = ina219.getCurrent\_mA();
power_mW = ina219.getPower\_mW();
loadvoltage = busvoltage + (shuntvoltage / 1000);
energy = energy + loadvoltage \* current_mA / 3600;

Serial.print("Bus Voltage: "); Serial.print(busvoltage); Serial.println(" V");
Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V");
Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA");
Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW");
Serial.println("");
}
void displaydata() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(loadvoltage);
display.setCursor(31, 0);
display.println("V");
display.setCursor(62, 0);
display.setCursor(75, 0);
display.println(current_mA);
display.setCursor(110, 0);
display.println("mA");
display.setCursor(0, 6);
display.println("--------------------");

display.setCursor(0, 13);
display.println(loadvoltage \* current_mA);
display.setCursor(57, 13);
display.println("mW");
display.setCursor(0, 23);
display.println(energy);
display.setCursor(57, 23);
display.println("mWh");
display.display();
}

代码如何运行?

1)导入依赖库

1
2
3
4
#include <Wire.h>
#include <Adafruit\_INA219.h>
#include <Adafruit\_SSD1306.h>

2)设备定义

1
2
3
4
5
6
7
#define SCREEN\_WIDTH 128 // OLED display width, in pixels
#define SCREEN\_HEIGHT 32 // OLED display height, in pixels
#define OLED\_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN\_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_INA219 ina219;

3)定义测量相关变量

1
2
3
4
5
6
7
8
9
unsigned long previousMillis = 0;
unsigned long interval = 100;
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
float energy = 0;

4)在setup函数中,初始化设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void setup(void) 
{
Serial.begin(115200);
while (!Serial) {
// will pause Zero, Leonardo, etc until serial console opens
delay(1);
}

uint32\_t currentFrequency;

Serial.println("Hello!");
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();

// Initialize the INA219.
// By default the initialization will use the largest range (32V, 2A). However
// you can call a setCalibration function to change this range (see comments).
if (! ina219.begin()) {
Serial.println("Failed to find INA219 chip");
while (1) { delay(10); }
}
// To use a slightly lower 32V, 1A range (higher precision on amps):
//ina219.setCalibration\_32V\_1A();
// Or to use a lower 16V, 400mA range (higher precision on volts and amps):
//ina219.setCalibration\_16V\_400mA();

Serial.println("Measuring voltage and current with INA219 ...");
}

5)在loop函数中,采集传感器

1
2
3
4
5
6
7
8
9
10
11
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
ina219values();
displaydata();
}
}

6)数据显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void ina219values()  {

shuntvoltage = ina219.getShuntVoltage\_mV();
busvoltage = ina219.getBusVoltage\_V();
current_mA = ina219.getCurrent\_mA();
power_mW = ina219.getPower\_mW();
loadvoltage = busvoltage + (shuntvoltage / 1000);
energy = energy + loadvoltage \* current_mA / 3600;

Serial.print("Bus Voltage: "); Serial.print(busvoltage); Serial.println(" V");
Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V");
Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA");
Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW");
Serial.println("");
}
void displaydata() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(loadvoltage);
display.setCursor(31, 0);
display.println("V");
display.setCursor(62, 0);
display.setCursor(75, 0);
display.println(current_mA);
display.setCursor(110, 0);
display.println("mA");
display.setCursor(0, 6);
display.println("--------------------");

display.setCursor(0, 13);
display.println(loadvoltage \* current_mA);
display.setCursor(57, 13);
display.println("mW");
display.setCursor(0, 23);
display.println(energy);
display.setCursor(57, 23);
display.println("mWh");
display.display();
}

文章来源: https://iotsmart.blog.csdn.net/article/details/128183467