Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Problema servocomando

Elettronica lineare e digitale: didattica ed applicazioni

Moderatori: Foto UtenteIsidoroKZ, Foto UtenteDirtyDeeds, Foto Utentecarloc, Foto UtenteBrunoValente, Foto Utenteg.schgor

0
voti

[81] Re: Problema servocomando

Messaggioda Foto Utentec1b8 » 23 nov 2013, 23:51

Ciao, ti inserisco il codice così come lo averi scritto io.
Non l'ho provato.

Ho modificato la setServo per controllare che non vengano impostati valori oltre i limiti previsti.
Codice: Seleziona tutto
   //Routine per impostare pisizione di un servo
   // riceve 2 parametri:
   // char servo = numero del servo da impostare. Può valere 1 o 2
   // char time = durata del Ton che si desidera impostare al servo
   //                imdicato nel primo parametro
   void setServo(unsigned char servo, unsigned char time)   
   {
      if (time>valueLeft) time=valueLeft;
      if (time<valueRight) time=valueRight;
      
      servo--;                        // decremento servo di 1 quindi:
      // - se valeva 1 adesso diventa 0
      // - se valeva 2 adesso diventa 0
      servo=servo<<1;                 // assegno a servo il valore di servo con shift a sinistra
      // cioè moltiplico per 2:
      // - se routine richiamata con servo che valeva 1 adesso vale 0
      // - se routine richiamata con servo che valeva 2 adesso vale 2
      intTime[servo]=time;            // salvo il tempo Ton richiesto nella posizione dell'interrupt
      servo++;                        // incremento servo di 1
      intTime[servo]=200-time;        // Calcolo (200-time) e salvo il temponecessario a completare 2500us
      // per il servo
   }
   

Ho creato una nuova getServo che serve a sapere la poszione attuale del servo.
Codice: Seleziona tutto
   
   // Routine per recuperare posizione attuale di un servo
   //   riceve in input il numero del servo
   //   ritorna la posizione attuale del servo
   unsigned char getServo(unsigned char servo) {
      servo--;                        // decremento servo di 1
      servo=servo<<1;                 // moltiplico per 2
      return intTime[servo];         // ritorno posizione attuale
   }


Nel main ho poi messo un ciclo con gestione dello spostamento
Codice: Seleziona tutto
   while(1) {
      
      // qui il ritardo in funzione della velocità desiderata
      delay......
      
      if (PL1==0)   setServo(1, getServo(1)+1);
      if (PL2==0)   setServo(1, getServo(1)-1);
      if (PL3==0)   setServo(2, getServo(2)+1);
      if (PL4==0)   setServo(2, getServo(2)-1);
   }

In questo punto devi inserire un delay in funzione della velocità di spostamento che vuoi ottenere.
Facciamo un esempio. I valori massimo e minimo di spostamento sono 131 (sinistra) e 6 (destra), questo significa che lo spostamento totale si ha con 125 valori.
Se vuoi ottenere una velocità tale che il servo si sposti da sinistra a destra in ad esempio 5 secondi dovrai inserire un delay di 5/125=0,04 = 40 ms.

Fammi sapere se funziona e se ci sono dubbi.

Ciao.
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[82] Re: Problema servocomando

Messaggioda Foto Utentefantamed » 24 nov 2013, 0:43

c1b8 ha scritto: if (PL1==0) setServo(1, getServo(1)+1);


potresti descrivermela,con due righe?

Ti ringrazio
Avatar utente
Foto Utentefantamed
30 5
Frequentatore
Frequentatore
 
Messaggi: 110
Iscritto il: 8 nov 2013, 13:44

0
voti

[83] Re: Problema servocomando

Messaggioda Foto Utentec1b8 » 24 nov 2013, 0:55

La riga
Codice: Seleziona tutto
if (PL1==0) setServo(1, getServo(1)+1);

dice semplicemente questo:
se premo il PL1 (spostamento a sinistra del servo 1) allora imposto la posizione del servo 1 come posizione attuale + 1.

Come vedi viene richiamata la setServo che vuole due parametri:
setServo(servo, posizione)
il primo parametro (il servo) viene impostato a costante uguale a 1.
Il secondo parametro (la posizione) viene calcolato con la
getServo(servo)+1
ovvero viene richiamata la getServo, che ritorna l'attuale posizione del servo passatogli come parametro (nel nostro caso 1), e somma 1 al valore tornato dalla getServo.

EDIT: Facciamo un esempio.
Supponiamo che il servo 1 sia nella posizione 70 (posizione scelta a caso) e venga premuto PL1:
- si entra nella if
- viene richiamata la getServo(1) che ritorna il valore 70
- viene sommato 1 ottenendo 70+1=71
- si richiama la setSrvo(1, 71)
- a questo punto il servo 1 si sposta nella posizione 71
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[84] Re: Problema servocomando

