篇首语:本文由小编为大家整理,主要介绍了使用MM32 MicroPython产生双音频信号的局限性相关的知识,希望对你有一定的参考价值。
简 介: 利用ESP32的MicroPython PWM 模块可以产生很精确的输出频率,但是所有MicroPython的PWM都共享同一个Timer,所以他们的基频都相同。利用MM32 MicroPython可以使用其中两个硬件Timer, 但是输出的频率精度无法满足要求。因此: 要么使用其它的信号源来检测DTMF; 要么通过mem32来提高MM32的输出频率的精度;
关键词
: MM32,MicroPython,PWM,DTMF
§01 DTMF解码器
DTMF是由Bell实验室在上个世纪发明的用于电话拨号的方案,该方案可以在相同的电话心中通过双音频来传递电话号码编码。在DTMF的原理:为什么选择这些频率?测试了这些频率选择是为了能够最大化频率值及其谐波之间差异最大化。
本文测试一下对于带有谐波的双音频信号,也就是通过ESP8266产生的双音频产生的方波信号是否可以用于双音频信号。
1.1 ESP8266输出双音频
利用ESP8266的两个通道的 PWM 产生双音频,然后通过不同的方式进行叠加在一起,测试该信号是否可以利用DTMF硬件解码器进行正确的解码。
1.1.1 ESP32模块
在ESP32-S模块转接板设计与实现给出了ESP32硬件设计与接口。
▲ 图1.1.1 ESP32的接口说明
参考 MicroPython官网 给出了ESP32的编程参考资料。
1.1.2 产生两个PWM信号
利用ESP32转接模块的PIN17,18(从右边数第4,3管脚)输出PWM波形。
(1)代码和输出结果
from machine import Pin,PWMimport timeled1 = Pin(5, Pin.OUT)led2 = Pin(18, Pin.OUT)lowf = [697, 770, 852, 941]highf = [1209, 1336, 1477, 1633]pwm1 = PWM(Pin(15), freq=lowf[0], duty=0x1ff)pwm2 = PWM(Pin(2), freq=highf[0], duty=0x1ff)while True: led1.on() led2.off() time.sleep_ms(100) led2.on() led1.off() time.sleep_ms(100)
▲ 图1.1.2 输出的PWM波形
(2)存在问题
输出结果可以看到 Pin15,Pin2对应的PWM向相同的PWM Timer,可以看到它输出的PWM 的频率是随着最后一个PWM频率对应的数值。
在 MicroPython Machine.PWM 中给出了对于共享相同的Timer的PWM都具有相同的基频。那么问题来了:如何定义PWM使用不同的Timer?
在 Quick reference for ESP32 PWM 给出了在ESP32中最多能够有8个不同的PWM频率,这也说明可以在ESP32中设置不同的PWM的基频。
在 Using micropython on ESP32, how to have 2 PWM pins with different frequencies? 也有人提出了相同的问题。并给出了链接 **ports/esp32/machine_pwm: Add support for all PWM timers and modes. ** 中给出了ESP32 MicroPython的新的实现版本。
pwm3 = PWM(Pin(2), freq=440, timer=0, speed_mode=PWM.LOW_SPEED_MODE)pwm4 = PWM(Pin(15), freq=880, timer=1, speed_mode=PWM.LOW_SPEED_MODE)
但是经过测试,上面的函数在当前的ESP32模块的软件中不支持。
1.2 使用MM32模块
既然ESP32不支持多个TIMER,那么使用 MM32中的MicroPython 来进行实验。
1.2.1 下载MM32的MicroPython程序
最新的版本来自于灵动苏勇的MicroPython版本:
D:\\zhuoqing\\window\\ARM\\IAR\\MM32\\MicroPython
▲ 图1.2.1 利用MM32-LinkProgram下载程序
▲ 图1.2.2 下载MM32 MicroP越活娘
在 MM32F3277 MicroPython 实验板设计和软件测试 给出了实验电路板的电路图。
▲ 图1.2.3 MM32F3277 MicroPython 实验板
1.2.2 MM32支持两个PWM通道
下表给出了MM32中的两个PWM两个通道的PWM分别使用TIM3,TIM6的PWM,利用PWM0,PWM4,使用TIM3,TIM4测试。
【表1-1 MM32 PWM资源配置】
PWM | 定时器 | GPIO |
---|---|---|
PWM0 | TIM3 | PA6 |
PWM1 | TIM3 | PA7 |
PWM2 | TIM3 | PB0 |
PWM3 | TIM3 | PB1 |
PWM4 | TIM4 | PB6 |
PWM5 | TIM4 | PB7 |
PWM6 | TIM4 | PB8 |
PWM7 | TIM4 | PB9 |
(1)测试代码
from machine import Pin,PWMimport utimeled0 = Pin('PB2', mode=Pin.OUT_PUSHPULL)pwm0 = PWM(0, freq=500, duty=500)pwm1 = PWM(4, freq=501, duty=500)print("Test PWM.")while True: led0(1-led0()) utime.sleep_ms(100)
(2)测试结果
▲ 图1.2.4 在A6,B6输出500,501Hz的PWM波形
(3)存在问题
来自于苏勇的这个PWM版本,输出频率存在着误差。比如设置freq=490,但输出频率为:492.3Hz。
▲ 图1.2.5 在500-600Hz之间设置频率与输出频率的差异
from machine import Pin,mem32,PWMimport utimeled = Pin('PB2', Pin.OUT_PUSHPULL)f = 697pwm0 = PWM(0, freq=f, duty=500)pwm1 = PWM(4, freq=f, duty=500)from micropython import constAPB2PERIPH_BASE = const(0x40010000)UART1_BASE = const(APB2PERIPH_BASE + 0x3800)UART1_RDR = const(UART1_BASE + 1*4)UART1_CSR = const(UART1_BASE + 2*4)replbuf = bytes(0)def procREPL(f): global replbuf if mem32[UART1_CSR] & 0x2: replbuf += bytes([mem32[UART1_RDR]]) if replbuf[-1:] == b'\\r': f(replbuf[:-1]) replbuf = bytes(0)def f(s): global pwm0,pwm1 frq= int(s) print(frq) pwm0.deinit() pwm1.deinit() pwm0 = PWM(0, freq=frq, duty=500) pwm1 = PWM(4, freq=frq, duty=500)while True: procREPL(f)
▲ 图1.2.6 500 - 2000范围内的频率差异
1.3 DTMF 频率编码
下图给出了DTMF编码所使用的频率取值。
▲ 图1.2.3 DTMF频率编码
1.3.1 测量MM32 MicroPython频率
测量MM32 MicroPython PWM输出的方波频率。
[697, 770, 852, 941, 1209, 1336, 1477, 1633]
[-3.799987999999985, -4.270020000000045, -5.229979999999955, -0.270020000000045, -6.3000489999999445, -16.300048999999944, -23.200072999999975, -22.300048999999944]
1.3.2 存在问题
通过上面的测试,可以看到MM32 MicroPython PWM的频率不适合用于 产生双音频信号的测试。
※ 测试总结 ※
利用ESP32的MicroPython PWM 模块可以产生很精确的输出频率,但是所有MicroPython的PWM都共享同一个Timer,所以他们的基频都相同。利用MM32 MicroPython可以使用其中两个硬件Timer, 但是输出的频率精度无法满足要求。
因此:
- 要么使用其它的信号源来检测DTMF;
- 要么通过mem32来提高MM32的输出频率的精度;
■ 相关文献链接:
- DTMF的原理:为什么选择这些频率?
- ESP32-S模块转接板设计与实现
- MicroPython官网
- MicroPython Machine.PWM
- Quick reference for ESP32 PWM
- Using micropython on ESP32, how to have 2 PWM pins with different frequencies?
- ports/esp32/machine_pwm: Add support for all PWM timers and modes.
- MM32中的MicroPython
- MM32F3277 MicroPython 实验板设计和软件测试
● 相关图表链接:
- 图1.1.1 ESP32的接口说明
- 图1.1.2 输出的PWM波形
- 图1.2.1 利用MM32-LinkProgram下载程序
- 图1.2.2 下载MM32 MicroP越活娘
- 图1.2.3 MM32F3277 MicroPython 实验板
- 表1-1 MM32 PWM资源配置
- 图1.2.4 在A6,B6输出500,501Hz的PWM波形
- 图1.2.5 在500-600Hz之间设置频率与输出频率的差异
- 图1.2.6 500 - 2000范围内的频率差异
- 图1.2.3 DTMF频率编码
from machine import Pin,mem32,PWMimport utimeled = Pin('PB2', Pin.OUT_PUSHPULL)f = 697pwm0 = PWM(0, freq=f, duty=500)pwm1 = PWM(4, freq=f, duty=500)from micropython import constAPB2PERIPH_BASE = const(0x40010000)UART1_BASE = const(APB2PERIPH_BASE + 0x3800)UART1_RDR = const(UART1_BASE + 1*4)UART1_CSR = const(UART1_BASE + 2*4)REPLBUF_LENGTH = const(64)replbuf = [0]*REPLBUF_LENGTHreplpoint = 0def procREPL(f): global replbuf,replpoint if mem32[UART1_CSR] & 0x2: bc = mem32[UART1_RDR] if replpoint < REPLBUF_LENGTH-1: replbuf[replpoint] = bc replpoint += 1 if bc == 13: f(bytes(replbuf[0:replpoint-1])) replpoint = 0def f(s): global pwm0,pwm1 frq= int(s) print(frq) pwm0.deinit() pwm1.deinit() pwm0 = PWM(0, freq=frq, duty=500) pwm1 = PWM(4, freq=frq, duty=500)while True: procREPL(f)
#!/usr/local/bin/python 以上是关于使用MM32 MicroPython产生双音频信号的局限性的主要内容,如果未能解决你的问题,请参考以下文章