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

Joseph Halfmoon

前回生成した25MHzクロックを使って別シリーズにてDDS、AD9837を駆動、美麗な正弦波を得ることができました。ただブレッドボード接続だったので配線が汚いです。そこでM5Stackの側面のピンソケットに差し込める「アタッチメント」ボートを作製。チェック不十分にて大慌て。壊れずに動いて良かった。

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

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

AD9837

アナログ・デバイセズ製AD9837は、DDS(ダイレクト・デジタル・シンセサイザ)です。デジタル・シンセシスした正弦波、三角波、矩形波をDAコンバータを通してアナログ出力できるもの。波形、周波数、位相などはSPIマスタからの書き込みに応じて動作します。別件シリーズで正弦波出力の動作確認した記事が以下です。回路図なども以下に。

部品屋根性(113) AD9837、プログラマブル波形生成器、M5Stackで生成テスト

アタッチメントボード

ただね、上記別件シリーズでは通例のごとくブレッドボード上で被テスト回路をこさえたのでジャンパ線の接続が汚いです。そこでM5Stackの側面ピンソケットに差し込める「アタッチメント」形式のボートに設えました。こんな感じ。attachmentBoard

出来たところで、つい嬉しくなって、よく確かめもせずにM5Stackに接続し危うく虎の子のAD9837DIP化ボードを壊すところでした。まさかのショート。簡単なボードだからといって手を抜くなよ、自分。。。

上記は配線修正後です。まあ壊れもせず波形出力できているのでまあいいか。

今回作成のMicroPythonスクリプト

別件シリーズでは闇雲に正弦波を出力するだけだったので、こちらでは、波形や周波数をM5Stackの画面とボタンを使ってローカルに設定して動作させたいです。まあ、GUIというほどでないけれども老眼の目にも見える設定方法が良い。今回はボードを作るところで疲れてしまったので、とりあえず以下のようなところまで。

    1. 正弦波、三角波、矩形波の選択機能のみ実装
    2. Aボタンを押すと、正弦波、三角波、矩形波の選択が「回る」
    3. Bボタンで決定するとその波形が出力される
# AD9837UI.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
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
    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)
    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 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        

    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((0x50C7).to_bytes(2, 'big')) # Set Freq Low
    ad9837.write((0x4000).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()
実機動作確認

以下のようにAボタンを何回か押して、上から3行目の青のラインで波形を選択し、Bボタンを押すと上から4行目に選択結果が白のラインで表示され、出力がイネーブルとなります。M5Stack_AD9837board

波形を観察したものが以下に。まずは前回同様の設定の正弦波。SINE

つづいて三角波。Triangle

最後に矩形波。Rectangle

矩形波だけは「デジタル」なので振幅が異なります。

波形の選択はできた。でも周波数が400Hz固定のまま。当然、周波数設定のところも作るよね、自分。UI作るのメンドクセーなあ。

MicroPython的午睡(134)M5Stack UIFlow2、CLOCK出力 へ戻る

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