WHCSRL 技术网

自制ESP32教学开发板[ESP32_Py

摘要

由于教学需要,自己设计了一款ESP32开发板,用于《短距离无线通信》课堂教学使用。开发板整体效果如下图:

整体预览图
该开发板采用Type-C接口供电,板载CH340K串口芯片,支持自动下载。240*240全彩SPI接口显示屏,温度传感器DS18B20,温湿度传感器DHT11,RGB三色灯,WS2812灯珠,蜂鸣器,红外热释传感器,光敏电阻,红外发射/接收,微动按键,触摸按键,部分IO引出。

硬件原理图全开源:https://oshwhub.com/Dr.Zhang/esp32_py_board

USB转串口驱动安装

USB转串口使用的是CH340K芯片,需要安装新版本驱动才能使用,新版本驱动下载地址:

http://www.wch.cn/downloads/file/65.html

下载完成后双击安装程序,然后点击安装即可:

CH340驱动安装

固件烧录

固件烧录需要使用乐鑫原厂的烧录工具,工具下载地址:

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

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闪烁,说明设备正常工作。
点灯程序

RGB LED灯示例程序

RGBLED

开发板上有一个三个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) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

PWM 彩色LED渐变

使用三路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) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

在这里插入图片描述

PWM驱动蜂鸣器播放音乐

开发板上板载了一个蜂鸣器,连接在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) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

WS2812灯珠

开发板上板载了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()              # 将设置的颜色写入到灯组中
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

光敏电阻

在这里插入图片描述
光敏电阻通过如上图所示的方式连接在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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

热释红外传感器

在这里插入图片描述

热释红外传感器连接在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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

温湿度传感器

在这里插入图片描述
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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

红外发射与接收

开发板上板载了红外发射管和红外接收管,连接图如下: 作者:我是鹏老师 https://www.bilibili.com/read/cv13345911 出处:bilibili
红外发射管由IO25控制,红外接收管数据由IO34读取,暂时还没有应用代码,有兴趣可以自己写。

LCD显示屏

开发板上搭载了中景园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'x0Cx0Cx00x33x33')
    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'xA4xA1')
    self.LCD_Cmd_Data(b'xE0',b'xD0x04x0Dx11x13x2Bx3Fx54x4Cx18x0Dx0Bx1Fx23')
    self.LCD_Cmd_Data(b'xE1',b'xD0x04x0Cx11x13x2Cx3Fx44x51x2Fx1Fx1Fx20x23')

    self.lcd_dc.off()
    self.hspi.write(b'x21x29')

  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'xf8x00')
          else:
            self.hspi.write(b'xffxff')
            
  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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117

显示字体需要将字体文烧录到0x300000地址,显示图片需要使用Image2LCD软件将图片转换成RGB565格式的Bin文件后,烧录到Flash的空白地址,如: 0x3100000x330000

字体文件下载连接: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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

后面还有WiFi和蓝牙方面的知识,有空再更新。

十一过后计划录制些视频上传到B站,详细讲解下这些知识,敬请期待。。。。

B站ID:我是鹏老师

另外,如果您觉得这篇文章对你有帮助,可通过如下方式支持一下鹏老师:下载华秋DFM,让鹏老师恰口饭!

推荐阅读