今回は、サーボの制御に挑戦してみました。

使用するサーボは「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秒ごとに角度を変化させます。

おすすめの記事