Vai al contenuto
PLC Forum


Contachilometri Con Pic16f84 - autocostruito...


Giorgio Demurtas

Messaggi consigliati


  • Risposte 72
  • Created
  • Ultima risposta

Top Posters In This Topic

  • Giorgio Demurtas

    27

  • giacomo56

    14

  • dlgcom

    7

  • wnc

    6

Giorgio ,

Se i dubbi sono nell'uso della routine prova direttamente in c con le istruzioni che ti hanno consigliato.

Usa l'assembler solo in caso di mancanza di memoria.

Link al commento
Condividi su altri siti

Giorgio Demurtas

ok sto provando in c...

uso la funzione idiv=div(num, denom)

ma non ho ben capito, mi sembra che il risultato (quoziente) e il resto della divisione siano entrambi contenuti dentro "idiv"

idiv is an object of type div_t and lidiv is an object of type ldiv_t.  The div function returns a structure of type div_t, comprising of both the quotient and the remainder.
Link al commento
Condividi su altri siti

Cosi hai nelle var uni , deci e centi il numero n separato in cifre.

#include <16f84.h>



void main(){

int   n,uni,deci,centi;


n=125;
uni = n%10;
deci = (n/10)%10;
centi = n/100;


}

Link al commento
Condividi su altri siti

Giorgio Demurtas

ciao luca,

allora è proprio vero che a mente lucida si pensa meglio....infatti ci sono arrivato anche da solo, ma comunque grazie della risposta. (così confrermo quello che ho pensato).

la scuola mi sta impegando molto (anzi non solo la scuola). Il brutto è che a fare queste cose che richiedono concentrazione mi ci metto sempre dopo le 10:00 :ph34r:

comunque ora provo!

ciao

Link al commento
Condividi su altri siti

Giorgio Demurtas

che figo! funziona!!!

ora gli automatizzo il cambio del numero. :D

come si rilevano i fronti di salita?

io stavo pensando...

int1 a, FP;

FP=(a xor RA0) and RA0;
a=RA0;

si fa così?

Link al commento
Condividi su altri siti

Giorgio Demurtas

ok! ho fatto anche un conteggio in avanti...

non riesco a trovare l'istruzione per fare l'xor fra due bit... puoi aiutarmi?

grazie

Link al commento
Condividi su altri siti

Giorgio Demurtas

#include "C:\Documenti\pic c\nuovi_progetti\xor\xor.h"

int1 in1, in2, out;

void main() {
set_tris_a(0xFF);
set_tris_b(0x00);


while(1)
   {
   in1=input(PIN_A0);
   in2=input(PIN_A1);
   out=in1^in2;
   if(out==1)
   output_bit(PIN_B0, 1);
   else output_bit(PIN_B0, 0);
   }


}

questo codice funziona come una not xor, che strano, quando gli ingressi son diversi il led che ho messo nell'uscita si spegne. la xor funziona diversamente...comunq l'importante è saperlo, così ci posso mettere una bella not davanti! ;)

Link al commento
Condividi su altri siti

Giorgio Demurtas

no, invece non è più strano.

In effetti è giusto così...

come led sto usando un segmento di un display ad ANODO comune, quindi quando l'uscita è alta il segmento si spegne (e viceversa chiaramente).

ora devo pensare al tempo di campionamento dei fronti di discesa sull'ingresso dove ho collegato l'ampolla reed. io pensavo:

IF (frontenegativo&&tempoc) giriruota++;

tempoc è un bit che rimane settato per un tempo di un secondo (x interruzioni).

quando tempoc va a zero significa che ha finito di campionare e può chiamare la routine che dal numero di giri ricava la velocità in km/h e la mette nella variabile "velox".

al più presto mi metto a scrivere il listato.

ciao

Link al commento
Condividi su altri siti

Giorgio Demurtas

son riuscito a rilevare i fronti...

