ESP8266系列文章目录
目录
经过不断的努力,处女之作终于做出来了。用的Arduino
最近自己又画了个10MOS的开关板子,用于控制逆变器开关。IO高低电平也是代码中增加识别,判断开关状态。增加了散热风扇手动开关。
用在风扇PWM控制的Nmos板子,嘉立创免费打样。
控制逆变器的板子,嘉立创免费打样。
1、功能讲解
(感兴趣的和我一样初学的朋友可以进主页可直接下载原文件,太长了网页不好放,用了太多的IF语句用来判断不同状态向APP发送不同的文字颜色、图标)进入主页可直接下载源文件。
带有一个SSD1306 OLED屏,可以显示电压、电流、功率、温度,BLINKERapp上可查看电压、电流、功率、mah、Wh、峰值功率、运行时间、电量比例、环境温度、环境湿度、控制器温度、控制器温控散热风扇(可在APP查看实时转速)。低电压报警、电池低电压自动切断电压输出(可在APP查看状态)、还有图标功能。App端文字颜色可根据参数自动变更、图标也是根据参数变更(用了很多的if语句。 按刷新健对APP数据进行刷新。 刚上电截的图,电量比例需要放电完一次开发板复位再开始充才准。我使用的是监测24V系统,三元锂电18650电池20并6串,满电25.2V。
电量比例可以根据个人想要的方式改变公式即可。我这个设计容量是1000Wh,所以除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,所以不用特殊设计直接接)外置分压电路也可以从开发板取电3.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("fas 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 点灯的官网都有详细讲解。直接网上搜索点灯科技即可。