Jump to content
PLC Forum


Sign in to follow this  
Giorgio Demurtas

Contachilometri Con Pic16f84 - autocostruito...

Recommended Posts


dlgcom

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
dlgcom

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;


}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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ì?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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! ;)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
giacomo56

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.

Edited by giacomo56

Share this post


Link to post
Share on other sites
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??? <_<

Share this post


Link to post
Share on other sites
wnc
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).

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
wnc

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!

Share this post


Link to post
Share on other sites
Livio Orsini

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.

Share this post


Link to post
Share on other sites
wnc

Scusa ma non puoi usare, invece dei float, i long (interi a 32bit) o short long (intero a 24bit)?

Ciao!

Share this post


Link to post
Share on other sites
Livio Orsini
Scusa ma non puoi usare, invece dei float, i long (interi a 32bit) o short long (intero a 24bit)?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
dlgcom
Ad esempio se la variabile è di tipo intera senza segno puoi arrivare a 65535

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...