Rilevare fino a 8 transazioni contemporaneamente

Salve a tutti, sto avendo a che fare con un progetto che non immaginavo fosse tanto complicato.
Devo monitorare fino a 8 pin contemporaneamente.
Per fare bene le cose, devo rilevare una transazione LOW - HIGH - LOW.

Inizialmente avevo assegnato gli 8 pin ad un unico banco che leggevo tutto insieme con la funzione PINx ma poi mi sono perso un pò e adesso mi chiedo se non sia meglio utilizzare 8 interrupt (posso abilitarli su pin a scelta sul Mega2560?).

Avete dei suggerimenti in merito?
grazie

Cominciamo con il dire che le tue non sono transazioni ma transizioni (da uno stato ad un altro).

Questo non tanto per correggerti, ma per il fatto che in informatica la transazione ha un significato completamento diverso.

Con il MEGA e l'attuale compilatore puoi gestire un massimo di 6 external interrupt alcuni dei quali sono eventualmente utilizzati dalla porta Serial1 e da I2C.

Quindi l'unica via tramite interrupt è quella di utilizzare il pin change interrupt: in pratica, monitorizzi il cambio di stato di un gruppo di pin, restando poi a te l'onere di capire quale dei pin ha subito una transizione di stato ed agire di conseguenza.

Non ho ancora mai utilizzato questa tecnica, ma se ne parlato qualche tempo fa.

E' un po' pallosa perché attivando i PCINT (PinChangeInterrupt) i pin sono raggruppati a gruppi di 8. Esiste un registro che raccoglie gli interrupt (PCICR). Se si attiva un interrupt su un pin di una porta, il relativo flag viene portato ad 1 (PCIEx).
Intercettando la relativa routine di gestione dell'interrupt (ISR) devi poi andare a vedere qual è il pin corrispondente analizzando il registro che "registra" i cambi di stato dei pin (PCMSKx).

Se non vuoi lavorare a mano modificando i registri (datasheet cap 15.2) puoi usare se c'è una lib preconfezionata, la PinChangeInt:
http://code.google.com/p/arduino-pinchangeint/

Non so quanti interrupt è in grado di gestire contemporaneamente, io mi sono limitato sempre a gestirne 1.

Ok adesso verifico quanti pin riesce a gestire.

Ma mi sorge un dubbio.
Se ogni interrupt attivasse una funzione divers, non avrei risolto il problema di capire quale degli interrupt è stato attivato?

Nel caso risultasse più semplice, mi piacerebbe valutare insieme a voi anche soluzioni diverse dall'interrupt.
Leggendo cioè il banco di pin in input per rilevare le transizioni.

Avevi cominciato bene facendolo con PORTA-B-C e PINA-B-C ecc, se non ti serve un rilevamento di us, confrontare il PORTA precedente con il PORTA istantaneo ad ogni loop è la soluzione migliore.

Tra le altre cose l'ho fatto sulla Mega per tutti gruppi PORT ritoccandoli un po' per necessità di spazio su eeprom, li comando e li leggo tutti con una matrice di 2 byte

Molto interessante! No i us non mi interessano.

Vedere un pò di codice sarebbe molto d'aiuto.

Mettevi tutto in un byte e poi confrontavi bit a bit?
La mia sensazione è questa:

Devo controllare 8 motori, di cui ne posso attivare da 1 a 8 contemporaneamente. Dipende dalle circostanze.
Poi ho 8 sensori, uno per motore la cui uscita va da 0 a 1 al verificarsi di certe condizioni.
Non appena rilevo questa transizione, devo spegnere il motore.

Per far si che tutto avvenga nello stesso istante di tempo setto i pin di OUTPUT dei motori con il comando PORT (A).
Allo stesso scopo, per leggere i pin di INPUT collegati ai sensori uso il comando PIN sul registro corrispondente (L).
Quindi quello che voglio fare è:

  • leggere solo i pin corrispondenti ai motori attivi;
  • cercare le transizioni da 0 a 1;
  • spegnere il motore corrispondente al sensore che mi ha dato la transizione
  • continuare a fare questa operazione finchè tutti i motori non sono spenti

