|
我们都知道基本的电压表、电流表和功率表,这是测量任何电子项目或电路上的值所需的三个基本设备。借助万用表测量电压和电流是一个很好的方法,但是我在测试电路时面临的最大问题之一就是测量电源效率。因此,今天我们将通过搭建一个基于Arduino和ESP32的功率计来解决该问题,该功率计可以测量输入电压、输入电流、输出电压和输出电流。因此,它可以同时测量输入功率和输出功率,利用这些值,我们可以轻松地测量效率。
搭建数字表不仅可以降低成本,而且还为您提供了升级和改进的空间。由于我们使用ESP32来构建此项目,因此我们可以轻松地使此仪表具有IoT功能并通过Web记录数据,现在让我们开始吧。
ESP32功率计所需的材料 下图显示了用于构建电路的材料。由于这是由非常通用的组件组成的。
我还列出了以下组件以及所需数量。如果您自己构建电路,强烈建议从下面的列表中所有材料。 ● ESP32开发板-1 ● 128X64 OLED-1 ● ACS712-20 IC-2 ● DC电源插头-1 ● 100uF电容-2 ● 104pF电容-2 ● 102pF电容-2 ● 10K,1%-4 ● 68K,1%-2 ● 6.8K,1%-2
基于Arduino和ESP32的功率计 - 电路图 基于Arduino和ESP32的功率计的原理图如下所示。创建此电路非常简单,使用通用组件。
电路的操作非常简单。我们将以一种独特的方式来测量该项目中的电压和电流。我们同时测量输入和输出的电压和电流,因此我们可以实时看到电路的效率。对于某些项目,这非常方便。这些电路的工作方式如下所述。
ACS712电流传感器
如上图所示,我们使用ACS712电流传感器来测量电流。这是一个非常有趣的IC,因为它使用霍尔效应来测量电流。我们使用的是20A的型号,具体为ACS712-20。
ACS712数据表建议在4.5-5.5的电压范围内正常运行。当我们使用ESP32测量电流时,它只能承受3.3V的电压,这就是为什么我使用带有两个10K电阻的分压器来降低ACS712 IC的输出电压的原因。当没有电流流过IC时,它会输出2.5V,而当有电流流过IC时,它会根据电流的流向降低电压或提高电压。
分压电路
为了测量输入和输出电压,我们在电路的输入和输出侧有两个分压器。该电路可以测量的最大电压为35V,但可以通过更改分压器的电阻值轻松地对其进行更改。
稳压器
使用通用LM7805稳压器为ESP32、OLED和ACS712 IC供电。当我们使用非常干净的电源为其供电时,可以不使用任何去耦电容器,但我们在输入和输出端均使用了100uF电容来稳定IC。
ESP32 IC和OLED显示屏
我们使用ESP32作为主处理器,负责所有的读数、计算、输入和输出。另外,我们使用了128X64 OLED显示屏来显示这些值。
基于Arduino和ESP32的功率计的PCB设计 我们的基于Arduino和ESP32的效率计的PCB设计在单面板上。使用Eagle来设计PCB,但是您可以使用任何选择的设计软件。电路板设计的2D图像如下所示。
足够的接地线用于在所有组件之间进行正确的接地连接。此外,我们确保使用正确的5V和3.3V走线以减少噪声并提高效率。
Arduino代码 现在,我们对硬件方面有了很好的了解之后,可以打开Arduino IDE并开始编写代码。该代码的目的是从ESP32开封板的引脚35和33读取模拟电压。另外,我们从32引脚读取电压和34引脚读取电流值。完成此操作后,我们可以将它们相乘以获得输入功率和输出功率,并将其放在效率公式中,就可以得出效率。最后,我们将其显示在LCD屏幕上。
由于我们使用的是128X64 OLED显示器,因此我们需要Adafruit_GFX库和Adafruit_SSD1306库与显示屏进行通信。您可以从Arduino的默认板管理器中下载;也可以从与其关联的GitHub存储库中下载并包含库,如下所示。 ● 下载Adafruit_GFX库 ● 下载Adafruit_SSD1306库
与往常一样,首先我们包含所有必需的库。然后,我们定义所有的引脚和变量,如下所示。 - #include <Wire.h>
- #include <Adafruit_GFX.h>
- #include <Adafruit_SSD1306.h>
- #include <math.h>
- #define SCREEN_WIDTH 128 // OLED display width, in pixels
- #define SCREEN_HEIGHT 64 // OLED display height, in pixels
- #define INPUT_VOLTAGE_SENSE_PIN 33
- #define OUTPUT_VOLTAGE_SENSE_PIN 35
- #define INPUT_CURRENT_SENSE_PIN 32
- #define OUTPUT_CURRENT_SENSE_PIN 34
- double R1_VOLTAGE = 68000; //68K
- double R2_VOLTAGE = 6800; // 6.8K
- double R1_Current 10000 //10K
- double R2_Current 22000 //22K
- //We have used 50 as mVperp value; please refer to the documentation for further information
- double mVperAmp = 50; // use 100 for 20A Module and 66 for 30A Module
- double ACSoffset = /*1130*/ 1136;
- // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
- Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
复制代码
SCREEN_WIDTH和SCREEN_HEIGHT定义用于定义屏幕尺寸。接下来,我们定义了所有必需的引脚,通过这些引脚我们将测量电压和电流。接下来,我们定义了电阻值,这些电阻值在硬件中使用,如从原理图中可以看到的。如果您没有这些值,或者想要更改仪表的范围,则可以更改这些值,代码就可以正常工作。
当我们使用ACS712测量电流时,我们需要mVperAmp值来根据电压计算电流。当我使用20A ACS712模块时,数据表中给出的mV / A值为100。但是由于使用的是ESP32和分压器,因此只有一半的值(即50)。
ACSoffset是从电压计算电流所需的偏移量。由于ACS712 IC由5V供电,因此偏移电压为2.5V。但是,当我们使用分压器时,它会降至1.25V。如果遇到校准问题,可以调整这些值并补偿ADC。
最后,我们使用Adafruit_SSD1306类创建一个显示对象,并传递屏幕宽度、高度、I2C配置和最后一个-1参数来定义函数。如果您的显示屏没有外部复位引脚,那么最后一个参数必须使用-1。 - void setup() {
- Serial.begin(115200);
- if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
- Serial.println(F("SSD1306 allocation failed"));
- for (;;);
- }
- display.clearDisplay();
- display.setRotation(2);
- display.setTextSize(1);
- delay(100);
- }
复制代码
接下来,我们介绍setup()部分。在本节中,我们将启用串行调试功能,并借助显示对象的begin方法来检查I2C显示是否可用。另外,我们设置I2C地址。接下来,我们使用clearDisplay()清除显示内容。另外,我们使用setRotation函数旋转显示屏。接下来,我们为使函数生效设置了100 ms的延迟。完成后,我们现在可以继续loop函数。但是在这之前,我们需要讨论另外两个函数,分别是return_voltage_value()和return_current_value()。 - double return_voltage_value(int pin_no)
- {
- double tmp = 0;
- double ADCVoltage = 0;
- double inputVoltage = 0;
- double avg = 0;
- for (int i = 0; i < 150; i++)
- {
- tmp = tmp + analogRead(pin_no);
- }
- avg = tmp / 150;
- ADCVoltage = ((avg * 3.3) / (4095)) + 0.138;
- inputVoltage = ADCVoltage / (R2_VOLTAGE / (R1_VOLTAGE + R2_VOLTAGE)); // formula for calculating voltage in i.e. GND
- return inputVoltage;
- }
复制代码return_voltage_value()函数用于测量进入ADC的电压,它以引脚编号作为参数。在此函数中,我们首先声明一些变量,它们是tmp、ADCVoltage、inputVoltage和avg。 tmp变量用于存储从analogRead()函数获得的临时ADC值,然后在for循环中将其取平均值150次,然后将该值存储到一个称为avg的变量中。然后,根据给定的公式计算ADCVoltage,最后,计算输入电压并返回值。您看到的+0.138值是我用来校准电压电平的校准值。 - double return_current_value(int pin_no)
- {
- double tmp = 0;
- double avg = 0;
- double ADCVoltage = 0;
- double Amps = 0;
- for (int z = 0; z < 150; z++)
- {
- tmp = tmp + analogRead(pin_no);
- }
- avg = tmp / 150;
- ADCVoltage = ((avg / 4095.0) * 3300); // Gets you mV
- Amps = ((ADCVoltage - ACSoffset) / mVperAmp);
- return Amps;
- }
复制代码接下来,我们介绍return_current_value()函数。此函数也使用引脚编号作为参数。在该函数中,我们还有四个变量viz、tmp、avg、ADCVoltage和Amps。接下来,我们使用analogRead()函数读取该引脚并将其取平均值150次,然后使用公式计算ADC电压,然后计算电流并返回该值。
- void loop()
- {
- float input_voltage = abs(return_voltage_value(INPUT_VOLTAGE_SENSE_PIN)) ;
- float input_current = abs(return_current_value(INPUT_CURRENT_SENSE_PIN)) ;
- float output_voltage = abs(return_voltage_value(OUTPUT_VOLTAGE_SENSE_PIN)) ;
- float output_current = abs((return_current_value(OUTPUT_CURRENT_SENSE_PIN))) ;
- input_current = input_current - 0.025;
- Serial.print("Input Voltage: ");
- Serial.print(input_voltage);
- Serial.print(" | Input Current: ");
- Serial.print(input_current);
- Serial.print(" | Output Voltage: ");
- Serial.print(output_voltage);
- Serial.print(" | Output Current: ");
- Serial.println(output_current);
- delay(300);
- display.clearDisplay();
- display.setCursor(0, 0);
- display.print("I/P V: ");
- display.setCursor(37, 0);
- display.print(input_voltage);
- display.setCursor(70, 0);
- display.print("V");
- }
复制代码首先我们声明并定义4个float变量。我们调用相应的函数,将引脚编号作为参数传递,因为ACS712模块可以返回负的当前值。我们使用数学库的abs()函数将负值设为正。接下来,我们串口打印所有值以进行调试。接下来,我们清除显示、设置光标,然后打印值。
测试基于Arduino和ESP32的功率计
您可以在上图中看到我的测试设置。我将30V变压器作为输入,并将仪表连接到测试板。我使用的是基于LM2596的降压转换器板,并且用于负载,并且使用了三个并联的10欧姆电阻。
如上图所示,我已连接到万用表以检查输入和输出电压。变压器产生大约32V的电压,降压转换器的输出为3.95V。
上图显示了由功率计和万用表测得的输出电流。万用表显示为0.97安培,这是由于ACS712模块中存在非线性而略有偏离,但这符合我们的目的。
希望您喜欢本文并从中学到新东西。如有任何疑问,请随时在本贴下面进行回复。 |