ESP32用ADC1即36引脚analogRead读数为111111 1111 最大值为4095的1111, 资料 传送门 上述读取的最大电压.3V,实测3V当读数为4095时,模拟电压为3V,万用表测量误差可能存在,当满量程为3时.3V吧。 demo如下:
void setup() {
Serial.begin(115200); } void loop() {
int vtmp=analogRead(36); //ADC获取电压 Serial.printf("采样值为%:d\n", vtmp); Serial.printf("电压为:%.3fV\n", vtmp * 3.3 / 4095); delay(1000); }
ACS712霍尔互感器,5A量程输出为185mV/A,20A量程输出为100mV/A,30A量程输出为66mV/A,我买的是20A的。 接线如下
ESP32 | ACS712 |
---|---|
5V | VCC |
G | GND |
36 | OUT |
在空载的情况下,ACS理论上,712输出是2.5V,2.5V即0点。如果测量是直流电,数量为2.5 ;如果测量交流电,值为2.5 2.5-上。实测后发现几个问题:
- 空载输出不是2.5V但在2.7±0.2V浮动。 解决方案:用50次测量取平均值,使值相对稳定。有资料说要在硬件上加低通滤波,不会搞T_T。
- 就算是零点2.5V稳定,按20A量程输出为100mV/A如果电流测量为20A,那ACS712输出电压为2.5 0.120=4.5V,而ESP32的测量模拟量为3.3V,已经超过了ESP32的量程。怎么办? 解决方案:想想工作电压是否为5V,零点为2.5V,工作电压为3.3V,零点也到1吗?.65V是的?按照这个想法来测量,确实如此。就是不知道还是1000。mV/A,待测量。如果仍然是这个标准,满量程输出电压为1.65 0.120=3.75V,粗心也可以测量。假设工作电压下降,输出标准同比下降,那么20A标准变为66mV/A,满测量输出为:4.5*0.66=2.97V,那就在ESP测量范围在32范围内,但只是猜测,待测量确认。
注:github搜索ACS712会出来很多别人写的。arduino都是针对的arduino模拟测量程5V ,10位采样是1023写的。需要调整程序中的参数。例如,我将根据以下内容进行调整ESP32参数有所改进: ACS712.h
#ifndef ACS712_h #define ACS712_h #include <Arduino.h> #define ADC_SCALE 4095.0//采样值 arduino为1023 #define VREF 3.3 //参考电压,即全量程模拟电压,arduino为5 #define DEFAULT_FREQUENCY 50///交流频率 enum ACS712_type {
ACS712_05B, ACS712_20A, ACS712_30A}; class ACS712 {
public:
ACS712(ACS712_type type, uint8_t _pin);
int calibrate(); // 零点校准值
void setZeroPoint(int _zero);
void setSensitivity(float sens);
float getCurrentDC(); // 测直流电
float getCurrentAC(uint16_t frequency = 50); // 测交流电
private:
int zero = 2048;//零点模拟值
float sensitivity;
uint8_t pin;
};
#endif
ACS712.cpp
#include "ACS712.h"
ACS712::ACS712(ACS712_type type, uint8_t _pin) {
pin = _pin;
// 不同量程模块的灵敏度,工作电压变了,这里的灵敏度值估计也要同比调整
switch (type) {
case ACS712_05B: // 5A
sensitivity = 0.185;
break;
case ACS712_20A: // 20A
sensitivity = 0.100;
break;
case ACS712_30A: // 30A
sensitivity = 0.066;
break;
}
}
// 零点校准
int ACS712::calibrate() {
uint16_t acc = 0;
for (int i = 0; i < 50; i++) {
// 50次取样平均,原版10次
acc += analogRead(pin);
}
zero = acc / 50;
return zero;
}
// 设置零点值
void ACS712::setZeroPoint(int _zero) {
zero = _zero;
}
// 设置灵敏度值
void ACS712::setSensitivity(float sens) {
sensitivity = sens;
}
// 测量直流电,单位:mA 毫安
float ACS712::getCurrentDC() {
int16_t acc = 0;
for (int i = 0; i < 50; i++) {
//50次采样,原版10次
acc += analogRead(pin) - zero;
}
float I = (float)acc / 50.0 / ADC_SCALE * VREF / sensitivity * 1000 ;
return I;
}
// 测量交流电,单位:mA 毫安
float ACS712::getCurrentAC(uint16_t frequency) {
uint32_t period = 1000000 / frequency;
uint32_t t_start = micros();
uint32_t Isum = 0, measurements_count = 0;
int32_t Inow;
while (micros() - t_start < period) {
Inow = analogRead(pin) - zero;
Isum += Inow*Inow;
measurements_count++;
}
float Irms = sqrt(Isum / measurements_count) / ADC_SCALE * VREF / sensitivity * 1000;
return Irms;
}
测量直流电DEMO
#include "ACS712.h"
/* This example shows how to measure DC current */
// We have 30 amps version sensor connected to A0 pin of arduino
// Replace with your version if necessary
ACS712 sensor(ACS712_30A, A0);
void setup() {
Serial.begin(115200);
// calibrate() method calibrates zero point of sensor,
// It is not necessary, but may positively affect the accuracy
// Ensure that no current flows through the sensor at this moment
// If you are not sure that the current through the sensor will not leak during calibration - comment out this method
Serial.println("Calibrating... Ensure that no current flows through the sensor at this moment");
int zero = sensor.calibrate();
Serial.println("Done!");
Serial.println("Zero point for this sensor = " + zero);
}
void loop() {
// Read current from sensor
float I = sensor.getCurrentDC();
// Send it to serial
Serial.println(String("I = ") + I + " mA");
// Wait a second before the new measurement
delay(1000);
}
测量交流电DEMO
#include "ACS712.h"
/* This example shows how to measure the power consumption of devices in 230V electrical system or any other system with alternative current */
// We have 30 amps version sensor connected to A0 pin of arduino
// Replace with your version if necessary
ACS712 sensor(ACS712_30A, A0);
void setup() {
Serial.begin(9600);
// calibrate() method calibrates zero point of sensor,
// It is not necessary, but may positively affect the accuracy
// Ensure that no current flows through the sensor at this moment
// If you are not sure that the current through the sensor will not leak during calibration - comment out this method
Serial.println("Calibrating... Ensure that no current flows through the sensor at this moment");
sensor.calibrate();
Serial.println("Done!");
}
void loop() {
// We use 230V because it is the common standard in European countries
// Change to your local, if necessary
float U = 230;
// To measure current we need to know the frequency of current
// By default 50Hz is used, but you can specify desired frequency
// as first argument to getCurrentAC() method, if necessary
float I = sensor.getCurrentAC();
// To calculate the power we need voltage multiplied by current
float P = U * I;
Serial.println(String("I = ") + I + " mA");
Serial.println(String("P = ") + P + " Watts");
delay(1000);
}
原版库传送门