Showing posts with label modellismo. Show all posts
Showing posts with label modellismo. Show all posts

Thursday, June 02, 2011

RS Servo Tester

Progetto per movimentare un servo RC da aeromodelli con un Pic 12F628A (8Pin)

Il progetto è alquanto semplice usare un timer del pic per generare un PWM idoneo a controllare la posizione del servomotore. Il servo alla accensione si posiziona al centro della corsa e con due tasti Destro e Sinistro raggiunge la posizione -120° e +120°.
Alla pressione di ambedue i tasti ritorna alla posizione centrale.
Qualcuno mi ha domandato perchè non usare il PWM del Chip? La spiegazione è semplice i servi RC hanno una temporizzazione alquanto delicata e il PWM Hardware del pic non ha una risoluzione adeguata alla richiesta di posizionamento di precisione dei Servi RC digitali.
Quindi vista la velocità di esecuzione del microcodice dei pic e optando per un generatore di clock interno a 4mhz disponibile nel CHIP ( nessun quarzo esterno ) ho scritto il codice e mi sono messo a provarlo. Confesso che sono partito da una versione in basic scritta per PIC che funzionava alquanto male, della quale nel source OPEN ho mantenuto l'intestazione originale del writer.
Tradotto in "C" e corretto il codice, usando il timer il comparatore gli interrupt e un po di calcoli svolge splendidamente il suo lavoro. Ha una risoluzione di posizionamento dei contatori di 1microsecondo pari a circa 0,07° gradi, con i controllo tasti a 0,3° per step.
Il codice è scritto in MickroC che è free per impieghi con tutti i PIC 12/16/18/24/32 e la loro bella libreria compilando codice fino a 2Kbyte in ROM (download). Consiglio per chi volesse un approccio soft al PIC di adottarlo usando la probe PICKIT2 o 3 della Microchip che trovate presso qualsiasi distributore elettronico a €37,00(circa)
Con questo investimento potete sperimentare una serie di progetti che sono veramente interessanti con il PIC e che pubblico qui sul mio Blog.

Per reneder ancora più intrigante il codice stò elaborandone una versione per controllarlo da I2Bus ( non supportato da PIC12F628) in versione slave 10bit per comandare la posizione di strumenti analogici virtuali in Xplane.

Il codice:

/***************************************************************************
***** *****
***** 50Hz SINGLE SERVO TESTER USING 2 BUTTONS *****
***** 16F628A @ 4MHz INTOSC_NoClkout *****
***** Written By Warren Schroeder on 12.31.08 Mikrobasic 7.2 *****
***** Rewrite By mcmax on 10-05-2011 MikroC *****
***** software tested and run with *****
***** 1 microsecond position accuracy *****
***** Range of 1us to 19,999us *****
***** User can setup Min, Max, & Center Sweep Range as needed *****
***** *****
***** Features 2 Button Control For 3 Main Functions: *****
***** *****
***** Button1 = move to min position by user declared Step Value *****
***** Button2 = move to max position by user declared Step Value *****
***** Button1+Button2 = move to center position *****
***** *****
***** HOLDING a BUTTON WILL AUTO INCREMENT/DECREMENT Till MAX/MIN *****
***** *****
****************************************************************************/

// macro

typedef unsigned char uchar;
typedef unsigned int uint;

#define delay30() Delay_ms(30)
#define SetTMR1(t) { CCPR1L = (uchar)(t & 0x00FF); \
CCPR1H = (uchar)((t & 0xFF00) >> 8 ); }
#define GetTMR1() (int)CCPR1L + ((int)CCPR1H << 8 )
#define ClearTimer1() TMR1L=0; TMR1H=0;

// definition

#define _STEPVAL 5 // in microseconds Step ogni 30ms
#define _MAXPWM 20000 // 20ms (valori in millisecondi)
#define _MINPOS 600 // 0,6ms -90 -+
#define _CENTER 1500 // 1,5ms 0 -+----position servo centrale
#define _MAXPOS 2400 // 2,4ms +90 -+

// global var

unsigned int ServoPos;

//***** I N T E R R U P T ************************************************

void Interrupt( void )
{
if ( CCP1IF_bit == 1) {
if ( GP4_bit == 1 ){ // bit ccp1 bit 5 pin 3
GP4_bit = 0; // turn servo off
SetTMR1( _MAXPWM - ServoPos ); // off time to finish 20ms
}
else {
GP4_bit = 1; // turn servo on
SetTMR1( ServoPos); // on time in microseconds
}
ClearTimer1(); // rimette a 0 il timer1
PIR1.CCP1IF = 0; // clear int flag
}
}

//-------------------------------------------------------------------------

void CCP_Setup( void )
{
T1CON = 0; // no prescale; off; 1us ticks
ClearTimer1(); // clear timer1

ServoPos = _MINPOS; // posizione iniziale

CCP1CON = 0b00001010; // compare-match no ADC start or
// reset timer1 when match
SetTMR1( ServoPos ); // set intitial position

PIR1.CCP1IF = 0; // clear int flag
PIE1.CCP1IE = 1; // enable int
T1CON.TMR1ON = 1; // timer1 run

PEIE_bit = 1; // start periferical int
GIE_bit = 1; // GIE, PEIE enabled
}

/*********************************************************
***** *****
***** Buttons Inputs are Pulled Low on RA0 and RA1 *****
***** *****
*********************************************************/


void KeyCtrl(void)
{
char Temp;

if ((GPIO & 3) != 0x03 ) { // check for active buttons

Delay_Ms(30); // debounce delay
Temp = GPIO & 0x03; // save button value

while ( Temp != 0) { // while a button is active do

if ( Temp == 3) { // both buttons active
ServoPos = _CENTER; // goto center position
}
else {
if ( Temp == 1) { // dec position by stepval
ServoPos = ServoPos - _STEPVAL;
if ( ServoPos < _MINPOS )
ServoPos = _MINPOS;
}
else { // inc position by stepval
ServoPos = ServoPos + _STEPVAL;
if ( ServoPos > _MAXPOS)
ServoPos = _MAXPOS;
}
}
Delay_Ms(30); // button release delay
Temp = GPIO & 3 ; // check again for release
}
} // if not released will inc or dec more
}

/****** M A I N ***********/

void main(void)
{
INTCON = 0; // disable alla interrupt

OSCCON = 0b01100000; // work at 4Mhz of internal
// clock without ext clk
ANSEL = 0x00; // disable analog ad digital I/O
CMCON0 = 0x07; // disable comparator

GPIO = 0x00; // init port setup
TRISIO = 0x03; // bit 0 = 7 Key UP
// bit 1 = 6 Key DW
// pwm su pin 3 al servo motor

CCP_Setup(); // setup value application and timing

while(1) // main loop
KeyCtrl(); // key controll

}

// end source

Lo schema del prototipo

Il PCB

Le foto del prototipo

Buon divertimento.