![]() |
|
George Vastianos |
---|
Dipl. from Electronics Department, Faculty of Technological Applications, Technological Educational Institute of Piraeus, Greece george.vastianos@ieee.org |
Table of contents
0. Abstract
1. Basic theory
1.1 The servo motors
1.2 How to use servo motors to walk!
1.3 The AT90S4414 microcontroller
2. Project's hardware
3. Project's software
4. References
0. Abstract
This article describes a servo motor controller that is able to control up to 16 hobby servo motors and its based on the AT90S4414 microcontroller (a member of Atmel's AVR Family). This servo controller is ideal in cases of building small robotic arms (3 to 5 axes) or small walker mobile robots (quadrapods or hexapods).
The servo controller receives position commands through a serial connection which can be provided by using one I/O pin of another microcontroller, or a PCs serial port! The communication protocol, that is used for this controller, is the same with the protocol of all the famous servo controllers of Scott Edwards Electronics Inc., this makes this new controller 100% compatible with all the programs that have been written for the "SSC" controllers...! However, if you want to write your own software, it is as easy as sending positioning data to the serial port as follows:
Byte1 = Sync (255)
Byte2 = Servo #(0-15)
Byte3 = Position (0-254)
So sending a 255,4,150 would move servo 4 to position 150, sending 255,12,35 would move servo 12 to position 35.
The standards of the serial communication should be the following: 9600 baud, 8 data bits, 1 stop bit and no parity.
1. Basic theory
1.1 Servo motors
Servo motors are geared dc motors with positional control feedback and are used for position control. The shaft of the motor can be positioned or rotated through 180 degrees. They are commonly used in the hobby R/C market for controlling model cars, airplanes, boats, and helicopters.
Because of their widespread use in the hobby market, servo motors are available in a number of stock sizes. While larger industrial servos are also available, they are priced out of range for most hobby applications. This article is restricted to the hobby servo motors that are inexpensive and readily available.
There are three leads to a servo. Two are for power, + 4 to 6 volts and ground. The third lead feeds a position control signal to the motor, and the control signal is a variable-width pulse. A neutral, midrange positional pulse is a 1.5-ms (millisecond) pulse, which is sent 50 times (20 ms) a second to the motor.
This pulse signal will cause the shaft to locate itself at the midway position +/-90 degrees. The shaft rotation on a servo motor is limited to approximately 180 degrees (+/-90 degrees from center position). A 1-ms pulse will rotate the shaft all the way to the left, while a 2-ms pulse will turn the shaft all the way to the right. By varying the pulse width between 1 and 2 ms, the servo motor shaft can be rotated to any degree position within its range.
1.2 How to use servo motors to walk!
In general, legged locomotion systems are quite complicated. There are however, a few simple variations. An insectlike leg can be constructed using only two model hobby servos, as shown in Figure 2.
To take a step, servo 1 first swings the leg outward, away from the body. This is designed to raise the leg over any obstruction. Next, servo 2 rotates the servo pair so as to move the leg forward. Servo 1 then rotates the leg downward until it makes contact with the ground. Finally, servo 2 rotates back, pushing the robot forward. A coordinated motion of six such legs allows the robot to move forward or backward or to turn.
1.3 The AT90S4414 microcontroller
The AT90S4414 is a low-power CMOS 8-bit microcontroller based on the AVR RISC architecture. By executing powerful instructions in a single clock cycle, the AT90S4414 achieves throughputs approaching 1 MIPS per MHz allowing the system designer to optimize power consumption versus processing speed.
The AVR core combines a rich instruction set with 32 general purpose working registers. All the 32 registers are directly connected to the Arithmetic Logic Unit (ALU), allowing two independent registers to be accessed in one single instruction executed in one clock cycle. The resulting architecture is more code efficient while achieving throughputs up to ten times faster than conventional CISC microcontrollers.
The AT90S4414 provides the following features: 4K bytes of In-System Programmable Flash, 256 bytes EEPROM, 256 bytes SRAM, 32 general purpose I/O lines, 32 general purpose working registers, flexible timer/counters with compare modes, internal and external interrupts, a programmable serial UART, programmable Watch-dog Timer with internal oscillator, an SPI serial port and two software selectable power saving modes. The Idle Mode stops the CPU while allowing the SRAM, timer/counters, SPI port and interrupt system to continue functioning. The power down mode saves the register contents but freezes the oscillator, disabling all other chip functions until the next external interrupt or hardware reset.
The device is manufactured using Atmel’s high density nonvolatile memory technology. The on-chip in-system programmable Flash allows the program memory to be reprogrammed in-system through an SPI serial interface or by a conventional nonvolatile memory programmer. By combining an enhanced RISC 8-bit CPU with In-System Programmable Flash on a monolithic chip, the Atmel AT90S4414/8515 is a powerful microcontroller that provides a highly flexible and cost effective solution to many embedded control applications.
The AT90S4414 AVR is supported with a full suite of program and system development tools including: C compilers, macro assemblers, program debugger/simulators, in-circuit emulators, and evaluation kits.
2. Project's hardware
The schematic circuit of the 16 channel serial servo controller is shown in figure 3:
As shown in the above figure, the power supply voltage inserts the circuit through the K1 connector and stabilized to 5VDC from the regulator IC1 and the C1, C2 capacitors.
The circuit is based on the microcontroller IC2 which is a member of Atmel's AVR RISC family. The microcontroller used, is the AT90S4414 and its main task is to receive position commands through the serial connection and produce the right pulses for each servo.
The quartz Y1 with the capacitors C3 and C4 make the microcontroller's oscillator circuit to work on 3,6864 MHz. With this frequency the internal UART of the microcontroller works with 0% bit error rate. The capacitor C5 is used as a decoupling capacitor to improve the stability of the circuit and the resistor R1 is used to set the microcontroller into RUN mode. The button S1 is used to reset the microcontroller (when this is needed).
The microcontroller is able to transmit and receive data (through an RS232 serial connection - K2 connector) via the IC3. The IC3 (MAX232) is an RS232 driver-receiver and adapts the logic signals from TTL compatible to RS232 compatible (driver) and from RS232 compatible to TTL compatible (receiver). The capacitors C6 to C10 used from MAX232 for voltage doubling. This is necessary for the driver section to produce a voltage of 10V (from the 5V supply) otherwise the driver cannot work properly.
All the PWM signals (for the servo driving) directed to the connector K3 and the unused I/O pins of the microcontroller directed to the K4 connector for future usage.
Notice:
You may noticed that some things in the above circuit may be useless, like the IC3 and the K4 connector. The usage of these parts depends from your application. If you use the microcontroller only to drive the servos (and not to work on other tasks also) then you don't need the K4 connector. Also if the position data come from another microcontroller, then you don't need the IC3 and the C6 to C10 capacitors, because the transferred signals will be only in TTL levels. In case that you use the IC3 and you don't want to send data back to the computer (via the RS232 connection) you may remove the C6 to C10 capacitors. So decide what do you want to do with this controller... and keep in mind that the microcontroller's software that presented below makes it to receive data from the RXD line and produce the PWM signals (for the servos). This means that if you want to use the microcontroller and for other tasks, you have to make modifications to its software.
3. Project's software
The microcontroller's software has been developed in Assembly (of Atmel's AVR Family) and its source code can be found in Listing 1.
Listing 1:
; ******************************************* ; ** ** ; ** 16 Channel Serial Servo Controller ** ; ** For Robotic Applications ** ; ** ** ; ** Microcontroller's Unit Software ** ; ** ** ; ** Copyright (c) March 2000 ** ; ** by George Vastianos ** ; ** ** ; ******************************************* ; ******************* ; * Microcontroller * ; * characteristics * ; ******************* ; MCU = AT90S4414 ; Fclk = 3.6864 MHz .include "4414def.inc" .cseg .org $0000 ; * Reset handler rjmp start .org $0009 ; * UART RX Complete handler rjmp uart_rxc .org $000d ; * Main program start ;****************************** ;* Interrupt Service Routines * ;****************************** .def sregb = r16 .def stemp = r17 uart_rxc: in sregb, SREG ; * Store status register rjmp rcvdchar ; * Start the task uart_rxcf: out SREG, sregb ; * Restore status register ldi stemp, $90 ; * Enable UART Receiver & RX Complete Interrupt out UCR, stemp reti ; * Return to main program ;************************** ;* UART Reception Routine * ;************************** .def rxchar = r18 rcvdchar: ; * Store the received character in rxchar, udr cpi rxchar, $ff ; * Check if character is sync byte brne rcvdchar1 ldi r30, $60 ; * If character is sync byte then ldi r31, $00 ; * set Z register in the begin of packet area (in int. SRAM) rjmp uart_rxcf rcvdchar1: ; * If character is not sync byte then st Z+, rxchar ; * increase Z and store in int. SRAM the character cpi r30, $62 ; * Check if packet finished brne rcvdchar2 ldi r30, $60 rjmp panalysis ; * If packet finished go to analyze it rcvdchar2: rjmp uart_rxcf ;******************************** ;* Data Packet Analysis Routine * ;******************************** .equ baddr = 0 ; * Base address = 0 (in case of use up to 16 servos) panalysis: lds stemp, $0060 ; * Check if the base address of packet is the same andi stemp, $F0 cpi stemp, baddr * 10 brne panalysis1 ; * If its not the same then ignore the packet lds stemp, $0060 ; * If its the same then update the servo position data andi stemp, $0F ldi r28, $80 ldi r29, $00 add r28, stemp lds stemp, $0061 st Y, stemp panalysis1: rjmp uart_rxcf ; * Analysis finished ;************************************* ;* End Of Interrupt Service Routines * ;************************************* ;**************** ;* Main Program * ;**************** start: ;************** ;* Initiation * ;************** .def temp = r19 init: ldi temp, $01 ; * Set Stack pointer to $015F of internal SRAM out SPH, temp ldi temp, $5F out SPL, temp ldi temp, $17 ; * Set UART on 9600 bps (for 115200 bps use $01) out UBRR, temp ldi temp, $90 ; * Enable UART Receiver & RX Complete Interrupt out UCR, temp ldi temp, $00 out WDTCR, temp ; * Watchdog Timer disable out ACSR, temp ; * Analog Comparator disable sts $0060, temp ; * Init pck byte 01 sts $0061, temp ; * Init pck byte 02 ldi temp, $fe sts $0080, temp ; * Init pos byte 01 sts $0081, temp ; * Init pos byte 02 sts $0082, temp ; * Init pos byte 03 sts $0083, temp ; * Init pos byte 04 sts $0084, temp ; * Init pos byte 05 sts $0085, temp ; * Init pos byte 06 sts $0086, temp ; * Init pos byte 07 sts $0087, temp ; * Init pos byte 08 sts $0088, temp ; * Init pos byte 09 sts $0089, temp ; * Init pos byte 10 sts $008A, temp ; * Init pos byte 11 sts $008B, temp ; * Init pos byte 12 sts $008C, temp ; * Init pos byte 13 sts $008D, temp ; * Init pos byte 14 sts $008E, temp ; * Init pos byte 15 sts $008F, temp ; * Init pos byte 16 ldi temp, $ff ; * Init all PWM outputs out ddra, temp out ddrc, temp ldi temp, $00 ; * Reset all PWM outputs out porta, temp out portc, temp sei ; * Global interrupt enable mainloop: ;************************ ;* PWM Control Routines * ;************************ .equ servo0 = PA0 ; * Set the output pin of Servo01 .equ servo1 = PA1 ; * Set the output pin of Servo02 .equ servo2 = PA2 ; * Set the output pin of Servo03 .equ servo3 = PA3 ; * Set the output pin of Servo04 .equ servo4 = PA4 ; * Set the output pin of Servo05 .equ servo5 = PA5 ; * Set the output pin of Servo06 .equ servo6 = PA6 ; * Set the output pin of Servo07 .equ servo7 = PA7 ; * Set the output pin of Servo08 .equ servo8 = PC7 ; * Set the output pin of Servo09 .equ servo9 = PC6 ; * Set the output pin of Servo10 .equ servoA = PC5 ; * Set the output pin of Servo11 .equ servoB = PC4 ; * Set the output pin of Servo12 .equ servoC = PC3 ; * Set the output pin of Servo13 .equ servoD = PC2 ; * Set the output pin of Servo14 .equ servoE = PC1 ; * Set the output pin of Servo15 .equ servoF = PC0 ; * Set the output pin of Servo16 .def tsoutA = r20 ; * Temp servoA output pin register .def tsoutB = r21 ; * Temp servoB output pin register .def tsposA = r22 ; * Temp servoA position register .def tsposB = r23 ; * Temp servoB position register pwmmark: ldi tsoutA, exp2(servo0) ; * Control Servo0 & Servo1 ldi tsoutB, exp2(servo1) lds tsposA, $0080 lds tsposB, $0081 rcall pwmA ldi tsoutA, exp2(servo2) ; * Control Servo2 & Servo3 ldi tsoutB, exp2(servo3) lds tsposA, $0082 lds tsposB, $0083 rcall pwmA ldi tsoutA, exp2(servo4) ; * Control Servo4 & Servo5 ldi tsoutB, exp2(servo5) lds tsposA, $0084 lds tsposB, $0085 rcall pwmA ldi tsoutA, exp2(servo6) ; * Control Servo6 & Servo7 ldi tsoutB, exp2(servo7) lds tsposA, $0086 lds tsposB, $0087 rcall pwmA ldi tsoutA, exp2(servo8) ; * Control Servo8 & Servo9 ldi tsoutB, exp2(servo9) lds tsposA, $0088 lds tsposB, $0089 rcall pwmB ldi tsoutA, exp2(servoA) ; * Control ServoA & ServoB ldi tsoutB, exp2(servoB) lds tsposA, $008A lds tsposB, $008B rcall pwmB ldi tsoutA, exp2(servoC) ; * Control ServoC & ServoD ldi tsoutB, exp2(servoD) lds tsposA, $008C lds tsposB, $008D rcall pwmB ldi tsoutA, exp2(servoE) ; * Control ServoE & ServoF ldi tsoutB, exp2(servoF) lds tsposA, $008E lds tsposB, $008F rcall pwmB rjmp mainloopend ;******************** ;* PWM Mark Routine * ;******************** .def count = r24 ; * PWM routine for Servos 01-08 * pwmA: in temp, porta ; * Set output pins of ServoA & Servo B or temp, tsoutA or temp, tsoutB out porta, temp rcall delay ; * Wait for 900uS ldi count, $00 ; * Start 1400uS delay pwmA1: cp count, tsposA ; * Reset output pin of ServoA if positionA = count brne pwmA2 in temp, porta com tsoutA and temp, tsoutA com tsoutA out porta, temp pwmA2: cp count, tsposB ; * Reset output pin of ServoB if positionB = count brne pwmA3 in temp, porta com tsoutB and temp, tsoutB com tsoutB out porta, temp pwmA3: nop nop nop nop nop nop nop nop nop nop inc count cpi count, $ff ; * Check if delay completed brne pwmA1 ret ; * Stop 1400uS delay ; * PWM routine for Servos 09-16 * pwmB: in temp, portc ; * Set output pins of ServoA & Servo B or temp, tsoutA or temp, tsoutB out portc, temp rcall delay ; * Wait for 900uS ldi count, $00 ; * Start 1400uS delay pwmB1: cp count, tsposA ; * Reset output pin of ServoA if positionA = count brne pwmB2 in temp, portc com tsoutA and temp, tsoutA com tsoutA out portc, temp pwmB2: cp count, tsposB ; * Reset output pin of ServoB if positionB = count brne pwmB3 in temp, portc com tsoutB and temp, tsoutB com tsoutB out portc, temp pwmB3: nop nop nop nop nop nop nop nop nop nop inc count cpi count, $ff ; * Check if delay completed brne pwmB1 ret ; * Stop 1400uS delay ;***************** ;* Delay Routine * ;***************** delay: ldi temp, $DD ; * Start of 900 uSec delay delay1: nop nop nop nop nop nop nop nop nop nop nop dec temp cpi temp, $00 brne delay1 ret ; * End of 900 uSec delay ;******************************* ;* End Of PWM Control Routines * ;******************************* mainloopend: rjmp mainloop ;*********************** ;* End Of Main Program * ;***********************
Also a windows based program specifically designed (under Visual Basic 5) for testing and controlling the 16 channel serial servo controller. With this program, your PC can control up to 16 servos via the keyboard or mouse. A screenshoot of the program in action shown in Picture 4.
4. References