我们之前介绍过esp为了实现与手机的远程交互,32本地端的相关配置还需要Blynk软件。
Blynk APP
关于Blynk这里只介绍下载和初始配置。详见以下文章:【FireBeetle Board-ESP32教程之一】Blynk—控制LED灯 我们将BLynk手机端配置如下: 图中的V8、V10、V11等于虚拟引脚,即Virtual Pin,引脚的分配需要在arduino上进行。
ESP32 配置
首先需要引用Blynk的库函数:
#include <WiFi.h> #include <WiFiClient.h> #include <BlynkSimpleEsp32.h>
然后配置令牌和wifi相关的内容
//Blynk每个账户的令牌不同 char auth[] = "******************";//从手机上复制 //wifi名称和密码 char ssid[] = "wifi_name"; char pass[] = "password";
虚端口配置:
//Blynk端的虚端口 int vPin=10; int vPin2=8; int vPinChart=9;////这个引脚用于图表
一个获取当前互联网时间的网站配置:
const char *ntpServer = "pool.ntp.org"; const long gmtOffset_sec = 8 * 3600; const int daylightOffset_sec = 0; struct tm timeinfo; //画wifi图标 const uint8_t frame0 [] = {
0x00,0x00,0x00,0x00,0x07,0xE0,0x08,0x10,0x13,0xC8,0x24,0x24,0x09,0x90,0x02,0x40,
0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
//显示当前时间需要的函数
void printLocalTime()
{
if (!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain time");
return;
}
Serial.println(timeinfo.tm_hour); // 格式化输出
}
按键虚引脚的配置和回调函数,其中BLYNK_WRITE的参数V11即是我们Blynk端的按钮的引脚,我们通过这个引脚来实现手机端控制ESP32的功能。
int state=1;
BLYNK_WRITE(V11)
{
int pinValue=param.asInt();
state=pinValue;
//Serial.println(pinValue);
}
setup里也要进行相关修改:
void setup() {
Serial.begin(9600);
//SSD1306配置
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
display.clearDisplay();
//MLX90614配置
mlx.begin();
for(int i=0;i<128;i++)
{
Y[i]=0;
}
pinMode( pin, INPUT);//设置管脚为输入
Blynk.begin(auth, ssid, pass);//Blynk的初始化
}
之后就是在主函数体里进行配置了,完整的代码如下:
#include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Adafruit_MLX90614.h> #include "stdlib.h" #define BLYNK_PRINT Serial #include <WiFi.h> #include <WiFiClient.h> #include <BlynkSimpleEsp32.h> //Blynk的令牌,各个账户不同 char auth[] = "JbFznocQk7C8mkvWUdA4eXUJz_j3vqyz"; //wifi名称以及密码 char ssid[] = "HUAWEI P30"; char pass[] = "0987654321"; //心跳
传感器引脚 int pin =35; //后面用到的参数 int counter = 0; int Y[128]; int maxid=0; int second=0; double bpm; double Data[50]; double temperature; //Blynk端的虚端口 int vPin=10; int vPin2=8; int vPinChart=9; const char *ntpServer = "pool.ntp.org"; const long gmtOffset_sec = 8 * 3600; const int daylightOffset_sec = 0; struct tm timeinfo; //画wifi图标 const uint8_t frame0 [] = { 0x00,0x00,0x00,0x00,0x07,0xE0,0x08,0x10,0x13,0xC8,0x24,0x24,0x09,0x90,0x02,0x40, 0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; #define SCREEN_WIDTH 128 // OLED 屏幕宽, 单位像素点数 #define SCREEN_HEIGHT 64 // OLED 屏幕长, 单位像素点数 #define OLED_RESET -1 // 重置引脚 //实例化SSD1306显示屏 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //实例化MLX90614传感器 Adafruit_MLX90614 mlx = Adafruit_MLX90614(); int state=1; BLYNK_WRITE(V11) { int pinValue=param.asInt(); state=pinValue; //Serial.println(pinValue); } void printLocalTime() { if (!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); return; } Serial.println(timeinfo.tm_hour); // 格式化输出 } void setup() { Serial.begin(9600); //SSD1306配置 display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.display(); display.clearDisplay(); //MLX90614配置 mlx.begin(); for(int i=0;i<128;i++) { Y[i]=0; } pinMode( pin, INPUT);//设置管脚为输入 Blynk.begin(auth, ssid, pass); } void loop() { //串口打印温度传感器值 //Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempC()); //Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C"); //Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempF()); //Serial.print("*F\tObject = "); Serial.print(mlx.readObjectTempF()); Serial.println("*F"); //Serial.println(); temperature=mlx.readObjectTempC(); for(int j=0;j<50;j++) { Data[j]=analogRead(pin); delay(10); } for(int j=0;j<50;j++) { if(Data[j]>Data[maxid]) { maxid=j; } } for(int j=0;j<50;j++) { if(Data[j]>Data[second]&&Data[j]<=Data[maxid]&&abs(j-maxid)>5) { second=j; } } if((maxid-second!=0)&&(3000/abs(maxid-second)<200)) bpm=3000/abs(maxid-second); else bpm=bpm; Serial.println(Data[0]); for(int i=31;i>0;i--) { Y[i]=Y[i-1]; Y[0]=bpm-70;//64*(Data[0]-2700)/(100); } if(temperature>30&&state==1) { display.clearDisplay(); //display.drawString(0,0, "Counter: " + String(counter)); display.drawLine(96,0,96,64,SSD1306_WHITE);//y display.drawLine(0,32,96,32,SSD1306_WHITE); display.drawLine(96,45,128,45,SSD1306_WHITE); //x坐标轴绘制 for(int i=0;i<96;i++) { int count=i/4; int res=i%4; if(res==0) { display.drawLine(i,Y[count],i+4,Y[count+1],SSD1306_WHITE);//画线 } else { } } display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(100,5); display.println(int(temperature)); display.setCursor(115,1); display.println("o"); display.setCursor(120,5); display.println("C"); display.setCursor(100,22); display.println(int(bpm)); display.setCursor(100,30); display.println("BPM"); if (Blynk.getstate()) { display.drawBitmap(105,48,frame0,16,16,SSD1306_WHITE); } display.fillCircle(counter,32,2,SSD1306_WHITE); display.display(); } else { WiFi.begin(ssid, pass); //while (WiFi.status() != WL_CONNECTED) //{ //delay(500); // Serial.print("."); //} Serial.println("WiFi connected!"); // 从网络时间服务器上获取并设置时间 // 获取成功后芯片会使用RTC时钟保持时间的更新 configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); printLocalTime(); //WiFi.disconnect(true); //WiFi.mode(WIFI_OFF); //Serial.println("WiFi disconnected!"); display.clearDisplay(); display.drawCircle(20,32,16,SSD1306_WHITE); display.drawLine(20,32,26,32,SSD1306_WHITE); display.drawLine(20,32,20,16,SSD1306_WHITE); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(40,32); display.println(timeinfo.tm_hour); display.setCursor(70,32); display.println(":"); display.setCursor(90,32); display.println(timeinfo.tm_min); display.display(); printLocalTime(); delay(970); //state=1; } if(counter<96) { counter=counter+4; } else { counter=0; } delay(200); Serial.println(state); if(state==0) { Blynk.begin(auth, ssid, pass); Blynk.run(); delay(2000); } else { Blynk.run(); } //向blynk发送数据 Blynk.virtualWrite(vPin,bpm); Blynk.virtualWrite(vPin2,temperature); Blynk.virtualWrite(vPinChart,Y[0]); }
上面的代码中有几个部分需要讲解一下: 这一部分是显示时间的相关代码,在读取到当前的温度值时,若大于30度,说明此刻是有人使用的,那么OLED屏幕将显示心跳体温数据。而If语句中的state,是由Blynk端控制的,这样就可以实现Blynk控制ESP32的显示模式。 else中,将会显示当前的网络时间。
if(temperature>30&&state==1)
{
//这里是之前我们写好的代码
}
else
{
WiFi.begin(ssid, pass);
//while (WiFi.status() != WL_CONNECTED)
//{
//delay(500);
// Serial.print(".");
//}
Serial.println("WiFi connected!");
// 从网络时间服务器上获取并设置时间
// 获取成功后芯片会使用RTC时钟保持时间的更新
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
//WiFi.disconnect(true);
//WiFi.mode(WIFI_OFF);
//Serial.println("WiFi disconnected!");
display.clearDisplay();
display.drawCircle(20,32,16,SSD1306_WHITE);
display.drawLine(20,32,26,32,SSD1306_WHITE);
display.drawLine(20,32,20,16,SSD1306_WHITE);
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(40,32);
display.println(timeinfo.tm_hour);
display.setCursor(70,32);
display.println(":");
display.setCursor(90,32);
display.println(timeinfo.tm_min);
display.display();
printLocalTime();
delay(970);
//state=1;
}
由于显示时间使用的是另一个网站,所以在切换模式的时候,也需要进行网站的切换:
if(state==0)
{
Blynk.begin(auth, ssid, pass);
Blynk.run();
delay(2000);
}
else
{
Blynk.run();
}
之后就是向Blynk服务器发送数据:
//向blynk发送数据
Blynk.virtualWrite(vPin,bpm);
Blynk.virtualWrite(vPin2,temperature);
Blynk.virtualWrite(vPinChart,Y[0]);
主函数里有一个小If语句:
if (Blynk.getstate())
{
display.drawBitmap(105