电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
[ESP8266系列] NodeMCU之在OLED上显示温湿度(lua编程)
分 享
扫描二维码分享
[ESP8266系列] NodeMCU之在OLED上显示温湿度(lua编程)
I2C总线
OLED模块
esp8266
wybliw
关注
发布时间: 2020-10-09
丨
阅读: 2659
[TOC] --- --- 往期文章: * [ESP8266之NodeMCU固件编译](https://www.icxbk.com/article/detail?aid=1705) * [玩转DHT11温湿度和DS18B20温度模块](https://www.icxbk.com/article/detail?aid=1757) --- **难度:** ★★ **读者:** 熟悉lua脚本语言编程。 本文将介绍如何使用NodeMCU的I2C来控制OLED模块显示信息,让温湿度数据动态的显示在OELD屏幕上。 --- --- ## OLED模块介绍 OLED显示屏是指有机电激发光二极管(Organic Light-Emitting Diode,OLED),具备自发光,所以不需背光源,对比度高,厚度薄,视角广,反应速度快等特性,被认为是下一代的平面显示器新兴应用技术。 笔者使用的是0.96寸,白色,I2C总线的OLED模块显示屏,分辨率128x64,OLED常用接口有I2C和SPI。转接板自己画的,和某宝的上购买的模块接口基本一致。模块有5V转3.3V电路,可以兼容外接3.3V和5V电压。硬件部分这里就不多说了,购买oled模块后客服都会给模块相关资料。 ![](https://cf05.ickimg.com/bbsimages/202010/0ab08d1a3a75c9fb3575630850ed7b0a.png) **注:** 在购买OLED模块时,要查看该模块是否被 `u8g2库` 所支持,只有被 `u8g2库` 支持的OELD屏才能使用该库。 ## 启用I2C和OLED模块 在往期文章《 [ESP8266之NodeMCU固件编译](https://www.icxbk.com/article/detail?aid=1705) 》中,其实已经介绍了如何启用NodeMCU所支持的各种模块,启用对应的模块后,需要重新编译固件,烧录到ESP8266才能使用,一般根据自己的需求开启对应的模块,以减少固件的大小。 1)启用I2C模块,需要打开 `user_modules.h` 文件中的 `LUA_USE_MODULES_I2C` ,使用笔者之前编译的固件,默认是已经开启了。 ESP8266芯片没有硬件I2C接口,所以模块使用软件接口驱动程序。可包括GPIO16在内的任何GPIO引脚上设置。模块支持主模式,每条总线上可具有不同速度,最多10条总线。 速度标准: * 慢速:100kHz; * 快速:400kHz; * FastPlus:1MHz 也可设置任意时钟。GPIO16引脚可以作为SCL引脚使用,但所选的总线将被限制为不超过FAST速度。 模块不支持高速模式(3.5MHz时钟)和10位寻址方案。 2)启用OLED模块,需要打开 `user_modules.h` 文件中的 `LUA_USE_MODULES_U8G2` ,`u8g2模块` 已经将常见的OLED屏驱动都写好了,源码是开源的,可上GitHub查看。模块如下: ```c #define LUA_USE_MODULES_I2C #define LUA_USE_MODULES_U8G2 ``` ### I2C相关接口 由于使用了u8g2库,这里就只需要了解 `i2c.setup()` 接口。 #### i2c.setup(id, pinSDA, pinSCL, speed) 参数: * id:0~9,总线编号,NodeMCU支持10个I2C总线。 * pinSDA:1~12,SDA的IO口编号 * pinSCL:1~12, SCL的IO口编号 * speed:i2c.SLOW (100kHz), i2c.FAST (400kHz), i2c.FASTPLUS (1MHz)或者在25000 ~ 1000000Hz之间的任意时钟频率。FASTPLUS模式在默认80MHz的CPU频率下产生600kHz的I2C时钟速度,要得到1MHz的I2C时钟速度,要使用接口 `node.setcpufreq(node.CPU160MHZ)` 改变CPU频率到160MHz。 返回值: * speed:成功则返回设置的speed;失败则返回0。 想了解其他接口,可见NodeMCU官方文档。 ### U8G2库相关接口 #### SSD1306驱动的初始化 使用I2C接口,调用以下代码初始化: ```lua sla = 0x3c -- oled的I2C地址 -- id:I2C初始化时的id disp = u8g2.ssd1306_i2c_128x64_noname(id, sla) ``` 其他驱动类型的OLED初始化,见NodeMCU官方文档。 #### u8g2.disp:drawStr(x, y, *str) * x:x轴坐标 * y:y轴坐标 * str:要显示的字符串 #### u8g2.disp:sendBuffer(void) 将内存帧缓冲区的内容发送到显示器,执行该函数,OLED才会显示设置的内容。 ### OLED字体设置 字体设置在 `app/include` 目录下的 `u8g2_fonts.h` 文件,需要什么字体,只需在 `U8G2_FONT_TABLE_ENTRY(font_wqy16_t_chinese3)` 后面加入对应的字体宏即可,由于全中文字库很大,编译出的固件大小将会很大,可能会导致烧录失败或者ESP8266启动不了。笔者就直接使用默认的字体了。u8g2的字体设计又是一门技术,网上也有大佬出教程,有兴趣的可以搜搜。 ```c // Add a U8G2_FONT_TABLE_ENTRY for each font you want to compile into the image // See https://github.com/olikraus/u8g2/wiki/fntlistall for a complete list of // available fonts. Drop the 'u8g2_' prefix when you add them here. #define U8G2_FONT_TABLE \ U8G2_FONT_TABLE_ENTRY(font_6x10_tf) \ U8G2_FONT_TABLE_ENTRY(font_unifont_t_symbols) \ U8G2_FONT_TABLE_ENTRY(font_wqy16_t_chinese3) ``` u8g2支持的字体见u8g2官网。 ## 点亮OLED模块 首先要搞清楚ESP8266和NodeMCU引脚之间的关系,很多新手容易搞混。ESP8266和NodeMCU对应引脚关系如下图: ![](https://cf05.ickimg.com/bbsimages/202010/ae20ad82ced49c0cbef91c7404ad3a7b.png) 对应关系,比如下表: | NodeMCU Pin | ESP8266 Pin | | ----------- | ----------- | | D0 | GPIO16 | | D1 | GPIO5 | | D2 | GPIO4 | | D3 | GPIO0 | | D4 | GPIO2 | | D5 | GPIO14 | | ... | ... | 笔者的OLED模块引出脚是4个(有的是IIC和SPI兼容模块可能是7个引脚),OLED模块和NodeMCU之间连接关系如下: | OLED模块 | NodeMCU Pin | ESP8266 | | --------------- | ------------- | ------- | | VCC(带3.3V稳压) | VCC(3.3V或5V) | VCC | | GND | GND | GND | | SCL | D6 | GPIO12 | | SDA | D5 | GPIO14 | **注:** * ESP8266单模块的VCC是3.3V的。 * 若OLED模块还有RES,DC,CS引脚,可按照说明在程序中控制,或直接在硬件上配置好,具体看oled模块资料。 * 若OLED模块不带3.3V稳压,则OLED的VCC连接到NodeMCU的3.3V引脚上,因为0.96寸OLED屏大多是3.3V电源,具体以OLED屏规格书为准。 DHT11模块和NodeMCU之间连接关系: | DHT11 Pin | NodeMCU Pin | ESP8266 | | --------- | ----------- | ------- | | VCC | 3.3V | VCC | | GND | GND | GND | | DATA | D4 | GPIO2 | 先将OLED和NodeMCU开发板连接好,然后接上将usb接到电脑端,上传点亮oled的lua代码。 代码如下: ```lua -- 管脚定义 local sda = 5 -- GPIO14 local scl = 6 -- GPIO12 local sla = 0x3c -- oled的地址,一般为0x3c -- 初始化 function init_oled() -- iic总线 和 oled初始化 i2c.setup(0, sda, scl, i2c.SLOW) disp = u8g2.ssd1306_i2c_128x64_noname(0, sla) -- 设置字体 disp:setFont(u8g2.font_unifont_t_symbols) disp:setFontRefHeightExtendedText() --disp:setDrawColor(1) disp:setFontPosTop() --disp:setFontDirection(0) -- 画边框 --disp:drawFrame(0, 0, 128, 64) end -- 显示函数 function oled_show_msg() -- 设置显示内容 disp:drawStr(0, 0, "1 Hello OLED") disp:drawStr(0, 16, "2234567890ABCDEF") disp:drawStr(0, 32, "3234567890ABCDEF") disp:drawStr(0, 48, "4234567890ABCDEF") -- 将内容发送到oled disp:sendBuffer() end -- 主函数 function main() init_oled() oled_show_msg() end -- 运行程序 main() ``` 将代码保存到 `oled.lua` 文件,通过 `ESPlorer工具` 上传到ESP8266模块,刷新ESPlorer文件列表,点击 `oled.lua` 就可以看到oled屏显示信息了。如下图: ![](https://cf05.ickimg.com/bbsimages/202010/8fd12e242995dedba4a039c1d03c8035.png) 实际显示效果: ![](https://cf05.ickimg.com/bbsimages/202010/78c42446270c794e5eccb89c2b95fcf7.png) ## 将温湿度动态的显示在OLED上 温湿度模块使用的是DHT11模块,关于DHT11模块的使用,之前写过一篇文章。这里就直接使用了。 代码如下: ```lua DHT11pin = 4 -- D4, GPIO2 DHT11Temp = 0 DHT11TempDec = 0 DHT11Hum = 0 DHT11HumDec = 0 ErrChk = true ErrTimeOut = true DHT11Status = dht.ERROR_TIMEOUT -- OLED初始化 function init_oled() -- IIC管脚和OLED地址定义 local sda = 5 -- D5, GPIO14 local scl = 6 -- D6, GPIO12 local sla = 0x3c -- IIC总线初始化 i2c.setup(0, sda, scl, i2c.SLOW) -- OLED初始化 disp = u8g2.ssd1306_i2c_128x64_noname(0, sla) -- 设置OLED字体 disp:setFont(u8g2.font_unifont_t_symbols) disp:setFontRefHeightExtendedText() --disp:setDrawColor(1) disp:setFontPosTop() --disp:setFontDirection(0) -- 画边框 disp:drawFrame(0, 0, 128, 64) end -- 获取DHT11数据 function getDHT11Info() DHT11Status, DHT11Temp, DHT11Hum, DHT11TempDec, DHT11HumDec = dht.read11(DHT11pin) if DHT11Status == dht.OK then ErrChk = false; ErrTimeOut = false; print(string.format("DHT Temperature:%d.%03d; Humidity:%d.%03d\r\n", DHT11Temp, DHT11TempDec, DHT11Hum, DHT11HumDec)) elseif DHT11Status == dht.ERROR_CHECKSUM then ErrChk = true print( "DHT Checksum error." ) elseif DHT11Status == dht.ERROR_TIMEOUT then ErrTimeOut = true print( "DHT TimeOut." ) end end -- 显示温湿度 function oled_show_msg() getDHT11Info() -- 判断通讯无误,就将数据就显示在OLED上 if not(ErrChk or ErrTimeOut) then disp:drawStr(5, 30, "Temp: "..DHT11Temp.." ") disp:drawStr(5, 46, "Hum : "..DHT11Hum.." ") disp:sendBuffer() end end -- main function main() init_oled() disp:drawStr(5, 5, " Welcome") disp:sendBuffer() -- 定时器,每2秒刷新一次数据 local dht_timer = tmr.create() dht_timer:alarm(1000, tmr.ALARM_AUTO, function() oled_show_msg() end) end main() ``` 将代码保存到 `oled-dht11.lua` 文件,通过 `ESPlorer工具` 上传到ESP8266中,然后刷新文件,点击 `oled-dht11` 运行程序。效果如下图: ![](https://cf05.ickimg.com/bbsimages/202010/dd21e9691f883f19c1ee72aa827ad0ce.gif) 用DHT11模块,温湿度数据有一点延迟,毕竟一分钱一分货。 后期读者也可以自行美化一下显示界面,可以加一些按键,再添加一些其他模块,可以做一个功能比较丰富的应用。 == end ==
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
wybliw
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交