在2018年折腾过一次用米家温湿度连接ESP32上用OLED显示,OLED显示是已经成功了.可是当时打算让EPS在读取到蓝牙温度计数值后上传到blynk,可是编译后提示空间不足(即使不要OLED驱动只接入blynk也一样)。由于我不是专业开发人员,也没时间去找解决方法。同时,觉得这功能大把东西可以取代,搞出来觉得没啥用,所以代码一直仍在硬盘里直到现在才记得.这里顺便发出来,大家觉得有用的话拿去研究参考,看能不能解决空间问题,运行效果如下:
这个项目灵感主要来自于这位作者,https://github.com/turlvo/KuKuMi,有兴趣可以看看。
事前准备
-
软件和环境
- PlatformIO 或者Arduino IDE配置好ESP32 Arduino架构板库
- Adafruit SSD1306 OLED 库
- Adafruit GFX 库
以上库都可以在IDE内搜索到
-
硬件准备 项目名称 数量 单位 备注 ESP32 1 块 这里用 doit esp32 devkit v1
0.96'OLED液晶模块 1 个 SSD1306主控,建议I2C版本,我这里用SPI接口版本 小米米家蓝牙温湿度计 1 个 我这里使用的是旧版圆形那个版本,由于已经是3年前,现在新款的版本不知道行不行 杜邦线 若干 面包板 1 块
3.注意事项
在开始动手前,请你把周边所有蓝牙(如手机蓝牙等)设备关掉,以免影响ESP32的实验结果。
硬件接线
SPI版本
ESP32 | 15 | 2 | 4 | 5 | GND | 3.3V/5V | GND |
---|---|---|---|---|---|---|---|
OLED | CLK(SCK) | MOSI(SCK) | RESET(RES) | DC | CS | VCC | GND |
I2C版本
(省略,请自行看Adafruit SSD1306 OLED 库中的示例)
Arduino代码
这里是SPI OLED的版本:
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_system.h"
#include <sstream>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#define SCAN_TIME 10 //扫描的间隔10秒
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
boolean METRIC = true; //不需要公制单位的话设为:false
BLEScan *pBLEScan;
void IRAM_ATTR resetModule() {
ets_printf("reboot\n");
esp_restart();
}
#define OLED_CLK 15
#define OLED_MOSI 2
#define OLED_RESET 4
#define OLED_DC 5
#define OLED_CS 255
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
float current_humidity = -100;
float previous_humidity = -100;
float current_temperature = -100;
float previous_temperature = -100;
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.haveName() && advertisedDevice.haveServiceData() && !advertisedDevice.getName().compare("MJ_HT_V1")) {
std::string strServiceData = advertisedDevice.getServiceData();
uint8_t cServiceData[100];
char charServiceData[100];
strServiceData.copy((char *)cServiceData, strServiceData.length(), 0);
Serial.printf("\n\nAdvertised Device: %s\n", advertisedDevice.toString().c_str());
for (int i = 0; i < strServiceData.length(); i++) {
sprintf(&charServiceData[i * 2], "%02x", cServiceData[i]);
}
std::stringstream ss;
ss << "fe95" << charServiceData;
Serial.print("Payload:");
Serial.println(ss.str().c_str());
char eventLog[256];
unsigned long value, value2;
char charValue[5] = {0,};
switch (cServiceData[11]) {
case 0x04:
sprintf(charValue, "%02X%02X", cServiceData[15], cServiceData[14]);
value = strtol(charValue, 0, 16);
if (METRIC)
{
current_temperature = (float)value / 10;
} else
{
current_temperature = CelciusToFahrenheit((float)value / 10);
}
break;
case 0x06:
sprintf(charValue, "%02X%02X", cServiceData[15], cServiceData[14]);
value = strtol(charValue, 0, 16);
current_humidity = (float)value / 10;
Serial.printf("HUMIDITY_EVENT:");
Serial.printf(charValue, value);
Serial.println();
break;
case 0x0A:
sprintf(charValue, "%02X", cServiceData[14]);
value = strtol(charValue, 0, 16);
Serial.printf("BATTERY_EVENT:");
Serial.printf(charValue, value);
Serial.println();
break;
case 0x0D:
sprintf(charValue, "%02X%02X", cServiceData[15], cServiceData[14]);
value = strtol(charValue, 0, 16);
if (METRIC)
{
current_temperature = (float)value / 10;
} else
{
current_temperature = CelciusToFahrenheit((float)value / 10);
}
Serial.printf("TEMPERATURE_EVENT:");
Serial.printf(charValue, value);
Serial.println();
sprintf(charValue, "%02X%02X", cServiceData[17], cServiceData[16]);
value2 = strtol(charValue, 0, 16);
current_humidity = (float)value2 / 10;
Serial.printf("HUMIDITY_EVENT:" );
Serial.printf(charValue, value2);
Serial.println();
break;
}
}
}
};
void setup() {
display.begin(SSD1306_SWITCHCAPVCC);
//清楚OLED屏幕缓存
display.clearDisplay();
display.display();
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
Serial.println("ESP32 XIAOMI DISPLAY");
initBluetooth();
}
void loop() {
char printLog[256];
Serial.printf("Start BLE scan for %d seconds...\n", SCAN_TIME);
BLEScanResults foundDevices = pBLEScan->start(SCAN_TIME);
int count = foundDevices.getCount();
printf("Found device count : %d\n", count);
delay(100);
displayTemperature();
}
void initBluetooth()
{
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(0x50);
pBLEScan->setWindow(0x30);
}
void displayTemperature() {
if (current_temperature != previous_temperature) {
previous_temperature = current_temperature;
previous_humidity = current_humidity;
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Tem:");
display.print(convertFloatToString(current_temperature));
if (METRIC) {
display.setCursor(115, 0);
display.print("C");
} else {
display.setCursor(115, 0);
display.print("F");
}
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 40);
display.print("Hum:");
display.print(current_humidity, 1);
display.print(" %");
display.display();
}
}
String convertFloatToString(float f)
{
String s = String(f, 1);
return s;
}
//转换成华氏的自定义函数
float CelciusToFahrenheit(float Celsius)
{
float Fahrenheit = 0;
Fahrenheit = Celsius * 9 / 5 + 32;
return Fahrenheit;
}