akira.kei が 2026年09月17日12時12分01秒 に編集
コメント無し
本文の変更
[<前の記事](https://elchika.com/article/88959a4c-929f-4e5d-b286-00db22a35b14/) : 次の記事>
## サーボ回す 前回の記事ではステッピングモータを回したが、今回は定番サーボ[SG90](https://akizukidenshi.com/catalog/g/g108761/)を回してみた。
## サーボを回す [前の記事](https://elchika.com/article/88959a4c-929f-4e5d-b286-00db22a35b14/)ではステッピングモータを回したが、今回は定番サーボ[SG90](https://akizukidenshi.com/catalog/g/g108761/)を回してみた。

@[youtube](https://youtu.be/OSyz0pu2CC8)
@[youtube](https://youtu.be/OSyz0pu2CC8) 最初は電源をrp2040-zeroからUSB経由で取っていたのだが、ボードが暴走して煙が出たw。サーボ電源はボードから取っちゃダメぜったい。PWMのピーク電圧は3.3V、サーボ電源は5Vでも問題なく動いたが(当たり前だけど)外部電源のGNDとボードのGNDは共通化しないとダメだ(繋がないと電源を入れただけでガチャガチャ動き出した!)。 ## スクリプトは単純 [データシート](https://akizukidenshi.com/goodsaffix/SG90_a.pdf)を参照するとパルスを送れば対応する角度まで動くみたいなことが書いてある。だが、そもそも配線の色はどう見ても「黄色、オレンジ、茶色」なんだが、データシートには「Orange, Red, Brown」とある。色覚異常か?  50Hz(20ms)のPWMでパルス幅が0.5msから2.4msなんだから2.5%から12%の狭い幅で制御されるらしい。角度分解能は頑張っても1度以上らしいし、速度の制御はやりにくい。ゆっくり回したい場合は位置指定をちょっとずつ送るような形になる。 PWMの1周期を0-65535とすると1638から7864までになる。これを順に送ってやればゆっくり回せる。 ```Python: from machine import Pin, PWM import time freq=50 dt=1/freq servo = PWM(Pin(0)) servo.freq(freq) min_u16=int((0.0005*freq)*65535) max_u16=int((0.0024*freq)*65535) skip=10 while True: for i in range(min_u16,max_u16-1,skip): servo.duty_u16(i) time.sleep(dt) for i in range(max_u16,min_u16-1,-skip): servo.duty_u16(i) time.sleep(dt) ``` ## 角度精度って悪そう 0°のパルス幅を0.5ms、180°を2.4msと定義しても実際にその角度にはならない。なるべく正確にするには補正というかキャリビュレーションを行う必要があるが、角度分解能はどうやっても1°程度になるらしいから、あまり頑張っても意味はないかもそれない。90°ずつビュっビュっと回すサンプルは以下のようになる。 しかしデューティを設定する関数が```duty_u16```と```duty_ns```の二つしかないのか。。。 ```Python: from machine import Pin, PWM import time servo = PWM(Pin(0)) servo.freq(50) def set_angle(angle): min_ns = 500_000 max_ns = 2_400_000 pulse_ns = int(min_ns + (angle / 180) * (max_ns - min_ns)) servo.duty_ns(pulse_ns) while True: set_angle(0) time.sleep(1) set_angle(90) time.sleep(1) set_angle(180) time.sleep(1) set_angle(90) time.sleep(1) ``` --- [<前の記事](https://elchika.com/article/88959a4c-929f-4e5d-b286-00db22a35b14/) : 次の記事>