MicroPython的午睡(136)M5Stack UIFlow2、DDSの出力周波数設定

Joseph Halfmoon

前回はM5StackにDDS、AD9837を接続し出力波形を選択可としました。しかし肝心の周波数については400Hz固定になってました。そこで今回は周波数設定UIを追加、1Hzから999Hzの正弦波、三角波、矩形波を生成できるようにいたしました。なりゆきで「UI」つくっているので無駄が多い感じ。なんとかしたいが。。。

※「MicroPython的午睡」投稿順 Indexはこちら

※M5Stack Grayに書き込んだUIFlow2.0 (Alpha-27)対応のMicroPython処理系とWindowsパソコン上で動作しているThonny 4.0.1で動作確認しています。

ハードウエアは前回と同じ

今回も前回作成の「アタッチメント」ボードを使ってます。M5Stackの側面に刺せばよいだけなので良い感じデス。念のため回路図を再掲載しておきます。AD9837_DUT_Schematic

MicroPythonスクリプトに周波数設定機能を追加

前回は起動後、正弦波、三角波、矩形波の選択をM5Stack表面のAボタンとBボタンで選択するだけで周波数は400Hz固定でした。今回は波形の選択後、3桁の十進数で周波数選択を行い、3桁決定すると波形を出力するようにいたしました。機能的にはAボタンとBボタンのみ使用です。

    1. 起動後、Aボタンで正弦波、三角波、矩形波を選択、4回目Aボタンを押すと正弦波に戻る。Bボタンを押すまでこの状態。
    2. 上記でBボタンを押すと波形が確定(LCDに表示される)し、周波数の100Hz桁の選択モードとなる。Aボタンを押すたびに数字がインクリメントされる9の後は0に戻る。Bボタンを押すと確定
    3. 上記後周波数の10Hzの桁、1Hzの桁を同様にAボタンとBボタンで設定。1Hzの桁設定後のBボタンで設定した周波数をLCDに表示し、波形出力を開始。

今回追加分を含むスクリプト全文が以下に。成り行きでUIを作り始めたので、なんだかな~な出来です。メンドイ、なんとかしたいが。

# AD9837UIfreq.py

import machine
import M5
from M5 import *
import time

mclkOutPin = 5
PWMfreq = 25000000
PWMduty = 512 #50%
CSpin= 2
SCK=machine.Pin(16)
MO=machine.Pin(17)
title0 = None
labelA = None
labelB = None
labelC = None
labelD = None
labelE = None
numSEL = 1
numMAX = 3
finFlag = False

def btnA_wasClicked(state):
    global numSEL, numMAX
    numSEL += 1
    if numSEL > numMAX:
        numSEL = 1

def btnB_wasClicked(state):
    global finFlag
    finFlag = True

def showTitle():
    global title0, labelA, labelB, labelC, labelD, labelE
    Widgets.fillScreen(0x222222)
    title0 = Widgets.Title("AD9837 DDS", 20, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24)
    labelA = Widgets.Label("Select Waveform", 20, 24, 1.0, 0x222222, 0xFFFFFF, Widgets.FONTS.DejaVu24)
    labelB = Widgets.Label("SINE     ", 20, 48, 1.0, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24)
    labelC = Widgets.Label("---", 20, 72, 1.0, 0x222222, 0xFFFFFF, Widgets.FONTS.DejaVu24)
    labelD = Widgets.Label("400", 20, 96, 1.0, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24)
    labelE = Widgets.Label("---", 20, 120, 1.0, 0x222222, 0xFFFFFF, Widgets.FONTS.DejaVu24)
    M5.update()

def selWave():
    global finFlag, numSEL, numMAX, labelB, labelC
    numMAX = 3
    while not finFlag:
        M5.update()
        if numSEL == 1:
            labelB.setText("SINE     ")
        elif numSEL == 2:
            labelB.setText("TRIANGLE ")
        else:
            labelB.setText("RECTANGLE")
        time.sleep_ms(100)
    if numSEL == 1:
        labelC.setText("SINE     ")
    elif numSEL == 2:
        labelC.setText("TRIANGLE ")
    else:
        labelC.setText("RECTANGLE")       
    finFlag = False
    return numSEL

def selFreq():
    global finFlag, numSEL, numMAX, labelD, labelE
    numSEL = 5
    numMAX = 10
    n100 = 4
    n10 = 0
    n1 = 0
    while not finFlag:
        M5.update()
        n100 = (numSEL-1)*100
        labelD.setText(str(n100))
    finFlag = False
    numSEL = 1
    while not finFlag:
        M5.update()
        n10 = (numSEL-1)*10
        labelD.setText(str(n100+n10))
    finFlag = False
    numSEL = 1
    while not finFlag:
        M5.update()
        n10 = numSEL-1
        labelD.setText(str(n100+n10+n1))
    finFlag = False
    labelE.setText(str(n100+n10+n1))
    return n100+n10+n1

def main():
    M5.begin()
    print("M5STACK, testAD9837.")
    showTitle()
    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btnA_wasClicked)
    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnB_wasClicked)
    selectResult = selWave()
    print("select: {0}".format(selectResult))
    if selectResult == 1:
        cword = 0x2000
    elif selectResult == 2:
        cword = 0x2002
    else:
        cword = 0x2028
    numFreq = selFreq()
    tempFreq = round(numFreq * 10.7374)
    numFreqL = 0x4000 | (tempFreq & 0x3FFF)
    numFreqH = 0x4000 | ((tempFreq >> 16) & 0x3FFF)
    print("F: {0} [Hz]".format(numFreq))
    print("0x{0:04x} 0x{1:04x}".format(numFreqL,numFreqH))

    cs = machine.Pin(CSpin, mode=machine.Pin.OUT, value=1) 
    mclkOut = machine.PWM(machine.Pin(mclkOutPin), freq=PWMfreq, duty=PWMduty)
    ad9837 = machine.SoftSPI(baudrate=100000, polarity=1, phase=0, bits=8, firstbit=machine.SPI.MSB, sck=SCK, mosi=MO, miso=machine.Pin(25))
    cs(0)
    ad9837.write((0x2100).to_bytes(2, 'big')) # RESET(Disable OUTPUT)
    ad9837.write(numFreqL.to_bytes(2, 'big')) # Set Freq Low
    ad9837.write(numFreqH.to_bytes(2, 'big')) # Set Freq High
    ad9837.write((0xC000).to_bytes(2, 'big')) # Set Phase
    ad9837.write((cword).to_bytes(2, 'big'))  # Enable OUTPUT
    cs(1)
   
    loopCounter = 0
    while True:
        loopCounter += 1
        print("LOOPCOUNTER: ", loopCounter)
        time.sleep(10)
            
if __name__ == "__main__":
    main()
実機動作確認

前回とは異なる「500Hz」の正弦波を出力設定した様子が以下に。Selet500HzSineWave

そのときの出力波形が以下に。500HzSineWave

周波数は変更できるようになったみたい。すると今度は振幅も変更したくなりますな。しかしその部分はDDSチップのお仕事ではない。ソフトウエアでゲイン設定可能なアンプを作らないと。。。またハードへ戻る?

MicroPython的午睡(135)M5Stack UIFlow2、DDSで波形出力 へ戻る

MicroPython的午睡(137)M5Stack UIFlow2、IO端子数を大幅拡張 へ進む