トピックス

Raspberry Pi と Raspberry Pi Pico

Raspberry PiはHDMIのモニタ出力とUSBやイーサネットのインターフェースを備えたARMコアの超小型シングルボード・コンピュータで、 DebianベースのRaspbianが標準で動くLinux PCとして登場しました。現在ではARMは64ビット・マルチコア化でパワーアップしつつ、 RaspbianはRaspberry Pi OSと名称が変わり、他にサポートするOSの種類も増えているようです。

私は5年程前にシングルコアのRaspberry Pi Model B+ とRaspberry Pi Zeroを購入して、Pythonのsmbusモジュールで主に複数のI2C制御のデバイスを制御に利用していました。

一方Raspberry Pi PicoはイーサネットやHDMIのモニタ出力は持たず、USBも開発ツールとのインターフェース用のみで、MicroPythonで動かせるマイクロコントローラという位置づけです。 MicroPythonの開発ツールはThonny Python IDEで、WindowsだけでなくRaspberry Pi上のRaspberry Pi OSでも動作します。私は今回手持ちのRaspberry Pi Zeroを使用しました。


ページトップ ▲

正弦波発生ロジックのmicroPythonへの移植

もともとハードウェア記述言語VHDLで作成したロジックを強引にMATLAB互換の数値演算プログラムOctaveでシミュレーションしたときのスクリプト Sine Wave(正弦波をつくる)/PWMからPDMへ/Octaveの .m ファイル を更に今回はRaspberry Pi Pico用のMicroPythonに移植し、とりあえずRaspberry Pi Picoを動かしてみました。そのようなわけで本来出力波形の精度を決定するインターバル・タイマも1msのスリープ命令という手抜きのため精度はイマイチなはずです。

from machine import Pin
import utime
#
gpio6 = Pin (6, Pin.OUT)
gpio7 = Pin (7, Pin.OUT)
gpio8 = Pin (8, Pin.OUT)
gpio9 = Pin (9, Pin.OUT)
gpio10 = Pin (10, Pin.OUT)
gpio11 = Pin (11, Pin.OUT)
gpio12 = Pin (12, Pin.OUT)
gpio13 = Pin (13, Pin.OUT)
#initial
st = 0
cnt9bit = [0,0,0,0,0,0,0,0,0,0]
cnt5ref = [0,0,0]
dbl5sin = [0,0,0]
dbl5cos = [0,0,0]
cnt5sin = [0,0,0,0,0]
cnt5cos = [0,0,0,0,0]
div9sin = [0,0,0,0]
div9cos = [0,0,0,0]
enb_sin = [0,0,0,0,0]
enb_cos = [0,0,0,0,0]
cnt9lst = [1,1]
enor_sin = 0
enor_cos = 0
load = 0
sin_p = 0
sin_n = 0
cos_p = 0
cos_n = 0
pwmsin = 0
pwmcos = 0
#
#increment 2-bit binary counter
def cntr2inc1(a):
    a[1] = a[1] ^ a[0]
    a[0] = 1 ^ a[0]
    return a
#increment 3-bit binary counter
def cntr3inc1(a):
    a[2] = a[2] ^ (a[1] & a[0])
    a[1] = a[1] ^ a[0]
    a[0] = 1 ^ a[0]
    return a
#increment 4-bit binary counter
def cntr4inc1(a):
    a[3] = a[3] ^ (a[2] & a[1] & a[0])
    a[2] = a[2] ^ (a[1] & a[0])
    a[1] = a[1] ^ a[0]
    a[0] = 1 ^ a[0]
    return a
#increment 5-bit binary counter
def cntr5inc1(a):
    a[4] = a[4] ^ (a[3] & a[2] & a[1] & a[0])
    a[3] = a[3] ^ (a[2] & a[1] & a[0])
    a[2] = a[2] ^ (a[1] & a[0])
    a[1] = a[1] ^ a[0]
    a[0] = 1 ^ a[0]
    return a
#increment two 5-bit binary counter
def cntr5inc2(a):
    a[4] = a[4] ^ (a[3] & a[2] & a[1])
    a[3] = a[3] ^ (a[2] & a[1])
    a[2] = a[2] ^ a[1]
    a[1] = 1 ^ a[1]
    return a
#increment 9-bit binary counter
def cntr9inc1(a):
    a[8] = a[8] ^ (a[7] & a[6] & a[5] & a[4] & a[3] & a[2] & a[1] & a[0])
    a[7] = a[7] ^ (a[6] & a[5] & a[4] & a[3] & a[2] & a[1] & a[0])
    a[6] = a[6] ^ (a[5] & a[4] & a[3] & a[2] & a[1] & a[0])
    a[5] = a[5] ^ (a[4] & a[3] & a[2] & a[1] & a[0])
    a[4] = a[4] ^ (a[3] & a[2] & a[1] & a[0])
    a[3] = a[3] ^ (a[2] & a[1] & a[0])
    a[2] = a[2] ^ (a[1] & a[0])
    a[1] = a[1] ^ a[0]
    a[0] = 1 ^ a[0]
    return a
#
xnor = lambda x, y: (x ^ y) ^ 1
#
#clock cycle loop
for k in range(512+2048):
    cos_p = xnor(cnt5ref[1], dbl5cos[1]) & (cnt5ref[2] ^ dbl5cos[2])
    cos_n = xnor(cnt5ref[1], dbl5cos[1]) & xnor(cnt5ref[2], dbl5cos[2])
    sin_p = xnor(cnt5ref[1], dbl5sin[1]) & (cnt5ref[2] ^ dbl5sin[2])
    sin_n = xnor(cnt5ref[1], dbl5sin[1]) & xnor(cnt5ref[2], dbl5sin[2])