So che devo giocare con i binari, ma mi sta risultando complicato mettere tutto su codice.

Grazie mille la sto già provando e vedo che va benissimo.

Solo un dubbio, anche se non è fondamentale.

Come ti dicevo devo spegnere il motore non appena rilevo una variazione sul sensore corrispondente.
Ora, per una questione di temporizzazione, sarebbe utile spegnere il motore dopo 2 sec dal cambiamento del sensore.

Ma un delay mi farebbe perdere le variazioni sugli altri sensori che nel frattempo potrebbero accadere.
Dico bene? Esiste qualche stratagemma?

Ma allora stai facendo quello che ho fatto io!! :slight_smile:

Quale gruppo di pin hai scelto per gli 8 sensori?

Ah si?!
E tu come hai risolto?

Per i sensori ho usato il banco pin 42-49!

:cold_sweat:
Interessante cerco di analizzarlo un pò per comprenderlo appieno.

Nel mio caso gli input non sono impulsivi, ma hanno solo un'uscita active-low. Cambia qualcosa?

Infine volevo chiederti un chiarimento su questa vondizione

if ((New_Val_Port ^ Hold_Val_Port) & 1<<i && Pin[i] != 99)

fai un xor per rilevare vaziazioni fra i due val_port
Poi fai un and con 1 ma non capisco a cosa serva <<i. E' uno shift di bit o cosa?

Scusa la domanda banale ma non sono riuscito a comprenderlo.

Ma un delay mi farebbe perdere le variazioni sugli altri sensori che nel frattempo potrebbero accadere.

senza dubbio

Poi fai un and con 1 ma non capisco a cosa serva <<i. E' uno shift di bit o cosa?

Si è un operatore bit a bit Shift Left sposta a sinistra, se può esserti utile 1.3 Operatori.

Nel mio caso gli input non sono impulsivi, ma hanno solo un'uscita active-low. Cambia qualcosa?

