1. Progetto Biomeccatronica
Anno accademico 2011/2012
Traccia 1
Belardi Luca
Benedettini Luca
Caretta Flavio
Crabolu Michele
Fais Andrea
Maracci Daniele
Raffi Giuseppe
Sanna Daniela
2. Progetto
Realizzare e testare un programma per il
controllo del servomotore Parallax 900-00008.
Il motore si dovrà controllare in posizione e
pilotare in modo da compiere spostamenti di
+/- 90° gradi rispetto al punto di riferimento
(SET POINT) in funzione dell'inclinazione
rispetto la verticale di una maniglia di
comando strumentata con un accelerometro
ADXL 330.
3. Procedimento
• Calibrazione del potenziometro e
dell’accelerometro.
• Firmware per il controllo del servomotore
rispetto al riferimento.
• Realizzazione della piattaforma su cui fissare la
maniglia di comando con l’accelerometro e la
board.
4. Calibrazione potenziometro
• Realizzazione di una base che ha permesso di ricavare in
corrispondenza delle posizioni del servomotore desiderate
(0°/+-90°) l’uscita del potenziometro convertita in digitale
tramite il modulo ADC del PIC usando la porta A0 e
leggendone direttamente il valore tramite la variabile pot
nella finestra di debug dell’ambiente di programmazione.
ANGOLO VALORE POTENZIOMETRO
0° 128
+90° 244
-90° 38
5. Calibrazione accelerometro
Per la calibrazione dell’accelerometro si è usato
un oscilloscopio, ruotando l’accelerometro il
segnale in uscita da quest’ultimo (x) variava.
PROBLEMA: il segnale risulta essere molto
rumoroso.
6. Calibrazione accelerometro
Successivamente sono state misurate le soglie
tramite in convertitore ADC del pic usando la
porta A1 e leggendone direttamente il valore
tramite la variabile x nella finestra di debug
dell’ambiente di programmazione. :
Posizione accelerometro Risultato conversione
0° 72
90° 56
-90° 80
7. Controllo del servomotore
• Programma firmware di controllo tramite
PIC16F887;
• Controllo segnale tramite interrupt timer;
• Invio onda quadra tramite la porta B0;
• Selezione tramite Case-Break del duty cycle.
Coppia Delay
Di tenuta 1500
Rotazione oraria 1300
Rotazione antioraria 1700
8. Firmware per il controllo
• Canale AN0 e canale AN1 impostati come
ingressi analogici;
• Alla variabile x è assegnato il contenuto della
conversione ADC sul canale AN0;
• Alla variabile pot è assegnato il contenuto
della conversione ADC sul canale AN1.
9. Piattaforma di comando
Condizioni per la rotazione del motore:
Posizione Direzione Variabile x
maniglia
0° fermo pos1+4 < x<pos1-4
90° orario pos2+4<x<pos2-4
-90 antiorario pos3+4< x<pos3-4
Quando il motore sposta il potenziometro nella
posizione data dalla maniglia si ferma.
10. Alimentazione
• Board PIC: 5V DC da alimentatore
• Parallax: +5 V DC dalla scheda del PIC
• Accelerometro: +3 V DC da alimentatore
15. Codice:Variabili
#include <progetto finale.h>
static int rotazione; // variabile relativa al case break, ad ogni case corrisponde un movimento del motore (orario,
antiorario,stop)
static int pot; // variabile relativa alla posizione del potenziometro, supporta il risultato della conversione ADC del
canale AN0 che riceve il segnale del potenziometro.
static int x; // variabile relativa alla posizione della maniglia, supporta il risultato della conversione ADC del canale AN1
che riceve il segnale dall'accelerometro
static int pos1=72; // variabile relativa alla posizione 0° della maniglia, 72 è il valore medio della conversione che si
ottiene dal segnale della maniglia lungo x
static int pos2=56; // variabile relativa alla posizione 90° della maniglia, 56 è il valore medio della conversione che si
ottiene dal segnale della maniglia lungo x
static int pos3=80; // variabile relativa alla posizione -90° della maniglia, 80 è il valore medio della conversione che si
ottiene dal segnale della maniglia lungo x
static int control=0;
//Range motore orario
static int potn90=234; // variabile relativa alla posizione del potenziometro, quando si trova a -90°, 28 è la conversione del
canale AN0
//Range motore antiorario
static int pot90=28; // variabile relativa alla posizione del potenziometro, quando si trova a 90°, 28 è la conversione del
canale AN0
static int pot0=128;
#INT_timer2
16. Codice:Funzione interrupt timer
void timer2_isr() //funzione di interrupt del timer2
{
delay_us(10000); //delay 10ms da sommare al tempo del timer
output_high(PIN_B0); //pin B0 alto, manda il segnale al motore;
output_high(PIN_B4); //accendo led per verifica visiva dell'accensione della scheda
switch (rotazione){
case 0: delay_us(1500); //delay di 1500 x 10^-6 s per la coppia di tenuta del motore
break;
case 1: delay_us(1300); //delay di 1300 x 10^-6 sper la coppia rotazione senso orario del motore
break;
case 2: delay_us(1700); //delay di 1700 x 10^-6 per la coppia rotazione senso antiorario del motore
break;
}
output_low(PIN_B0); //pin B0 basso, riabbassa l'onda inviata al motore
output_low(PIN_B4); //spengo led
clear_interrupt(INT_TIMER2); //clear flag interrupt timer1
enable_interrupts(global); //abilita l'interrupt globale
enable_interrupts(INT_TIMER2); //abilitazione interrupt timer 1
}
17. Codice
Main: settaggio timer
void main()
{
rotazione=0; //motore fermo di default
setup_timer_2(T2_div_by_16,207,16); //setaggio del timer2
per il funzionamento a 10ms, ((Tosc/4)/16)/16) il flag di interrupt
scatta dopo 207 scatti del timer
output_low(PIN_B0); //pin B0 basso
enable_interrupts(global); //abilitazione interrupt
globale
clear_interrupt(INT_TIMER2); //pulizia del flag di
interrupt del timer
enable_interrupts(INT_TIMER2); //abilitazione interrupt
timer 1
18. Codice
Main: gestione del convertitore ADC
setup_adc(ADC_CLOCK_INTERNAL); //utilizzo il clock interno al pic per temporizzare l'ADC
setup_adc_ports(sAN0); //pin A0 analogico riceve il segnale dal potenziometro
setup_adc_ports(sAN1); //pin A1 analogico riceve il segnale dell'accelerometro
while(TRUE)
{
set_adc_channel(1); //setta il canale A1 in cui leggere nel prossimo comando
read_adc
delay_us(50);
x=read_adc(); //legge continuamente il valore della conversione del segnale
proveniente dall'accelerometro
delay_us(50);
set_adc_channel(0); //setta il canale A0 in cui leggere nel prossimo comando
read_adc
delay_us(50);
pot=read_adc(); //legge continuamente il valore della conversione del segnale
proveniente dal potenziometro
delay_us(50);
19. Codice
Main: gestione del motore
if ( x<pos1+6 && x>pos1-6){
rotazione=0; // Quanto la maniglia si trova 0° il motore è fermo, non ruota (SETpoint)
}
if( x<pos2+4 && x>pos2-4){
rotazione=1;//orario //Quando la maniglia viene portata a 90° il motore inizia a ruotare in senso
orario
if(pot<=pot90){
rotazione=0; //il motore ruota in maniera solidale col potenziometro, quando arriva alla
posizione 90° si ferma
}
}
else if(x<pos3+4 && x>pos3-4) {
rotazione=2; //Qunado la maniglia viene portata a -90° il motore inizia a ruotare in senso
antiorario
if(pot>=potn90){
rotazione=0; //il motore ruota in maniera solidale col potenziometro, quando arriva alla posizione
-90° si ferma
}
}