06-14-2023 03:36 AM
昨日からBing AIを使いだしたのでタイトルを考えてもらいました。
「MicroPythonによるラインセンサILX511の制御とLabVIEWによる分光データの表示」
ラインセンサの制御とADCのタイミングはほぼESP32 + Arduino IDEでのプログラミングと似たような感じでできました。MicroPythonではPWM出力のパルスのエッジで割り込みをかけることができなかったので、PWM出力を別のピンの入力にワイヤーで接続してそのピンの割り込みを使いました。一応動くようになりましたが、PCへのデータ出力が最大の難関で、2000個ぐらいのデータなのに1.5秒ぐらいかかっています。
ESP32 + Arduino IDEに対して優位性はありませんが、MicroPythonを使うときの備忘録としてアップします。
配線
ILX511の駆動はCLKが14ピン、ROGが27ピンとしました。Voutは28ピンのADCを使いました。CLK用のPWMは15ピンで生成しています。ADCの割り込みとして26ピンを使いました。15ピンのPWM信号を26ピンに結線しています。
下左のオシロスコープ画面はCLKがオレンジ、ROGが青です。下右のオシロスコープ画面はVoutがオレンジ、ROGが青です。
MicroPythonプログラムはRP2040のUSBメモリ状態のエリアにmain.pyとしてコピーすれば自動的に起動してくれます。
import utime
from machine import Pin, PWM, Timer, ADC
CLK_PIN = 14 #PWM 7A
TRIG_PWM_PIN = 15 #PWM 7B
TRIG_IRQ_PIN = 26 #INPUT Connected to TRIG_PWM_PIN
ROG_PIN = 27 #ROG
READ_VOUT_PIN = 28
CLK_PWM_FRQ = 10000
CLK_PWM_DUTY = int(65535*0.5)
TRIG_PWM_FREQ = CLK_PWM_FRQ
TRIG_PWM_DUTY = CLK_PWM_DUTY
ROG_WIDTH = 100 #100μsec
ROG_INTRVAL_MS = 1700 #500msec(reading:200msec, sending:1500msec)
pulse_CLK = Pin(CLK_PIN, Pin.OUT)
trig_irq = Pin(TRIG_IRQ_PIN, Pin.IN)
pulse_ROG = Pin(ROG_PIN, Pin.OUT)
PIXELS = 2086
data_count = 0
sensorValue = 0
rising_Edge=True
pixelArray = bytearray(PIXELS * 2)
HEADER = bytearray([0x00, 0x00, 0xFF, 0xFF])
def rising_CLK(pin):
global rising_Edge
rising_Edge = True
def read_vout(pin):
global sensorValue, sensorValue12it,pixelArray, data_count
sensorValue = ADC(READ_VOUT_PIN).read_u16()
sensorValue12it = sensorValue >> 4
pixelArray[data_count * 2] = (sensorValue12it >> 😎 & 0xFF
pixelArray[data_count * 2 + 1] = sensorValue12it & 0xFF
data_count += 1
def writeArrayData():
for i in range(4):
print('{:02X}'.format(HEADER[i]), end="")
for i in range(PIXELS):
print('{:02X}'.format(pixelArray[i*2]), end="")
print('{:02X}'.format(pixelArray[2*i+1]), end="")
trig_pwm = PWM(Pin(TRIG_PWM_PIN))
trig_pwm.freq(TRIG_PWM_FREQ)
trig_pwm.duty_u16(TRIG_PWM_DUTY)
while True:
start = utime.ticks_ms()
data_count = 0
pulse_CLK.low()
utime.sleep_us(50)
pulse_CLK.high()
utime.sleep_us(50)
pulse_ROG.high()
pulse_CLK.low()
utime.sleep_us(ROG_WIDTH)
pulse_ROG.low()
rising_Edge = False
trig_irq.irq(rising_CLK,Pin.IRQ_RISING)
while (rising_Edge == False):
pass
pulse_CLK.high()
trig_irq.irq(handler=None)
clk_pwm = PWM(Pin(CLK_PIN))
clk_pwm.freq(CLK_PWM_FRQ)
clk_pwm.duty_u16(CLK_PWM_DUTY)
trig_irq.irq(read_vout,Pin.IRQ_FALLING)
while (data_count < PIXELS):
pass
trig_irq.irq(handler=None)
pulse_CLK = Pin(CLK_PIN, Pin.OUT)
pulse_CLK.high()
writeArrayData()
while(utime.ticks_diff(utime.ticks_ms(), start) < ROG_INTRVAL_MS):
pass
RP2040 + MicroPythonの(私にとっての)最大のネックはprint()関数がバイトデータをそのまま送り出してくれず、UTF-8に変換して0x80から0xFFまでが2バイトで送られることです。この辺りの対処法がわかる方はぜひ教えてください。今回は0からFまで英数字で送っていますので1.7秒間隔ですが、対応策があれば1秒間隔ぐらいで動作すると思います。
それともう一つ驚いたのがADCの出力で、12ビットADCなのにrp2040用MicroPythonでは16ビットに拡大して出力しています。他のマイコンに合わせたということです。
MicroPythonプログラムとLabVIEWプログラムを添付します。動作確認はMac版のLabVIEW Community2022で行っています。