Messaggioda Foto Utentefantamed » 24 nov 2013, 1:29

ho fatto una prova insrendo DelayMs(40); ma quando compilo mi da questo errore alla riga 55.1 ,quella del Delay

cmed\esercizi mplab\servo 2\main interr.c; 55.1 function declared implicit int

ti volevo anche chiedere:mi succede che quando provo la scheda con i due servi collegati,solo uno dei due risponde ai comandi l'altro no,nonostante il segnale del suo pin funzioni regolarmente.
Avatar utente
Foto Utentefantamed
30 5
Frequentatore
Frequentatore
 
Messaggi: 110
Iscritto il: 8 nov 2013, 13:44

0
voti

[85] Re: Problema servocomando

Messaggioda Foto Utentec1b8 » 24 nov 2013, 12:34

Hai incluso i file che abbiamo utilizzato l'altra volta per i delay?
Mi posti tutto il codice così come è ora?
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[86] Re: Problema servocomando

Messaggioda Foto Utentefantamed » 24 nov 2013, 14:33

si li ho inclusi

settaggio:
Codice: Seleziona tutto
#define PL1    RB0    // puls1
#define PL2    RB1    // puls2
#define PL3    RB2    // puls3
#define PL4    RB3    // puls4
#define LED    RA0    //led rete
#define SER1   RB4    //segnale servo 1
#define SER2   RB5    //segnale servo 2
#define numServo   2                  //  imposto che i servo sono 2
#define byteIntTime   numServo*2      //  imposto i byte di IntTime a 4 che sono i primi 4 periodi per il movimento dei servo ,e cosi? il segno * è un per(x) ?
#define maxIntNumber   byteIntTime*4  // imposto a 16 il numero max di interrupt per ottenere i 20ms per il segnale
#define valueLeft   131               // posizione dx 45°
#define valueRight   6                // posizione sx 45°
#define valueCenter   69             // posizione centrale

volatile unsigned char intNumber;   //dichiaro la variabile volatile (cioe che puo essere modificata sia dall'interrupt che dal programma) di tipo char per il conteggio interrupt
volatile unsigned char intTime[byteIntTime];  //dichiaro un'array volatile di tipo char,di dimensione 4 
void settaggio(void)
{   
   OPTION=0b10000010;
   INTCON=0b10100000;
   TRISA=0b11111110;   
   TRISB=0b00001111;                                         
   LED=0;
   SER1=0;
   SER2=0;

   TMR0=131;       // assegno al timer0 il valore 131 ,ovvero mmancano 125 cicli dei 256 per andare in overflow     
   intNumber=0;    // assegno alla variabile di conteggio intrrupt il valore  0
   
}


programma:
Codice: Seleziona tutto
#include <PIC.h>       // contiene i nomi mnemonici di registri e porte

__CONFIG(0x3FF9);      //configurazione fuses

#include "settaggioservo2.h"      // file che contiene il settaggio delle porte

void interrupt ISR (void)
{
   if (T0IF==1)                              // se si e verificato un'interrupt
    {                             
      if (intNumber>=byteIntTime) {          // se il numero di interrupt e magg.o uguale a 4   
         TMR0=100;                           // imposto il timer0 a 100: dal 5 al 16 interrupt
      } else {                   
         SER1=0;                             //azzero servo1
         SER2=0;                             // azzero servo2
         TMR0=intTime[intNumber];            //assegno al tiemr0 il valore di durata dell'attuale interrupt.
                                           
         if (intNumber==0) SER1=1;           // se siamo nel primo periodo 
         if (intNumber==2) SER2=1;           // se siamo nel secondo periodo
      }
      intNumber++;                           //incremento di 1 il numero di interrupt
      if (intNumber==maxIntNumber)           // se gli interrupt sono arrivati a 16
         intNumber=0;                        // azzero il conteggio degli interrupt per ricontare da 0
      T0IF=0;                                //  azzero il flag per nuovo interrupt
   }
}


void setServo(unsigned char servo, unsigned char time)   //Routine per movimento servo
{
   if (time>valueLeft) time=valueLeft;                   //
   if (time<valueRight) time=valueRight;
     
   servo--;                                              // decremento servo di 1 quindi da 2 diventa 1
   servo=servo<<1;                                       // assegno a servo il valore di servo con shift a sinistra cioe diventa 2
   intTime[servo]=time;                                  // salvo il tempo Ton richiesto nella posizione dell'interrupt
   servo++;                                              // incremento servo di 1
   intTime[servo]=200-time;                              //Calcolo (200-time) e salvo il temponecessario a completare 2500us
                                                         // per il servo
}
 
   unsigned char getServo(unsigned char servo)
   {
      servo--;                        // decremento servo di 1
      servo=servo<<1;                 // moltiplico per 2
      return intTime[servo];         // ritorno posizione attuale
   }

