由于教学需要,自己设计了一款ESP32开发板,用于《短距离无线通信》课堂教学使用。开发板整体效果如下图:
该开发板采用Type-C接口供电,板载CH340K串口芯片,支持自动下载。240*240全彩SPI接口显示屏,温度传感器DS18B20,温湿度传感器DHT11,RGB三色灯,WS2812灯珠,蜂鸣器,红外热释传感器,光敏电阻,红外发射/接收,微动按键,触摸按键,部分IO引出。
硬件原理图全开源:https://oshwhub.com/Dr.Zhang/esp32_py_board
USB转串口使用的是CH340K芯片,需要安装新版本
驱动才能使用,新版本驱动下载地址:
http://www.wch.cn/downloads/file/65.html
下载完成后双击安装程序,然后点击安装即可:
固件烧录需要使用乐鑫
原厂的烧录工具,工具下载地址:
https://www.espressif.com/zh-hans/support/download/other-tools
该工具无需安装,直接解压后即可使用:
除了烧录工具外,我们还需要最新版MicroPython的固件,下载地址为:
https://micropython.org/download/esp32/
然后回到刚才打开的烧录工具页面,ChipType
选择ESP32,WorkMode
选择develop,然后点击OK,在接下来的页面中选择刚刚下载的MicroPython固件,地址填写0x1000
,勾选DoNotChgBin
,BAUD设置为921600
,COM口根据实际情况选择,最后点击START
按钮即可开始烧录,等到进度条跑到最右边就烧录完成了。
MicroPython多种可用的IDE(集成开发环境),建议使用uPyCraft,操作起来比较简单。
V1.1版本uPyCraft下载地址:https://shyboy.oss-cn-shenzhen.aliyuncs.com/readonly/uPyCraft_V1.1.exe
下载后无需安装,双击即可运行(首次运行将提示安装字体,点击OK即可),打开后依次点击Tools
>> Serial
>>COM*
连接设备,出现右下图所示的 >>> 说明连接设备成功:
依次点击 File
>> Examples
>> Basic
>> Blink.py
,打开示例代码,将引脚修改为14
,点击后侧的 三角形
运行代码,若设备上红色LED闪烁,说明设备正常工作。
开发板上有一个三个LED灯,分别连接在14,27,26号引脚上,可使用如下代码控制LED灯:
import time
from machine import Pin
led_r = Pin(14,Pin.OUT)
led_g = Pin(27,Pin.OUT)
led_b = Pin(26,Pin.OUT)
while True:
led_r.value(1)
time.sleep(0.5)
led_r.value(0)
led_g.value(1)
time.sleep(0.5)
led_g.value(0)
led_b.value(1)
time.sleep(0.5)
led_b.value(0)
使用三路PWM分别驱动RGB三个LED,可调制出很多种颜色:
from machine import Pin,PWM
import time
pwm_r =PWM(Pin(14))
pwm_g =PWM(Pin(27))
pwm_b =PWM(Pin(26))
pwm_r.freq(1000)
pwm_g.freq(1000)
pwm_b.freq(1000)
led_r = 1000
led_g = 0
led_b = 0
stage = 1
while True:
if stage == 1:
led_r -= 1
led_g += 1
if led_r == 0:
stage = 2
if stage == 2:
led_g -= 1
led_b += 1
if led_g == 0:
stage = 3
if stage == 3:
led_b -= 1
led_r += 1
if led_b == 0:
stage = 1
pwm_r.duty(led_r)
pwm_g.duty(led_g)
pwm_b.duty(led_b)
time.sleep(0.02)
开发板上板载了一个蜂鸣器,连接在ESP32的16引脚。可以使用PWM驱动蜂鸣器播放音乐。
音乐的本质是不同频率的声音随时间的流动,所以乐谱主要记录的是频率随时间的变化关系。以简谱为例,通过数字和上下面的点表示频率的高低,通过下划线表示该音符持续的时间。
如果全音符的持续时间为4S,则二分音符的持续时间为2S,四分音符的持续时间为1S,八分音符的持续时间为0.5S … …
比如在上述乐谱中,第一个音符的频率为784Hz,时值为0.5S,使用如下代码可播放上图简谱的前两句:
from machine import Pin,PWM
import time
pwm_beep =PWM(Pin(16))
pwm_beep.duty(500)
while True:
pwm_beep.freq(784)
time.sleep(0.5)
pwm_beep.freq(880)
time.sleep(0.5)
pwm_beep.freq(784)
time.sleep(0.5)
pwm_beep.freq(698)
time.sleep(0.5)
pwm_beep.freq(659)
time.sleep(0.5)
pwm_beep.freq(587)
time.sleep(0.5)
pwm_beep.freq(523)
time.sleep(1.5)
pwm_beep.freq(523)
time.sleep(0.5)
pwm_beep.freq(659)
time.sleep(0.5)
pwm_beep.freq(1046)
time.sleep(0.5)
pwm_beep.freq(988)
time.sleep(0.5)
pwm_beep.freq(880)
time.sleep(0.75)
pwm_beep.freq(659)
time.sleep(0.25)
pwm_beep.freq(784)
time.sleep(1.5)
开发板上板载了4颗WS2812灯珠,连接在ESP32的13引脚上,可使用如下代码点亮这些灯珠:
from machine import Pin
from neopixel import NeoPixel
np = NeoPixel(Pin(13, Pin.OUT) , 4) # 使用13引脚创建一个拥有4颗灯珠的灯带
np[0] = (20, 60, 10) # 设置第一颗灯灯珠的颜色(RGB)
np[1] = (100, 0, 50) # 设置第二颗灯灯珠的颜色(RGB)
np[2] = (0, 230, 20) # 设置第三颗灯灯珠的颜色(RGB)
np[3] = (200, 160, 10) # 设置第四颗灯灯珠的颜色(RGB)
np.write() # 将设置的颜色写入到灯组中
光敏电阻通过如上图所示的方式连接在ESP32的39引脚上,可通过系列代码读取光敏电阻数据:
from machine import Pin, ADC
import time
adc = ADC(Pin(39)) #使用39号引脚创建ADC
adc.atten(ADC.ATTN_11DB) #设置ADC数据长度
while True:
print(adc.read()) #读取ADC的值并输出
time.sleep(0.5) # 延时0.5S
热释红外传感器连接在ESP32的36引脚上,可使用如下代码读取该传感器的数据,有人员活动输出高电平,无人员活动输出低电平:
from machine import Pinimport time
sr = Pin(36, Pin.IN) #将36引脚设为输入模式
while True:
print(sr.value()) #读取36号引脚的值并输出
time.sleep(0.5) # 延时0.5S
DHT11连接在ESP32的32引脚上,可使用如下代码读取温湿度数据;
from machine import Pin
import time, dht #导入相关功能模块
d = dht.DHT11(Pin(32)) # 使用32引脚读取DHT11数据
while True:
d.measure() #执行一次测量
#输出测量结果
print( "温度: " , d.temperature() , "湿度:" , d.humidity())
time.sleep(1) #延时1S
开发板上板载了红外发射管和红外接收管,连接图如下:
红外发射管由IO25控制,红外接收管数据由IO34读取,暂时还没有应用代码,有兴趣可以自己写。
开发板上搭载了中景园SPI接口的LCD显示屏,分辨率240*240,驱动芯片为ST7789V,原厂驱动程序可参考:
https://pan.baidu.com/s/1nF34QoV9Dh_59AWkbowwGQ 提取码:8888
显示屏与ESP32的连接如下图:
BLK ----- 23
DC ----- 22
SCL ----- 21
SDA ----- 19
RST ---- 17
可使用如下Python程序代码驱动:
ST7789V.py
显示屏驱动程序
from machine import Pin, SPI
import time
import machine
import esp
class LCD_240_240(object):
def __init__(self):
self.hspi = SPI(1, 10000000, polarity=1, phase=0, sck=Pin(21), mosi=Pin(19))
self.lcd_bk = Pin(23, Pin.OUT)
self.lcd_dc = Pin(22, Pin.OUT)
self.lcd_res= Pin(17, Pin.OUT)
self.lcd_bk.value(1)
self.lcd_res.value(0)
time.sleep(0.1)
self.lcd_res.value(1)
time.sleep(0.05)
self.lcd_dc.off()
self.hspi.write(b'\x11')
time.sleep(0.05)
self.LCD_Cmd_Data(b'\x36',b'\x70')
self.LCD_Cmd_Data(b'\x3A',b'\x05')
self.LCD_Cmd_Data(b'\xB2',b'\x0C\x0C\x00\x33\x33')
self.LCD_Cmd_Data(b'\xB7',b'\x35')
self.LCD_Cmd_Data(b'\xBB',b'\x19')
self.LCD_Cmd_Data(b'\xC0',b'\x2C')
self.LCD_Cmd_Data(b'\xC2',b'\x01')
self.LCD_Cmd_Data(b'\xC3',b'\x12')
self.LCD_Cmd_Data(b'\xC4',b'\x20')
self.LCD_Cmd_Data(b'\xC6',b'\x0F')
self.LCD_Cmd_Data(b'\xD0',b'\xA4\xA1')
self.LCD_Cmd_Data(b'\xE0',b'\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23')
self.LCD_Cmd_Data(b'\xE1',b'\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23')
self.lcd_dc.off()
self.hspi.write(b'\x21\x29')
def LCD_Cmd_Data(self,cmd, data):
self.lcd_dc.off()
self.hspi.write(cmd)
self.lcd_dc.on()
self.hspi.write(data)
def SetDisArea(self,xStart,yStart,xEnd,yEnd):
buf = bytearray(4)
buf[0] = 0
buf[1] = xStart
buf[2] = 0
buf[3] = xEnd
self.LCD_Cmd_Data(b'\x2A',buf)
buf[1] = yStart
buf[3] = yEnd
self.LCD_Cmd_Data(b'\x2B',buf)
self.lcd_dc.off()
self.hspi.write(b'\x2C')
def Disp_Color(self,Color):
self.SetDisArea(0,0,239,239)
self.lcd_dc.on()
buf = bytearray(480)
for j in range(240):
buf[j*2] = Color >> 8
buf[j*2+1] = Color & 0xFF
for i in range(240):
self.hspi.write(buf)
def DrawPoint(self,x,y,color):
buf = bytearray(2)
buf[0] = 0
buf[1] = x
self.LCD_Cmd_Data(b'\x2A',buf)
buf[1] = y
self.LCD_Cmd_Data(b'\x2B',buf)
buf[0] = color >> 8
buf[1] = color &0xFF
self.LCD_Cmd_Data(b'\x2C',buf)
def Disp_Str(self,x,y,str_datda):
font_buf = bytearray(64)
for c in str_datda:
start_addr = 0x300000 + 64*(c - 0x20)
esp.flash_read(start_addr, font_buf)
self.SetDisArea(x,y,x+15,y+31)
x+=16
self.lcd_dc.on()
for j in range(64):
for k in range(8):
if (font_buf[j] & (0x01<<k)) == (0x01 << k):
self.hspi.write(b'\xf8\x00')
else:
self.hspi.write(b'\xff\xff')
def Disp_Pic(self, star_addr):
self.SetDisArea(0,0,239,239)
self.lcd_dc.on()
buf = bytearray(480)
byte_offset = star_addr
for i in range(240):
esp.flash_read(byte_offset, buf)
self.hspi.write(buf)
byte_offset += 480
显示字体需要将字体文烧录到0x300000地址,显示图片需要使用Image2LCD
软件将图片转换成RGB565
格式的Bin文件
后,烧录到Flash的空白地址,如: 0x310000
,0x330000
字体文件下载连接:https://shyboy.oss-cn-shenzhen.aliyuncs.com/readonly/font3216.bin
Image2LCD软件下载链接:https://shyboy.oss-cn-shenzhen.aliyuncs.com/readonly/Image2Lcd%202.9%28%E7%A0%B4%E8%A7%A3%E7%89%88%29.rar
from ST7789V import LCD_240_240
lcd = LCD_240_240()
lcd.Disp_Color(0x8563) #整屏填充颜色
lcd.Disp_Pic(0x320000) #显示存储在0x320000的图片
lcd.Disp_Str(30,50, b'abc123') #在(30,50位置显示文字abc123)
后面还有WiFi和蓝牙方面的知识,有空再更新。
十一过后计划录制些视频上传到B站,详细讲解下这些知识,敬请期待。。。。
另外,如果您觉得这篇文章对你有帮助,可通过如下方式支持一下鹏老师:下载华秋DFM,让鹏老师恰口饭!