home | area personale         schemi | tutorial | robotica | pic micro | recensioni         forum | chat irc         faq | contatti         store | Ordina PCB
username
password
cerca

 
FORUM: Pic Micro
Tutto quanto riguarda questi microprocessori... progetti, suggerimenti, aiuti, discussioni...ecc


Fronte di salita o discesa.
     
Autore Messaggio opzioni
FrancoGual



[pagine pubblicate]

postato il:
17.02.2019, alle ore 20:22
Fronte di salita o discesa. 

Buonasera, una domanda su arduino.
Sto giocando con un misuratore, i sensori sono dei finecorsa recuperati da una stampante, i fotosensori ad U per capirci.
Se io volessi far partire il trigger su un fronte piuttosto che l'altro, salita o discesa intendo, nel codice come dovrei agire?
Grazie.



Anche il viaggio più lungo inizia con un piccolo passo.
Si vis pacem, para bellum!!!
Mark Zuckerberg ha reso suoi schiavi milioni di persone senza che se ne rendessero conto. F.G.
<Avete vinto voi,ma almeno non riuscirete a considerarmi vostro complice> Da Mediterraneo.
Inferno,Canto III,verso 51 Virgilio dice.........
rcc.roberto



[pagine pubblicate]

postato il:
17.02.2019, alle ore 20:51
fai un doppio ciclo if

se è alto
--se è basso
-------fai questo
--fine se
fine se

e viceversa
double_wrap




una ogni 100 livelli
una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli


postato il:
17.02.2019, alle ore 21:47
Una strada alternativa e' usare gli interrupt sui pin D2 o D3. puoi usarne due contemporaneamente con arduinoUno
https://www.arduino.cc/reference/en/language/functions/exter…
QUi un esempio di base

volatile  boolean finecorsa_uno; // deve essere <volatile> nella routine ISR
volatile  boolean finecorsa_due; // deve essere <volatile> nella routine ISR

setup(){
...
attachInterrupt(digitalPinToInterrupt(2), routine_ISR_uno, mode);
attachInterrupt(digitalPinToInterrupt(3), routine_ISR_due, mode);
// mode= RISING, FALL, CHANGE, LOW
...
}

void routine_ISR_uno {
finecorsa=true;
}

void routine_ISR_due {
finecorsa_due=true;
}
void loop(){
...

if(finecorsa_uno) {
//fai la cosa A
finecorsa=false;
}

if(finecorsa_due) {
//fai la cosa B
finecorsa_due=false;
}

... 
}



"se peso cado, ma se cado non peso"
adamatj.altervista.org
double_wrap




una ogni 100 livelli
una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli


postato il:
17.02.2019, alle ore 21:50
errata!

Dove e' scritto <finecorsa> si deve scrivere <finecorsa_uno>
abbi pazienza....



"se peso cado, ma se cado non peso"
adamatj.altervista.org
FrancoGual



[pagine pubblicate]

postato il:
17.02.2019, alle ore 22:13
Grazie per le risposte e del vostro tempo.
Ehm.... piccolo problema, che ho dimenticato di esporre, ho poco tempo.
In pratica se unisco start e stop e metto a massa, quando rilascio, ovvero immagino legga il fronte di salita il display mostra 8 microsecondi, Dovrebbe essere il tempo di elaborazione, purtroppo non posso andare oltre.
Nella mia ignoranza suppongo che fargli fare un doppio if allungo i tempi di valutazione.
In ogni caso utilizzo già gli ingressi D2 D3 come interrupt, sto utilizzando un 4011 su entrambi gli ingressi per adattare i segnali.



Anche il viaggio più lungo inizia con un piccolo passo.
Si vis pacem, para bellum!!!
Mark Zuckerberg ha reso suoi schiavi milioni di persone senza che se ne rendessero conto. F.G.
<Avete vinto voi,ma almeno non riuscirete a considerarmi vostro complice> Da Mediterraneo.
Inferno,Canto III,verso 51 Virgilio dice.........
double_wrap




una ogni 100 livelli
una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli


postato il:
17.02.2019, alle ore 22:49
Con tempi sotto i 10 microsecondi servirebbe disabilitare tutti gli interrupts interni, ad esempio <delay()> usa l'interrupt del timer_0 che qualche ciclo se lo prende.
Per riabilitare gli interrupt esterni (pin2 e 3) servirebbe lavorare sui registri, si dovrebbe poter fare.

Tieni presente che la funzione <micros()> riporta i microsecondi passati dall'avvio ma solo a passi di 4 microsecondi e che anche la funzione <delaymicroseconds()> non e' affidabile sotto i 4 microsecondi
https://www.arduino.cc/reference/en/language/functions/time/…
https://www.arduino.cc/reference/en/language/functions/time/…



"se peso cado, ma se cado non peso"
adamatj.altervista.org
FrancoGual



[pagine pubblicate]

postato il:
17.02.2019, alle ore 23:19
Dunque la misura reale può andare da 500 a 3000 microsecondi, di più occorre rivedere il lavoro fatto.
Il crono di per se arriva a 3 secondi come timeout o errore.
Quindi se riesco a stare sotto i 10 posso dire che la PRECISIONE , maiuscolo per non usare le virgolette... è accettabile.
L'integrato all'ingresso introduce un ritardo di propagazione di circa 60 nanosecondi, oltretutto sia in start che in stop, quindi diciamo che è trascurabile.
Diciamo che via harware avrei risolto, tuttavia diventa una questione di principio, ovvero è un microcontrollore quindi deve fare quello che voglio, non quello che vuole. :-)



