Gioco di luci su 14 pin arduino.

Premetto di essere alle prime armi con l’utilizzo della programmazione per tanto abbiate pazienza se sembrerà uno sketch orribile ma posso garantirvi che fa ciò che mi servirebbe o quasi.Se aveste la pazienza di dargli uno sguardo avrei delle domande in merito da porvi:

  1. A prescindere dal fatto che funzioni o meno si potrebbe scrivere ciò in modo migliore?Non voglio che mi scriviate il software vorrei giusto capire come muovermi meglio per rifarlo da me.

  2. Dato che devo usare due registri diversi per azionare tutte le uscite di Arduino nel mio modo di programmare ho riscontrato l’impossibilità di azionare gli stessi con delay diversi posso porvi rimedio in qualche modo?

Lista del mio programma:

.   
int i = 0;
void setup() {
 // put your setup code here, to run once:
DDRD = DDRD | !B11111111;
DDRB = DDRB | B00111111;
}




void loop() {
 // put your main code here, to run repeatedly:
for (i = 0; i < 5 ; i++){
PORTD = PORTD | B10000000;
PORTB = PORTB | B00000001;
delay(500);
PORTD = PORTD | B10100000;
PORTB = PORTB | B00000011;
delay(500); 
PORTD = PORTD | B10101000;
PORTB = PORTB | B00000111;
delay(500);
PORTD = PORTD | B10101010;
PORTB = PORTB | B00001111;
delay(500);
PORTD = PORTD & B00000000;
PORTD = PORTD | B01000000;
PORTB = PORTB | B00011111;
delay(500);
PORTD = PORTD | B01010000;
PORTB = PORTB | B00111111;
delay(500);
PORTB = PORTB & B00101010;
PORTD = PORTD | B01010100;
delay(500);
PORTB = PORTB & B00000000;
PORTB = PORTB | B00010101;
PORTD = PORTD | B01010101;
delay(500);
PORTD = PORTD & B00000000;
PORTB = PORTB & B00000000;
//delay(500);
}
for (i = 0; i < 5 ; i++){
PORTD = PORTD | B10101010;
PORTB = PORTB | B00101010;
delay(500);
PORTD = PORTD >> 1;
PORTB = PORTB >> 1;
delay(500);
PORTD = PORTD << 1;
PORTB = PORTB << 1;
}
PORTD = PORTD & B00000000;
PORTB = PORTB & B00000000;
  }
}

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento se non lo hai già fatto: Regolamento
Qui una serie di link utili, non inerenti al tuo problema:

Il codice devi racchiuderlo nei tag code, vedi sezione 7 del regolamento, spiega bene come fare ( pulsante </> ).
Altrimenti parte del codice può essere visualizzata male o mancare perchè interpretato come attributo del testo stesso.

Non ho capito la domanda del punto 2. Vuoi azionare i singoli bit/pin ? Vedi la bitWrite(PORTD,pin, 0 oppure 1);

Questo mi sembra inutile come operazione AND sui bit, PORTD = PORTD & B00000000; Tanto vale PORTD=0;

Se vuoi usare ritardi diversi indipendenti, non puoi usare "delay", perche' blocca tutto (cioe', mentre aspetta che passi il delay, il micro non fa assolutamente nient'altro) ... credo tu debba usare cicli di controllo indipendenti con i ritardi gestiti da millis (un po come nell'esempio "blinkwithoutdelay", ma con molti piu cicli indipendenti, in base a quanti te ne servono per la tua applicazione)

nid69ita: Non ho capito la domanda del punto 2. Vuoi azionare i singoli bit/pin ? Vedi la bitWrite(PORTD,pin, 0 oppure 1);

Questo mi sembra inutile come operazione AND sui bit, PORTD = PORTD & B00000000; Tanto vale PORTD=0;

Grazie per le risposte, non voglio manovrare un singolo bit, ho usato i registri per manovrarli anche tutti in una sola riga di comando, non so se sia corretto o meno ma ho scelto di usare AND ed OR perché normalmente sono logiche facilmente gestibili dai processori al contrario di una assegnazione diretta che manovra tutti i bit. Tra l'altro la mia informatica è piuttosto entry level e non sapevo potessi eguagliare il registro ad un solo bit al posto di 8. Nella 2ª domanda chiedevo appunto come differenziare i tempi tra i due registri perche con delay blocco per il tempo stabilito tutto il programma...

Ciao, vedendo questo pezzo di codice:

PORTB = PORTB & B00000000;
PORTB = PORTB | B00010101;

alla prima riga moltiplichi il valore della porta B * 0 quindi come dice Nid69ita Etemenanki tantovale che dici B=0 (in pratica resetti la porta). Alla seconda riga sommi 10101 allo 0 che hai appena impostato, a questo punto elimini le due righe e sostituisci con

PORTB = B00010101;

Per il ritardo programmabile è un pò più complicato, io memorizzerei i vari stati del gioco di luce in una variabile a matrice poi, creati i 2 timer farei incrementare 2 contatori (es. Cg1 e Cg2 )ogni tot millisecondi tramite due if più o meno così

#define dt1 500 // delay gioco 1
#define dt2 700 // delay gioco 1

