Go Down

Topic: Coda di bit (Read 1 time) previous topic - next topic

leo72

Forse stai usando lo strumento sbagliato. Quella lib serve ad implementare una struttura di tipo FIFO, First In-First Out. A te serve un comune array dove andare a mettere i valori nelle celle che desideri.

Hydrarian

#16
Aug 26, 2013, 06:05 pm Last Edit: Aug 26, 2013, 06:10 pm by Hydrarian Reason: 1
Forse, allora cerco di spiegare meglio il problema. Ho 4 pulsanti che corrispondono a 4 relay. Premendo una sola volta ogni pulsante si scorre il menu e tenendo premuto si seleziona la voce. Selezionare la voce vuol dire attivare i relay per un certo periodo di tempo che varia a seconda della voce che si sceglie: 2, 4+4 o 8 ore. Attivare il relay per 8 ore ha più priorità del farlo per 4+4 o 2, 4+4 ha più priorità del 2. 4+4 significa che fa 4 ore e poi vede se gli altri 3 relay sono stati anche essi programmati per 8 o 4 e nel caso fa prima quelli per poi tornare a fare le sue altre 4 ore. Quindi serve una coda per gestire tutto questo, ma una coda che mi vada a inserire l'elemento che aggiungo nella giusta posizione, perché altrimenti si perderebbero le priorità. Gli elementi all'interno della coda sono byte che ho suddiviso in: primi due bit per etichettare i relay e gli altri 6 per le ore. Siccome la priorità è per le ore, devo tenere conto per l'ordine che andrò a fare sulla coda degli ultimi 6 bit che devono quindi essere in ordine decrescente. Dovrebbe essere questo lo scopo della struttura dati che mi serve... Non so se sia fattibile...

nid69ita

Ma i relay essendo 4, alla fine solo quattro valori devi al massimo memorizzare, giusto?
Cioè se da menu ti riselezionano es. rele2->tempo 8   mentre tu avevi già in code rele2->tempo 2  in questo caso devi togliere quel rele2->2 e mettere rele2->8 verificando anche la priorità in base al tempo?
my name is IGOR, not AIGOR

nid69ita

Se i valori da memorizzare sono tutti, non solo quattro allora ti suggerisco di usare 3 code, una per ogni priorità.
Il programma servirà prima la coda ad alta priorità, se vuota la seconda, altrimenti la terza.
Se metti qualcosa in coda lo fai in quella con priorità giusta. A questo punto nelle varie code non devi più ordinare ma sono solo degli stack code (primo che entra primo che esce per essere servito)
mentre per i valori da memorizzare sono solo gli id dei rele (non devi più avere quella strutturazione dei bits)
my name is IGOR, not AIGOR

leo72

Io dico che un semplice array va più che bene. Ci sono solo 3 casi da controllare:
1) verificare se l'inserimento di un elemento porta l'array a crescere oltre la dimensione massima (e questo è facile da fare, basta usare un indice che punta all'ultima cella dell'array e quando l'indice è uguale alla dimensione, vuol dire che siamo alla situazione limite);
2) se il punto 1) è soddisfatto, controllare se la priorità dell'elemento e posizionarlo dove deve andare. Se va posto in fondo, basta aggiungerlo nella cella puntata dall'indice di cui sopra ed incrementarlo;
3) se va infilato tra gli altri elementi, basta localizzare la cella dove deve andare, spostare in avanti tutte quelle che seguono e mettere poi l'elemento nella cella.

Scrivendo un algoritmo fatto bene, i punti 2 e 3 possono diventare uno solo, dato che il caso dell'elemento da porre nell'ultima cella è identico al caso di un elemento da porre in mezzo alla lista dove, per far posto, va spostato un numero di elementi pari a 0.

Hydrarian

#20
Aug 28, 2013, 12:34 pm Last Edit: Aug 28, 2013, 01:04 pm by Hydrarian Reason: 1
Alla fine ho optato per 3 code perché con una era un po' un casino. Il problema ora è un altro. In una modalità , quella da 4+4 ore, in realtà devo fare devo fare in modo che le 8 ore vengano fatte consecutivamente se la coda con le modalità da 8 ore è vuota; se invece nel mentre faccio la modalità 4+4 viene premuto un altro pulsante modalità 4+4 ma per un altro relay allora vado a finire le prime quattro ore del primo per poi passare alle prime quattro del secondo e fatte queste ritornare al primo per finire il ciclo per poi andare ancora al secondo per finire anche il suo ciclo. Ho provato a stendere una funzione che lo faccia, però entrambi i relay non si fermano mai, continuano a switcharsi all'infinito. Magari è una banalità nel codice:

