' ********************************************************************** ' * File: uk_BASAVR_044.BAS * ' * Version: 1.1 * ' * Date: 03.04.11 * ' * Development Tools: Bascom-AVR Demo Ver. 1.11.9.1 + * ' * + AVR bootloader grifo(r) Ver. 1.2 * ' * Cards: GMM AM08 + GMM TST3 * ' * Developed by: GRIFO(r) Italian Technology * ' * via Dell'Artigiano 8/6 * ' * 40016 S. Giorgio di Piano (BO) * ' * Tel. +39 051 892052 Fax. +39 051 893661 * ' * http://www.grifo.com http://www.grifo.it * ' * Author: Gianluca Angelini * ' ********************************************************************** ' Example program 44 of BASCOM AVR course. ' Servomotor. ' The program allows to define Servomotor rotations in all the allowed positions ' (0°÷200°), through a proper value, expressed in degree, inserted by console. ' The signal selected to drive the Servomotor is the PB1 of Mini Module, reported ' on CN4.3 connector of GMM TST3. This signal is not generated by BASCOM's ' instructions dedicated to Servo, but by low level instructions. ' In order to obtain the maximum resolution on the motor position, it has been ' necessary to obtain the highest resolution on timings; this condition has ' been satisfied only with parts of programs coded in assembly. ' The program has been tested with the model Servo standard 900-00005 produced ' by Parallax. ' The program describes its functionalities and uses a serial console provided ' of monitor and keyboard with a fixed physical protocol at 19200 Baud, 8 Bit ' x chr, 1 Stop bit, No parity. ' This console can be another system capable to support a serial RS 232 ' communication. In order to simplify the use it can be used a PC provided of ' one COMx line, that execute a terminal emulation program as HYPERTERMINAL or ' the homonym modality provided by BASCOM AVR (see IDE Configuration). ' The program works only when the GMM AM08 is mounted on Z2 socket of GMM TST3!! ' ' Added instructions: $Asm, $End Asm, . ' 03/04/11: uk_BASAVR_044.BAS - Ver 1.1 - By G.A. ' First version. ' ' '**************************** IDE Configurations ******************************* ' NOTE: in order to coorectly use this demo program, please execute the following ' steps: ' 1) Check the availability of M8DEF.DAT file into the directory where the ' BASCOM AVR is installed and copy it if not present. ' 2) Into the window "Options | Compiler | Chip" set: ' Chip: m8def.dat ' XRAM: None ' HW Stack: 64 ' Soft Stack: 32 ' Framesize: 64 ' XRAM waitstate: disabled ' External Access Enable: disabled ' 3) Into the window "Options | Communication" set: ' COM port = the PC line connected to GMM AM08, through GMM TST3 ' Baudrate = 19200 ' Parity = None ' Databits = 8 ' Stopbit = 1 ' Handshake = None ' Emulation = TTY ' Font = Terminal, Normal, 12 points, white colour ' Backcolor = Navy ' 4) At the end of compilation, after the code is programmed on GMM AM08, open ' the terminal emulation window of BASCOM AVR with the option: Tools | ' Terminal emulator (Ctrl+T) and then reset or powen on the Mini Module. '************************* Compiler directives ********************************* $regfile "M8DEF.DAT" ' Definitions file for used microcontroller $romstart = &H0 ' Code start address on FLASH $crystal = 7372800 ' Microcontroller crystal frequency $hwstack = 64 ' Hardware stack space $swstack = 32 ' Software stack space $framesize = 64 ' Frame space $map ' Generate debug information $baud = 19200 ' Serial communication speed: 19200 Baud ' Other parameters fixed to: 8 bit x chr ' 1 Stop bit ' No parity '******************************* Definitions *********************************** ' The resources used by program are connected as described in following table. ' !!! Note: On GMM TST3 the jumpers must be set in following positions: ' J1 in 2-3 ; J2 in 1-2 ; J3 in 1-2 ; J5 in 2-3 ; J7 in 2-3 ; J8 in 2-3 ' J9 in 2-3 !!! ' ' Servo GMM TST3 pin Z2 pin Signal Signal ' signal resource GMM TST3 GMM AM08 GMM AM08 uP ' PCM CN4.3 30 24 PB1 OC1A PB1 ' ' Signal pin COMx pin CN5 pin Z2 pin Signal Signal ' PC DB9 GMM TST3 GMM TST3 GMM AM08 GMM AM08 uP ' TX 3 3 9 3 RxD RS232 PD0 ' RX 2 2 10 4 TxD RS232 PD1 ' GND 5 5 20 14 GND - ' This table shows that the connection cable between PC COM line and CN5 of ' GMM TST3 is a normal pin to pin cable or direct. Grifo(r) can supply it by ' requesting the CCR 9+9E code. Pinservo1 Alias Portb.1 ' Bit with output signal connected to Servomotor 1 Pinrx Alias Ddrd.0 ' Bit with direction signal connected to GMM AM08 RxD Pintx Alias Ddrd.1 ' Bit with direction signal connected to GMM AM08 TxD '************************* Constants declaration ******************************* Const Pcmmin = 77 ' PCM pulse duration equal to start rotation position Const Pcmmax = 477 ' PCM pulse duration equal to stop rotation position Const Pcmdt = Pcmmax - Pcmmin ' Duration range for PCM signal pulse of Servo Const Pcmmid =(pcmdt / 2) + Pcmmin ' PCM pulse duration equal to middle rotation position Const Pcmris = Pcmdt / 200 ' Pulse time equal to one degree '************************* Variables declaration ******************************* Dim Dtservo As Word ' Pulse duration for Servo Dim Posservo As Single ' Servo output shaft position in degrees Dim Pcm As Single ' PCM pulse duration for servo driving Dim Hlpw As Word ' General purpose help variable '************************ Subroutines declaration ****************************** Declare Sub Ini_pcmtmrirq() ' Initialize timer for PCM signal generation Declare Sub Pcm_pulse() ' Generate Servo controlling pulse on PCM signal '****************************** Main program *********************************** Main: Pinrx = 0 ' Initialize signals for serial communication Pintx = 0 ' as digital inputs Pinservo1 = 1 ' Initialize signals connected to Servo 1 as digital output at high level Ddrb.1 = 1 Print ' Separate from previous visualization by showing an empty new line Print Print " Servomotor movement to inserted angle positions" Print "Mount Mini Module on Z2 of GMM TST3, connect Servo PCM signal to CN4.3." ' The Servomotor management is performed with low level instructions plus ' interrupt and assembly. These generates a signal that exactly matches the ' timing specifications of the Servo control signal PCM, and they anyway ' allow to increase and reduce the pulse duration, in order to cover all the ' Servo rotation range. ' The program uses a periodic interrupt generated by TIMER0, that can't be ' used for other functions!!! ' This demo defines the PCM pulse duration, thanks to value assigned to ' variable Dtservo, expressed in multiply of about 4,882 microseconds. ' The resolution of this duration defines also the resolution on positions. ' As the real duration of PCM signal range from 0,383 to 2,335 milliseconds, ' equal to Pcmmin and Pcmmax values, you obtain: ' 2335 - 383 = 1952 microseconds ' 1952 / 4,882 = 400 pulse duration = 400 position of output shaft ' by using a rotation range of 200°, the resolution on position will be ' 200 / 400 = 0,5°. Dtservo = Pcmmid ' Servo on middle position Call Ini_pcmtmrirq() ' Initialize timer for PCM signal generation Do ' Start endless loop ' The degrees position inserted by user (even decimal) is converted in ' pulse duration of PCM signal, through a linear transfer function, that ' performs the following conversion: ' Position -> PCM pulse duration ' 0° -> Pcmmin ' 200° -> Pcmmax ' In this conversion it must be used Single type variables in order to mantain ' all the significant digits. Print Input "Insert new shaft position in degrees (0.0÷200.0):" , Posservo Pcm = Posservo ' Calculate PCM pulse duration for inserted position Pcm = Pcm * Pcmris Pcm = Pcm + Pcmmin Hlpw = Pcm ' Save pulse duration on Word type variable Dtservo = Hlpw ' Set obtained PCM pulse duration Loop ' End endless loop End '*************************** End of main program ******************************* '*********************** Subroutines used by program *************************** ' Initialize periodic interrupt generation by TIMER0 of microcontroller, used ' for all the times management of the program. The remarks of this subroutine ' briefly specify the executed operations but detailed informations are ' available in data sheet of microcontroller and inside on line help of BASCOM. ' The loaded time constant produce a 20 msec period and it has been obtained ' as follow: ' TIMER0 counting frequency = Clock Frequency / 1024 = 7372800 / 1024 = 7200 Hz ' TIMER0 counting period = 1 / TIMER0 counting frequency = 1 / 7200 = 0,000138888 sec ' TIMER0 interrupts counter = 0,02 / TIMER0 counting period = 0,02/ 0,000138888 = 144 Sub Ini_pcmtmrirq() Config Timer0 = Timer , Prescale = 1024 ' TIMER0 as 8 bit timer with 1024 prescaler and internal activation On Ovf0 Timer0_irq ' Define TIMER0 overflow interrupt service routine Load Timer0 , 144 ' Load time constant for 20 usec Enable Timer0 ' Enable interrupt from TIMER0 Enable Interrupts ' General interrupts enable Start Timer0 ' Enable TIMER0 End Sub ' Subroutine that generates pulse on PCM signal of Servo, with a duration defined ' by value passed in global variable Dtservo, through the below formula: ' (4,882 * Dtservo + 4) in microseconds. The duration doesn't exactly match the ' formula result, but differences have microseconds fractions, and so they are ' meaningless. ' Input: Dtservo = PCM pulse duration, as in reported formula ' Output: None Sub Pcm_pulse() Pinservo1 = 1 ' Set PCM Servo control signal high ' Generates delay in assembly in order to obtain maximum resolution and to ' use the lower number of microcontroller registers. $asm push R24 ' Save R24 register: 2 clk in R24,sreg ' Get SREG register: 1 clk push R24 ' Save SREG register: 2 clk PUSH R25 ' Save R25 register: 2 clk ' The duration of each delay loop is not exactly 5 microseconds but: ' Clock frequency = 7372800 ' Clock period = 1 / 7372800 = 0,000000135 sec ' Duration single delay loop L = 12+12+12+12+24 = 36 periods ' Duration single delay loop L = 36 * 0,000000135 = 0,000004882 sec LDS R24,{Dtservo} ' Initialize delay loops counter: 2 clk LDS R25,{Dtservo+1} ' R24 is byte L, R25 is byte H: 2 clk Delpcm: ' Start delay loop NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk NOP ' 1 clk DEC R24 ' Decrease loops counter L: 1 clk CPI R24,255 ' Check end of delay loop L: 1 clk BRNE Delpcm ' If delay loop L not completed, repeat it: 2 clk DEC R25 ' Decrease loops counter H: 1 clk CPI R25,255 ' Check end of delay loop H: 1 clk BRNE Delpcm ' If delay loop H not completed, repeat it: 2 clk POP R25 ' Restore R25 register: 2 clk pop R24 ' Restore SREG register: 2 clk Out Sreg , R24 ' Set SREG register: 2 clk pop R24 ' Restore R24 register: 2 clk $end Asm Pinservo1 = 0 ' Set PCM Servo control signal low End Sub ' Interrupt service routine associated to periodic TIMER0 overflow. ' It generates a pulse on Servo control signal, with the duration defined by ' variable Dtservo, each 20 msec. ' Even if the routine is very short, it uses three registers of microprocessor ' and it can't be declared with Nosave directive. Timer0_irq: Load Timer0 , 144 ' Reload time constant for 20 usec Start Timer0 ' Re-enable TIMER0 Call Pcm_pulse() ' Generate Servo pulse control on PCM signal Return '******************* End of subroutines used by program ************************