トピックス
Raspberry Pi Pico
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>](Screenshot_Scoppy.jpg)