byte  gioco1[]{B10000000,B10100000,B10101000,B10101010};
byte  gioco2[]{B11000000,B00110000,B00001100,B00000011};

void setup{
byte cg1;
byte cg2;
unsigned long t1=millis();
unsigned long t2=millis();
}

void loop{
if (millis()-t1>dt1){
dt1=millis();
PORTB =gioco1[cg1];
if(cg1>3) cg1=0;
}
if (millis()-t2>dt2){
dt2=millis();
PORTD =gioco2[cg2];
if(cg2>3) cg2=0;
}

}

Senz'altro sembra macchinoso ma (spero sia già quasi a posto) spero ti possa essere di aiuto.... In sostanza memorizzo il millis, quando vedo che è oltre il tempo prefissato riporto la variabile=millis, incremento il contatore che pesca dalla matrice il gioco e lo visualizza. quando la differenza tra millis e la variabile ritorna oltre il tempo prefissato pesco il gioco successivo e lo mostro. Il tutto per entrambi i giochi

Ovvio... salvo errori ed omissioni :)

@seti81: Come ti è stato già detto, il codice, in conformità al REGOLAMENTO, punto 7, DEVE essere racchiuso tra i tag CODE (… sono quelli che in edit inserisce il bottone fatto così: </>, tutto a sinistra). Quindi, edita (in basso a destra del post, bottone More → Modify) il tuo post e racchiudi il codice all’interno dei tag CODE. Grazie.

Guglielmo

Scusate l'errata immissione dello sketch, ho fatto tutto da cellulare. Grazie cam9500 ora mi è chiara l'inutilita della funzione logica in certe circostanze, per quanto riguarda il codice che hai scritto ho difficoltà ad apprenderlo nell'interezza,devo studiarlo con pazienza e non voglio copiarlo ,vorrei comprenderlo in modo da poterlo sfruttare nel miglior modo.

Ciao, immagino… ma in caso di dubbi discutiamone :slight_smile:

Stefano

Si scusa, ho messo Etemenanki al tuo posto (corretto), poi ho aggiunto anche l'OR successivo al reset che anch'esso è inutile

Con un'attenta lettura riesco a comprendere l'intento dello sketch che hai scritto ed effettivamente risolverebbe ma così com'era non andava, lo ho modofocato e per il compilatore è ok ma per arduino meno, allego lo sketch:

#define dt1 500 // delay gioco 1
#define dt2 700 // delay gioco 1
byte  gioco1 [] {B11000000,B00110000,B00001100,B00000011};
byte  gioco2 [] {B00100001,B00110000,B00001100,B00000011};
unsigned long t1 = millis();
unsigned long t2 = millis();
byte cg1;
byte cg2;

void setup (){
DDRD = DDRD | B11111111;
DDRB = DDRB | B00111111;
}
void loop (){
  
if (millis() - t1 > dt1){
dt1 == millis();
PORTD = gioco1[cg1];
if(cg1=4) cg1=0;
}
if (millis() - t2 > dt2){
dt2 == millis();
PORTB = gioco2[cg2];
if(cg2=4) cg2=0;
}

}

Il problema e che la matrice di sequenze visibilmente non cicla o non la vedo dunque resta fermo alla prima definizione per entrambi i registri.

Hai ragione, scusa, l’ho fatto al volo in treno!
In effetti mancano anche cg1++ e cg2++ nei rispettivi if. Senza quelli il contatore non si incrementa ed il gioco rimane fermo.
Altro errore è dt1. Definendolo in define non è una varibile ma, per semplicità, una costante quindi non potevo assegnarli un valore (un refuso dai…).
Occhio alla differenza == e = comparazione di eguaglianza (==) e assegnazione (=).

Il codice dovrebbe andare (l’ho compilato x sicurezza):

void loop (){
  
if (millis() - t1 > dt1){
// dt1 == millis();<----------- errato, (corretto con il == ancora più errato)
t1=millis();
PORTD = gioco1[cg1];
cg1++;  // <----------- mancava
if(cg1==4) cg1=0;
}
if (millis() - t2 > dt2){
// dt2 == millis();<----------- errato, (corretto con il == ancora più errato)
t2 = millis();
PORTB = gioco2[cg2];
cg2++;  // <----------- mancava
if(cg2==4) cg2=0;
}

}

…poi nel setup perchè metti:

void setup (){
DDRD = DDRD | B11111111;
DDRB = DDRB | B00111111;
}
//metti solo:
void setup (){
DDRD = B11111111;
DDRB = B00111111;
}

Non hai alcun motivo di scusarti! Anzi! Ora funziona alla perfezione, effettivamente non capivo come facesse ad aumentare il valore dei registri e come farlo io, non ho ancora affrontato a fondo "IF" ed ora grazie a te so anche quello... Posso racchiudere il ciclo in un for per fargli fare un definito numero di cicli per poi andare in un altro? come avevo fatto nella mia versione che lavora direttamente sui registri?

Si, oppure puoi allungare gioco1 e gioco2 ed includere altri giochi (non credo ci siano particolari problemi di lunghezza). Unica cosa, nell'if dove trovi if(cg1==4) cg1=0; devi correggere il 4 con la nuova lunghezza.

Appena hai capito come gira sarà una sciocchezza ;)