今回は、サーボの制御に挑戦してみました。
使用するサーボは「SG-90」で、秋月電子やamazonなどで入手できます。
主な仕様は、
・トルク 1.8kgf/cm
・制御角 ±約90°
・制御パルス 0.5ms~2.4ms(Hレベル)、20ms(Lレベル)
・動作電圧 4.8V(~5.0V)
のようになっています。
回路図は下記のようになります。
今回はUSBaspからの電源VCC補給を外部電源5Vに切り替えています。
サーボの信号線は3本で、
制御信号(橙)、VCC(赤)、GND(茶)となっています。

制御信号は、PB1に接続しています。
制御パルスは0.5ms~2.4msと比較的短いので、10usでwaitループを作成し、レジスタr18(8bit)で制御パルスの長さを指定しています。
0.5ms=10us*レジスタr18(50)
2.4ms=10us*レジスタr18(240)
servo_pos: ;r17 * 10us
ldi r16, 0b00000010 ;PB1 high level outpit
out PORTB, r16
;
rcall wait_servo_pos
ldi r16, 0b00000000 ;PB1 low level outpit
out PORTB, r16
rcall wait20ms ;low level 20mS
ret
wait_servo_pos: push r18 ;r18 * 10us
wait_servo_loop:
rcall wait10us
dec r18
brne wait_servo_loop
pop r18
ret
制御パルスのlowレベル時間20msと、時間待ち2sは同様にwaitループで時間待ちしています。
wait2S:
push r17
ldi r17,100 ;2S
wait2sloop:
rcall wait20ms
dec r17
brne wait2sloop
pop r17
ret
wait20ms: ;20ms
push r17
ldi r17,20
wait20msloop:
rcall wait1ms
dec r17
brne wait20msloop
pop r17
ret
wait1ms: ;1ms
rcall wait500us
rcall wait500us
ret
wait500us: push r17 ;50us
ldi r17,50
wait500loop:
rcall wait10us
dec r17
brne wait500loop
pop r17
ret
wait10us: push r17 10us
ldi r17,23
wait10us_loop:
dec r17
brne wait10us_loop
pop r17
ret
下記のプログラムは、サーボを約0°→約90°→約180°→約90°→約0°にループするプログラムです。
;AT90S2313 servo SG90
;
;; AT90S2313 cpu
;; rom 0000h -- 03ffh
;; ram 0000h -- 00dfh
;; eeprom 0000h -- 007fh
;; External clock 8MHz
;;
;; Operating environment
;; Raspberry Pi OS raspbian
;; assemblers avra
;; install [(sudo) apt install avra]
;; file name 2313_servo.asm
;; $ asavr -l 2313_servo.lst 2313_servo.asm
;; $ (sudo) avrdude -v -p m88 -c usbasp -P usb -F -e -U flash:w:2313_servo.hex
;;
.include "/usr/share/avra/2313def.inc"
start: rjmp reset ;Reset
reti ;INT0
reti ;INT1
reti ;Timer/Counter1 CAPT1
reti ;Timer/Counter1 COMP1
reti ;Timer/Counter1 OVF1
reti ;Timer/Counter0 OVF0
reti ;UART RX
reti ;UART UDRE
reti ;UART TX
reti ;Analog Comparator ANA_COMP
reset:
ldi r16, RAMEND
out SPl, r16
ldi r16, 0b00000010 ;PB1 output setting
out DDRB, r16
loop:
ldi r18,50
rcall servo_pos
ldi r16, 0b00000000 ;PB1 low level outpit
out PORTB, r16
rcall wait2s
ldi r18,145
rcall servo_pos
ldi r16, 0b00000000 ;PB1 low level outpit
out PORTB, r16
rcall wait2s
ldi r18,240
rcall servo_pos
ldi r16, 0b00000000 ;PB1 low level outpit
out PORTB, r16
rcall wait2s
ldi r18,145
rcall servo_pos
ldi r16, 0b00000000 ;PB1 low level outpit
out PORTB, r16
rcall wait2s
rjmp loop
servo_pos: ;r17 * 10us
ldi r16, 0b00000010 ;PB1 high level outpit
out PORTB, r16
;
rcall wait_servo_pos
ldi r16, 0b00000000 ;PB1 low level outpit
out PORTB, r16
rcall wait20ms ;low level 20mS
ret
wait_servo_pos: push r18 ;r18 * 10us
wait_servo_loop:
rcall wait10us
dec r18
brne wait_servo_loop
pop r18
ret
wait2S:
push r17
ldi r17,100 ;2S
wait2sloop:
rcall wait20ms
dec r17
brne wait2sloop
pop r17
ret
wait20ms: ;20ms
push r17
ldi r17,20
wait20msloop:
rcall wait1ms
dec r17
brne wait20msloop
pop r17
ret
wait1ms: ;1ms
rcall wait500us
rcall wait500us
ret
wait500us: push r17 ;50us
ldi r17,50
wait500loop:
rcall wait10us
dec r17
brne wait500loop
pop r17
ret
wait10us: push r17 ;10us
ldi r17,23
wait10us_loop:
dec r17
brne wait10us_loop
pop r17
ret
今回からアセンブラは avraを使用しています。
インストール方法は、こちらの「AVRA(AVRアセンブラ)をインストールする。」を参照してください。
アセンブルします。
$ avra -l 2313_servo.lst 2313_servo.asm
AVRA: advanced AVR macro assembler Version 1.3.0 Build 1 (8 May 2010)
Copyright (C) 1998-2010. Check out README file for more info
AVRA is an open source assembler for Atmel AVR microcontroller family
It can be used as a replacement of 'AVRASM32.EXE' the original assembler
shipped with AVR Studio. We do not guarantee full compatibility for avra.
AVRA comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of avra under the terms
of the GNU General Public License.
For more information about these matters, see the files named COPYING.
Pass 1...
/usr/share/avra/2313def.inc(44) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(48) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(53) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(379) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(380) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(381) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(382) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(402) : PRAGMA directives currently ignored
Pass 2...
/usr/share/avra/2313def.inc(44) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(48) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(53) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(379) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(380) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(381) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(382) : PRAGMA directives currently ignored
/usr/share/avra/2313def.inc(402) : PRAGMA directives currently ignored
done
Used memory blocks:
Code : Start = 0x0000, End = 0x004E, Length = 0x004F
Assembly complete with no errors.
Segment usage:
Code : 79 words (158 bytes)
Data : 0 bytes
EEPROM : 0 bytes
書き込みします。
$ avrdude -v -p 2313 -c usbasp -P usb -F -e -U flash:w:2313_servo.hex
avrdude: Version 6.3-20171130
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/etc/avrdude.conf"
User configuration file is "/home/rika/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : usb
Using Programmer : usbasp
AVR Part : AT90S2313
Chip Erase delay : 20000 us
PAGEL : P00
BS2 : P00
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 4 12 64 0 no 128 0 0 4000 9000 0x80 0x7f
flash 4 12 128 0 no 2048 0 0 4000 9000 0x7f 0x7f
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
fuse 0 0 0 0 no 1 0 0 0 0 0x00 0x00
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
Programmer Type : usbasp
Description : USBasp, http://www.fischl.de/usbasp/
avrdude: auto set sck period (because given equals null)
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude: Device signature = 0x1e9101 (probably 2313)
avrdude: safemode: Fuse reading not support by programmer.
Safemode disabled.
avrdude: erasing chip
avrdude: auto set sck period (because given equals null)
avrdude: reading input file "2313_servo.hex"
avrdude: input file 2313_servo.hex auto detected as Intel Hex
avrdude: writing flash (158 bytes):
Writing | ################################################## | 100% 2.63s
avrdude: 158 bytes of flash written
avrdude: verifying flash memory against 2313_servo.hex:
avrdude: load data flash data from input file 2313_servo.hex:
avrdude: input file 2313_servo.hex auto detected as Intel Hex
avrdude: input file 2313_servo.hex contains 158 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.88s
avrdude: verifying ...
avrdude: 158 bytes of flash verified
avrdude: safemode: Sorry, reading back fuses was unreliable. I have given up and exited programming mode
avrdude done. Thank you.
正常に書き込みが終了すると、サーボは、0°→90°→180°→90°→0°と 2秒ごとに角度を変化させます。