void main(void)
{
   settaggio();
   
   setServo(1, valueCenter);                            // inizio con il servo1 in posizione tutto dx (131)
   setServo(2, valueCenter);                          // inizio con il servo2 in posizione centrale (69)
   while(1)
{
   
      DelayMs(40);
      if (PL1==0)   setServo(1, getServo(1)+1);
      if (PL2==0)   setServo(1, getServo(1)-1);
      if (PL3==0)   setServo(2, getServo(2)+1);
      if (PL4==0)   setServo(2, getServo(2)-1);
   }
   

}

nella cartella del progetto ci sono i file che mi hai inviato: Delay.c , Delay.h e always.h,
se tolgo il DelayMs(40); dal programma ,compilo e provo su scheda,funziona con movimento veloce da -45 a +45.

Per poter provare entrambe i servi, devo pero collegare il segnale dei servo,uno alla volta poiche se li collego tutti e due,ne funziona sempre solo 1 eppure il segnale quando abilitato e presente in sia in RB4 che RB5.
O_/
Avatar utente
Foto Utentefantamed
30 5
Frequentatore
Frequentatore
 
Messaggi: 110
Iscritto il: 8 nov 2013, 13:44

0
voti

[87] Re: Problema servocomando

Messaggioda Foto Utentec1b8 » 24 nov 2013, 16:27

Adesso provo il codice, ma non vedo definita la frequenza del clock:
Codice: Seleziona tutto
#define  _XTAL_FREQ 4MHZ

e non vedo incluso il
Codice: Seleziona tutto
#include "delay.c"

Ricordati di utilizzare le delay funzionanti, non le prime che avevano qualche problema.

Non capisco il problema dei servo, alcune domende:
- se provi i 2 servo singolarmente, sullo stesso segnale (es RB4) funzionano entrambi?
- se provi i 2 servo singolarmente, uno su RB4 e uno su RB5 funzionano?
- se provi i 2 servo contemporaneamente funzionano?
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[88] Re: Problema servocomando

Messaggioda Foto Utentefantamed » 24 nov 2013, 17:08

:mrgreen: a furia di copia e incolla,li avevo fatti saprire ,pardon
Le delay sono quelle giuste che mi hai dato precedentemente

questo lo ho aggiunto nel settaggio
c1b8 ha scritto:#define _XTAL_FREQ 4MHZ

questo lo ho aggiunto nel programma
c1b8 ha scritto:#include "delay.c"


ora mi da questi errori
1)\esercizi mplab\servo 2\delay.h; 69.49 #error: delay.h - please define pic_clk correctly
2)\esercizi mplab\servo 2\delay.h; 96.49 #error: delay.h - please define pic_clk correctly
Avatar utente
Foto Utentefantamed
30 5
Frequentatore
Frequentatore
 
Messaggi: 110
Iscritto il: 8 nov 2013, 13:44

0
voti

[89] Re: Problema servocomando

Messaggioda Foto Utentefantamed » 24 nov 2013, 21:52

ho sostituito nel settaggio la definizione della frequenza in questo modo
Codice: Seleziona tutto
#define PIC_CLK 4000000 // quarzo a 4MHz

ora si compila anche con il DelayMs(40).
Può andare?
Purtroppo non posso più provare i servi,stranamente non funzionano più entrambi.
E un po strana la cosa,quando me li hanno regalati erano ancora nelle bustine,quindi credo nuovi.
Li ho scartati ,provati uno alla volta e funzionavano.
Poi ho cominciato a fare le prove con tutti e due collegati alla scheda,uno dei due non funzionava neppure se provato poi singolarmente,lasciato stare dopo un po ricominciava a funzionare,solo se connesso da solo pero,se provavo aconnettere anche l'altro si bloccava nuovamente..
Adesso non vanno più tutti e due,quando li alimento fanno un piccolo spostamento a dx come sempre fatto,ma quando inizia il programma e si dovrebbe/dovrebbero posizionare al centro,invece rimangono fermi.come se non leggessero più il segnale #-o
Avatar utente
Foto Utentefantamed
30 5
Frequentatore
Frequentatore
 
Messaggi: 110
Iscritto il: 8 nov 2013, 13:44

0
voti

[90] Re: Problema servocomando

Messaggioda Foto Utentec1b8 » 24 nov 2013, 21:57

Stavo provando proprio ora ed a me funziona, con le ultime modifiche che hai fatto.

Come alimenti il tutto, con una batteria?
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

PrecedenteProssimo

Torna a Elettronica generale

Chi c’è in linea

Visitano il forum: Nessuno e 28 ospiti