【Beetle ESP32-C3】六、OLED、AHT10和TCP(Arduino)
<div class='showpostmsg'><p> 本篇记录一个较复杂案例的实现,ESP32 C3的硬I<sup>2</sup>C驱动OLED和AHT10,测得温湿度显示到OLED上,并且连接WiFi,建立TCP连接向远端TCP Server发送温湿度值。</p><h2><b>1、ESP32 C3的硬I</b><b><sup>2</sup></b><b>C</b></h2>
<p> ESP32 C3的硬I<sup>2</sup>C默认为IO8-SDA和IO9-SCL,本例就不做改动了。具体的管脚分配,可以在Arduino-ESP32 Package的源码中找到,位于:“..\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.4\variants\esp32c3\pins_arduino.h”——一般Arduino的开发板管脚定义都在对应开发板目录(路径中的esp32c3)的pins_arduino.h头文件中。</p>
<p> </p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center">图6-1 pins_arduino.h中的I<sup>2</sup>C管脚定义</p>
<p align="center"> </p>
<p> C3管脚资源有限,所以OLED和AHT10连接到同一个I<sup>2</sup>C上,通过器件地址相互区分就可以了。实际这个案例初始是受到DFROBOT在线文档的示例启发,只不过文档用的SHT30(https://wiki.dfrobot.com.cn/_SKU_DFR0868_Beetle_ESP32_C3#target_17)。本人没有这个传感器,所以换成AHT10。正好AHT10和OLED的线序一致,在面包板上连接还挺方便。</p>
<p> </p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center">图6-2 管脚连接</p>
<p align="center"> </p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center">图6-3 实物连接</p>
<p align="center"> </p>
<h2><b>2、AHT10库和u8g2库</b></h2>
<p> AHT10和OLED的驱动直接下载的库,AHT10是Adafruit_AHTX0 V2.0.2,u8g2是V2.31.2。</p>
<p> </p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center"> </p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center">图6-4 库安装</p>
<p align="center"> </p>
<h2><b>3、完整代码</b></h2>
<p> 项目采取每秒测量温湿度,同时板载LED闪烁以指示程序运行中。每测量6次求平均值,然后分别在OLED、串口和TCP Server三端输出。</p>
<p> 测试过程发现一个问题,就是6次测量中,第一次的温度值总是很离谱,都在四十七、八度的样子。结果平均值就达到32度,一度让本人怀疑是不是空调坏了。解决方法也很简单粗暴,6次测量直接舍去第一次,改5次求平均。</p>
<p> 当然原因本人没有研究,猜想可能是没有在6次测量开始时进行AHT10启动引起的。</p>
<p> 另一个情况就是求平均值后,小数位数会增加(单次测量仅两位),使用u8g2.print()函数会出错造成ESP32重启,这个猜想可能是位数增加造成的内存溢出问题。于是改用dtostrf()函数将float类型平均值转为字符串,再用u8g2.drawStr()函数显示。</p>
<p> </p>
<pre>
<code>#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <Adafruit_AHTX0.h>
#define LED 10 //板载LED管脚
#define LEN 6 //测量LEN次求平均
float temp = 0; //温度平均值
float humi = 0; //湿度平均值
float temparr = {0}; //LEN次温度测量值数组
float humiarr = {0}; //LEN次湿度测量值数组
char str = {0}; //字符串缓存用于OLED显示
uint8_t times = 0; //测量计数器,每LEN次求平均
Adafruit_AHTX0 aht; //aht实例
const char *ssid = "yourssid"; //WIFI名称
const char *password = "yourpsw"; //密码
const uint16_t port = 1234; //TCP Server端口
const char *host = "192.168.31.74"; //TCP Server IP
/*
---显示屏硬件I2C接口---
U8G2_R0 不旋转,横向,绘制方向从左到右
U8G2_R1 顺时针旋转90度,绘制方向从上到下
U8G2_R2 顺时针旋转180度,绘制方向从右到左
U8G2_R3 顺时针旋转270度,绘制方向从下到上
U8G2_MIRROR 正常显示镜像内容(v2.6.x版本以上使用)
注意:U8G2_MIRROR需要与setFlipMode()配搭使用.
U8x8_PIN_NONE 表示引脚为空,不会使用复位引脚
---显示屏硬件SPI接口---
cs 按引脚接上即可(引脚可自己选择)
dc 按引脚接上即可(引脚可自己选择)
*/
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
void setup() {
/* 初始化LED(板载 IO10控制)*/
pinMode(LED, OUTPUT);
/* 初始化UART0(板载USB-UART)*/
Serial.begin(115200);
/* 初始化u8g2及OLED */
u8g2.begin();
/*
drawStr()默认字符的左下角为坐标标准,
setFontPosTop()改为左上角为坐标标准。
*/
u8g2.setFontPosTop();
/* AHT10初始化 */
if(!aht.begin()) {
Serial.println("Could not find AHT");
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_osb18_tf);
u8g2.drawStr(5,10,"no AHT");
u8g2.sendBuffer();
while(1) delay(10);
}
Serial.println("AHT10 or AHT20 found");
/* WiFi初始化,连接AP */
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected!");
}
void loop() {
/* 读取温湿度 */
sensors_event_t aht_humi, aht_temp;
aht.getEvent(&aht_humi, &aht_temp);
temparr = aht_temp.temperature;
humiarr = aht_humi.relative_humidity;
/* 每LEN次计算平均值,做三端输出*/
if(times++ >= LEN) {
times = 0; //计数器复位
/* 求得平均值 */
temp = 0;
humi = 0;
for(int i=0; i<LEN; i++) { //LEN次测量值求和
temp += temparr;
humi += humiarr;
Serial.print("temp: ");//输出每次温度值及当前和
Serial.print(temparr);
Serial.print(", tempsum: ");
Serial.print(temp);
Serial.println("");
Serial.print("humi: ");//输出每次湿度值及当前和
Serial.print(humiarr);
Serial.print(", humisum: ");
Serial.print(humi);
Serial.println("");
Serial.println("-----------------------------");
}
temp = (temp-temparr) / 5.0;//第一次温度值总是很大,所以减掉
humi = (humi-humiarr) / 5.0;//为了保持一致,湿度也减掉第一次
memset(temparr, 0, LEN);
memset(humiarr, 0, LEN);
/* 串口显示温湿度 */
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humi);
Serial.println("% rH");
/* TCP发送温湿度值 */
WiFiClient client; //TCP Client 实例
if(!client.connect(host, port)) { //连接失败串口消息
Serial.println("Connection failed.");
} else { //连接成功发送到TCP Server
client.print("Temperature: ");
client.print(temp);
client.println(" degrees C");
client.print("Humidity: ");
client.print(humi);
client.println("% rH");
client.stop(); //断开连接
}
/* OLED显示温湿度 */
u8g2.clearBuffer();//清屏幕
//OLED显示温度
u8g2.setFont(u8g2_font_osb18_tf); //选择字体
u8g2.drawStr(5, 10, "Temp"); //显示Temp字符
u8g2.setFont(u8g2_font_t0_18b_tr);
memset(str, 0, 6);
dtostrf(temp, 6, 2, str);
u8g2.drawStr(75, 15, str);
// u8g2.setCursor(75, 15);
// u8g2.print(temp);//temp平均值若小数部分长,会出错
//OLED显示湿度
u8g2.setFont(u8g2_font_osb18_tf);
u8g2.drawStr(5, 40, "Humi");
u8g2.setFont(u8g2_font_t0_18b_tr);
memset(str, 0, 6);
dtostrf(humi, 6, 2, str);
u8g2.drawStr(75, 45, str);
// u8g2.setCursor(75, 45);
// u8g2.print(humi);
//此句使得OLED真正显示出来
u8g2.sendBuffer();
}
/* 指示灯翻转 */
digitalRead(LED) ? digitalWrite(LED, LOW) : digitalWrite(LED, HIGH);
/* 延时1s */
delay(1000);
}</code></pre>
<p> </p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> 两个结合在一起,画的图很美,怎么摆弄出来的? lugl4313820 发表于 2022-8-17 16:27
两个结合在一起,画的图很美,怎么摆弄出来的?
<p>GUI是DFROBOT的案例给出的,都是u8g2库的预制字体</p>
页:
[1]