ソフトウェア処理の改善
前回(MicroPythonを使ってみる(その4)&エレキ素人が何か考える(その7):DAコンバーター)にて、ソフトウェア処理の限界をほのめかたしたところ、有識者からアドバイスされたコードがあり、その結果をここに記す。なお、ハードウェアとしては、継続してWio Terminalを用いている。
ソースコード
オリジナル(コードA)
import time
import math
from machine import DAC, Pin
freq = 100
num = 100
ary = list(range(num))
for i in range(num):
ary[i]=int(4095*(math.sin(2*math.pi*i/num)+1)/2)
dac = DAC(Pin(11))
while 1:
for i in range(num):
dac.write(ary[i])
time.sleep_us(int(1000000/(num*freq)))
アドバイスされたコード(コードB)
上記オリジナルコードの「while 1:」以下を下記コードで置き換える。
currentTicks = time.ticks_us()
while 1:
for i in range(num):
dac.write(ary[i])
lastTicks = currentTicks
currentTicks = time.ticks_us()
us = 1000000//(num*freq) - time.ticks_diff(currentTicks, lastTicks)
if us > 0:
time.sleep_us(us)
システム稼働時間(マイクロ秒)による調整である。
アドバイスされたコードの変形(コードC)
後述するが、切り捨て処理に差があったので、こちらも記載。
us = int(1000000/(num*freq)) - time.ticks_diff(currentTicks, lastTicks)
結果
設定値:freq=100Hz,num=100(分割数)
改善の効果が見られたと思う(簡易オシロスコープによる波形および典型的な周波数)。
コードB
コードC
ここでのまとめ+α
コード | A | B | C |
---|---|---|---|
計測値(Hz) | 62.9 | 113.4 | 108.9 |
コードBとコードCとで違いがあり(切り捨て処理)、下記コードで調査。
import time
freq = 100
num = 100
start = time.ticks_us()
us = int(1000000/(num*freq))
end = time.ticks_us()
print("int " + str(end-start) + " ticks")
start = time.ticks_us()
us = 1000000//(num*freq)
end = time.ticks_us()
print("// " + str(end-start) + " ticks")
>>> %Run -c $EDITOR_CONTENT
int 46 ticks
// 20 ticks
>>> %Run -c $EDITOR_CONTENT
int 46 ticks
// 21 ticks
>>> %Run -c $EDITOR_CONTENT
int 45 ticks
// 20 ticks
「int()」と「//」との切り捨て処理の処理時間に差があるようだ。
各種ケース
コードAとコードC(アドバイス改良版)の比較(num=100(分割数))
freq(設定値(Hz)) | 100 | 50 | 25 | 10 | 5 |
---|---|---|---|---|---|
コードA実測値(Hz) | 62.9 | 31.9 | 22.5 | 9.5 | 4.9 |
コードC計測値(Hz) | 108.9 | 68.2 | 38.9 | 18.1 | 9.0 |
コードAとコードC(アドバイス改良版)の比較(freq=100Hz)
num(分割数) | 100 | 50 | 25 |
---|---|---|---|
コードA実測値(Hz) | 62.9 | 77.7 | 87.8 |
コードC計測値(Hz) | 108.9 | 141.6 | 166.3 |
コードC:num=100(分割数)
freq(設定値(Hz)) | 25 | 50 | 75 | 100 | 150 | 200 |
---|---|---|---|---|---|---|
計測値(Hz) | 38.9 | 68.2 | 97.4 | 107.2 | 146.1 | 136.4 |
設定値200Hzの実測値不明(何度やってもこの周辺の値だった)。
コードC:num=200(分割数)
freq(設定値(Hz)) | 25 | 50 | 100 |
---|---|---|---|
計測値(Hz) | 36.2 | 52.3 | 68.4 |
コードC:num=400(分割数)
freq(設定値(Hz)) | 25 | 50 |
---|---|---|
計測値(Hz) | 28.2 | 33.78 |
コメント
素人+αには、よくわからないのが本音。ゴメンナサイ。なぜか、100us程度のSleepがあるケースでは改善があるように見える。
おまけ
ついでにDA処理の時間も計測。
import time
from machine import DAC, Pin
dac = DAC(Pin(11))
start = time.ticks_us()
dac.write(2048)
end = time.ticks_us()
print(str(end-start) + " ticks")
>>> %Run -c $EDITOR_CONTENT
10062 ticks
>>> %Run -c $EDITOR_CONTENT
21 ticks
>>> %Run -c $EDITOR_CONTENT
21 ticks
>>> %Run -c $EDITOR_CONTENT
21 ticks
>>>
1回目だけはものすごくかかる。その後は一定。
とりあえず、今回はEOF。