ora sto scrivendo la parte di sw che fa il campionamento del numero dei giri in un secondo.

in un int8 posso ospitare un numero come 1.27 ?

e il prodotto fra numeri di diverso formato si può fare?

Link al commento
Condividi su altri siti

Lo puoi fare se lo memorizzi come 127 cioè come un intero. Per usare i numeri reali devi dichiarare variabili di tipo float.

Si possono fare operazioni con numeri di tipo diverso. Normalmente il compilatore esegue automaticamente la conversione tra formati diversi ma bisogna stare attenti perchè, a volte, si possono avere risultati inaspettati.

Comunque le operazioni sui numeri reali sono lente e comportano una gran quantità di codice in più rispetto agli interi e quindi è meglio evitarne l'uso se possibile.

Ciao.

Modificato: da giacomo56
Link al commento
Condividi su altri siti

Giorgio Demurtas

ok, sei stato chiarissimo.

//contachilometri con display
//giorgio demurtas
//agosto-settembre 2004
//il watchdog dev'essere disable

#include "C:\Documenti\pic c\nuovi_progetti\ckm_numero\ckm_numero.h"
#define cuni PIN_A1   //pin 18
#define cdeci PIN_A2  //pin 1
#define ccenti PIN_A3 //pin 2

int1 a, in1, FN, bitTempoc;
int8 numero, velox, cifra_on, tempoc, uni, deci, centi, giri; //tempoc è il tempo di campionamento. 1000 ms


//--------------------------------------------------------------------------
#int_RTCC
RTCC_isr()  //Interrupt Service Routine
     {
     cifra_on=cifra_on+1;
     if (cifra_on==4) cifra_on=1;
        
     tempoc=tempoc+1;
     if (tempoc==36) tempoc=0; //il tempo di campionamento è di 30 interruzioni
     if (tempoc>30) giri=0;
     //nota: cambiare il 16 in 31
     }
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
void bcd(int8 velox) //funzione per separare le tre cifre
     {
     uni = velox%10;
     deci = (velox/10)%10;
     centi = velox/100;
     }
//--------------------------------------------------------------------------

void main() {         //inizio programma principale

set_tris_a(0x11); //ra4 ed ra0 ingressi
set_tris_b(0x00);
velox=0;
tempoc=0;
cifra_on=1;
output_b(0x03); //visualizza il numero 0
a=in1;
//nota: cambiare il 256 in 128
setup_timer_0 (RTCC_DIV_256|RTCC_INTERNAL); // imposto il prescaler a 128 divisioni in modo da ottenere
                                            // una frequenza di incremento del registro TMR0 di
                                            // 1 Mhz/128=7812.5 Hz
                             //TMR0 passa per lo 0 con una frequenza di 50 Hz
                             //7812.5/256=30 Hz
enable_interrupts(int_rtcc); //abilito l'interrupt da tmr0
enable_interrupts(global);   //abilito tutti gli interrupts

while(1) //ciclo continuo
   {
   in1=input(PIN_A0);
   if (a==1 && in1==0) FN=1;  //se c'è il fronte negativo FN=1
   else FN=0;

   //-----------------------------Acquisizione giri
   if (FN) giri++;
   velox=giri;
   bcd(velox);
   //if (tempoc>30) {velox=giri; bcd(velox); }
   //velox=(36*127*giri)/1000;
   
   //----------------------------
   
     if (cifra_on==1) { output_bit(ccenti, 1); numero=centi; }
     else output_bit(ccenti, 0);
     if (cifra_on==2) { output_bit(cdeci, 1); numero=deci; }
     else output_bit(cdeci, 0);
     if (cifra_on==3) { output_bit(cuni, 1); numero=uni; }
     else output_bit(cuni, 0);

     // invio del numero
     if (numero==0) output_b(0x03);
     if (numero==1) output_b(0x9F);
     if (numero==2) output_b(0x25);
     if (numero==3) output_b(0x0D);
     if (numero==4) output_b(0x99);
     if (numero==5) output_b(0x49);
     if (numero==6) output_b(0x41);
     if (numero==7) output_b(0x1F);
     if (numero==8) output_b(0x01);
     if (numero==9) output_b(0x09);

   
   a=in1;
   } //fine ciclo while
 } //fine main