Code: [Select]
while (codaPR.isEmpty()==true && codaRC.isEmpty()==false){
     if (esecuzionePRY==0){ // coda vuota e nessuna ricarica o priorità in esecuzione
       if (esecuzioneRC==0){ // controlla se è in esecuzione un'operazione di ricarica  
         Serial.println("PASSO UNO PRIMA RICARICA");
         startTimeRC=millis();
         esecuzioneRC=1;
       }
       durataRC =0;     // inizializzo la durata a 0. Questo mi serve perché altrimenti ad ogni iterazione durataRC avrebbe un modulo sempre maggiore e non soddisferebbe mai il prossimo while
       byte elementoRC=codaRC.pop();  // estraggo dalla coda il primo elemento e procedo col ciclo:
       int relayRC = elementoRC >> 6;
       //primo ciclo di ricarica
       
       while (durataRC < ricarica && esecuzioneRC==1 && codaPR.isEmpty()==true && numeroRicarica==0){    // finchè il contatore non raggiunge il tempo di ricarica e finché la ricarica è attiva
         buttonVal = analogRead(buttonPin);    // continua a leggere il valore dei pulsanti per interrompere la ricarica in caso di selezione di modalità priorità
         switchPulsanti();
         durataRC = millis() - startTimeRC;
         digitalWrite(relay[relayRC], HIGH);
         //Serial.println(durataRC);
         /*Serial.print("PRESA ");
          Serial.print(estrattaRC);
          Serial.println(" RC");
          lcd.setCursor(setC,setR);  
          lcd.print(stati[1]); */
       }
       numeroRicarica=1;
       Serial.println("FUORI IL CICLO WHILE ");
       digitalWrite(relay[relayRC], LOW);
       esecuzioneRC=0;
       
       
      if (codaPR.isEmpty()==true && codaRC.isEmpty()==true /*&& codaMN.isEmpty()==true*/ && numeroRicarica==1){  //se sia la coda priorità che ricarica sono vuote allora fai subito altre 4 ore di ricarica
         if (esecuzioneRC==0){ // controlla se è in esecuzione un'operazione di ricarica  
           Serial.println("PASSO DUE (SECONDA RICARICA)");
           startTimeRC=millis();
           esecuzioneRC=1;
         }
          //secondo ciclo di ricarica quando tutte le altre code sono vuote
         
         durataRC =0;     // inizializzo la durata a 0. Questo mi serve perché altrimenti ad ogni iterazione durataRC avrebbe un modulo sempre maggiore e non soddisferebbe mai il prossimo while
         while (durataRC < ricarica && esecuzioneRC==1 && codaPR.isEmpty()==true){    // finchè il contatore non raggiunge il tempo di ricarica e finché la ricarica è attiva
           //Serial.print("DENTRO IL CICLO WHILE ");
           buttonVal = analogRead(buttonPin);    // continua a leggere il valore dei pulsanti per interrompere la ricarica in caso di selezione di modalità priorità
           switchPulsanti();
           durataRC = millis() - startTimeRC;
           digitalWrite(relay[relayRC], HIGH);
         }
       Serial.println("FUORI IL CICLO DI SECONDA RICARICA ");
       digitalWrite(relay[relayRC], LOW);
       esecuzioneRC=0;
       numeroRicarica=0;
       }
       //secondo ciclo di ricarica quando la coda priorità o quella di ricarica sono occupate
     
       else if ((codaPR.isEmpty()==false || codaRC.isEmpty()==false) && numeroRicarica==1) {  
         codaRC.push(elementoRC);
         int nrelay = elementoRC >> 6;
         Serial.print("presa ");
         Serial.print(nrelay);
         Serial.print(" aggiunta alla coda ricarica ");
        numeroRicarica=0;
       }
     }
   }

m_ri

son d'accordo con leo72 che quella libreria è solo un buffer circolare fifo( esce per primo il primo elemento che hai inserito)..dato che ti trovi in una situazione semplice,puoi cavartela come t'han descritto gli altri utenti..

in una situazione con più priorità differenti, la soluzione ideale sarebbe una coda a priorità( gli elementi escono da essa in ordine di grandezza, indipendentemente dall'ordine di inserimento)..con arduino si potrebbe risolvere(con buone prestazioni) usando un albero AVL o RN mappato su array statico, ma non è il tuo caso..

Go Up