no, in questo caso i pin impulsivi che vado a comandare non sono Input (non potrebbe essere), ma devi inserire quali pin Output lo saranno (in realtà questo software agisce anche sugli input quando si trova in automatico, praticamente preme un pulsante da solo quando l'uomo è assente modificando di proposito il PINx elaborandone poi il pinchange, ma non è il tuo caso)

digitalWrite(i, 0); //spengo il pin dopo n secondi dall'intercettazione del pinchange degli Input
Per "i" intendo l'array dei pin output che sono soggetti a temporizzazione, non è proprio facile facile spiegartelo, è più facile farlo, se hai dei dubbi chiedi pure
Del resto ci sono sopra da un anno su questo progetto, quindi lo avrò riscritto migliaia di volte :sweat_smile: comprende buona parte di quello che riguarda arduino manipolazione dei registri, timers, compressione dati su eeprom, sd, shield, i2c, seriali, sensori analog di vario tipo, http, interfacce elettroniche, sound, acquisizione automatica di segnali IR salvata su EE, ripetizione IR prelevata da EE, 485, onde convogliate, display, tranne wifi e altre cosette riguardanti la meccanica che non mi interessa. Imparo cose nuove tutti i giorni, poi butto tutto e passo a un altro micro ahahahahahah

ciao

Quindi mi pare di capire che questo pezzo di codice a me non serve:

void read_time_pin_impuls()
{
    for ( byte i = 0; i < 8; i++)//leggo l'array dove scrivi i tempi da rispettare 1/255 (1 secondi a 4 minuti circa)
    {          
        qui richiami e leggi  l'array dei tempi registrati che dovrai mettere nella sez pubblica
        io  qui prendo i valori da eeprom, tu ti crei un array
        
       if( val_ee_impulse != 0 && millis() - millis_impuls_pin[i] > (val_ee_impulse*1000)) //se è =0 resta sempre acceso, non è impulsivo
        { 
          millis_impuls_pin[i]=0;  //cancello il valore millis che avevo registrato al cambiamento
          digitalWrite(i, 0); //spengo il pin dopo n secondi
                         
        }   
    }     
}

dico bene?

digitalWrite(i, 0); //spengo il pin dopo n secondi dall'intercettazione del pinchange degli Input

Non ho capito bene come implemento l'attesa di n secondi senza bloccare la lettura dei sensori.
Grazie per la disponibilità

allora adesso sono io che non ho capito :slight_smile:
questi 8 motori sono già accesi?
si accendono per x secondi quando premi il bottone corrispondente?

qual'è la logica partendo da uno stato di riposo
do alimentazione alla baracca ...... cosa sono pompe, ventole?
si attivano su livelli? temperature?

I motori sono vengono accesi da una funzione precedente.
Come già detto, possono essere attivi da 1 a 8 motori contemporaneamente.
(Movimentano 8 nastri trasportatori).

Supponiamo poi che ho 8 pulsanti, uno per ogni motore.
Non appena premo un pulsante deve spegnersi il motore corrispondente, dopo 2sec, durante i quali però
devo continuare a controllare lo stato degli altri tasti.

Spero di essere stato più chiaro, scrivere di ste robe può rivelarsi ostico.

Dunque mi sono schioppato i tuoi 50 post precedenti, volevo capire di cosa stai parlando.
Mi sembra che anche tu .... non è un anno ma poco ci manca

-Con il mio MEGA sto realizzando un sistema di movimentazione abbastanza complesso e devo stare attento a farmi bastare i pin di I/O.
Il punto è che devo realizzare 8 barriere IR, per monitorare il passaggio di alcuni pezzi in 8 punti specifici.
-Stavo cercando una soluzione per resettare il mio arduino mega via software.
-sto realizzando un sistema in grado di pilotare un motore dc con PWM a 4096 step(ottenuto grazie al TLC5940).
L'arduino dovrà incrementare la velocità del motore e leggere la velocità del motore dal suo encoder ed il valore in tensione di una cella di carico.
-Devo realizzare uno strumento di misura, basato su arduino, per prove su materiali.
L'obiettivo è acquisire l'uscita di una cella di carico con portata 100g con risoluzione minima di 0,01g.
La cella di carico è dotata di uscita 4-20mA, a 0g corrispondono 4mA, a 100g ne corrispondono 20 mA.
-Ho un motore DC MAVILOR MO-80 dotato di encoder con Ch A - Ch B e Ch Z, non ho info sul numero di impulsi per rotazione, ma potrai contarli con l'oscilloscopio fra due impulsi di zero (letti sul Ch Z) successivi.
Ciò che devo rilevare è la velocità di rotazione dell'albero, (o meglio i giri al minuto,)non mi interessa la posizione.
-sto lavorando ad un sistemino per la movimentazione di pezzi/oggetti/pacchetti.
Devo verificare che questi non si inceppino, accertandomi che il piatto/teglia usato per spostare la merce sia vuoto.
Il piatto è circa 20cmx80cm ed è di colore bianco.
-L'obiettivo è verificare che il nastro, a un certo punto, abbia scaricato tutti gli articoli.
-Adesso leggere 8 IR per bloccare i nastri dopo 2 secondi (che poi sarebbero i famosi 8 pulsanti)....

Sti caxxi ... e tu tutto questo lo fai con una mega? :astonished: :astonished: magari a livello hobbystico ]:smiley: ]:smiley:
Ma li hai risolti tutti questi problemi?

comunque quella funzione read_time_pin_impuls() la puoi usare per spegnere i motori dopo n secondi, in definitiva si tratta solo di confrontare i ms registrati con quelli istantanei.
Mi chiedi se lo fa controllando anche gli altri pin? certo che lo fa .... nonostante io abbia da leggere SD, eeprom , tutti i pin, rtc, webserver ecc lo fa 1036 volte/sec penso che ti possa bastare

Pablos,
le mie scuse per il ritardo nella risposta.
Ho avuto qualche problemuccio negli ultimi giorni.

Comunque i post che hai recuperato riguardano circa 4 progetti diversi, quindi non è poi molto complicato quello che sto facendo.

Mi sto rimettendo in sti giorni a combattere con il firmware che mi hai passato per tentare di adattarlo alla mia problematica.
Grazie per la disponibilità, nel caso torno a disturbare J