Anche il viaggio più lungo inizia con un piccolo passo.
Si vis pacem, para bellum!!!
Mark Zuckerberg ha reso suoi schiavi milioni di persone senza che se ne rendessero conto. F.G.
<Avete vinto voi,ma almeno non riuscirete a considerarmi vostro complice> Da Mediterraneo.
Inferno,Canto III,verso 51 Virgilio dice.........
gironico




una ogni 100 livelli


postato il:
18.02.2019, alle ore 09:06
un IF....

dentro eventualmente un altro IF...

e poi un altrimenti ELSE....

puoi scegliere anche la strada del WHILE.... rimane dentro li ma ricorda che poi per uscire, fai una verifica eventualmente con un un IF... e usi un BREAK... lascierei perdere un 4011...



La vita è troppo breve per bere vini mediocri
picmicro675




una ogni 10 livelli


postato il:
18.02.2019, alle ore 12:41
Se si tratta di rilevare dei pulsanti o finecorsa e ripulire i rimbalzi io userei un cosa del genere
#define  TMPRESS 20                    // ritardo di rilascio input
#define BOTTOM    200

uint16_t last_millis;
uint8_t numpress = 0;
bool state = 0;
bool prevstate = 0;


void ckbutton() {
   state = digitalRead(STARTBTN);
    if  ((state != prevstate) && (prevstate == 0)) {
        last_millis = millis();
        prevstate = state;
    }
    if ((state != prevstate) && (prevstate == 1)) {
        if ((millis() - last_millis) >= TMPRESS) {
            ++numpress;
        }
        prevstate = state;
   }
}
void loop() {
    ckbutton();
    switch (numpress ) {
    case 0 : {
        display = 0;
        delay(200);
    }
    break ;
    case 1 : {
        display = 1;
    }
    break;
    case 2 : {
        display = 8;
    }
    break;
    case 3 : {
        display = 64;
        numpress = 0;
    }
    break;
    }
}
}

Questo determina una automa a stati finiti
https://it.wikipedia.org/wiki/Automa_a_stati_finiti
che permette di determinare da quale stato a quale stato si passa. Inoltre in questo caso si verifica che sia passato anche un determinato periodo di tempo, utile a filtrare i rimbalzi.
In questo esempio, si usa numpress, per fare una selezione ciclica.
Ma se fosse per utilizzare con dei pulsanti allora la libreria Button è la più indicata, che usa comunque la FMS, permettendo anche diversi tipi di funzioni con un solo pulsante (premuto breve, a lungo, ritenuto basso, doppio click)



Anno nuovo, forum nuovo.
Mi sa che lascio.
double_wrap




una ogni 100 livelli
una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli una ogni 10 livelli


postato il:
18.02.2019, alle ore 19:02
FrancoGual:
[CUT] utilizzo già gli ingressi D2 D3 come interrupt [CUT]

Se ho ben capito stai realizzando un timer start-stop per misurare intervalli fra 500 e 3000 microsecondi con una <risoluzione> ammessa di poco meno di 10 microsecondi.

Visto che gia' usi gli interrupt esterni, verifica che stai usando il D2 (pin4 dell'atmega e Int_0) per lo start e il D3 per lo stop (pin5 5 e int_1) perche' la priorita' degli interrupt e' RESET, int_0_, int_1, ecc
https://docplayer.it/7634461-Gestione-dell-interrupt-con-il-…
Se bastano 4/8 microsecondi di risoluzione puoi usare la funzione <micros()> in entrambe le routine di interrupt

volatile unsigned long time_start;
volatile unsigned long time_stop;
volatile boolean flag_stop=false;
unsigned long tempo;

void routine_ISR_start {  //routine lanciata da D2
time_start=micros();
}

void routine_ISR_stop {   // routine lanciata da D3
time_stop=micros();
flag_stop=true;     // dato pronto
}  

void loop(){
....
if(flag_stop){     // se il dato e' pronto
tempo=stop-start;  // calcola la durata
flag_stop=false;   // dato acquisito
}

//display tempo;



Per risoluzioni sotto 4 microsecondi si potrebbe impostare il prescaler del timer_1 ad <1> (di default e' 64) e in tal modo il timer avanza con la velocita di 16 MHz, poi le routine di interrupt start e stop vanno a leggere il valore corrente del timer_1.
C'e' anche la modalita' nativa <timer input capture> che legge il timer quando ce' un evento
http://www.electronicwings.com/avr-atmega/atmega1632-timer-i…
pero' e' tutto da approfondire




"se peso cado, ma se cado non peso"
adamatj.altervista.org
segui questo thread con grixFC, per questa funzione devi aver installato il software grixFC

torna su
     

Come utente anonimo puoi leggere il contenuto di questo forum ma per aprire una discussione
o per partecipare ad una discussione esistente devi essere registrato ed accedere al sito




 







 
 
indietro | homepage | torna su copyright © 2004/2024 GRIX.IT - La community dell'elettronica Amatoriale