#	led.value (sin_p)
#	utime.sleep(0.01) 
#clock state-0
    for st in range(4):
        if st == 0:
            enor_sin = xnor(cnt5ref[1], cnt5sin[3])
            enor_cos = xnor(cnt5ref[1], cnt5cos[3])
            cnt9bit = cntr9inc1(cnt9bit)
            if load == 1:
                div9sin = [0,0,0,0]
                div9cos = [0,0,0,0]
            else:
                if enor_cos == 1:
                    if div9sin == [0,0,0,1]:
                        enb_sin = cntr5inc2(enb_sin)
                        div9sin = [0,0,0,0]
                    else:
                        if div9sin[0] == 1:
                            enb_sin = cntr5inc2(enb_sin)
                        else:
                            enb_sin = cntr5inc1(enb_sin)
                        div9sin = cntr4inc1(div9sin)
                if enor_sin == 1:
                    if div9cos == [0,0,0,1]:
                        enb_cos = cntr5inc2(enb_cos)
                        div9cos = [0,0,0,0]
                    else:
                        if div9cos[0] == 1:
                            enb_cos = cntr5inc2(enb_cos)
                        else:
                            enb_cos = cntr5inc1(enb_cos)
                        div9cos = cntr4inc1(div9cos)
#clock state-1
        elif st == 1:
            dbl5cos = cntr3inc1(dbl5cos)
            dbl5sin = cntr3inc1(dbl5sin)
            cnt5ref = cntr3inc1(cnt5ref)
            load = (cnt9bit[7] ^ cnt9lst[0]) | (cnt9bit[8] ^ cnt9lst[1])
#clock state-2
        elif st == 2:
            if load == 1:
                cnt5sin = [0,0,0,cnt9bit[7] ^ 1, cnt9bit[8] ^ 1]
                cnt5cos = [0,0,0,cnt9bit[7], xnor(cnt9bit[7], cnt9bit[8])]
                if enb_sin == [1,0,0,1,0]:
                    enb_sin = [0,0,0,1,1]
                elif enb_sin == [0,1,0,1,0]:
                    enb_sin = [0,0,0,1,1]
                elif enb_sin == [1,1,0,1,0]:
                    enb_sin = [0,0,0,1,1]
                elif enb_sin == [0,0,1,1,0]:
                    enb_sin = [0,0,0,1,1]
                elif enb_sin == [1,0,1,1,0]:
                    enb_sin = [0,0,0,1,1]
                elif enb_sin == [0,1,1,1,0]:
                    enb_sin = [0,0,0,1,1]
                elif enb_sin == [1,1,1,1,0]:
                    enb_sin = [0,0,0,1,1]
                else:
                    enb_sin = [0,0,0,1,0]
                if enb_cos == [1,0,0,1,0]:
                    enb_cos = [0,0,0,1,1]
                elif enb_cos == [0,1,0,1,0]:
                    enb_cos = [0,0,0,1,1]
                elif enb_cos == [1,1,0,1,0]:
                    enb_cos = [0,0,0,1,1]
                elif enb_cos == [0,0,1,1,0]:
                    enb_cos = [0,0,0,1,1]
                elif enb_cos == [1,0,1,1,0]:
                    enb_cos = [0,0,0,1,1]
                elif enb_cos == [0,1,1,1,0]:
                    enb_cos = [0,0,0,1,1]
                elif enb_cos == [1,1,1,1,0]:
                    enb_cos = [0,0,0,1,1]
                else:
                    enb_cos = [0,0,0,1,0]
            else:
                if enb_sin[4] == 1:
                    enb_sin[4] = 0
                else:
                    cnt5sin = cntr5inc1(cnt5sin)
                if enb_cos[4] == 1:
                    enb_cos[4] = 0
                else:
                    cnt5cos = cntr5inc1(cnt5cos)
#clock state-3
        else:
            dbl5cos = [cnt5cos[2],cnt5cos[3],cnt5cos[4]]
            dbl5sin = [cnt5sin[2],cnt5sin[3],cnt5sin[4]]
            cnt5ref = [cnt9bit[2],cnt9bit[3],cnt9bit[4]]
            cnt9lst = [cnt9bit[7],cnt9bit[8]]
            
        if cos_p == 1:
            pwmcos = 1
        elif cos_n == 1:
            pwmcos = 0
        else:
            pwmcos = pwmcos ^ 1
            
        if sin_p == 1:
            pwmsin = 1
        elif sin_n ==1:
            pwmsin = 0
        else:
            pwmsin = pwmsin ^ 1
#
        gpio6.value (enor_cos)
        gpio7.value (enor_sin)
        gpio8.value (cos_p)
        gpio9.value (cos_n)
        gpio10.value (sin_p)
        gpio11.value (sin_n)
        gpio12.value (pwmcos)
        gpio13.value (pwmsin)
        utime.sleep(0.001)

ページトップ ▲

Scoppy

ScoppyはRaspberry Pi Picoのアナログ入力ピンを使用したオシロスコープのAndroidアプリです。Scoppyはまた8chのロジック・アナライザの機能も持っています。更にもう一個Raspberry Pi Picoを購入して Raspberry Pi Pico用のMicroPythonに移植した正弦波発生ロジックの出力波形をScoppyの8chのロジック・アナライザ機能で確認してみました。なお信号名を確認し易いようにMicroPythonによる出力のGPIOピンとScoppyの8chのロジック・アナライザのGPIO入力ピンを一致させています。

画像<Screenshot_Scoppy.jpg>
ページトップ ▲