funziona in parte...

praticamente la variabile "giri" viene incrementata ogni volta che premo un pulsante sull'ingresso RA0, ogni secondo (30 interrupt) la variabile giri viene azzerata.

Però prima che trascorra un secondo sul display vedeo incrementarsi le cifre ogni volta che premo, invece io vorrei che il numero del diplay venga aggiornato ogni secondo con il valore dei giri dell'ultimo secondo di campionamento.

Quindi ho provato a mettrere nella ISR la chiamata per la funzione bcd() prima di azzerare la variabile "giri", in modo che il valore di "giri" e di "velox" sia sempre l'ultimo valore (il più grande).

a parte che devo spostare la funzione bcd() prima di ISR (altrimenti non riconosce la chiamata per la funzione), non funziona e sul disply vedo numeri non significativi. (tipo 001 ogni tanto).

cosa mi sfugge??? <_<

Link al commento
Condividi su altri siti

a parte che devo spostare la funzione bcd() prima di ISR (altrimenti non riconosce la chiamata per la funzione), non funziona e sul disply vedo numeri non significativi. (tipo 001 ogni tanto).
Link al commento
Condividi su altri siti

Giorgio Demurtas

ciao,

ho fatto come mi hai suggerito e funziona tutto.

uso il PCW compiler della CCS.

posso fare un calcolo come questo: velox=(36*127*giri)/1000; ?

nella compilazione non da errori e nella prova hw nemmeno, ma magari c'è un valore che non posso superare...o non so che genere di limitazione :huh:

Ho fatto la prova simulando l'ampolla reed con due fili che faccevo toccare si e no per generare gli impulsi più velocemente possibile; sono arrivato a 10 imp/s cioè sul display vedevo circa 50 km/h.

Ora devo costruire il circuito definitivo e provarlo sulla bici o sullo scooter (quando lo aggiusto perchè ora è guasto).

ciao

Link al commento
Condividi su altri siti

Certo che puoi farlo sempre senza superare il valore massimo dal tipo di variabile. Ad esempio se la variabile è di tipo intera senza segno puoi arrivare a 65535. Il compilatore non te lo segnala ma puoi controllare i bit di stato della CPU bit C. Più specificatamente non posso aiutarti perchè non è il compilatore che uso di solito.

Ricorda che la divisione è intera quindi non avrai resto. Se ti interessa anche il resto devi usare l'operatore %.

Ciao!

Link al commento
Condividi su altri siti

Il floating point CCS ha solo un problema: divora memoria, e tanta anche! Ne consuma un'infinità solo per preparare i dati. Io avevo usato l'espediente di visualizzare l'assembler, copiare la parte di preparazione pre e post aperazione (mul, div, add, floatint e intfloat) e costruirmi una sub libreria float. In questo modo la memoria la occupavo una sola volta e non ad ogni chiamata.

Poi se guardi nella directory del compilatore dovresti avere un eseguibile che un'utilità davvero... utile. Ti permette di fare le conversioni, su PC, dal formato float ad intero e viceversa. Non ricordo più il massimo esponente ma comunque è un due elavoto a .... molto. Non dovresti avere problemi di grandezza.

Link al commento
Condividi su altri siti

Giorgio Demurtas

scusatemi ma non ho ancora avuto il tempo di provare il circuito sullo scooter. Quindi non so se potrebbe andare bene anche così com'è. Dandogli gli impulsi a mano riesco ad arrivare a 50 km/h... finchè non lo monto non posso dire altro.

ciao

grazie comunque dei consigli

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora

×
×
  • Crea nuovo/a...