' ********************************************************************** ' * File: Corso_BASCOMAVR_044.BAS * ' * Versione: 1.1 * ' * Data: 30.10.09 * ' * Ambiente sviluppo: Bascom-AVR Demo Ver. 1.11.9.1 + * ' * + AVR bootloader grifo(r) Ver. 1.2 * ' * Schede: GMM AM08 + GMM TST3 * ' * Sviluppato da: 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 * ' * Autore: Gianluca Angelini * ' ********************************************************************** ' Programma di esempio 044 del corso BASCOM AVR. ' Servo motore. ' Il programma consente di posizionare un Servo motore in tutte le posizioni ' della sua corsa (0°÷200°), tramite valore in gradi inserito da console. Il ' segnale prescelto per controllare il Servo è il PB1 del Mini Modulo, ' riportato sul connettore CN4.3 della GMM TST3. Tale segnale non è generato ' con le istruzioni per Servo del BASCOM, bensì con istruzioni a basso livello. ' Per ottenere la massima risoluzione sulla posizione del motore si è dovuto ' ottenere la massima risoluzione sulle temporizzazioni; questo è stato ' possibile solo con parti di programma in assembly. ' Per le prove del programma è stato usato il modello Servo standard 900-00005 ' prodotto dalla Parallax. ' Il programma si presenta ed usa una console seriale dotata di monitor e ' tastiera, con un protocollo fisico costante a 19200 Baud, 8 Bit x chr, ' 1 Stop bit, Nessuna parità. ' Questa console può coincidere con un sistema in grado di gestire una ' comunicazione seriale in RS 232. Al fine di semplificarne l'uso si può ' usare un PC dotato di una linea COMx, che esegue un programma di emulazione ' terminale come HYPERTERMINAL o l'omonima modalità offerta dal BASCOM AVR ' (vedere Configurazioni IDE). ' Il programma funziona solo se la GMM AM08 è montata sullo zoccolo Z2 della ' GMM TST3!! ' ' Aggiunte: $Asm, $End Asm, . ' ' 30/10/09: Corso_BASCOMAVR_044.BAS - Ver 1.1 - By G.A. ' Prima versione. ' ' '*************************** Configurazioni IDE ******************************** ' NOTE: per usare correttamente questo programma demo, eseguire i seguenti ' punti: ' 1) Controllare la presenza del file M8DEF.DAT nella directory di ' installazione del BASCOM-AVR e se non disponibile copiarlo e dopo ' rilanciare l'IDE. ' 2) Nella finestra "Options | Compiler | Chip" impostare: ' Chip: m8def.dat ' XRAM: None ' HW Stack: 64 ' Soft Stack: 32 ' Framesize: 64 ' XRAM waitstate: disattivo ' External Access Enable: disattivo ' 3) Nella finestra "Options | Communication" settare: ' COM port = la linea del PC collegata alla GMM AM08, tramite la GMM TST3 ' Baudrate = 19200 ' Parity = None ' Databits = 8 ' Stopbit = 1 ' Handshake = None ' Emulation = TTY ' Font = Terminal, Normale, 12 punti, colore bianco ' Backcolor = Navy ' 4) Al termine della compilazione, della programmazione del codice nella ' GMM AM08, aprire la finestra di emulazione terminale del BASCOM AVR con ' l'opzione: Tools | Terminal emulator (Ctrl+T) ed a questo punto resettare ' o riaccendere il Mini Modulo. '********************** Direttive del compilatore ****************************** $regfile "M8DEF.DAT" ' File di definizione microcontrollore usato $romstart = &H0 ' Indirizzo inizio codice in FLASH $crystal = 7372800 ' Frequenza quarzo del microcontrollore $hwstack = 64 ' Spazio per stack hardware $swstack = 32 ' Spazio per stack software $framesize = 64 ' Spazio per frame $map ' Genera informazioni di debug $baud = 19200 ' Velocità comunicazione seriale: 19200 Baud ' Altri parametri sono fissi a: 8 bit x chr ' 1 Stop bit ' No parity '******************************* Definizioni *********************************** ' Le risorse usate dal programma sono collegate come illustrato nella seguenti ' tabelle: ' !!! N.B. Sulla GMM TST3 i jumper devono essere posizionati come segue: ' 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 !!! ' ' Segnale Risorsa pin Z2 pin Segnale Segnale uP ' Servo GMM TST3 GMM TST3 GMM AM08 GMM AM08 usato ' PCM CN4.3 30 24 PB1 OC1A PB1 ' ' Segnale pin COMx pin CN5 pin Z2 pin Segnale Segnale uP ' PC DB9 GMM TST3 GMM TST3 GMM AM08 GMM AM08 usato ' TX 3 3 9 3 RxD RS232 PD0 ' RX 2 2 10 4 TxD RS232 PD1 ' GND 5 5 20 14 GND - ' Da questa tabella si ricava che il cavo di collegamento tra la COM del PC ed ' il CN5 della GMM TST3 è un normale cavo dritto o prolunga. Volendolo ' richiedere alla grifo(r) si deve specificare il codice CCR 9+9E. Pinservo1 Alias Portb.1 ' Bit con segnale d'uscita collegato a Servo motore 1 Pinrx Alias Ddrd.0 ' Bit con direzione segnale collegato a RxD GMM AM08 Pintx Alias Ddrd.1 ' Bit con direzione segnale collegato a TxD GMM AM08 '************************ Dichiarazioni costanti ******************************* Const Pcmmin = 77 ' Durata impulso PCM corrispondente ad inizio corsa Const Pcmmax = 477 ' Durata impulso PCM corrispondente a fine corsa Const Pcmdt = Pcmmax - Pcmmin ' Escursione durata impulso per segnale PCM del Servo Const Pcmmid =(pcmdt / 2) + Pcmmin ' Durata impulso PCM corrispondente a metà corsa Const Pcmris = Pcmdt / 200 ' Tempo impulso relativo ad un grado '************************ Dichiarazioni variabili ****************************** Dim Dtservo As Word ' Durata impulso per Servo Dim Posservo As Single ' Posizione albero Servo in gradi Dim Pcm As Single ' Durata impulso PCM di comando servo Dim Hlpw As Word ' Variabile word di aiuto ad uso generico '************************ Dichiarazioni procedure ****************************** Declare Sub Ini_pcmtmrirq() ' Inizializza timer per generazione segnale PCM Declare Sub Pcm_pulse() ' Genera impulso controllo Servo su segnale PCM '************************** Programma principale ******************************* Main: Pinrx = 0 ' Inizializza segnali per comunicazione seriale Pintx = 0 ' come ingressi digitali Pinservo1 = 1 ' Inizializza segnale collegato a Servo 1 come uscita digitale alta Ddrb.1 = 1 Print ' Separa da precedenti indicazioni, andando su nuova riga Print Print " Movimento Servo motore su posizioni angolari inserite" Print "Montare Mini Modulo su Z2 della GMM TST3, collegare PCM del Servo a CN4.3." ' La gestione del Servo motore viene effettuata con delle istruzioni a basso ' livello con interrupt ed assembly. Queste generano un segnale che segue ' esattamente le specifiche temporali del segnale PCM di controllo del Servo, ' e consentono comunque di ridurre ed allungare la durata dell'impulso, in ' modo da coprire tutto il campo di rotazione del Servo. ' Il programma usa un interrupt periodico generato dal TIMER0, che quindi non ' può essere usato per altre funzioni!!! ' Questo demo imposta la durata dell'impulso PCM tramite il valore assegnato ' alla variabile Dtservo, espressa in multipli di 4,882 microsecondi, circa. ' La risoluzione di tale durata determina anche la risoluzione sulle posizioni. ' Visto che la durata reale del segnale PCM varia da 0,383 a 2,335 millisecondi, ' equivalenti ai valori Pcmmin e Pcmmax, si ottiene: ' 2335 - 383 = 1952 microsecondi ' 1952 / 4,882 = 400 durate impulso = 400 posizioni dell'albero ' con un campo di rotazione di 200°, la risoluzione nelle posizioni sarà di ' 200 / 400 = 0,5°. Dtservo = Pcmmid ' Servo a metà corsa Call Ini_pcmtmrirq() ' Inizializza timer per generazione segnale PCM Do ' Inizio loop infinito ' La posizione in gradi inserita dall'utente (anche decimale) viene convertita ' in durata impulso del segnale PCM, tramite una funzione di trasferimento ' lineare, che opera la seguente conversione: ' Posizione -> Durata impulso PCM ' 0° -> Pcmmin ' 200° -> Pcmmax ' In questa trasformazione devono essere usate variabili di tipo Single al ' fine di non perdere cifre significative. Print Input "Inserire nuova posizione albero in gradi (0.0÷200.0):" , Posservo Pcm = Posservo ' Calcola durata impulso PCM per posizione inserita Pcm = Pcm * Pcmris Pcm = Pcm + Pcmmin Hlpw = Pcm ' Salva durata impulso su variabile di typo Word Dtservo = Hlpw ' Imposta durata impulso PCM determinata Loop ' Fine ciclo infinito Stop Timer0 ' Ferma TIMER0 e funzioni associate End '************************ Fine programma principale **************************** '****************** Inizio procedure usate dal programma *********************** ' Inizializza generazione interrupt periodico tramite TIMER0 del microcontrollore ' usato per tutte le gestioni temporali del programma. I commenti di questa ' procedura indicano concisamente le operazioni svolte ma informazioni ' dettagliate sono disponibili nel data sheet del microcontrollore e nell'aiuto ' in linea del BASCOM. ' La costante di tempo caricata determina un tempo di 20 msec ed è ottenuta come ' segue: ' Frequenza conteggio TIMER0 = Frequenza clock / 1024 = 7372800 / 1024 = 7200 Hz ' Periodo conteggio TIMER0 = 1 / Frequenza conteggio TIMER0 = 1 / 7200 = 0,000138888 sec ' Numero conteggi interrupt TIMER0 = 0,02 / Periodo conteggio TIMER0 = 0,02/ 0,000138888 = 144 Sub Ini_pcmtmrirq() Config Timer0 = Timer , Prescale = 1024 ' TIMER0 come 8 bit timer, precalsr 1024 ed attivazione interna On Ovf0 Timer0_irq ' Definisce procedura risposta interrupt di overflow del TIMER0 Load Timer0 , 144 ' Carica costante di tempo per 80 usec Enable Timer0 ' Abilita interrupt da TIMER0 Enable Interrupts ' Abilitazione generale interrupts Start Timer0 ' Attiva TIMER0 End Sub ' Genera impulso sul segnale di controllo del Servo PCM, con una durata ' proporzionale al valore passato nella variabile globale Dtservo, con la ' seguente formula: (4,882 * Dtservo + 4) in microsecondi. La durata non ' coincide esattamente con il risultato della formula, ma le differenze sono ' dell'ordine di frazioni di microsecondi e quindi trascurabili. ' Ingresso: Dtservo = Durata impulso PCM come da formula ' Uscita: Nulla Sub Pcm_pulse() Pinservo1 = 1 ' Alza segnale PCM di controllo Servo ' Genera ritardo in assembly in modo da ottenere la massima risoluzione e per ' usare il minor numero di registri del microcontrollore. $asm push R24 ' Salva registro R24: 2 clk in R24,sreg ' Preleva registro SREG: 1 clk push R24 ' Salva registro SREG: 2 clk PUSH R25 ' Salva registro R25: 2 clk ' La durata di ogni ciclo del ritardo non è esattamente 5 microsecondi bensì: ' Frequenza clock = 7372800 ' Periodo clock = 1 / 7372800 = 0,000000135 sec ' Durata singolo ciclo ritardo L = 12+12+12+12+24 = 36 periodi ' Durata singolo ciclo ritardo L = 36 * 0,000000135 = 0,000004882 sec LDS R24,{Dtservo} ' Inizializza contatori cicli di ritardo: 2 clk LDS R25,{Dtservo+1} ' R24 è byte L, R25 byte H: 2 clk Delpcm: ' Inizio ciclo di ritardo 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 ' Decrementa contatore cicli L: 1 clk CPI R24,255 ' Controlla fine ciclo ritardo L: 1 clk BRNE Delpcm ' Se ciclo ritardo L non finito, lo ripete: 2 clk DEC R25 ' Decrementa contatore cicli H: 1 clk CPI R25,255 ' Controlla fine ciclo ritardo H: 1 clk BRNE Delpcm ' Se ciclo ritardo H non finito, lo ripete: 2 clk POP R25 ' Ripristina registro R25: 2 clk pop R24 ' Ripristina registro SREG: 2 clk Out Sreg , R24 ' Setta registro SREG: 2 clk pop R24 ' Ripristina registro R24: 2 clk $end Asm Pinservo1 = 0 ' Abbassa segnale PCM di controllo Servo End Sub ' Procedura di risposta all'interrupt periodico associato al TIMER0. ' Genera impulso sul segnale di controllo Servo, della durata impostata nella ' variabile globale Dtservo, ogni 20 msec. ' La procedura di risposta anche se minimale usa registri del microprocessore ' e non può essere dichiarata con la direttiva Nosave. Timer0_irq: Load Timer0 , 144 ' Ricarica costante di tempo per 20 msec Start Timer0 ' Riattiva TIMER0 Call Pcm_pulse() ' Genera impulso controllo Servo su segnale PCM Return '******************* Fine procedure usate dal programma ************************