本帖最后由 lugl4313820 于 2023-6-26 14:56 编辑
【感谢】感谢EEWORLD与得捷电子提供了这次非常有意义的活动
根据项目的要求,我完成项目如下:
一、环境搭建工作
该任务发表帖子为:【得捷电子Follow me第1期】开箱及学习使用hello world - Digi-Key得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
二、驱动外设任务
1、驱动OLED屏,发表帖子为:【得捷电子Follow me第1期】第2步 学习驱动OLED - Digi-Key得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
2、驱动GPS,获取定位信息,发表帖子为:【得捷电子Follow me第1期】第3步获取GPS定位信息 - Digi-Key得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
3、连接wifi,获取IP地址等,发表帖子为:【得捷电子Follow me第1期】连接wifi - Digi-Key得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
4、实现mqtt数据收发,发表帖子为:【得捷电子Follow me第1期】MQTT数据收发 - Digi-Key得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
5、实现NTC获取时间,发表帖子为:【得捷电子Follow me第1期】NTP获取网络时间+电子时钟 - Digi-Key得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
三、项目介绍
综合项目为制作一个带有日历的温湿度计
1、项目的主要功能:显示室内的温度与湿计,同时显示日历
2、实现步骤
1)实现wifi连入局域网,代码为:
ssid='SSID'
passwd='pwssword'
wlan = None
max_wait = 10
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, passwd)
# Wait for connect or fail
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
time.sleep(1)
if wlan.status() != 3:
raise RuntimeError('network connection failed')
else:
print('connected')
status = wlan.ifconfig()
print('ip = ' + status[0])
2) 实现NTC获取时间,并更新RTC时间,代码如下:
def sync_ntp():
ntptime.NTP_DELTA = 3155644800 # 可选 UTC+8偏移时间(秒),不设置就是UTC0
ntptime.host = 'ntp1.aliyun.com' # 可选,ntp服务器,默认是"pool.ntp.org"
ntptime.settime() # 修改设备时间,到这就已经设置好了
3、驱动OLED屏,ssd1306的驱动代码如下:
from micropython import const
import framebuf
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class SSD1306(framebuf.FrameBuffer):
def __init__(self, width, height, external_vcc):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
try:
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
self.init_display()
except Exception as e:
print("erro" +str(e))
def init_display(self):
for cmd in (
SET_DISP | 0x00, # off
# address setting
SET_MEM_ADDR,
0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
SET_MUX_RATIO,
self.height - 1,
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
SET_DISP_OFFSET,
0x00,
SET_COM_PIN_CFG,
0x02 if self.width > 2 * self.height else 0x12,
# timing and driving scheme
SET_DISP_CLK_DIV,
0x80,
SET_PRECHARGE,
0x22 if self.external_vcc else 0xF1,
SET_VCOM_DESEL,
0x30, # 0.83*Vcc
# display
SET_CONTRAST,
0xFF, # maximum
SET_ENTIRE_ON, # output follows RAM contents
SET_NORM_INV, # not inverted
# charge pump
SET_CHARGE_PUMP,
0x10 if self.external_vcc else 0x14,
SET_DISP | 0x01,
): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
def poweron(self):
self.write_cmd(SET_DISP | 0x01)
def contrast(self, contrast):
self.write_cmd(SET_CONTRAST)
self.write_cmd(contrast)
def invert(self, invert):
self.write_cmd(SET_NORM_INV | (invert & 1))
def show(self):
x0 = 0
x1 = self.width - 1
if self.width == 64:
# displays with width of 64 pixels are shifted by 32
x0 += 32
x1 += 32
self.write_cmd(SET_COL_ADDR)
self.write_cmd(x0)
self.write_cmd(x1)
self.write_cmd(SET_PAGE_ADDR)
self.write_cmd(0)
self.write_cmd(self.pages - 1)
self.write_data(self.buffer)
class SSD1306_I2C(SSD1306):
def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
self.write_list = [b"\x40", None] # Co=0, D/C#=1
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.writeto(self.addr, self.temp)
def write_data(self, buf):
self.write_list[1] = buf
self.i2c.writevto(self.addr, self.write_list)
class SSD1306_SPI(SSD1306):
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
self.rate = 10 * 1024 * 1024
dc.init(dc.OUT, value=0)
res.init(res.OUT, value=0)
cs.init(cs.OUT, value=1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
import time
self.res(1)
time.sleep_ms(1)
self.res(0)
time.sleep_ms(10)
self.res(1)
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buf)
self.cs(1)
同时为显示中文,我引入了ufont库,库的源码与字库见附件。
4)为了获取温湿度计,驱动了stht30。驱动代码如下:
def sht30_get_temp_hmi():
temp = bytearray(2)
t_celsius=0
rh=0
temp[0]=0x2c
temp[1]=0x10
i2c0.writeto(0x44, temp)
time.sleep_ms(60)
data = i2c0.readfrom(0x44, 6)
t_celsius = (((data[0] << 8 | data[1]) * 175) / 0xFFFF) - 45
rh = (((data[3] << 8 | data[4]) * 100.0) / 0xFFFF)
str_temp = "温度:%.2f℃"%t_celsius
str_rh = "湿度:%.2f%%" % rh
f.text(oled, str_temp, 0, 32, color=0xf8, show=False)
f.text(oled, str_rh, 0, 48, color=0xf8, show=False)
print(str_temp)
4、功能展示:
在OLED屏上展示了目期、温、湿度,每5秒列新一次:
主要特点是,开机后会主动同步服务器时间。实时同步。
详见视频。
5、心得体会
1)这次活动,很大佬参与进来,学习起来非常之方便。
2)micropython的生态非常好,学习资源也非常丰富。
3、这次活动,提供了很好的产品、外设,学习起来非常方便。
6、工程代码:
7、视频介绍:
工程介绍
|