使用MM32 MicroPython产生双音频信号的局限性

简 介: 利用ESP32的MicroPython PWM 模块可以产生很精确的输出频率,但是所有MicroPython的PWM都共享同一个Timer,所以他们的基频都相同。利用MM32 MicroPython可以使用其中两个硬件Timer, 但是输出的频率精度无法满足要求。因此: 要么使用其它的信号源来检测DTMF; 要么通过mem32来提高MM32的输出频率的精度;

关键词 MM32MicroPythonPWMDTMF

DTMF解码器 目 录
Contents
ESP8266输
出双音频
ESP32模块 产生两个PWM信号 使用MM32模块 下载MM32的
MicroPython程序
MM32支持两
个PWM通道
DTMF 频率编码 测量MM32
MicroPython频率
存在问题 测试总结

 

§01 DTMF解码器


  DTMF是由Bell实验室在上个世纪发明的用于电话拨号的方案,该方案可以在相同的电话心中通过双音频来传递电话号码编码。在DTMF的原理:为什么选择这些频率?测试了这些频率选择是为了能够最大化频率值及其谐波之间差异最大化。

  本文测试一下对于带有谐波的双音频信号,也就是通过ESP8266产生的双音频产生的方波信号是否可以用于双音频信号。

1.1 ESP8266输出双音频

  利用ESP8266的两个通道的 PWM 产生双音频,然后通过不同的方式进行叠加在一起,测试该信号是否可以利用DTMF硬件解码器进行正确的解码。

1.1.1 ESP32模块

  在ESP32-S模块转接板设计与实现给出了ESP32硬件设计与接口。

使用MM32 MicroPython产生双音频信号的局限性

▲ 图1.1.1 ESP32的接口说明

  参考 MicroPython官网 给出了ESP32的编程参考资料。

1.1.2 产生两个PWM信号

  利用ESP32转接模块的PIN17,18(从右边数第4,3管脚)输出PWM波形。

(1)代码和输出结果

from machine                import Pin,PWM
import time

led1 = 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)

使用MM32 MicroPython产生双音频信号的局限性

▲ 图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

使用MM32 MicroPython产生双音频信号的局限性

▲ 图1.2.1 利用MM32-LinkProgram下载程序

使用MM32 MicroPython产生双音频信号的局限性

▲ 图1.2.2 下载MM32 MicroP越活娘

  在 MM32F3277 MicroPython 实验板设计和软件测试 给出了实验电路板的电路图。
使用MM32 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,PWM
import utime

led0 = 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)测试结果

使用MM32 MicroPython产生双音频信号的局限性

▲ 图1.2.4 在A6,B6输出500,501Hz的PWM波形

(3)存在问题

  来自于苏勇的这个PWM版本,输出频率存在着误差。比如设置freq=490,但输出频率为:492.3Hz。

使用MM32 MicroPython产生双音频信号的局限性

▲ 图1.2.5 在500-600Hz之间设置频率与输出频率的差异

from machine                import Pin,mem32,PWM
import utime

led = Pin('PB2', Pin.OUT_PUSHPULL)
f = 697
pwm0 = PWM(0, freq=f, duty=500)
pwm1 = PWM(4, freq=f, duty=500)

from micropython            import const
APB2PERIPH_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)

使用MM32 MicroPython产生双音频信号的局限性

▲ 图1.2.6 500 - 2000范围内的频率差异

1.3 DTMF 频率编码

  下图给出了DTMF编码所使用的频率取值。

使用MM32 MicroPython产生双音频信号的局限性

▲ 图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的输出频率的精度;


■ 相关文献链接:

● 相关图表链接:

from machine                import Pin,mem32,PWM
import utime

led = Pin('PB2', Pin.OUT_PUSHPULL)
f = 697
pwm0 = PWM(0, freq=f, duty=500)
pwm1 = PWM(4, freq=f, duty=500)

from micropython            import const
APB2PERIPH_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_LENGTH
replpoint = 0
def 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 = 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)
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST3.PY                     -- by Dr. ZhuoQing 2022-02-05
#
# Note:
#============================================================

from headm import *                 # =

from tsmodule.tsstm32       import *

setf = range(500, 2000, 5)
outf = []

stm32cmd('SNDCD%d\r'%setf[0])
time.sleep(2)

for f in setf:
    stm32cmd('SNDCD%d\r'%f)
    printf(f)
    time.sleep(1)
    meter = meterval()
    outf.append(meter[0])
    tspsave('measure', setf=setf, outf=outf)

delf = [f1-f2 for f1,f2 in zip(setf, outf)]
plt.plot(setf, delf)

plt.xlabel("SetFrequency")
plt.ylabel("Delta Frequency")
plt.grid(True)
plt.tight_layout()
plt.show()



printf('\a')


#------------------------------------------------------------
#        END OF FILE : TEST3.PY
#============================================================
上一篇:启明云端分享:低功耗的 MCU 系统级芯片——ESP32-S3


下一篇:weblogic环境,应用上传图片报Could not initialize class sun.awt.X11.XToolkit