前言
畢設(shè)需要測(cè)量一個(gè)電路的電壓和電流,從而計(jì)算出來功率。這個(gè)電路是和移動(dòng)設(shè)備綁在一起的,所以測(cè)量的信號(hào)要通過WiFi傳遞出來。而接收信號(hào)的方法,可以是網(wǎng)頁(yè)接收或者app,app太復(fù)雜了,所以寫一個(gè)前端小網(wǎng)頁(yè)要簡(jiǎn)單得多。
1. 硬件設(shè)計(jì)
硬件電路主要就是一個(gè)采樣電路和一個(gè)單片機(jī):NodeMCU。
1.1. 采樣電路
這個(gè)采樣電路的作用就是讓需要采樣的數(shù)據(jù)從它流過,然后采集返回?cái)?shù)據(jù)。
電路圖的上半部分就是對(duì)經(jīng)過的電壓電流采樣的電路。P1輸入的電壓范圍為010V,所以在紅框1中使用兩個(gè)20kΩ的分壓電阻使得采樣的電壓范圍為05V,為什么分壓到這個(gè)范圍,是因?yàn)橹蟮?a target="_blank">ADS1115只能采樣到0~VCC的電壓,而該芯片的電壓在該電路中設(shè)計(jì)為5V。如果輸入電壓范圍更寬的話,可以適當(dāng)調(diào)整分壓電阻的大小。
紅框1中還有一個(gè)電流采樣點(diǎn)R3,它是0.2Ω的采樣電阻,這樣會(huì)將電流轉(zhuǎn)化為電壓信號(hào),傳遞給ADS1115采樣。在這個(gè)電路中,如果過3A的電流,采樣電阻上就有0.6V的電壓傳遞給ADS1115。采樣電阻可以更大,這樣采得的電流數(shù)據(jù)就更準(zhǔn)確。但是,電阻太大導(dǎo)致?lián)p耗也會(huì)增大,同時(shí)壓降也會(huì)很大。主電路是要給后續(xù)設(shè)備供電的,采樣壓降太大,后續(xù)設(shè)備也會(huì)受影響。
紅框2中就是采樣信號(hào)的芯片:ADS1115,它有四個(gè)采樣腳,可以差分采樣和單獨(dú)采樣。通過SCL和SDA兩個(gè)管腳以I2C的方式和單片機(jī)連接,從而將采樣的信號(hào)傳輸出去。在本文中,單片機(jī)用的是NodeMCU。
采樣電路通過穩(wěn)壓芯片產(chǎn)生一路5V輸出給NodeMCU供電,同時(shí)SCL、SDA兩個(gè)管腳接受NodeMCU的控制,將采樣數(shù)據(jù)傳遞出去。
1.2. NodeMCU
NodeMCU是一個(gè)開源的物聯(lián)網(wǎng)平臺(tái)。它使用Lua腳本語(yǔ)言編程。該平臺(tái)基于eLua開源項(xiàng)目,底層使用ESP8266 sdk 0.9.5版本。該平臺(tái)使用了很多開源項(xiàng)目,例如 lua-cjson,spiffs。NodeMCU包含了可以運(yùn)行在esp8266 WiFi SoC芯片之上的固件,以及基于ESP-12模組的硬件。
本文中使用的是D1 mini版的NodeMCU,該開發(fā)板上集成了esp8266芯片,它可以用來產(chǎn)生熱點(diǎn)或者連接WiFi,從而構(gòu)成一個(gè)服務(wù)器。這個(gè)開發(fā)板可以讓開發(fā)者以arduino的方式進(jìn)行編程設(shè)計(jì),只不過需要在arduino IDE上導(dǎo)入對(duì)應(yīng)的開發(fā)板即可。
2. 軟件設(shè)計(jì)
2.1. arduino ide添加開發(fā)板
進(jìn)入arduino ide的首選項(xiàng)
回到主面板,進(jìn)入"工具->開發(fā)板->開發(fā)板管理器",在如下圖中輸入esp:
安裝即可實(shí)現(xiàn)新開發(fā)板的添加。
在開發(fā)板中就可以看到NodeMCU的選擇。
2.2. 建立網(wǎng)絡(luò)
arduino有相關(guān)的ESP8266WIFI庫(kù)來操作WiFi,建立網(wǎng)絡(luò)。
首先,這個(gè)開發(fā)板既可以連接WiFi,也可以創(chuàng)建熱點(diǎn)讓其他設(shè)備連接。兩種方式都可以為之后的服務(wù)器做準(zhǔn)備。
2.2.1. 連接WiFi
首先導(dǎo)入ESP8266WiFi.h頭文件,該文件可以在庫(kù)管理中添加WiFi庫(kù)獲得。
在setup
函數(shù)中通過WiFi.begin(ssid, password);
發(fā)起連接WiFi的調(diào)用,然后通過while
不斷輪詢WiFi.status()
檢測(cè)是否連接成功。
如果連接成功,在串口上打印出它獲得的IP。
// Import required libraries
#include < ESP8266WiFi.h >
// WiFi parameters
const char* ssid = "MI8pro";
const char* password = "12345600";
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
}
2.2.2. 開啟熱點(diǎn)
使用NodeMCU產(chǎn)生一個(gè)熱點(diǎn),因?yàn)镹odeMCU沒有和外部網(wǎng)絡(luò)連接,所以這個(gè)熱點(diǎn)是局域網(wǎng)式的。
很簡(jiǎn)單,就是在setup
中通過WiFi.softAP
函數(shù)來開啟熱點(diǎn)。
在此基礎(chǔ)上可以進(jìn)一步實(shí)現(xiàn)網(wǎng)絡(luò)的連接??梢栽?.2.1節(jié)代碼中添加重試次數(shù),如果重試多次還無法連接到對(duì)應(yīng)WiFi,就自己建立熱點(diǎn)。
不過后期,為了便捷開發(fā),只是使用WiFi連接來建立網(wǎng)絡(luò)。
#include < ESP8266WiFi.h >
IPAddress local_IP(192,168,0,100);
IPAddress gateway(192,168,0,100);
IPAddress subnet(255,255,255,0);
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("Setting soft-AP configuration ... ");
Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
Serial.print("Setting soft-AP ... ");
Serial.println(WiFi.softAP("ESPsoftAP", "12345600", 1, false, 10) ? "Ready" : "Failed!");
Serial.print("Soft-AP IP address = ");
Serial.println(WiFi.softAPIP());
}
void loop() {}
2.3. 服務(wù)器
arduino也有相應(yīng)的庫(kù)來建立HTTP服務(wù)器。
這個(gè)服務(wù)器主要處理兩個(gè)路徑的請(qǐng)求:/
和/get
。其中,根目錄就是返回給瀏覽器一個(gè)網(wǎng)頁(yè),而網(wǎng)頁(yè)中會(huì)通過js不停向/get
發(fā)送請(qǐng)求,獲取采集的電壓電流等數(shù)據(jù)。
網(wǎng)頁(yè)如下。
< !DOCTYPE html >
< script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js' >< /script >
< h1 >current and voltage sample< /h1 >
< br/ >
< body >
< script type='text/javascript' >
$(function () {
setInterval(reflush, 1000)
})
function reflush() {
$.getJSON('./get', function(json) {
//解決原生js更新數(shù)據(jù)產(chǎn)生頁(yè)面閃爍的問題
$('#tmp')[0].innerHTML = json.voltage
$('#voltage').html($('#tmp').html())
$('#tmp')[0].innerHTML = json.current
$('#current').html($('#tmp').html())
$('#tmp')[0].innerHTML = json.power
$('#power').html($('#tmp').html())
$('#tmp')[0].innerHTML = json.serial
$('#serial').html($('#tmp').html())
})
}
< /script >
< label id='tmp' hidden >< /label >
< label >voltage: < /label >
< b >
< i >
< label id='voltage' >0.00< /label >
< /i >
< /b >
V< br/ >
< label >current: < /label >
< b >
< i >
< label id='current' >0.00< /label >
< /i >
< /b >
A< br/ >
< label >power: < /label >
< b >
< i >
< label id='power' >0.00< /label >
< /i >
< /b >
W< br/ >
< label >serial-number: < /label >
< b >
< i >
< label id='serial' >0.00< /label >
< /i >
< /b >
< /body >
首先導(dǎo)入頭文件,并定義全局變量server并定義對(duì)應(yīng)的handler。在handleRoot
中會(huì)直接將上述網(wǎng)頁(yè)返回,而在handleGet
中會(huì)將電壓、電流、功率等數(shù)據(jù)通過json的形式返回給客戶端。為了表示數(shù)據(jù)的實(shí)時(shí)性,還附帶了一個(gè)序列號(hào),序列號(hào)在網(wǎng)頁(yè)上的變化,表示了數(shù)據(jù)是實(shí)時(shí)接收的。
#include < ESP8266WebServer.h >
#include < ArduinoJson.h >
//Web Server
ESP8266WebServer server(8080);
void handleRoot() {
server.send(200, "text/html", rootpage);
}
void handleGet() {
StaticJsonDocument< 100 > json;
json["voltage"] = voltage;
json["current"] = current;
json["power"] = power;
char serial[100];
sprintf(serial, "0x%x", millis());
json["serial"] = serial;
char msg[measureJson(json) + 1];
serializeJson(json, msg, measureJson(json) + 1);
server.send(200, "text/plain", msg);
Serial.printf("handleGet: %sn", msg);
}
然后在setup()
函數(shù)中配置對(duì)應(yīng)的handler。
server.on("/", HTTP_GET, handleRoot);
server.on("/get", HTTP_GET, handleGet);
server.begin();
在loop()
函數(shù)中處理客戶端的請(qǐng)求,其實(shí)也就是調(diào)用一個(gè)函數(shù),在loop這個(gè)死循環(huán)中不停處理請(qǐng)求。
//server處理客戶端的請(qǐng)求
server.handleClient();
2.4. 采樣
采樣是通過arduino的一個(gè)ADS1115庫(kù)來實(shí)現(xiàn)的,也是很簡(jiǎn)單。
首先導(dǎo)入需要的庫(kù),并實(shí)例化一些對(duì)象。
#include < Adafruit_ADS1015.h >
// 電壓電流測(cè)量
Adafruit_ADS1115 ads(0x48);
float voltage = 5.00;
float current = 1.11;
float power = voltage * current;
在setup()
函數(shù)中開啟ADS芯片,這個(gè)是很重要的。
ads.begin();
然后在loop()
函數(shù)中,獲取硬件電路中的ADS1115芯片四個(gè)采樣腳的電壓,進(jìn)一步獲得電壓和電流值,0.1875是電壓因數(shù)。
因?yàn)锳DS采樣腳的輸入阻抗問題,測(cè)得的電壓值和實(shí)際的電壓值是有偏移的,不過是線性偏移。只要求兩組采樣值x和實(shí)際值y,然后通過y=ax+b來求得其系數(shù)。
//ADC電壓電流采集,功率計(jì)算
int16_t adc0, adc1, adc2, adc3;
adc0 = ads.readADC_SingleEnded(0);
adc1 = ads.readADC_SingleEnded(1);
adc2 = ads.readADC_SingleEnded(2);
adc3 = ads.readADC_SingleEnded(3);
// AD測(cè)得的值
voltage = ((adc0 - adc1) * 0.1875) / 1000;
current = (adc3 - adc2)*0.1875 / 1000;
//矯正,通過取兩個(gè)點(diǎn)求斜率y=ax+b,a=2.028,b=1.1568,x是測(cè)量值,y是實(shí)際輸入電壓值
voltage = 2.028 * voltage + 1.1568;
//current就是測(cè)得的電壓除以采樣電阻0.2
current = current * 5;
power = voltage * current;
-
采樣電路
+關(guān)注
關(guān)注
10文章
65瀏覽量
28300 -
SDA
+關(guān)注
關(guān)注
0文章
124瀏覽量
28133 -
分壓電阻
+關(guān)注
關(guān)注
0文章
18瀏覽量
11594 -
ESP8266
+關(guān)注
關(guān)注
50文章
962瀏覽量
45000 -
NODEMCU
+關(guān)注
關(guān)注
13文章
289瀏覽量
21403
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論