ESP8266系列文章目录
ESP8266系列文章目录
经过不断的努力,处女作终于出来了。Arduino
带有一个SSD1306 OLED显示电压、电流、功率、温度的屏幕,BLINKERapp检查电压、电流、功率mah、Wh、峰值功率、运行时间、功率比、环境温度、环境湿度、控制器温度、控制器温度控制散热风扇(可在APP检查实时转速)。低电压报警,电池低电压自动切断电压输出APP查看状态)和图标功能。App端文字的颜色可以根据参数自动变化,图标也可以根据参数变化(用了很多if语句。 按刷新健对APP刷新数据。 刚上电截图时,需要放电一次开发板复位,然后开始充电。我用监控24V三元锂18650电池20并6串,满电25.2V。
电比可以根据个人想要的方式改变公式。我的设计容量是1万Wh,所以除1000。
也可以用电压来计算比例,看个人喜好。
ta=Da/1000*100;
2、硬件
ESP8266开发板一块,SSD1306屏幕(0.96寸IIC接口)、INA226电压电流检测模块(IIC接口),双向电流,我选择的采样电阻0.002Ω卖方声称最大能承受20A,最大电压36V、dht11温湿度传感器,10K电阻 10K热敏电阻(用于A0 ADC接口测温),所有硬件都没有拍照。
3、硬件连接
将INA226的SCL、SDA与开发板分开D1、D2连接;将SSD1306的SCL、SDA与开发板分开D5、D6连接;两个模块都支持3.3V在开发板上直接供电。将DHT11单总线通信口和开发板D7连接。温敏电阻直接分压电路ADC 开发板A0接口(开发板内置分压电路,核心板ADC接口不会超1V,因此,外部分压电路也可以从开发板取电,无需直接设计).3V,一些电路图来自网络,以节省绘图时间。开发板D8用于控制MOS管开断实现输出低压保护,开发板D3用于PWM输出控制MOS控制散热风扇。
下图为INA226测量端接线图。
4、程序编写
需要额外下载的库文件:INA226.h、U8g2.h、DHT11.h后两者可以直接存在Arduion内部下载开发软件。
1.整体框架是BLINKER WiFi这里就不写结构了。
2、读取DHT11数据
float h = dht.readHumidity(); float t = dht.readTemperature(); if (isnan(h) || isnan(t)) { BLINKER_LOG("Failed to read from DHT sensor!"); } else { BLINKER_LOG("Humidity: ", h, " %"); BLINKER_LOG("Temperature: ", t, " *C"); humi_read = h; temp_read = t; } //DHT11读温湿度
3、读ADC接口数据并转换为温度(监测控制器温度)。
float ADCvalue; float Resistance; ADCvalue = analogRead(NTCPin); Serial.print("Analog value "); Serial.print(ADCvalue); Serial.print(" = "); //convert value to resistance Resistance = (1023 / ADCvalue) - 1; Resistance = SERIESRESISTOR / Resistance; Serial.print(Resistance); Serial.println(" Ohm"); float steinhart; steinhart = Resistance / NOMINAL_RESISTANCE; // (R/Ro) steinhart = log(steinhart); // ln(R/Ro) steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro) steinhart = 1.0 / (NOMINAL_TEMPERATURE 273.15); // (1/To) steinhart = 1.0 / steinhart; // Invert steinhart -= 273.15; // convert to C //steinhart = steinhart * 1.8 32; // convert to F Serial.print("Temperature "); Serial.print(steinhart); Serial.println("°C"); tem11=steinhart;
4.这是在回调函数中使用的IF写不同的情况APP发送不同的图标、不同的颜色文本、文本和数据。
void dataRead(const String & data) { BLINKER_LOG("Blinker readString: ", data); Blinker.vibrate(); uint32_t BlinkerTime = millis(); //Blinker.print("V", BusVoltage); Number1.icon("fad fa-car-battery"); Number1.print(BusVoltage); //Blinker.print("A", ShuntCurrent); if(ShuntCurrent>0) { Number2.color("#00FF7F"); Number2.icon("fas fa-battery-bolt"); Number2.print(ShuntCurrent*1000); }else { Number2.color("#FF0000"); Number2.icon("fal fa-battery-half"); Number2.print(ShuntCurrent*1000); } //Blinker.print("W", BusPower); Number3.print(BusPower); //Blinker.print("mAh", CapaPower); if(CapaPower<=8000) { if(CapaPower<=8000&&CapaPower>=4000) { Number4.color("#FFA500"); Number4.print(CapaPower); } if(CapaPower<4000) { Number4.color("#FF0000"); Number4.print(CapaPower); } }else { Number4.print(CapaPower); } //Blinker.print("millis", BlinkerTime); //Number5.print(BlinkerTime/1000/60); if(Da<=200) { if(Da>=100&&Da<=200) { //Blinker.print("Wh", Da); Number9.color("#FFA500"); Number9.print(Da); } if(Da<100) { //Blinker.print("Wh", Da); Number9.color("#FF0000"); Number9.print(Da); } }else { Number9.print(Da); } //Blinker.print("W",BusPower1); Number8.print(BusPower1); //Blinker.print("%",ta); if(ta<=30) { if(ta<=30&&ta>=20) { TA.color("#FFA500"); TA.icon("fas fa-battery-quarter"); TA.print(ta); } if(ta<20) { TA.color("#FF0000"); TA.icon("fs fa-battery-quarter");
TA.print(ta);
}
if(ta<=0)
{
TA.color("#FF0000");
TA.icon("fas fa-battery-empty");
TA.print(ta);
}
}else
{
if(ta>=100)
{
TA.color("#32CD32");
TA.icon("fas fa-battery-full");
TA.print(ta);
}
if(ta<100&&ta>30)
{
TA.color("#00FF7F");
TA.icon("fas fa-battery-three-quarters");
TA.print(ta);
}
}
if(humi_read<70)
{
if(humi_read<=70&&humi_read>=60)
{
HUMI.color("#9ACD32");
HUMI.print(humi_read);
HUMI.text("较舒适");
}
if(humi_read<60&&humi_read>=40)
{
HUMI.color("#00FF7F");
HUMI.print(humi_read);
HUMI.text("舒适");
}
if(humi_read<40&&humi_read>30)
{
HUMI.color("#FFD700");
HUMI.print(humi_read);
HUMI.text("环境较干燥");
}
if(humi_read<30)
{
HUMI.color("#FFA500");
HUMI.print(humi_read);
HUMI.text("环境干燥");
}
}else
{
//Blinker.print("%",humi_read);
HUMI.color("#008080");
HUMI.print(humi_read);
HUMI.text("环境潮湿");
}
if(temp_read<37.5)
{//Blinker.print("℃",temp_read);
if(temp_read<37.5&&temp_read>=35)
{
TEMP.icon("fas fa-temperature-up");
TEMP.color("#FF6347");
TEMP.print(temp_read);
TEMP.text("环境炎热");
}
if(temp_read<35&&temp_read>=28)
{
TEMP.icon("fad fa-temperature-up");
TEMP.color("#FFA500");
TEMP.print(temp_read);
TEMP.text("环境闷热");
}
if(temp_read<28&&temp_read>=18)
{
TEMP.icon("fas fa-air-conditioner");
TEMP.color("#00FA9A");
TEMP.print(temp_read);
TEMP.text("环境舒适");
}
if(temp_read<18&&temp_read>=8)
{
TEMP.icon("fas fa-temperature-low");
TEMP.color("#00FFFF");
TEMP.print(temp_read);
TEMP.text("环境微凉");
}
if(temp_read<8&&temp_read>=0)
{
TEMP.icon("fas fa-temperature-frigid");
TEMP.color("#1E90FF");
TEMP.print(temp_read);
TEMP.text("环境寒冷");
}
if(temp_read<0)
{
TEMP.icon("fad fa-temperature-frigid");
TEMP.color("#8A2BE2");
TEMP.print(temp_read);
TEMP.text("环境酷冷");
}
}else
{
TEMP.icon("fad fa-temperature-hot");
TEMP.color("#FF0000");
TEMP.print(temp_read);
TEMP.text("环境酷热");
}
//TEXT1.print(rts());
//Blinker.print("℃",tem11);
if(tem11>=40)
{
if(tem11>=40&&tem11<60)
{
TEM.icon("fad fa-temperature-down");
TEM.color("#00FA9A");
TEM.print(tem11);//控制器温度
TEM.text("控制器中温");
}
if(tem11>=60)
{
TEM.icon("fad fa-temperature-hot");
TEM.color("#FF4500");
TEM.print(tem11);//控制器温度
TEM.text("控制器高温");
}
}else
{
TEM.icon("fad fa-oil-temp");
TEM.color("#00FF00");
TEM.print(tem11);//控制器温度
TEM.text("控制器温度");
}
if(tem11>=40)
{
if((tem11-39)*225>6975)
{
TEXT3.color("#FF4500");
TEXT3.print(String("散热风扇转速")+String(String((tem11-39)*225)+String("转/分钟")),"猛烈运行");
}else
{
TEXT3.color("#FFA500");
TEXT3.print(String("散热风扇转速")+String(String((tem11-39)*225)+String("转/分钟")),"平稳运行");
}
}else
{
TEXT3.color("#32CD32");
TEXT3.print("散热风扇停止");
}
if(BusVoltage<=19.8)
{
TEXT2.color("#FF0000");
TEXT2.icon("fad fa-siren-on");
TEXT2.print("低电压保护");
} else
{ if(BusVoltage>=20)
{
TEXT2.color("#32CD32");
TEXT2.print("输出正常");
}
if(BusVoltage<20&&BusVoltage>19.8)
{
TEXT2.color("#FF8C00");
TEXT2.print("输出等待");
}
}
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
5、这是心跳包发送运行时间、图标信息发送
void heartbeat()
{
//DL.print(ShuntCurrent);
//GL.print(BusPower);
TEXT1.icon("fas fa-alarm-clock");
TEXT1.print(rts());
}
//心跳包
void dataStorage()
{
Blinker.dataStorage("gl",BusPower);
Blinker.dataStorage("dl",ShuntCurrent);
Blinker.dataStorage("humi1",humi_read);
Blinker.dataStorage("temp1",temp_read);
}//图表
6、主函数我用的循环函数使电压信息和温度信息轮番显示。让电压等信息显示,大概1秒钟刷新3次,循环60次,温度等信息循环20次。不知道哪位大神还能有其他办法可以让屏幕轮番显示不,请指教啊。 我是想了好久才想到while循环的。
void loop()
{
static unsigned long time1 = millis();
static unsigned long time3 = millis();
static unsigned long time2 = 0, time4 = 0;
int i=0;
while(i<=60)
{
Blinker.run();
/******************************************/
time2 = millis();
if ((time2 - time1) >= 10)
{
BusVoltage = ina.readBusVoltage();
ShuntCurrent = ina.readShuntCurrent();
BusPower = ina.readBusPower();
Sa = ShuntCurrent * (time2 - time1) / 3600;
time1 = time2;
CapaPower = CapaPower + Sa;
Da = Da + BusVoltage * Sa / 1000;
ta=Da/1000*100;
if (BusPower>=BusPower1)
{
BusPower1 = BusPower;
}
if(BusVoltage<19.8)
{
Blinker.notify(String("电压过低!")+String(String(BusVoltage)+String("V")));
}
if(BusVoltage>25.2)
{
Blinker.notify(String("电压过高!")+String(String(BusVoltage)+String("V")));
}
float ADCvalue;
float Resistance;
ADCvalue = analogRead(NTCPin);
Serial.print("Analog value ");
Serial.print(ADCvalue);
Serial.print(" = ");
//convert value to resistance
Resistance = (1023 / ADCvalue) - 1;
Resistance = SERIESRESISTOR / Resistance;
Serial.print(Resistance);
Serial.println(" Ohm");
float steinhart;
steinhart = Resistance / NOMINAL_RESISTANCE; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (NOMINAL_TEMPERATURE + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
//steinhart = steinhart * 1.8 + 32; // convert to F
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println("°C");
tem11=steinhart;
//读散热器温度(ADC端口采集温度)
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t))
{
BLINKER_LOG("Failed to read from DHT sensor!");
}
else
{
BLINKER_LOG("Humidity: ", h, " %");
BLINKER_LOG("Temperature: ", t, " *C");
humi_read = h;
temp_read = t;
}
//DHT11读温湿度
if (BusVoltage<=19.8)
{
digitalWrite(D8, LOW);//关闭输出
// 反馈开关状态
//TEXT2.print("低电压保护");
}
if(BusVoltage>=20){
digitalWrite(D8, HIGH);//打开输出
// 反馈开关状态
//TEXT2.print("输出打开");
}
//buttonState = digitalRead(D3);
if (tem11>=40) {
// 打开风扇
// forward(); //执行前进(正转)函数
byte speed=(tem11-39)*25.575;
analogWrite(IA,speed);
} else {
//关闭风扇
digitalWrite(IA, LOW);
//TEXT3.print("风扇关闭");
}
}
/* Number1.print(BusVoltage);
Number2.print(ShuntCurrent*1000);
Number3.print(BusPower);
Number4.print(CapaPower);
// Number5.print(BlinkerTime/1000/60);
Number9.print(Da);
Number8.print(BusPower1);
TA.print(ta);
HUMI.print(humi_read);
TEMP.print(temp_read);
//TEXT1.print(rts());
*/
time4 = millis();
if ((time4 - time3) >= 300)
{
time3 = time4;
u8g2.clearBuffer(); // clear the internal memory
u8g2.setCursor(113, 14); // transfer internal memory to the display
u8g2.print("V");
u8g2.setCursor(113, 30);
u8g2.print("A");
u8g2.setCursor(110, 46);
u8g2.print("W");
u8g2.setCursor(83, 64);
u8g2.print("mAh");
u8g2.setCursor(0, 14);
u8g2.print(BusVoltage, 3);
u8g2.setCursor(0, 30);
u8g2.print(ShuntCurrent, 3);
u8g2.setCursor(0, 46);
u8g2.print(BusPower, 3);
u8g2.setCursor(0, 64);
u8g2.print(CapaPower);
u8g2.sendBuffer();
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
/* delay(3000);
u8g2.clearBuffer();//清除缓存
u8g2.firstPage();
//u8g2.setFont(u8g2_font_ncenB14_tr);//字体
//环境温度
u8g2.drawStr(0,21,"TEMP:");
u8g2.setCursor(65,21);//位置
u8g2.print(temp_read);
u8g2.drawCircle(115,11,2,U8G2_DRAW_ALL);
//画一个圆上去
u8g2.setCursor(120,21);
u8g2.print("C");
//环境湿度
u8g2.drawStr(0,42,"HUMI:");
u8g2.setCursor(65,42);
u8g2.print(humi_read);
u8g2.setCursor(115,42);
u8g2.print("%");
//控制器温度
u8g2.drawStr(0,64,"TEM1:");
u8g2.setCursor(65,64);
u8g2.print(tem11);
u8g2.drawCircle(115,54,2,U8G2_DRAW_ALL);
//画一个圆上去
u8g2.setCursor(120,64);
u8g2.print("C");
u8g2.sendBuffer();//显示
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
delay(3000);*/
}
i++; }
i=0;
while(i<=20)
{
Blinker.run();
/******************************************/
time2 = millis();
if ((time2 - time1) >= 10)
{
BusVoltage = ina.readBusVoltage();
ShuntCurrent = ina.readShuntCurrent();
BusPower = ina.readBusPower();
Sa = ShuntCurrent * (time2 - time1) / 3600;
time1 = time2;
CapaPower = CapaPower + Sa;
Da = Da + BusVoltage * Sa / 1000;
ta=Da/1000*100;
if (BusPower>=BusPower1)
{
BusPower1 = BusPower;
}
if(BusVoltage<19.8)
{
Blinker.notify(String("电压过低!")+String(String(BusVoltage)+String("V")));
}
if(BusVoltage>25.2)
{
Blinker.notify(String("电压过高!")+String(String(BusVoltage)+String("V")));
}
float ADCvalue;
float Resistance;
ADCvalue = analogRead(NTCPin);
Serial.print("Analog value ");
Serial.print(ADCvalue);
Serial.print(" = ");
//convert value to resistance
Resistance = (1023 / ADCvalue) - 1;
Resistance = SERIESRESISTOR / Resistance;
Serial.print(Resistance);
Serial.println(" Ohm");
float steinhart;
steinhart = Resistance / NOMINAL_RESISTANCE; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (NOMINAL_TEMPERATURE + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
//steinhart = steinhart * 1.8 + 32; // convert to F
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println("°C");
tem11=steinhart;
//读散热器温度(ADC端口采集温度)
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t))
{
BLINKER_LOG("Failed to read from DHT sensor!");
}
else
{
BLINKER_LOG("Humidity: ", h, " %");
BLINKER_LOG("Temperature: ", t, " *C");
humi_read = h;
temp_read = t;
}
//DHT11读温湿度
if (BusVoltage<=19.8)
{
digitalWrite(D8, LOW);//关闭输出
// 反馈开关状态
//TEXT2.print("低电压保护");
}
if(BusVoltage>=20){
digitalWrite(D8, HIGH);//打开输出
// 反馈开关状态
//TEXT2.print("输出打开");
}
//buttonState = digitalRead(D3);
if (tem11>=40) {
// 打开风扇
// forward(); //执行前进(正转)函数
byte speed=(tem11-39)*25.575;
analogWrite(IA,speed);
} else {
//关闭风扇
digitalWrite(IA, LOW);
//TEXT3.print("风扇关闭");
}
}
/* Number1.print(BusVoltage);
Number2.print(ShuntCurrent*1000);
Number3.print(BusPower);
Number4.print(CapaPower);
// Number5.print(BlinkerTime/1000/60);
Number9.print(Da);
Number8.print(BusPower1);
TA.print(ta);
HUMI.print(humi_read);
TEMP.print(temp_read);
//TEXT1.print(rts());
*/
time4 = millis();
if ((time4 - time3) >= 300)
{
time3 = time4;
/*u8g2.clearBuffer(); // clear the internal memory
u8g2.setCursor(113, 14); // transfer internal memory to the display
u8g2.print("V");
u8g2.setCursor(113, 30);
u8g2.print("A");
u8g2.setCursor(110, 46);
u8g2.print("W");
u8g2.setCursor(83, 64);
u8g2.print("mAh");
u8g2.setCursor(0, 14);
u8g2.print(BusVoltage, 3);
u8g2.setCursor(0, 30);
u8g2.print(ShuntCurrent, 3);
u8g2.setCursor(0, 46);
u8g2.print(BusPower, 3);
u8g2.setCursor(0, 64);
u8g2.print(CapaPower);
u8g2.sendBuffer();
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
*/
u8g2.clearBuffer();//清除缓存
u8g2.firstPage();
//u8g2.setFont(u8g2_font_ncenB14_tr);//字体
//环境温度
u8g2.drawStr(0,16,"TEMP:");
u8g2.setCursor(65,16);//位置
u8g2.print(temp_read);
u8g2.drawCircle(116,5,2,U8G2_DRAW_ALL);
//画一个圆上去
u8g2.setCursor(120,16);
u8g2.print("C");
//环境湿度
u8g2.drawStr(0,39,"HUMI:");
u8g2.setCursor(65,39);
u8g2.print(humi_read);
u8g2.setCursor(115,39);
u8g2.print("%");
//控制器温度
u8g2.drawStr(0,64,"TEM1:");
u8g2.setCursor(65,64);
u8g2.print(tem11);
u8g2.drawCircle(116,53,2,U8G2_DRAW_ALL);
//画一个圆上去
u8g2.setCursor(120,64);
u8g2.print("C");
u8g2.sendBuffer();//显示
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
i++;
}
i=0;
}
7、PWM输出调速
if (tem11>=40) {
// 打开风扇
analogWriteRange(53628);//修改PWM得精度范围
byte speed=(tem11-39)*1308;
analogWrite(IA,speed);
}
else
{
//关闭风扇
byte speed=0;
analogWrite(IA,speed);
//digitalWrite(IA, LOW);
//TEXT3.print("风扇关闭");
}
5、编译环境
安装Arduino等等一系列在BLINKER 点灯的官网都有详细讲解。直接网上搜索点灯科技即可。