diff --git a/docs/Advanced_development/zh/QuecPythonBus/ExtInt.md b/docs/Advanced_development/zh/QuecPythonBus/ExtInt.md new file mode 100644 index 0000000000000000000000000000000000000000..8212f411d32600013ac5fbdc48a1e56c33d2395b --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/ExtInt.md @@ -0,0 +1,58 @@ +# 外部中断实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ------- | -------- | +| 1.0 | 2021-09-22 | Grey.Tu | 初版 | + +文档主要介绍如何实现 ExtInt 检测外部中断,从硬件设计和软件设计两方面讲解,通过阅读本文,您将学会 ExtInt 外部中断功能使用。 + +有关API详解请参考 [QuecPython-machine - ExtInt](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=extint) + + + +## 硬件设计 + +ExtInt 外部中断原理为检测 PIN 脚外部电平转变,既 PIN 脚上有上升沿或下降沿信号。 + +![media_ExtInt_1](media/media_ExtInt_1.jpg) + +原理图与按键原理图类似: + +![media_ExtInt_2](media/media_ExtInt_2.jpg) + +## 软件设计 + +首先确定要控制硬件的哪个引脚,然后通过官网的 API 类库找到对应的 GPIO 编号 。详解请参考 [QuecPython-machine - ExtInt](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=extint) + +例: ![media_ExtInt_3](media/media_ExtInt_3.jpg)EC600S/N的引脚10为GPIO1。 + +开始编写代码,选择对应的 GPIO 进行 ExtInt 外部中断初始化: + +```python +from machine import ExtInt + + +def callback(args): + print('interrupt: {}'.format(args)) + + +extint13 = ExtInt(ExtInt.GPIO13, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, callback) # 创建对象 +extint12 = ExtInt(ExtInt.GPIO12, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, callback) # 创建对象 +extint13.enable() # 使能中断 +extint12.enable() # 使能中断 +print('开启GPIO: {}中断. \r\n'.format(extint13.line())) +print('开启GPIO: {}中断. \r\n'.format(extint12.line())) + +# extint13.disable() # 关闭中断 +# extint12.disable() # 关闭中断 +``` + +配套代码 + +## 配套代码 + + + 下载代码 + diff --git a/docs/Advanced_development/zh/QuecPythonBus/button.md b/docs/Advanced_development/zh/QuecPythonBus/button.md new file mode 100644 index 0000000000000000000000000000000000000000..acfec324500112026c303a12032867fa95005da6 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/button.md @@ -0,0 +1,68 @@ +# 按键输入实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ---- | -------- | +| 1.0 | 2021-09-17 | Grey | 初版 | + +文档主要介绍如何实现检测 GPIO 电平,从硬件设计和软件设计两方面讲解,通过阅读本文,您将学会查看硬件连接关系、代码编写思路和验证实验理论。 + +有关API详解请参考 [QuecPython-machine - PIN](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=pin) + + + +## 硬件资源 + +EC600x 开发板引出了两个 PIN 脚供客户实验按键输入实验。 + +我们配置对应 GPIO 为上拉输入模式便可以通过按而不按按键改变 GPIO的电平。 + +![media_button_1](media/media_button_1.jpg) + + + +## 软件设计 + +首先确定要检测的硬件引脚是那一个 GPIO ,我们通过官网的 API 类库找到对应的 GPIO编号 。详解请参考 [QuecPython-machine - PIN](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=pin) + +例: ![media_button_2](media/media_button_2.jpg)EC600S/N的引脚10为GPIO1。 + +而我们 EC600x 开发板两个按键 PIN59/PIN60,对应EC600S/N为:PIN59 => GPIO12;PIN60 => GPIO13。对应EC600U为:PIN60 => GPIO4;PIN59 无对应 GPIO,不能进行按键输入检测。这边我们实现一个按键的按键检测功能。 + +### 代码实现 + +```python +import utime +from machine import Pin + + +if __name__ == '__main__': + gpio13 = Pin(Pin.GPIO13, Pin.IN, Pin.PULL_PU, 1) # EC600S/N开发板使用 + # gpio13 = Pin(Pin.GPIO4, Pin.IN, Pin.PULL_PU, 1) # EC600U开发板使用 + while True: + if gpio13.read() == 0: + utime.sleep_ms(10) + if gpio13.read() == 0: + while gpio13.read() == 0: + pass + print("GPIO13按下") + pass +``` + + + +## 下载验证 + +下载.py 文件到模组运行: + +![media_button_3](media/media_button_3.jpg) + +下载之后,按下按键,便会有信息打印: + +![media_button_4](media/media_button_4.jpg) + +## 配套代码 + + + 下载代码 \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonBus/buzzer.md b/docs/Advanced_development/zh/QuecPythonBus/buzzer.md new file mode 100644 index 0000000000000000000000000000000000000000..5f9288b79e4e2effbb066d07e8f89dcdc6173761 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/buzzer.md @@ -0,0 +1,138 @@ +# 蜂鸣器实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +|------|------|------|------| +| 1.0 | 2021-03-20 | gary.zhou | 初版 | +| 1.1 | 2021-09-15 | Grey.Tu | 修改有源蜂鸣器绘制为无源蜂鸣器控绘制. | +| 1.2 | 2021-11-29 | Grey.Tu | 勘误. | + +文档主要介绍如何 PWM 控制 **无源蜂鸣器** ,使 **无源蜂鸣器** 发声。从硬件设计和软件设计两方面讲解,通过阅读本文,可以学习 PWM 基本使用。 + +有关 API 详解请参考 [QuecPython-misc - PWM](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=pwm) + + + +## 硬件描述 + +蜂鸣器分为 **有源蜂鸣器** 与 **无源蜂鸣器** 两种。 **有源蜂鸣器** 直接供电就会发声,控制如同 LED ,控制引脚输出高低电平即可。硬件电路也与 LED 电路类似。 有关驱动请参考 LED 控制章节。本文主要介绍 **无源蜂鸣器** 的驱动,实现 PWM 控制 **无源蜂鸣器** 。 + +![media_buzzer_1](media/media_buzzer_1.jpg) + +淘宝搜索购买无源蜂鸣器 + +![media_buzzer_2](media/media_buzzer_2.jpg) + +无源蜂鸣器通过PWM开关三极管驱动。 我们只需要电源,以及2KHz~5KHz 的pwm方波即可。 + +![media_buzzer_3](media/media_buzzer_3.jpg) + + + +## 软件设计 + +#### 查询开发板对应的IO口 + +首先确定要控制硬件的哪个引脚,然后通过官网的 API 类库找到对应的 PWM 编号 。详解请参考 [QuecPython-misc - PWM](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=pwm) 例: + +| 模块型号 | **对应引脚号** | +| -------------------------------------- | -------------- | +| EC600S/N ==> PWM2
EC600U ==> PWM0 | 引脚号70 | + + +### **实验代码** + +```python + +from misc import PWM +import utime as time +import urandom as random +import log + +# API https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=pwm +# 蜂鸣器模块 https://detail.tmall.com/item.htm?id=41251333522 +# 无源蜂鸣器-频率可控版 + +""" + +pwm0 = PWM(PWM.PWMn,PWM.ABOVE_xx,highTime,cycleTime) + +注:EC600SCN平台,支持PWM0-PWM3,对应引脚如下: + +PWM0 – 引脚号52 + +PWM1 – 引脚号53 + +PWM2 – 引脚号70 + +PWM3 – 引脚号69 + +""" + +# 获取logger对象 + +buzzer_log = log.getLogger("buzzer_test") + +# Duration 为 ms + +def outputpwm(HZ, duty_cycle, Duration): + + # 将HZ 转化为 10us 级别 + + cycleTime = int((10000000/HZ)/10) + highTime = int(cycleTime * duty_cycle) + + # 输出debug级别的日志 + + buzzer_log.debug( + """out put pin70 cycleTime {0} * 10us, + highTime {1} * 10us, Duration of {2}""" + .format(cycleTime, highTime, Duration)) + pwm1 = PWM(PWM.PWM2, PWM.ABOVE_10US, highTime, cycleTime) + pwm1.open() + + # 休眠给定毫秒数的时间 + + time.sleep_ms(Duration) + pwm1.close() + pass + + +def test_Buzzer(): + + #设置日志输出级别 + + log.basicConfig(level=log.DEBUG) + + # 循环遍历10次 + + for i in range(10): + + # 随机生成 start 到 end 范围内的浮点数,范围可以自己选择, 0~1 + + duty_cycle = random.uniform(0.1, 0.8) + + # 建议输出2000~5000HZ 的PWM波形 + # 随机生成一个 start 到 end 之间的整数 + + HZ = random.randint(2000, 5000) + outputpwm(HZ, duty_cycle, 500) + time.sleep_ms(1500) + + pass + + +if __name__ == "__main__": + + # creat a thread Check key status + + test_Buzzer() + +# 将代码下载运行,可以听到蜂鸣器产生随机的声音 +``` + +## 配套代码 + +* [下载代码](code/code_buzzer.py) + \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonBus/code/code_ExtInt.py b/docs/Advanced_development/zh/QuecPythonBus/code/code_ExtInt.py new file mode 100644 index 0000000000000000000000000000000000000000..241ccd79ca3130dce058c71b9577fac8dc4b6da7 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/code/code_ExtInt.py @@ -0,0 +1,29 @@ +from machine import ExtInt +import utime as time +# PIN脚及API介绍请参考 https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=extint +state = 10 # 测试次数 + + +def callback(args): + print('interrupt: {}'.format(args)) + + +def main(): + extint13 = ExtInt(ExtInt.GPIO13, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, callback) # 创建对象 + extint12 = ExtInt(ExtInt.GPIO12, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, callback) # 创建对象 + extint13.enable() # 使能中断 + extint12.enable() # 使能中断 + print('开启GPIO: {}中断. \r\n'.format(extint13.line())) + print('开启GPIO: {}中断. \r\n'.format(extint12.line())) + # 等待按键按下,触发 + while state: + time.sleep_ms(1) + pass + # 停止映射外部中断 + extint13.disable() # 关闭中断 + extint12.disable() # 关闭中断 + print("The main function has exited") + + +if __name__ == "__main__": + main() diff --git a/docs/Advanced_development/zh/QuecPythonBus/code/code_UART_CDC.py b/docs/Advanced_development/zh/QuecPythonBus/code/code_UART_CDC.py new file mode 100644 index 0000000000000000000000000000000000000000..a8d288d5ef5c2687598f5a9bd78c390b6eb664ab --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/code/code_UART_CDC.py @@ -0,0 +1,70 @@ +# import log +import utime +import _thread +import ubinascii +from machine import UART + +state = 1 +uart_x = None +usbcdc = None + +# # | 参数 | 参数类型 | 说明 | +# # | -------- | ------- | ------------------ | +# # | CRITICAL | 常量 | 日志记录级别的数值 50 | +# # | ERROR | 常量 | 日志记录级别的数值 40 | +# # | WARNING | 常量 | 日志记录级别的数值 30 | +# # | INFO | 常量 | 日志记录级别的数值 20 | +# # | DEBUG | 常量 | 日志记录级别的数值 10 | +# # | NOTSET | 常量 | 日志记录级别的数值 0 | +# log.basicConfig(level=log.CRITICAL) # 设置日志输出级别 +# log = log.getLogger("Grey") # 获取logger对象,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象 + + +def uart_x_read(): + global state + global uart_x + global usbcdc + + while state: + msglen = uart_x.any() # 返回是否有可读取的数据长度 + if msglen: # 当有数据时进行读取 + msg = uart_x.read(msglen) # 读取数据 + utf8_msg = msg.decode() # 初始数据是字节类型(bytes),将字节类型数据进行编码 + if "Grey" in utf8_msg: + break + else: + usbcdc.write("{}".format(utf8_msg)) # 发送数据 + utime.sleep_ms(1) + state = 0 + + +def usbcdc_read(): + global state + global uart_x + global usbcdc + + while state: + msglen = usbcdc.any() # 返回是否有可读取的数据长度 + if msglen: # 当有数据时进行读取 + msg = usbcdc.read(msglen) # 读取数据 + utf8_msg = msg.decode() # 初始数据是字节类型(bytes),将字节类型数据进行编码 + if "Grey" in utf8_msg: + break + else: + uart_x.write("{}".format(utf8_msg)) # 发送数据 + utime.sleep_ms(1) + state = 0 + + +if __name__ == "__main__": + uart_x = UART(UART.UART2, 115200, 8, 0, 1, 0) + usbcdc = UART(UART.UART3, 115200, 8, 0, 1, 0) + + uart_x.write("Grey_测试") + usbcdc.write("Grey_测试") + + _thread.start_new_thread(uart_x_read, ()) # 创建一个线程来监听接收uart消息 + _thread.start_new_thread(usbcdc_read, ()) # 创建一个线程来监听接收CDC消息 + + while state: + utime.sleep_ms(1) diff --git a/docs/Advanced_development/zh/QuecPythonBus/code/code_button.py b/docs/Advanced_development/zh/QuecPythonBus/code/code_button.py new file mode 100644 index 0000000000000000000000000000000000000000..097c0992ad2c319c7eabecbc90f4caa34713697c --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/code/code_button.py @@ -0,0 +1,15 @@ +import utime +from machine import Pin + + +if __name__ == '__main__': + gpio13 = Pin(Pin.GPIO13, Pin.IN, Pin.PULL_PU, 1) # EC600S/N开发板使用 + # gpio13 = Pin(Pin.GPIO4, Pin.IN, Pin.PULL_PU, 1) # EC600U开发板使用 + while True: + if gpio13.read() == 0: + utime.sleep_ms(10) + if gpio13.read() == 0: + while gpio13.read() == 0: + pass + print("GPIO13按下") + pass diff --git a/docs/Advanced_development/zh/QuecPythonBus/code/code_buzzer.py b/docs/Advanced_development/zh/QuecPythonBus/code/code_buzzer.py new file mode 100644 index 0000000000000000000000000000000000000000..5225c7bbaed9b85736d1dad9b7cd261fc11b6215 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/code/code_buzzer.py @@ -0,0 +1,83 @@ +from misc import PWM +import utime as time +import urandom as random +import log + +# API https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=pwm +# 蜂鸣器模块 https://detail.tmall.com/item.htm?id=41251333522 +# 无源蜂鸣器-频率可控版 + +""" + +pwm0 = PWM(PWM.PWMn,PWM.ABOVE_xx,highTime,cycleTime) + +注:EC600SCN平台,支持PWM0-PWM3,对应引脚如下: + +PWM0 – 引脚号52 + +PWM1 – 引脚号53 + +PWM2 – 引脚号70 + +PWM3 – 引脚号69 + +""" + +# 获取logger对象 + +buzzer_log = log.getLogger("buzzer_test") + +# Duration 为 ms + +def outputpwm(HZ, duty_cycle, Duration): + + # 将HZ 转化为 10us 级别 + + cycleTime = int((10000000/HZ)/10) + highTime = int(cycleTime * duty_cycle) + + # 输出debug级别的日志 + + buzzer_log.debug( + """out put pin70 cycleTime {0} * 10us, + highTime {1} * 10us, Duration of {2}""" + .format(cycleTime, highTime, Duration)) + pwm1 = PWM(PWM.PWM2, PWM.ABOVE_10US, highTime, cycleTime) + pwm1.open() + + # 休眠给定毫秒数的时间 + + time.sleep_ms(Duration) + pwm1.close() + pass + + +def test_Buzzer(): + + #设置日志输出级别 + + log.basicConfig(level=log.DEBUG) + + # 循环遍历10次 + + for i in range(10): + + # 随机生成 start 到 end 范围内的浮点数,范围可以自己选择, 0~1 + + duty_cycle = random.uniform(0.1, 0.8) + + # 建议输出2000~5000HZ 的PWM波形 + # 随机生成一个 start 到 end 之间的整数 + + HZ = random.randint(2000, 5000) + outputpwm(HZ, duty_cycle, 500) + time.sleep_ms(1500) + + pass + + +if __name__ == "__main__": + + # creat a thread Check key status + + test_Buzzer() \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_1.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41421feb83f7955a3de178e949d94ed47a6287ea Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_1.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_2.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5355ab9897d86fdc57c91e1bd269567dba99043b Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_2.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_3.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f7d9a8fdcc6186a90a06efeaced6fcf0e872fe4 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_ExtInt_3.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_1.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0dd3d266fee8f2b92601ded72dbc03f677130a5b Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_1.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_2.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1337a536d4331ae03a0f3bc74ff52fe0abef3bc5 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_2.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_3.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..042fc4cfc8b4c1ccdc900ca31be90588cfcace38 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_UART_3.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_button_1.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..99ad61a5655bdc24f0b63c0480548be6014594d0 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_1.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_button_2.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f7d9a8fdcc6186a90a06efeaced6fcf0e872fe4 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_2.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_button_3.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1b8ca2f4595ea54bb892cfbf6c6854e1b9b195e0 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_3.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_button_4.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..80bd9f7dd8497851cab1c8ea92455a595be6a9a7 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_button_4.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_1.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..08655fb0aca59b86c0c8c0c856522fe0f440cd1a Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_1.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_2.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..04f1abf9f20c5d03199c9f018b7fb957cc5db9b4 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_2.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_3.jpg b/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e46d0e65656a8f8d992dd1a51dc20e7c6157d2a0 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonBus/media/media_buzzer_3.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonBus/uart.md b/docs/Advanced_development/zh/QuecPythonBus/uart.md new file mode 100644 index 0000000000000000000000000000000000000000..9fd997311654bce2958ac7c9594f0385401a8beb --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonBus/uart.md @@ -0,0 +1,78 @@ +# UART实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ------- | -------- | +| 1.0 | 2021-09-22 | Grey.tu | 初版 | +| 1.1 | 2021-11-29 | Grey.tu | 勘误 | + +文档主要介绍QuecPython_UART,UART作为一种常用的通用方式,主要用数据交互,可实现全双工传输。通过本文你将了解到EC600x(包括EC600S、EC600N、EC600U)UART的设置参数及使用方法。 + +有关API详解请参考 [QuecPython-machine-UART](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=uart) + + + +## 硬件设计 + +针对不同的模组,开放的UART列表如下: + +| 模块型号 | UART编号 | UART_PIN | +| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| EC600S/N | UART0_DEBUG PORT
UART1_BT PORT
UART2_MAIN PORT
UART3_USB CDC PORT | UART0_DEBUG_PORT(TX => PIN71 & RX => PIN72)
UART1_BT_PORT(TX => PIN3 & RX => PIN2)
UART2_MAIN_PORT(TX => PIN32 & RX => PIN31)
USB_CDC_PORT ==> USB虚拟口,波特率不受限 | +| EC600U | UART0_DEBUG PORT
UART1_BT PORT
UART2_MAIN PORT
UART3_USB CDC PORT | UART0_DEBUG_PORT(TX => PIN71 & RX => PIN72)
UART1_BT_PORT(TX => PIN124 & RX => PIN123)
UART2_MAIN_PORT(TX => PIN32 & RX => PIN31)
USB_CDC_PORT ==> USB虚拟口,波特率不受限
注: EC600U_DEBUG PORT只能作为DEBUG_LOG输出使用,
不能作为UART通信使用. | + +官方QuecPython开发板V1.2/V1.3的UART位置标记如下图: + +![media_UART_1](media/media_UART_1.jpg) + +注:此图仅适用于官方QuecPython开发板V1.2/V1.3。后续开发板视情况而定。 + + + +## 软件设计 + +物理 UART 基本连接使用我们在 UART 功能章节已经介绍,我们本章介绍下 USB CDC PORT。 + +USB CDC PORT 为USB虚拟的串行通信口,此通信口采用 UART 一样的通信协议,但并未真正意义的 UART。它的通信速率不受 UART 波特率的限制,可根据USB协议自动设别。可以更快速率的传输数据,也无需固定波特率的繁琐。 + +```python +from machine import UART + +uart_x = UART(UART.UART2, 115200, 8, 0, 1, 0) +usbcdc = UART(UART.UART3, 115200, 8, 0, 1, 0) # 此波特率设置无效, 通信时可以任意波特率 + +while True: + uart_x_msglen = uart_x.any() + if uart_x_msglen: + uart_x_msg = uart_x.read(uart_x_msglen) + uart_x_utf8_msg = uart_x_msg.decode() + usbcdc.write("{}".format(uart_x_utf8_msg)) + + usbcdc_msglen = usbcdc.any() + if usbcdc_msglen: + usbcdc_msg = usbcdc.read(usbcdc_msglen) + usbcdc_utf8_msg = usbcdc_msg.decode() + uart_x.write("{}".format(usbcdc_utf8_msg)) +``` + +运行上面的脚本代码,便可实现物理 UART2 与 USB CDC PORT 的数据透传。 + + + +## 下载验证 + +下载.py 文件到模组运行: + +![media_UART_2](media/media_UART_2.jpg) + +下载之后,便可实现物理 UARTx 与 USB CDC PORT 的数据透传功能。 + +![media_UART_3](media/media_UART_3.jpg) + + + +## 配套代码 + + + 下载代码 \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonSub/LCD.md b/docs/Advanced_development/zh/QuecPythonSub/LCD.md new file mode 100644 index 0000000000000000000000000000000000000000..ddac0b7a4d5a5aae388da7fae71c2054dcce44b2 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/LCD.md @@ -0,0 +1,598 @@ +# LCD液晶显示实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ------- | -------- | +| 1.0 | 2021-10-06 | Grey.Tu | 初版 | + +本片文章主要基于 EC600x 介绍 LCD 显示,做一个 LCD 显示的小实验。 + + + +## 硬件介绍 + +### 开发板lcd接口说明 + +media_lcd_1 + +| 序号 | 开发板lcd引脚 | 引脚定义 | 备份 | +| ---- | ------------- | ------------------------------ | ---- | +| 1 | GND | 电源地 | | +| 2 | VCC_3V3 | 电源3.3V | | +| 3 | LCD_SCL_3V3 | SPI总线时钟信号 | | +| 4 | LCD_SDA_3V3 | SPI总线写数据信号 | | +| 5 | LCD_RST_3V3 | 液晶屏复位控制信号,低电平复位 | | +| 6 | LCD_DC_3V3 | 写寄存器/写数据控制信号 | | +| 7 | LCD_BLK | 液晶屏背光控制信号 | | +| 8 | LCD_CS_3V3 | LCD片选引脚 | | + +### ST7789V lcd 接口说明 + +本实验使用的ST7789V LCD显示屏。显示屏引脚定义与开发板的LCD接口是完全匹配的,可以直接插到开发板的LCD接口使用。 + +![media_lcd_2](media/media_lcd_2.jpg) + +| 序号 | lcd引脚 | 引脚定义 | 备份 | +| ---- | ------- | ------------------------------ | ---- | +| 1 | GND | 电源地 | | +| 2 | VCC | 电源3.3V | | +| 3 | SCL | SPI总线时钟信号 | | +| 4 | SDA | SPI总线写数据信号 | | +| 5 | RES | 液晶屏复位控制信号,低电平复位 | | +| 6 | DC | 写寄存器/写数据控制信号 | | +| 7 | BLK | 液晶屏背光控制信号 | | + +### 接线方式 + +以下为 ST7789V 显示屏屏模块与 EC600x_QuecPython 开发板的接线对应关系。 + +| 序号 | ST7789V显示屏 | EC600x_QuecPython开发板 | 备份 | +| ---- | ------------- | ----------------------- | -------- | +| 1 | GND | GND | | +| 2 | VCC | VCC_3V3 | | +| 3 | SCL | LCD_SCL_3V3 | | +| 4 | SDA | LCD_SDA_3V3 | | +| 5 | RES | LCD_RST_3V3 | | +| 6 | DC | LCD_DC_3V3 | | +| 7 | BLK | LCD_BLK | | +| 8 | | LCD_CS_3V3 | 无需连接 | + + + +## 软件设计 + +本示例中的接口是基于QuecPython 的machine.LCD库实现。由于代码量相对较大,本章我们分文件管理代码,具体可阅读示例程序的源码。 + +### 文件说明 + +| 序号 | 文件 | 描述 | 备份 | +| ---- | ------------------ | ------------------------------------------------------------ | ---- | +| 1 | st7789v.py | 包含驱动IC为ST7789V的液晶屏驱动程序以及显示字符与图片等接口。 | | +| 2 | fonts.py | 示例程序中用到的字库。 | | +| 3 | image.py | 示例程序中用到的小图片显示数据 | | +| 4 | image.txt | 示例程序中用到的大图片显示数据 | | +| 5 | example_display.py | 显示主程序,调用其它几个文件中的方法与数据。 | | + +### LCD初始化函数 + +本章封装了部分 API 函数。 在介绍这些 API 之前,我们先了解一下已固件中提供的函数接口。这里我们主要介绍 LCD 初始化函数,其他函数较为简单,请自行参考:[QuecPython-machine - LCD](https://python.quectel.com/wiki/#/zh-cn/api/QuecPythonClasslib?id=lcd) 进行了解。 + +```python +# lcd.lcd_init函数参数说明 +# lcd_init_data: 传入LCD的配置命令 +# lcd_width: LCD屏幕的宽度。宽度不超过 500 +# lcd_hight: LCD屏幕的高度。高度不超过 500 +# lcd_clk: LCD SPI时钟。SPI时钟为 6.5K/13K/26K/52K +# data_line: 数据线数。参数值为 1 和 2。 +# line_num: 线的数量。参数值为 3 和 4。 +# lcd_type: 屏幕类型。0:rgb;1:fstn。 +# lcd_invalid: 传入LCD 区域设置的配置命令 +# lcd_display_on: 传入LCD 屏亮的配置命令 +# lcd_display_off: 传入LCD 屏灭的配置命令 +# lcd_set_brightness: 传入LCD屏亮度的配置命令。设置为 None表示由 LCD_BL_K 控制亮度(有些屏幕是由寄存器控制屏幕亮度,有 些是通过 LCD_BL_K 控制屏幕亮度) +lcd.lcd_init(lcd_init_data, lcd_width, lcd_hight, lcd_clk, data_line, line_num, lcd_type, lcd_invalid, lcd_display_on, lcd_display_off, lcd_set_brightness) +``` + +下面通过实际代码介绍 LCD 初始化函数的参数传入。 + +```python +from machine import LCD # 屏幕显示模块 + +# 常用颜色定义 +red = 0xF800 # 红色 +green = 0x07E0 # 绿色 +blue = 0x001F # 蓝色 +white = 0xFFFF # 白色 +black = 0x0000 # 黑色 +purple = 0xF81F # 紫色 +colour = white # 默认背景色 + +# 屏幕参数 +screen_high = 240 # 屏高 +screen_wide = 240 # 屏高 +XSTART_H = 0xf0 # 起始点X坐标高字节寄存器 +XSTART_L = 0xf1 # 起始点X坐标低字节寄存器 +XEND_H = 0xE0 # 结束点X坐标高字节寄存器 +XEND_L = 0xE1 # 结束点X坐标低字节寄存器 +YSTART_H = 0xf2 # 起始点Y坐标高字节寄存器 +YSTART_L = 0xf3 # 起始点Y坐标低字节寄存器 +YEND_H = 0xE2 # 结束点Y坐标高字节寄存器 +YEND_L = 0xE3 # 结束点Y坐标低字节寄存器 + +# 屏幕初始化参数 +# 元组中三个元素为一组, 单组中每个元素定义如下: +# 1: 类型, 0 表示命令; 1 表示数据; 2 表示延时 +# 2: 长度, 若类型为 0,则长度表示命令后的数据数量;若类型为 1,则长度表示数据的长度 +# 3: 参数值, 对应值 +init_data = ( + 0, 0, 0x11, + 0, 1, 0x36, + 1, 1, 0x00, + 0, 1, 0x3A, + 1, 1, 0x05, + 0, 0, 0x21, + 0, 5, 0xB2, + 1, 1, 0x05, + 1, 1, 0x05, + 1, 1, 0x00, + 1, 1, 0x33, + 1, 1, 0x33, + 0, 1, 0xB7, + 1, 1, 0x23, + 0, 1, 0xBB, + 1, 1, 0x22, + 0, 1, 0xC0, + 1, 1, 0x2C, + 0, 1, 0xC2, + 1, 1, 0x01, + 0, 1, 0xC3, + 1, 1, 0x13, + 0, 1, 0xC4, + 1, 1, 0x20, + 0, 1, 0xC6, + 1, 1, 0x0F, + 0, 2, 0xD0, + 1, 1, 0xA4, + 1, 1, 0xA1, + 0, 1, 0xD6, + 1, 1, 0xA1, + 0, 14, 0xE0, + 1, 1, 0x70, + 1, 1, 0x06, + 1, 1, 0x0C, + 1, 1, 0x08, + 1, 1, 0x09, + 1, 1, 0x27, + 1, 1, 0x2E, + 1, 1, 0x34, + 1, 1, 0x46, + 1, 1, 0x37, + 1, 1, 0x13, + 1, 1, 0x13, + 1, 1, 0x25, + 1, 1, 0x2A, + 0, 14, 0xE1, + 1, 1, 0x70, + 1, 1, 0x04, + 1, 1, 0x08, + 1, 1, 0x09, + 1, 1, 0x07, + 1, 1, 0x03, + 1, 1, 0x2C, + 1, 1, 0x42, + 1, 1, 0x42, + 1, 1, 0x38, + 1, 1, 0x14, + 1, 1, 0x14, + 1, 1, 0x27, + 1, 1, 0x2C, + 0, 0, 0x29, + 0, 1, 0x36, + 1, 1, 0x00, + 0, 4, 0x2a, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0xef, + 0, 4, 0x2b, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0xef, + 0, 0, 0x2c, +) + +# 屏幕区域显示参数 +# 元组中三个元素为一组, 单组中每个元素定义如下: +# 1: 类型, 0 表示命令; 1 表示数据; 2 表示延时 +# 2: 长度, 若类型为 0,则长度表示命令后的数据数量;若类型为 1,则长度表示数据的长度 +# 3: 参数值, 对应值 +lcd_set_display_area = ( + 0, 4, 0x2a, + 1, 1, XSTART_H, + 1, 1, XSTART_L, + 1, 1, XEND_H, + 1, 1, XEND_L, + 0, 4, 0x2b, + 1, 1, YSTART_H, + 1, 1, YSTART_L, + 1, 1, YEND_H, + 1, 1, YEND_L, + 0, 0, 0x2c, + ) + +lcd = LCD() # 创建对象 +lcd_init_data = bytearray(init_data) # 转换初始化参数数组 +lcd_invalid = bytearray(lcd_set_display_area) # 转换区域设定参数数组 +self.lcd.lcd_init(lcd_init_data, screen_high, screen_wide, + 6500, 1, 4, 0, lcd_invalid, None, None, None) # 初始化LCD屏 +``` + +### 封装API函数 + +#### 创建st7789v对象 + +> **from usr import st7789v** +> +> **lcd_st7789v = st7789v.ST7789V(width, hight)** + +* 功能: + + 创建一个lcd对象,进行lcd初始化。 + +* 参数: + +| 参数 | 类型 | 说明 | +| ----- | ---- | ---------- | +| width | 整型 | 显示屏的宽 | +| hight | 整型 | 显示屏的高 | + +* 返回值: + + 返回一个lcd对象。 + +* 示例: + +```python +from usr import st7789v +lcd_st7789v = st7789v.ST7789V(240, 240) +``` + + + +#### 显示单个字符 + +> **lcd_st7789v.lcd_show_char(x, y, xsize, ysize, ch_buf, fc, bc)** + +* 功能: + + 单个字符显示,可显示汉字和ASCII字符。 + +* 参数: + +| 参数 | 类型 | 说明 | +| ------ | ------------ | ----------------------------- | +| x | 整型 | x轴起点坐标 | +| y | 整型 | y轴起点坐标 | +| xsize | 整型 | 待显示字符的宽 | +| ysize | 整型 | 待显示字符的高 | +| ch_buf | 元组或列表 | 存放待显示字符的字模数据 | +| fc | 16位十六进制 | 字体颜色,如 0x0000 表示黑色 | +| bc | 16位十六进制 | 背景颜色,如 0xFFFF 表示白色 | + +* 返回值: + + 无 + + + +#### 单个ASCII字符显示 + +> **lcd_st7789v.lcd_show_ascii(x, y, xsize, ysize, ch, fc, bc)** + +* 功能: + + ASCII字符显示,目前支持8x16、16x24的字体大小,如果需要其他字体大小需要自己增加对应大小的字库数据,并在该函数中增加这个对应字库的字典。 + +* 参数: + +| 参数 | 类型 | 说明 | +| ----- | ------------ | ----------------------------- | +| x | 整型 | x轴起点坐标 | +| y | 整型 | y轴起点坐标 | +| xsize | 整型 | 待显示字符的宽 | +| ysize | 整型 | 待显示字符的高 | +| ch | 字符 | 待显示的ASCII字符 | +| fc | 16位十六进制 | 字体颜色,如 0x0000 表示黑色 | +| bc | 16位十六进制 | 背景颜色,如 0xFFFF 表示白色 | + +* 返回值: + + 无 + + + +#### ASCII字符串显示 + +> **lcd_st7789v.lcd_show_ascii_str(x, y, xsize, ysize, str, fc, bc)** + +* 功能: + + ASCII字符串显示,显示顺序,以设置的起始坐标开始自左向右显示。示例中只提供了8x16大小的ascii字符,如果用户需要其他大小的字符,需要自己重新制作字库,并在` lcd_st7789v.lcd_show_ascii(x, y, xsize, ysize, ch, fc, bc)` 接口中增加对新增字库的支持。 + + 注意,要确定传入的字符串能够在当前行显示完,即传入字符串总长度乘以单个字符宽度的值 ,加上起始坐标x的值不能超过屏宽,否则程序会直接报错,提示超过显示范围。 + +参数: + +| 参数 | 类型 | 说明 | +| ----- | ------------ | ----------------------------- | +| x | 整型 | x轴起点坐标 | +| y | 整型 | y轴起点坐标 | +| xsize | 整型 | 待显示字符的宽 | +| ysize | 整型 | 待显示字符的高 | +| str | 字符串 | 待显示的ASCII字符 | +| fc | 16位十六进制 | 字体颜色,如 0x0000 表示黑色 | +| bc | 16位十六进制 | 背景颜色,如 0xFFFF 表示白色 | + +* 返回值: + + 无。 + + + +#### 单个汉字显示 + +> **lcd_st7789v.lcd_show_chinese(x, y, xsize, ysize, ch, fc, bc)** + +* 功能: + + 汉字显示,目前支持示例中几个汉字的16x16、16x24、24x24的字体大小,如果需要显示其他汉字以及其他字体大小需要自己增加对应大小的字库数据,并在该函数中增加这个对应字库的字典。 + +* 参数: + +| 参数 | 类型 | 说明 | +| ----- | ------------ | ----------------------------- | +| x | 整型 | x轴起点坐标 | +| y | 整型 | y轴起点坐标 | +| xsize | 整型 | 待显示字符的宽 | +| ysize | 整型 | 待显示字符的高 | +| ch | 字符 | 待显示的汉字 | +| fc | 16位十六进制 | 字体颜色,如 0x0000 表示黑色 | +| bc | 16位十六进制 | 背景颜色,如 0xFFFF 表示白色 | + +* 返回值: + + 无 + + + +#### 汉字字符串显示 + +> **lcd_st7789v.lcd_show_chinese_str(x, y, xsize, ysize, str, fc, bc)** + +* 功能: + + 汉字字符串显示,显示顺序,以设置的起始坐标开始自左向右显示。示例中只提供了用到的几个汉字的16x16大小的字库,如果用户需要其他大小的字符,需要自己重新制作字库,并在 `lcd_st7789v.lcd_show_chinese(x, y, xsize, ysize, str, fc, bc)` 接口中增加对新增字库的支持。 + + 注意,要确定传入的字符串能够在当前行显示完,即传入汉字个数乘以单个汉字宽度的值 ,加上起始坐标x的值不能超过屏宽,否则程序会直接报错,提示超过显示范围。 + +* 参数: + +| 参数 | 类型 | 说明 | +| ----- | ------------ | ----------------------------------- | +| x | 整型 | x轴起点坐标 | +| y | 整型 | y轴起点坐标 | +| xsize | 整型 | 待显示字符的宽 | +| ysize | 整型 | 待显示字符的高 | +| str | 字符串 | 待显示的汉字字符串,比如 '移远通信' | +| fc | 16位十六进制 | 字体颜色,如 0x0000 表示黑色 | +| bc | 16位十六进制 | 背景颜色,如 0xFFFF 表示白色 | + +* 返回值: + + 无。 + + + +#### 显示小尺寸图片 + +> **lcd_st7789v.lcd_show_image(image_data, x, y, width, heigth)** + +* 功能: + + 显示图片,该方法适合显示尺寸较小的图片,如果图片分辨率(宽高)小于80x80,可直接用该方法一次性将图片数据写入显示。 + +* 参数: + +| 参数 | 类型 | 说明 | +| ---------- | ---------- | ----------------------- | +| image_data | 元组或列表 | 存放待显示图片的RGB数据 | +| x | 整型 | x轴起点坐标 | +| y | 整型 | y轴起点坐标 | +| width | 整型 | 待显示图片的宽度 | +| heigth | 字符 | 待显示图片的高度 | + +* 返回值: + + 无 + + + +#### 显示大尺寸图片 + +> **lcd_st7789v.lcd_show_image_file(path, x, y, width, heigth, h)** + +* 功能: + + 显示图片,该方法适合显示尺寸较大的图片,如果图片分辨率(宽高)大于80x80,需要使用该方法来显示。该方法从文件中读取图片数据分段写入。分段写入原理如下: + + 假如要显示图片的分辨率(宽高)为 width*heigth,将待显示的图片分成若干宽高为 width * h 大小的图片,最后一块高度不足h的按实际高度计算,h为分割后每个图片的高度,可由用户通过参数 h 指定,h的取值应该满足关系: `width * h * 2 < 4096` + +参数: + +| 参数 | 类型 | 说明 | +| ------ | ------ | --------------------------------------------------------- | +| path | string | 存放图片数据的txt文件路径,包含文件名,如 'usr/image.txt' | +| x | int | x轴显示起点 | +| y | int | y轴显示起点 | +| width | int | 图片宽度 | +| heigth | int | 图片高度 | +| h | int | 分割后每个图片的高度 | + +* 返回值: + + 无 + +示例: + +假如要显示一张240x240的图片,图片如下: + +![media_lcd_3](media/media_lcd_3.jpg) + +(1)使用Image2Lcd 软件获取图片色彩数据 + +![media_lcd_4](media/media_lcd_4.jpg) + +(2)得到数据如下图,将该 .c 文件中头部和尾部多余部分都删除,只保留中间的数据部分,确保处理后的数据第一行就是数据,且最后没有多余行,每一行前面没有空格等多余字符 + +![media_lcd_5](media/media_lcd_5.jpg) + +(3)将处理后的图片数据文件保存为txt格式文件,假设命名为image.txt + +(4)将image.txt文件上传到开发板模块中【注意,此时没有image.py文件,不需要 from usr import image】 + +(5)在主程序 example_display_image.py 中,使用如下代码来显示该图片 + +```python +# -*- coding: UTF-8 -*- + + +import utime +''' +如果用户使用的固件版本中没有checkNet库,请将checkNet.mpy文件上传到模块的usr目录, +并将 import checkNet 改为 from usr import checkNet +''' +import checkNet +from usr import st7789v +# from usr import image + +''' +下面两个全局变量是必须有的,用户可以根据自己的实际项目修改下面两个全局变量的值, +在执行用户代码前,会先打印这两个变量的值。 +''' +PROJECT_NAME = "QuecPython_ST7789V_LCD_Example" +PROJECT_VERSION = "1.0.0" + +checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION) +lcd_st7789v = st7789v.ST7789V(240, 240) + + +if __name__ == '__main__': + ''' + 手动运行本例程时,可以去掉该延时,如果将例程文件名改为main.py,希望开机自动运行时,需要加上该延时, + 否则无法从CDC口看到下面的 poweron_print_once() 中打印的信息 + ''' + # utime.sleep(5) + checknet.poweron_print_once() + + ''' + 如果用户程序包含网络相关代码,必须执行 wait_network_connected() 等待网络就绪(拨号成功); + 如果是网络无关代码,可以屏蔽 wait_network_connected() + ''' + # checknet.wait_network_connected() + + # 用户代码 + '''######################【User code star】#####################################''' + + # 显示一张240*240大小的图片 + lcd_st7789v.lcd_show_image_file("usr/image.txt", 0, 0, 240, 240, 8) + + '''######################【User code end 】#####################################''' + +``` + +显示结果: + + +![media_lcd_6](media/media_lcd_6.jpg) + + + +### 实验操作 + +在实验例程的目录下,找到【显示图片】目录,进入该目录下,有如下几个源码文件: + +| 序号 | 文件 | 描述 | 备份 | +| ---- | ------------------ | ------------------------------------------------------------ | ---- | +| 1 | st7789v.py | 包含驱动IC为ST7789V的液晶屏驱动程序以及显示字符与图片等接口。 | | +| 2 | fonts.py | 示例程序中用到的字库。 | | +| 3 | image.py | 示例程序中用到的小图片显示数据 | | +| 4 | example_display.py | 显示主程序,调用其它几个文件中的方法与数据。 | | + +##### 实验步骤 + +(1)将240*240的显示屏正确接到模块上; +(2)将本目录的4个py文件(st7789v.py、image.py、fonts.py、example_display.py)拷贝到模块的usr目录下; +(3)进入模块的命令行,执行如下指令即可看到显示屏显示图片: + +``` +import example +example.exec('usr/example_display_image.py') +``` + +##### 实验结果 + +![media_lcd_7](media/media_lcd_7.jpg) + + + +## 字符和图片取模工具使用 + +### 工具简介 + +(1)Image2Lcd + +Image2Lcd 软件用于图片取模,可以提取单色和彩色图片。 + +(2)PCtoLCD2002 + +PCtoLCD2002 是一款字符取模软件,可以生成汉字、英文以及标点符号的字模数据。 + + + +### 如何对图片取模 + +(1)打开 Image2Lcd 软件,点击【打开】按钮,选择要显示的图片; + +![media_lcd_8](media/media_lcd_8.png) + +(2)输出数据类型选择【C语言数组(*.c)】,扫描方式选择【水平扫描】,输出灰度一定要选择【16位真彩色】; + +(3)设置图片的最大宽度和高度,实际输出大小以上图中最下方的【输出图像:(xx, yy)】部分显示为准; + +(4)点击【保存】按钮,得到图片的取模数据,将其放到元组中保存即可。 + + + +### 如何对字符取模 + +(1)打开 PCtoLCD2002 软件,依次点击【模式】-【字符模式(W)】; + +(2)根据需要选择字体,设置字体大小等; + +![media_lcd_9](media/media_lcd_9.png) + +(3)点击齿轮图标,进入如下所示界面,选择 【阴码】、【逐行式】、【顺向】、【C51格式】,点击确定; + +![media_lcd_10](media/media_lcd_10.png) + +(4)输入要取模的字符后,点击【生成字模】,即可得到对应的字模数据,按照示例 fonts.py 文件中的格式,将字模数据保存到字典中。 + +![media_lcd_11](media/media_lcd_11.png) + + + +## 配套代码 + + 下载实验材料 \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonSub/code/LCD_file.rar b/docs/Advanced_development/zh/QuecPythonSub/code/LCD_file.rar new file mode 100644 index 0000000000000000000000000000000000000000..de02cb7575b4a7cd7ab5a03f36bff6f3ab3af6d7 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/code/LCD_file.rar differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/code/code_ebf_smd4805.py b/docs/Advanced_development/zh/QuecPythonSub/code/code_ebf_smd4805.py new file mode 100644 index 0000000000000000000000000000000000000000..ee9ac94fef04638b31b41e9a0017bf11a585210f --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/code/code_ebf_smd4805.py @@ -0,0 +1,148 @@ +''' +File: EBF_SMD4805.py +Project: others +File Created: Wednesday, 6th January 2021 2:16:52 pm +Author: chengzhu.zhou +----- +Last Modified: Wednesday, 6th January 2021 2:56:42 pm +Modified By: chengzhu.zhou +----- +Copyright 2021 - 2021 quectel +''' + +""" +参考资料 +1. API +https://python.quectel.com/wiki/#/zh-cn/api/?id=pwm +https://python.quectel.com/wiki/#/zh-cn/api/?id=pin +2. 模块资料 +https://item.taobao.com/item.htm?ft=t&id=543053172983 +步进电机驱动器 + 42步进电机 +2.1 模块开发资料 +https://ebf-products.readthedocs.io/zh_CN/latest/module/motor/ebf-msd4805.html +""" + +""" +引脚连接 +| 电机 | EC600开发板 | 对应的函数标号 | +| ---------- | ------------------ | ------- | +| ENA- (GPIO) | GPIO81 (引脚号16) | GPIO7 | +| DIR- (GPIO) | GPIO77 (引脚号15) | GPIO6 | +| PUL- (PWM) | GPIO2_1V8 (引脚号70) | PWM2 | +| ENA+ DIR+ PUL+ | 1V8(电源) | 无 | +""" + + + + +from misc import PWM +from machine import Pin +import utime as time +import urandom as random +import log +def delay_500us(): + for i in range(600): + pass + + +def delay_250us(): + for i in range(310): + pass + + +ENABLE_MOTOR = 0x1 +DISABLE_MOTOR = 0x0 + +DIR_CLOCKWISE = 0x1 +DIR_ANTI_CLOCKWISE = 0x0 + + +class ebf_smd4805(): + + dev_log = None + + # 步进电机的参数 + sm_para_step = None # 步进角度 + # 控制器的参数 + env_pin = None # 使能引脚 + dir_pin = None # 方向引脚 + pul_pwm = None # 脉冲输出引脚 + ctrl_divstep = None # 细分参数,具体请参考控制器手册 + + def init(self, step, divstep): + self.dev_log = log.getLogger("ebf_smd4805") + self.env_pin = Pin(Pin.GPIO7, Pin.OUT, Pin.PULL_DISABLE, 0) + self.dir_pin = Pin(Pin.GPIO6, Pin.OUT, Pin.PULL_DISABLE, 0) + # 配置电机的参数 + self.sm_para_step = step + # 配置控制器的参数 + self.ctrl_divstep = divstep + + def reset(self): + self.env_pin.write(DISABLE_MOTOR) + self.dir_pin.write(DIR_ANTI_CLOCKWISE) + if self.pul_pwm is not None: + self.pul_pwm.close() + + # 根据频率 初始化PWM + def outputpwm(self, HZ, duty_cycle): + # 将HZ 转化为 us 级别 + cycleTime = int(1000000/HZ) + highTime = int(cycleTime * duty_cycle) + return highTime, cycleTime + + # 根据速度,设置PWM的输出 + def enable_pwm(self, speed): + # 1. 首先根据步进电机的步进角度,计算旋转一圈需要多少个脉冲 + Count_pulse = int(360/self.sm_para_step) + self.dev_log.debug("sm motor step as {0}".format(Count_pulse)) + # 2. 根据控制器的细分参数,计算控制器控制步进电机旋转一圈,需要多少的脉冲 + Count_pulse = int(Count_pulse * self.ctrl_divstep) + # 3. 最后计算出1秒旋转speed圈,需要多少个脉冲 , 换句话说 就是频率 + Count_pulse = int(Count_pulse * speed) + # 4. 初始化PWM, 默认占空比%50 + highTime, cycleTime = self.outputpwm(Count_pulse, 0.1) + self.dev_log.debug( + """config frequency is {0}HZ,cycleTime {1}us, hightime {2}us""" + .format(Count_pulse, cycleTime, highTime)) + self.pul_pwm = PWM(PWM.PWM2, PWM.ABOVE_10US, + int(highTime), int(cycleTime)) + self.pul_pwm.open() + pass + + def disable_pwm(self): + self.pul_pwm.close() + pass + + # speed 为速度, 每秒多少圈 + # Duration 为持续时间, ms + # dir 表示方向 + def run(self, speed, Duration, dir=DIR_CLOCKWISE): + self.dir_pin.write(dir) + self.dev_log.info( + "Configure the motor to rotate {0} revolutions per second".format(speed)) + self.enable_pwm(speed) + self.env_pin.write(1) + # delay + for i in range(int(Duration * 4)): + delay_250us() + self.env_pin.write(0) + + self.reset() + pass + + +def test_ebf_smd4805(): + log.basicConfig(level=log.DEBUG) + # log.basicConfig(level=log.INFO) + ebf_smd4805_dev = ebf_smd4805() + ebf_smd4805_dev.init(step=1.8, divstep=2) + for i in range(2, 10): + ebf_smd4805_dev.run(i, Duration=1000, dir=DIR_CLOCKWISE) + print("test_ebf_smd4805 Function exit,!!!") + pass + + +if __name__ == "__main__": + # creat a thread Check key status + test_ebf_smd4805() diff --git a/docs/Advanced_development/zh/QuecPythonSub/code/code_i2c_aht10.py b/docs/Advanced_development/zh/QuecPythonSub/code/code_i2c_aht10.py new file mode 100644 index 0000000000000000000000000000000000000000..e706b11aaf1531f036b4eaa2091c898fa18b26fb --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/code/code_i2c_aht10.py @@ -0,0 +1,108 @@ +''' +File: i2c_aht10.py +Project: i2c +File Created: Monday, 28th December 2020 5:17:28 pm +Author: chengzhu.zhou +----- +Last Modified: Tuesday, 29th December 2020 9:01:35 pm +Modified By: chengzhu.zhou +----- +Copyright 2020 - 2020 quectel +''' + +import log +from machine import I2C +import utime as time +""" +1. calibration +2. Trigger measurement +3. read data +""" + +# API 手册 http://qpy.quectel.com/wiki/#/zh-cn/api/?id=i2c +# AHT10 说明书 +# https://server4.eca.ir/eshop/AHT10/Aosong_AHT10_en_draft_0c.pdf + + +class aht10class(): + i2c_log = None + i2c_dev = None + i2c_addre = None + + # Initialization command + AHT10_CALIBRATION_CMD = 0xE1 + # Trigger measurement + AHT10_START_MEASURMENT_CMD = 0xAC + # reset + AHT10_RESET_CMD = 0xBA + + def write_data(self, data): + self.i2c_dev.write(self.i2c_addre, + bytearray(0x00), 0, + bytearray(data), len(data)) + pass + + def read_data(self, length): + r_data = [0x00 for i in range(length)] + r_data = bytearray(r_data) + self.i2c_dev.read(self.i2c_addre, + bytearray(0x00), 0, + r_data, length, + 0) + return list(r_data) + + def aht10_init(self, addre=0x38, Alise="Ath10"): + self.i2c_log = log.getLogger(Alise) + self.i2c_dev = I2C(I2C.I2C1, I2C.STANDARD_MODE) # 返回i2c对象 + self.i2c_addre = addre + self.sensor_init() + pass + + def aht10_transformation_temperature(self, data): + r_data = data + # 根据数据手册的描述来转化温度 + humidity = (r_data[0] << 12) | ( + r_data[1] << 4) | ((r_data[2] & 0xF0) >> 4) + humidity = (humidity/(1 << 20)) * 100.0 + print("current humidity is {0}%".format(humidity)) + temperature = ((r_data[2] & 0xf) << 16) | ( + r_data[3] << 8) | r_data[4] + temperature = (temperature * 200.0 / (1 << 20)) - 50 + print("current temperature is {0}°C".format(temperature)) + + + def sensor_init(self): + # calibration + self.write_data([self.AHT10_CALIBRATION_CMD, 0x08, 0x00]) + time.sleep_ms(300) # at last 300ms + pass + + def ath10_reset(self): + self.write_data([self.AHT10_RESET_CMD]) + time.sleep_ms(20) # at last 20ms + + def Trigger_measurement(self): + # Trigger data conversion + self.write_data([self.AHT10_START_MEASURMENT_CMD, 0x33, 0x00]) + time.sleep_ms(200) # at last delay 75ms + # check has success + r_data = self.read_data(6) + # check bit7 + if (r_data[0] >> 7) != 0x0: + print("Conversion has error") + else: + self.aht10_transformation_temperature(r_data[1:6]) + + +def i2c_aht10_test(): + ath_dev = aht10class() + ath_dev.aht10_init() + + # 测试十次 + for i in range(10): + ath_dev.Trigger_measurement() + time.sleep(1) + + +if __name__ == "__main__": + i2c_aht10_test() diff --git a/docs/Advanced_development/zh/QuecPythonSub/code/code_i2c_lis2dh12.py b/docs/Advanced_development/zh/QuecPythonSub/code/code_i2c_lis2dh12.py new file mode 100644 index 0000000000000000000000000000000000000000..0d80c9fa86eb2aca92c888702fbd3e24760eb2ec --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/code/code_i2c_lis2dh12.py @@ -0,0 +1,165 @@ +import log +import utime +import _thread +from machine import I2C +from machine import Pin + +# 寄存器地址 +LIS2DH12_OUT_X_L = 0x28 +LIS2DH12_OUT_X_H = 0x29 +LIS2DH12_OUT_Y_L = 0x2A +LIS2DH12_OUT_Y_H = 0x2B +LIS2DH12_OUT_Z_L = 0x2C +LIS2DH12_OUT_Z_H = 0x2D +LIS2DH12_FIFO_CTRL_REG = 0x2E + +# 控制寄存器 +LIS2DH12_CTRL_REG1 = 0x20 +LIS2DH12_CTRL_REG2 = 0x21 +LIS2DH12_CTRL_REG3 = 0x22 +LIS2DH12_CTRL_REG4 = 0x23 +LIS2DH12_CTRL_REG5 = 0x24 +LIS2DH12_CTRL_REG6 = 0x25 +LIS2DH12_REFERENCE_REG = 0x26 +LIS2DH12_STATUS_REG = 0x27 + +# 状态寄存器 +LIS2DH12_STATUS_REG_AUX = 0x7 + +# 中断寄存器 +LIS2DH12_INT1_CFG = 0x30 +LIS2DH12_INT1_SRC = 0x31 +LIS2DH12_INT1_THS = 0x32 +LIS2DH12_INT1_DURATION = 0x33 + +# 身份寄存器 +LIS2DH12_WHO_AM_I = 0x0F + +# 单击有关的寄存器 +LIS2DH12_CLICK_CFG = 0x38 +LIS2DH12_CLICK_SRC = 0x39 +LIS2DH12_CLICK_THS = 0x3A +LIS2DH12_TIME_LIMIT = 0x3B +LIS2DH12_TIME_LATENCY = 0x3C + + +# 将其和外部的中断引脚绑定到一起。 +class lis2dh12(object): + i2c_dev = None + address = None + int_pin = None + dev_log = None + + def init(self, slave_address): + self.dev_log = log.getLogger("I2C") + self.address = slave_address + self.i2c_dev = I2C(I2C.I2C1, I2C.STANDARD_MODE) + self.int_pin = Pin(Pin.GPIO14, Pin.IN, Pin.PULL_PU, 0) # 中断引脚, 根据硬件连接不同而改变 + self.sensor_init() + self.single_tap_enable() # 配置单击检测 + self.start_sensor() + pass + + def read_data(self, regaddr, datalen, debug=True): + r_data = [0x00 for _ in range(datalen)] + r_data = bytearray(r_data) + reg_addres = bytearray([regaddr]) + self.i2c_dev.read(self.address, reg_addres, 1, r_data, datalen, 1) + ret_data = list(r_data) + if debug is True: + self.dev_log.debug(" read 0x{0:02x} from 0x{1:02x}".format(ret_data[0], regaddr)) + return ret_data + + def write_data(self, regaddr, data, debug=True): + w_data = bytearray([regaddr, data]) + # 临时将需要传送的地址放在数据位 + self.i2c_dev.write(self.address, bytearray(0x00), 0, bytearray(w_data), len(w_data)) + if debug is True: + self.dev_log.debug(" write 0x{0:02x} to 0x{1:02x}".format(data, regaddr)) + + def sensor_reset(self): + # 重置chip + self.write_data(LIS2DH12_CTRL_REG5, 0x80) + utime.sleep_ms(100) + r_data = self.read_data(LIS2DH12_WHO_AM_I, 1) + # 确定重启成功 + while r_data[0] != 0x33: + r_data = self.read_data(LIS2DH12_WHO_AM_I, 1) + utime.sleep_ms(5) + self.dev_log.debug("传感器重置成功") + pass + + def sensor_init(self): + self.sensor_reset() # 1. 重置设备 + # 2. 初始化传感器 + self.write_data(LIS2DH12_CTRL_REG2, 0x04) # 使能高分辨率 + self.write_data(LIS2DH12_CTRL_REG3, 0x80) # 将中断引到INT1 引脚上面, 默认高电平有效 + self.write_data(LIS2DH12_CTRL_REG4, 0x08) # ±2g, High-resolution mode + + def single_tap_enable(self): + self.write_data(LIS2DH12_CLICK_CFG, 0x15) # 使能 XYZ 三轴单击中断, + # self.write_data(LIS2DH12_CLICK_CFG, 0x10) # 使能 Z 轴单击中断, + self.write_data(LIS2DH12_CLICK_THS, 0x30) # 设置阈值 + self.write_data(LIS2DH12_TIME_LIMIT, 0x18) # 设置时间窗口限制 + self.write_data(LIS2DH12_TIME_LATENCY, 0x02) # 设置延时 + + def start_sensor(self): + self.write_data(LIS2DH12_CTRL_REG1, 0x77) # 设置ODR 400HZ ,enable XYZ. + # self.write_data(LIS2DH12_CTRL_REG1, 0x74) # 设置ODR ,enable Z轴. + utime.sleep_ms(20) # (7/ODR) = 18ms + + def read_xyz(self): + data = [] + for i in range(6): + r_data = self.read_data(LIS2DH12_OUT_X_L + i, 1) + data.append(r_data[0]) + return data + + def processing_data(self): + data = self.read_xyz() + self.dev_log.info("xL:{:0>3d},xH:{:0>3d},yL:{:0>3d},yH:{:0>3d},zL:{:0>3d},zH:{:0>3d}". + format(data[0], data[1], data[2], data[3], data[4], data[5])) + self.dev_log.info("X:{:0>3d} Y:{:0>3d} Z:{:0>3d}". + format((data[0] & data[1]), (data[2] & data[3]), (data[4] & data[5]))) + pass + + def exti_processing_data(self): + value = self.int_pin.read() + if value == 1: # 检测到中断信号了 + self.processing_data() + return 1 + else: + return 0 + + +# 参数说明 +# state: 是否使能中断读取. 1:使能; 0:不使能 +# delay: 延时时间(ms), 此参数在中断模式下无效 +# retryCount: 读取次数 +def is2dh12_thread(state, delay, retryCount): + # | 参数 | 参数类型 | 说明 | + # | -------- | ------- | ------------------ | + # | CRITICAL | 常量 | 日志记录级别的数值 50 | + # | ERROR | 常量 | 日志记录级别的数值 40 | + # | WARNING | 常量 | 日志记录级别的数值 30 | + # | INFO | 常量 | 日志记录级别的数值 20 | + # | DEBUG | 常量 | 日志记录级别的数值 10 | + # | NOTSET | 常量 | 日志记录级别的数值 0 | + log.basicConfig(level=log.INFO) # 设置日志输出级别 + dev = lis2dh12() + dev.init(0x19) + while True: + if state == 1: + if dev.exti_processing_data() == 1: + retryCount -= 1 + elif state == 0: + dev.processing_data() + utime.sleep_ms(delay) + retryCount -= 1 + if retryCount == 0: + break + print("检测结束退出") + + +if __name__ == "__main__": + _thread.start_new_thread(is2dh12_thread, (0, 1000, 10)) diff --git a/docs/Advanced_development/zh/QuecPythonSub/ebf_smd4805.md b/docs/Advanced_development/zh/QuecPythonSub/ebf_smd4805.md new file mode 100644 index 0000000000000000000000000000000000000000..9d434c1d4aca364265b283d4f4362573c62ebba9 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/ebf_smd4805.md @@ -0,0 +1,215 @@ +# 步进电机驱动实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ------- | -------- | +| 1.0 | 2021-09-24 | Grey.Tu | 初版 | + +本片文章主要描述使用 EC600x 来驱动步进电机控制器,从而驱动步进电机。 + + + +## 硬件说明 + +模块驱动步进电机需要步进电机控制器: + +#### 步进电机控制器 + +![media_ebf_smd4805_1](media/media_ebf_smd4805_1.jpg) + +#### 步进电机 + +![media_ebf_smd4805_2](media/media_ebf_smd4805_2.png) + +![media_ebf_smd4805_3](media/media_ebf_smd4805_3.jpg) + +步进电机有 42步进电机/ 57步进电机/ 86步进电机等之分,不同的步进电机适配不同的步进电机控制器。 + +### 实验设备 + +(1)直流电源,可以输 出 12V~48V 的直流电 + +(2)步进电机控制器 + +(3)步进电机 + +(4)连接线若干 + +### 驱动说明 + +步进电机驱动器只需要控制三个引脚,就可以驱动驱动器控制电机了。 + +(1)ENA使能控制引脚,使能驱动器驱动电机。根据驱动器型号不同电平有所不同。 + +(2)DIR方向控制引脚,确定顺时针或者是逆时针。根据驱动器型号不同电平有所不同。 + +(3)PUL步进脉冲引脚,给控制器脉冲。根据设置的细分有不同的脉冲数量步进一个步进角。细分设置为驱动器拨码开关设置。 + +### 引脚连接 + +(1)连接好 24V 电源,具体电压根据实际的步进电机驱动器规格确定。 + +| 驱动器引脚 | 电源引脚 | 说明 | 备份 | +| ---------- | -------- | -------- | ---- | +| V+ | 24V | 电源正极 | | +| V- | GND | 电源负极 | | + +(2)连接驱动器与步进电机,具体接线方式根据实际的步进电机驱动器与步进电机规格确定。 + +| 驱动器引脚 | 步进电机引脚 | 说明 | 备份 | +| ---------- | ------------ | ---- | ---- | +| A+ | A | A项+ | | +| A- | C | A项- | | +| B+ | B | B项+ | | +| B- | D | B项- | | + +(3)连接驱动器和 EC600x 开发板,,具体电压根据实际的步进电机驱动器规格确定。 + +步进电机驱动器可以采用共阳/共阴两种连接方式,我们这里采用共阳极的连接方式 + +![media_ebf_smd4805_4](media/media_ebf_smd4805_4.png) + +| 驱动器引脚 | EC600S 开发板引脚 | 说明 | 备份 | +| ---------- | ----------------- | ------------ | ---- | +| ENA+ | 1V8 | 共阳极 | | +| ENA- | GPIOx | 使能控制信号 | | +| DIR+ | 1V8 | 共阳极 | | +| DIR+ | GPIOx | 方向控制信号 | | +| PUL+ | 1V8 | 共阳极 | | +| PUL- | GPIOx / PWMx | 步进脉冲信号 | | + + + +## 软件设计 + +```python +# 引脚连接 +# | 电机引脚 | EC600开发板 | 对应的函数标号 | +# | ------------------- | --------------------- | ------------ | +# | ENA- (GPIO) | GPIO81 (引脚号16) | GPIO7 | +# | DIR- (GPIO) | GPIO77 (引脚号15) | GPIO6 | +# | PUL- (PWM) | GPIO2_1V8 (引脚号70) | PWM2 | +# | ENA+ DIR+ PUL+ | 1V8(电源) | 无 | + +from misc import PWM +from machine import Pin +import utime as time +import urandom as random +import log + + +def delay_500us(): + for i in range(600): + pass + + +def delay_250us(): + for i in range(310): + pass + + +ENABLE_MOTOR = 0x1 +DISABLE_MOTOR = 0x0 + +DIR_CLOCKWISE = 0x1 +DIR_ANTI_CLOCKWISE = 0x0 + + +class ebf_smd4805: + + dev_log = None + + # 步进电机的参数 + sm_para_step = None # 步进角度 + # 控制器的参数 + env_pin = None # 使能引脚 + dir_pin = None # 方向引脚 + pul_pwm = None # 脉冲输出引脚 + ctrl_divstep = None # 细分参数,具体请参考控制器手册 + + def init(self, step, divstep): + self.dev_log = log.getLogger("ebf_smd4805") + self.env_pin = Pin(Pin.GPIO7, Pin.OUT, Pin.PULL_DISABLE, 0) + self.dir_pin = Pin(Pin.GPIO6, Pin.OUT, Pin.PULL_DISABLE, 0) + # 配置电机的参数 + self.sm_para_step = step + # 配置控制器的参数 + self.ctrl_divstep = divstep + + def reset(self): + self.env_pin.write(DISABLE_MOTOR) + self.dir_pin.write(DIR_ANTI_CLOCKWISE) + if self.pul_pwm is not None: + self.pul_pwm.close() + + # 根据频率 初始化PWM + @staticmethod + def outputpwm(hz, duty_cycle): + # 将HZ 转化为 us 级别 + cycleTime = int(1000000 / hz) + highTime = int(cycleTime * duty_cycle) + return highTime, cycleTime + + # 根据速度,设置PWM的输出 + def enable_pwm(self, speed): + # 1. 首先根据步进电机的步进角度,计算旋转一圈需要多少个脉冲 + Count_pulse = int(360/self.sm_para_step) + self.dev_log.debug("sm motor step as {0}".format(Count_pulse)) + # 2. 根据控制器的细分参数,计算控制器控制步进电机旋转一圈,需要多少的脉冲 + Count_pulse = int(Count_pulse * self.ctrl_divstep) + # 3. 最后计算出1秒旋转speed圈,需要多少个脉冲 , 换句话说 就是频率 + Count_pulse = int(Count_pulse * speed) + # 4. 初始化PWM, 默认占空比%50 + highTime, cycleTime = self.outputpwm(Count_pulse, 0.5) + self.dev_log.debug( + """config frequency is {0}HZ,cycleTime {1}us, hightime {2}us""" + .format(Count_pulse, cycleTime, highTime)) + self.pul_pwm = PWM(PWM.PWM0, PWM.ABOVE_10US, + int(highTime), int(cycleTime)) + self.pul_pwm.open() + pass + + def disable_pwm(self): + self.pul_pwm.close() + pass + + # speed 为速度, 每秒多少圈 + # Duration 为持续时间, ms + # dir 表示方向 + def run(self, speed, duration, dir1=DIR_CLOCKWISE): + self.dir_pin.write(dir1) + self.dev_log.info( + "Configure the motor to rotate {0} revolutions per second".format(speed)) + self.enable_pwm(speed) + self.env_pin.write(1) + # delay + for i in range(int(duration * 4)): + delay_250us() + self.env_pin.write(0) + + self.reset() + pass + + +def test_ebf_smd4805(): + log.basicConfig(level=log.DEBUG) + # log.basicConfig(level=log.INFO) + ebf_smd4805_dev = ebf_smd4805() + ebf_smd4805_dev.init(step=1.8, divstep=2) + for i in range(2, 10): + ebf_smd4805_dev.run(i, duration=1000, dir1=DIR_CLOCKWISE) + print("test_ebf_smd4805 Function exit,!!!") + pass + + +if __name__ == "__main__": + test_ebf_smd4805() +``` + + + +## 配套代码 + + + 下载代码 \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonSub/i2c_aht.md b/docs/Advanced_development/zh/QuecPythonSub/i2c_aht.md new file mode 100644 index 0000000000000000000000000000000000000000..8229c9d39816c5553fd344aa3d0ca022cc595396 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/i2c_aht.md @@ -0,0 +1,135 @@ +# 内部温湿度传感器实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ------- | -------- | +| 1.0 | 2021-09-28 | Grey.Tu | 初版 | + +本片文章主要基于 EC600x 板载温湿度传感器AHT10,做一个温湿度检测的小实验。 + + + +## 硬件介绍 + +![media_i2c_aht_1](media/media_i2c_aht_1.png) + +AHT10是一款高精度,完全校准,贴片封装的温湿度传感器,MEMS的制作工艺,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个高性能CMOS微处理器相连接。该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。具体可以参考: [AHT10产品手册 A2 20201221.pdf](media\AHT10产品手册 A2 20201221.pdf) 。 + +AHT10 通过 I2C 接口通讯。按照说明书的简介。只需要按照下面的方式,发送数据就可以获取数据了。 + +1. 上电等待校准数据。 发送 0xE1 0x08 0x00 。 (只需要校准一次就可以) + +2. 触发测量,发送 0xAC, 0x33, 0x00 . 即可。 + +3. 读取数据, 等待70ms 转换。 读取6字节即可。 + +![media_i2c_aht_2](media/media_i2c_aht_2.png) + +查看原理图和数据手册 可以确定从机地址为 0x38。 + +由于是板载的模块,原理图参考上图原理图,不需要其他外部模块。 + +## 软件设计 + +1. 初始化AHT10 传感器 +2. 触发测量 +3. 延时70ms +4. 读取数据 +5. 转换温湿度 +6. 持续第2步 + +```python +import log +from machine import I2C +import utime as time + + +class aht10class: + i2c_log = None + i2c_dev = None + i2c_addre = None + + # Initialization command + AHT10_CALIBRATION_CMD = 0xE1 + # Trigger measurement + AHT10_START_MEASURMENT_CMD = 0xAC + # reset + AHT10_RESET_CMD = 0xBA + + def write_data(self, data): + self.i2c_dev.write(self.i2c_addre, + bytearray(0x00), 0, + bytearray(data), len(data)) + pass + + def read_data(self, length): + r_data = [0x00 for _ in range(length)] + r_data = bytearray(r_data) + self.i2c_dev.read(self.i2c_addre, + bytearray(0x00), 0, + r_data, length, + 0) + return list(r_data) + + def aht10_init(self, addre=0x38, alise="Ath10"): + self.i2c_log = log.getLogger(alise) + self.i2c_dev = I2C(I2C.I2C1, I2C.STANDARD_MODE) # 返回i2c对象 + self.i2c_addre = addre + self.sensor_init() + pass + + @staticmethod + def aht10_transformation_temperature(data): + r_data = data + # 根据数据手册的描述来转化温度 + humidity = (r_data[0] << 12) | ( + r_data[1] << 4) | ((r_data[2] & 0xF0) >> 4) + humidity = (humidity/(1 << 20)) * 100.0 + print("current humidity is {0}%".format(humidity)) + temperature = ((r_data[2] & 0xf) << 16) | ( + r_data[3] << 8) | r_data[4] + temperature = (temperature * 200.0 / (1 << 20)) - 50 + print("current temperature is {0}°C".format(temperature)) + + def sensor_init(self): + # calibration + self.write_data([self.AHT10_CALIBRATION_CMD, 0x08, 0x00]) + time.sleep_ms(300) # at last 300ms + pass + + def ath10_reset(self): + self.write_data([self.AHT10_RESET_CMD]) + time.sleep_ms(20) # at last 20ms + + def trigger_measurement(self): + # Trigger data conversion + self.write_data([self.AHT10_START_MEASURMENT_CMD, 0x33, 0x00]) + time.sleep_ms(200) # at last delay 75ms + # check has success + r_data = self.read_data(6) + # check bit7 + if (r_data[0] >> 7) != 0x0: + print("Conversion has error") + else: + self.aht10_transformation_temperature(r_data[1:6]) + + +def i2c_aht10_test(): + ath_dev = aht10class() + ath_dev.aht10_init() + + # 测试十次 + for i in range(10): + ath_dev.trigger_measurement() + time.sleep(1) + + +if __name__ == "__main__": + i2c_aht10_test() +``` + +## 配套代码 + + +下载代码 \ No newline at end of file diff --git a/docs/Advanced_development/zh/QuecPythonSub/i2c_lis2dh.md b/docs/Advanced_development/zh/QuecPythonSub/i2c_lis2dh.md new file mode 100644 index 0000000000000000000000000000000000000000..d298dfc5a4897dd1ca6801d3aa812cf478f711d4 --- /dev/null +++ b/docs/Advanced_development/zh/QuecPythonSub/i2c_lis2dh.md @@ -0,0 +1,264 @@ +# 加速度传感器实验 + +## 修订历史 + +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ------- | -------- | +| 1.0 | 2021-09-29 | Grey.Tu | 初版 | + +本片文章主要基于 EC600x_IIC接口介绍三轴加速度传感器LIS2DH12TR,做一个检测加速度的小实验。 + + + +## 硬件介绍 + +### LIS2DH12介绍 + +![media_i2c_lis2dh_1](media/media_i2c_lis2dh_1.png) + +LIS2DH12 是属于“nano”系列的超低功耗高性能 3 轴线性加速度计,具有数字 I2C、SPI串行接口标准输出。 器件具有超低功耗工作模式,可实现高级节能、智能、睡眠唤醒以及恢复睡眠功能。 LIS2DH12 具有 ±2g/±4g/±8g/±16g 的动态用户可选满量程,并能通过 1 Hz 到 5 kHz 的输出数据速率测量加速度。器件可配置为通过独立的惯性唤醒 / 自由落体事件以及通过器件自身的位置生成中断信号。中断发生器的阈值 和时序可由终端用户动态设定。具体可以参考 [LIS2DH12.pdf](media\LIS2DH12.pdf) 。 + +### 硬件连接 + +引脚功能介绍: + +| 引脚号 | 引脚名 | 说明 | 备份 | +| ------ | --------------------- | ------------------------------------------------------------ | ---- | +| 1 | SCL
SPC | IIC/SPI时钟引脚。 | | +| 2 | CS | SPI使能引脚,控制芯片通信方式。
1:IIC通信;2:SPI通信。 | | +| 3 | SDO
SA0 | SPI模式下为数据输出引脚;
IIC模式为设备从地址选择引脚,1:0x19;0:0x18。 | | +| 4 | SDA
SDI
SDO | IIC模式下为数据引脚;
标准SPI模式下为数据输入引脚;
也可以作为SPI的数据输出引脚。 | | +| 5 | Res | 接地即可。 | | +| 6 | GND | 地 | | +| 7 | GND | 地 | | +| 8 | GND | 地 | | +| 9 | VDD | 电源 | | +| 10 | VDD_IO | IO参考电平引脚 | | +| 11 | INT2 | 中断引脚2 | | +| 12 | INT1 | 中断引脚1 | | + +本章我们采用 I2C 接口通讯。原理图如下。 + +![media_i2c_lis2dh_2](media/media_i2c_lis2dh_2.png) + +本次我们 D0/SA0 引脚高电平。 因此可以确认加速度传感器的从机地址为0x19。 + + + +## 软件设计 + +### LIS2SH12 单击中断使用步骤 + +LIS2DH12 支持的功能: + +1. 单双击检测 + +2. 自由落体检测 + +3. 倾斜角测量 + +4. 切换横屏/竖屏模式 + +我们使用其单击检测功能,出现单击事件,将其映射到INT1 引脚上面,其处理逻辑大致如下: + +![media_i2c_lis2dh_3](media/media_i2c_lis2dh_3.png) + +### LIS2SH12 初始化 + +1. 设置 CTRL_REG2 寄存器,开启高通滤波。 +2. 设置 CTRL_REG3 寄存器,将中断引到INT1 引脚上面。 +3. 设置 CTRL_REG4 寄存器,配置Full-scale selection + +### 配置单击中断 + +1. 配置 CLICK_CFG 寄存器,使能需要检测的感应轴,X,Y,Z +2. 配置 CLICK_THS 寄存器,设置阈值 +3. 配置 TIME_LIMIT 寄存器,设置窗口限制 +4. 配置 TIME_LATENCY 寄存器,设置延时 + +### LIS2SH12 使能传感器 + +1. 配置CTRL_REG1 寄存器,开始使能传感器。 + +### 实验设计 + +1. 使用LIS2DH12 传感器的 INT1 引脚产生中断。 +2. 轮询此引脚的状态,检测到上升沿以后, 表示中断产生,处理中断。 +3. 在中断函数里面读取三轴的状态。 + +### 实验代码 + +```python +import log +import utime +import _thread +from machine import I2C +from machine import Pin + +# 寄存器地址 +LIS2DH12_OUT_X_L = 0x28 +LIS2DH12_OUT_X_H = 0x29 +LIS2DH12_OUT_Y_L = 0x2A +LIS2DH12_OUT_Y_H = 0x2B +LIS2DH12_OUT_Z_L = 0x2C +LIS2DH12_OUT_Z_H = 0x2D +LIS2DH12_FIFO_CTRL_REG = 0x2E + +# 控制寄存器 +LIS2DH12_CTRL_REG1 = 0x20 +LIS2DH12_CTRL_REG2 = 0x21 +LIS2DH12_CTRL_REG3 = 0x22 +LIS2DH12_CTRL_REG4 = 0x23 +LIS2DH12_CTRL_REG5 = 0x24 +LIS2DH12_CTRL_REG6 = 0x25 +LIS2DH12_REFERENCE_REG = 0x26 +LIS2DH12_STATUS_REG = 0x27 + +# 状态寄存器 +LIS2DH12_STATUS_REG_AUX = 0x7 + +# 中断寄存器 +LIS2DH12_INT1_CFG = 0x30 +LIS2DH12_INT1_SRC = 0x31 +LIS2DH12_INT1_THS = 0x32 +LIS2DH12_INT1_DURATION = 0x33 + +# 身份寄存器 +LIS2DH12_WHO_AM_I = 0x0F + +# 单击有关的寄存器 +LIS2DH12_CLICK_CFG = 0x38 +LIS2DH12_CLICK_SRC = 0x39 +LIS2DH12_CLICK_THS = 0x3A +LIS2DH12_TIME_LIMIT = 0x3B +LIS2DH12_TIME_LATENCY = 0x3C + + +# 将其和外部的中断引脚绑定到一起。 +class lis2dh12(object): + i2c_dev = None + address = None + int_pin = None + dev_log = None + + def init(self, slave_address): + self.dev_log = log.getLogger("I2C") + self.address = slave_address + self.i2c_dev = I2C(I2C.I2C1, I2C.STANDARD_MODE) + self.int_pin = Pin(Pin.GPIO14, Pin.IN, Pin.PULL_PU, 0) # 中断引脚, 根据硬件连接不同而改变 + self.sensor_init() + self.single_tap_enable() # 配置单击检测 + self.start_sensor() + pass + + def read_data(self, regaddr, datalen, debug=True): + r_data = [0x00 for _ in range(datalen)] + r_data = bytearray(r_data) + reg_addres = bytearray([regaddr]) + self.i2c_dev.read(self.address, reg_addres, 1, r_data, datalen, 1) + ret_data = list(r_data) + if debug is True: + self.dev_log.debug(" read 0x{0:02x} from 0x{1:02x}".format(ret_data[0], regaddr)) + return ret_data + + def write_data(self, regaddr, data, debug=True): + w_data = bytearray([regaddr, data]) + # 临时将需要传送的地址放在数据位 + self.i2c_dev.write(self.address, bytearray(0x00), 0, bytearray(w_data), len(w_data)) + if debug is True: + self.dev_log.debug(" write 0x{0:02x} to 0x{1:02x}".format(data, regaddr)) + + def sensor_reset(self): + # 重置chip + self.write_data(LIS2DH12_CTRL_REG5, 0x80) + utime.sleep_ms(100) + r_data = self.read_data(LIS2DH12_WHO_AM_I, 1) + # 确定重启成功 + while r_data[0] != 0x33: + r_data = self.read_data(LIS2DH12_WHO_AM_I, 1) + utime.sleep_ms(5) + self.dev_log.debug("传感器重置成功") + pass + + def sensor_init(self): + self.sensor_reset() # 1. 重置设备 + # 2. 初始化传感器 + self.write_data(LIS2DH12_CTRL_REG2, 0x04) # 使能高分辨率 + self.write_data(LIS2DH12_CTRL_REG3, 0x80) # 将中断引到INT1 引脚上面, 默认高电平有效 + self.write_data(LIS2DH12_CTRL_REG4, 0x08) # ±2g, High-resolution mode + + def single_tap_enable(self): + self.write_data(LIS2DH12_CLICK_CFG, 0x15) # 使能 XYZ 三轴单击中断, + # self.write_data(LIS2DH12_CLICK_CFG, 0x10) # 使能 Z 轴单击中断, + self.write_data(LIS2DH12_CLICK_THS, 0x30) # 设置阈值 + self.write_data(LIS2DH12_TIME_LIMIT, 0x18) # 设置时间窗口限制 + self.write_data(LIS2DH12_TIME_LATENCY, 0x02) # 设置延时 + + def start_sensor(self): + self.write_data(LIS2DH12_CTRL_REG1, 0x77) # 设置ODR 400HZ ,enable XYZ. + # self.write_data(LIS2DH12_CTRL_REG1, 0x74) # 设置ODR ,enable Z轴. + utime.sleep_ms(20) # (7/ODR) = 18ms + + def read_xyz(self): + data = [] + for i in range(6): + r_data = self.read_data(LIS2DH12_OUT_X_L + i, 1) + data.append(r_data[0]) + return data + + def processing_data(self): + data = self.read_xyz() + self.dev_log.info("xL:{:0>3d},xH:{:0>3d},yL:{:0>3d},yH:{:0>3d},zL:{:0>3d},zH:{:0>3d}". + format(data[0], data[1], data[2], data[3], data[4], data[5])) + self.dev_log.info("X:{:0>3d} Y:{:0>3d} Z:{:0>3d}". + format((data[0] & data[1]), (data[2] & data[3]), (data[4] & data[5]))) + pass + + def exti_processing_data(self): + value = self.int_pin.read() + if value == 1: # 检测到中断信号了 + self.processing_data() + return 1 + else: + return 0 + + +# 参数说明 +# state: 是否使能中断读取. 1:使能; 0:不使能 +# delay: 延时时间(ms), 此参数在中断模式下无效 +# retryCount: 读取次数 +def is2dh12_thread(state, delay, retryCount): + # | 参数 | 参数类型 | 说明 | + # | -------- | ------- | ------------------ | + # | CRITICAL | 常量 | 日志记录级别的数值 50 | + # | ERROR | 常量 | 日志记录级别的数值 40 | + # | WARNING | 常量 | 日志记录级别的数值 30 | + # | INFO | 常量 | 日志记录级别的数值 20 | + # | DEBUG | 常量 | 日志记录级别的数值 10 | + # | NOTSET | 常量 | 日志记录级别的数值 0 | + log.basicConfig(level=log.INFO) # 设置日志输出级别 + dev = lis2dh12() + dev.init(0x19) + while True: + if state == 1: + if dev.exti_processing_data() == 1: + retryCount -= 1 + elif state == 0: + dev.processing_data() + utime.sleep_ms(delay) + retryCount -= 1 + if retryCount == 0: + break + print("检测结束退出") + + +if __name__ == "__main__": + _thread.start_new_thread(is2dh12_thread, (0, 1000, 10)) +``` + + + +## 配套代码 + + + 下载代码 \ No newline at end of file diff --git "a/docs/Advanced_development/zh/QuecPythonSub/media/AHT10\344\272\247\345\223\201\346\211\213\345\206\214 A2 20201221.pdf" "b/docs/Advanced_development/zh/QuecPythonSub/media/AHT10\344\272\247\345\223\201\346\211\213\345\206\214 A2 20201221.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..6a56e59302e3132c056b617edcd091666b26911f Binary files /dev/null and "b/docs/Advanced_development/zh/QuecPythonSub/media/AHT10\344\272\247\345\223\201\346\211\213\345\206\214 A2 20201221.pdf" differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/LIS2DH12.pdf b/docs/Advanced_development/zh/QuecPythonSub/media/LIS2DH12.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c73cda1a27497548faa7a61670e84df3025e4fd3 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/LIS2DH12.pdf differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_1.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..448e34941fce5f3a89174e42a3e97046c185294c Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_1.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_2.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_2.png new file mode 100644 index 0000000000000000000000000000000000000000..30ffefcca8809e47b705b17f6c5bc7e08acf43da Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_2.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_3.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d1b9b96a236ee53dbffc43848d4b390e667fb693 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_3.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_4.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_4.png new file mode 100644 index 0000000000000000000000000000000000000000..1d10a7f41db0bf594df84ca39930b7d815c389c7 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_ebf_smd4805_4.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_aht_1.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_aht_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c30d0412462ed18a0b01e53a16469760bf467fb8 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_aht_1.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_aht_2.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_aht_2.png new file mode 100644 index 0000000000000000000000000000000000000000..4078a7a3eabcf523aa62f652543b5fe50ee7fd83 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_aht_2.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_1.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_1.png new file mode 100644 index 0000000000000000000000000000000000000000..2ba09fb8acb59b10598b25c4e33b02b1a70cf931 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_1.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_2.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_2.png new file mode 100644 index 0000000000000000000000000000000000000000..08698e7d38e908646d19b28162fa72d9fb28bf31 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_2.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_3.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_3.png new file mode 100644 index 0000000000000000000000000000000000000000..28754c22552bf9e5dffdb9e9b92c9070111265ce Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_i2c_lis2dh_3.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_1.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aaacc0d62b6a4ee59852f099886f2c5974c735e0 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_1.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_10.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_10.png new file mode 100644 index 0000000000000000000000000000000000000000..ccf35bc2c93b6b6e256a9d3e4d5801ab44043500 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_10.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_11.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_11.png new file mode 100644 index 0000000000000000000000000000000000000000..97d81540415f1baed0db17cea9378f04585a3ed9 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_11.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_2.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ea54fd40a581c98c074d1a8f7816221158178f5b Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_2.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_3.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..17c8904a56629528a8aa8c0a6a195ac4e68af91b Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_3.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_4.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a1c4ad75deb812cc754f762eaf25c41180409a9e Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_4.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_5.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6029ab10718625015444319b8758350c7e5040fa Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_5.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_6.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6aceb1ee883ca30d25f4eaebd264505aafe7e354 Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_6.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_7.jpg b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a800d1f51f28d925647c253278a5ccaa3a4447e Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_7.jpg differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_8.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_8.png new file mode 100644 index 0000000000000000000000000000000000000000..e674bdaf038a89b3164e3ee2f5aa7c9749af33ac Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_8.png differ diff --git a/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_9.png b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_9.png new file mode 100644 index 0000000000000000000000000000000000000000..68cd167605cd6bc331ac9f921c5b3325d649f5fd Binary files /dev/null and b/docs/Advanced_development/zh/QuecPythonSub/media/media_lcd_9.png differ