Errore 'Jump to label'

Salve. Sto realizzando un progetto per l’esame di maturità, un tris (o tic-tac-toe dir si voglia) elettronico.
Ci sono 2 label chiamati rispettivamente “GIOCATORE1” e “GIOCATORE2”.
Funzionano in questo modo:
Quando il 1° giocatore “clicca” la casella dove vuole piazzare la sua crocetta, se la casella è già occupata da un simbolo, “si attiva” il ‘goto GIOCATORE1’ per far andare il loop il programma fino a che il 1° giocatore non clicca una casella vuota. Viceversa, in caso la casella cliccata non fosse occupata, la casella viene attivata e marchiata come “occupata”, in seguito “si attiva” il ‘goto GIOCATORE2’ che fa partire il programma del 2° giocatore (che funziona allo stesso modo).

Il programma ancora non è completo, sto utilizzando solo 4 caselle (ne dovrei utilizzare 9). E’ più che altro un test per provare i comandi.
Comunque posto di seguito, il programmino:

// state_n = STATO ATTUALE DELLA CASELLA
//           0 = SPENTA
//           1 = DEL GIOCATORE 1
//           2 = DEL GIOCATORE 2
//----------------------------------------
//
// PIN = 2 --> CASELLA1 - state_1 == 1
//       3 --> CASELLA1 - state_1 == 2
//       4 --> CASELLA2 - state_2 == 1
//       5 --> CASELLA2 - state_2 == 2
//       6 --> CASELLA3 - state_3 == 1
//       7 --> CASELLA3 - state_3 == 2
//       8 --> CASELLA4 - state_4 == 1
//       9 --> CASELLA4 - state_4 == 2
//       A0 --> INPUT.CASELLA1
//       A1 --> INPUT.CASELLA2
//       A2 --> INPUT.CASELLA3
//       A3 --> INPUT.CASELLA4

int state_1 = 0;
int state_2 = 0;
int state_3 = 0;
int state_4 = 0;

void azzera() {
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  delayMicroseconds(1);
}

void leds_1() {
  if(state_1 == 0) {
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
  }
  if(state_1 == 1) {
  digitalWrite(2,HIGH);
  digitalWrite(3,LOW);
  }
  if(state_1 == 2) {
  digitalWrite(2,LOW);
  digitalWrite(3,HIGH);
  }
}
void leds_2() {
  if(state_1 == 0) {
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  }
  if(state_1 == 1) {
  digitalWrite(4,HIGH);
  digitalWrite(5,LOW);
  }
  if(state_1 == 2) {
  digitalWrite(4,LOW);
  digitalWrite(5,HIGH);
  }
}
void leds_3() {
  if(state_1 == 0) {
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
  }
  if(state_1 == 1) {
  digitalWrite(6,HIGH);
  digitalWrite(7,LOW);
  }
  if(state_1 == 2) {
  digitalWrite(6,LOW);
  digitalWrite(7,HIGH);
  }
}
void leds_4() {
  if(state_1 == 0) {
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  }
  if(state_1 == 1) {
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW);
  }
  if(state_1 == 2) {
  digitalWrite(8,LOW);
  digitalWrite(9,HIGH);
  }
}

void setup() {
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
}

void loop() {
unsigned long tempo = millis();
tempo = 0;
if(tempo > 0 && tempo <= 10) {
  leds_1();
}
azzera(); // USCITE TUTTE = 0
if(tempo > 10 && tempo <= 20) {
  leds_2();
}
azzera(); // USCITE TUTTE = 0
if(tempo > 20 && tempo <= 30) {
  leds_3();
}
azzera(); // USCITE TUTTE = 0
if(tempo > 30 && tempo <= 40) {
  leds_4();
}
azzera(); // USCITE TUTTE = 0
///
///
GIOCATORE1:
int casella_1 = digitalRead(A0);
if(casella_1 == 0) {
  if(state_1 = 0) {
    state_1 = 1;
    delayMicroseconds(1);
    goto GIOCATORE2;
  }
  if(state_1 == 1 || state_1 == 2) {
    goto GIOCATORE1;
  }
}
int casella_2 = digitalRead(A1);
if(casella_2 == 0) {
  if(state_2 = 0) {
    state_2 = 1;
    delayMicroseconds(1);
    goto GIOCATORE2;
  }
  if(state_2 == 1 || state_2 == 2) {
    goto GIOCATORE1;
  }
}
int casella_3 = digitalRead(A2);
if(casella_3 == 0) {
  if(state_3 = 0) {
    state_3 = 1;
    delayMicroseconds(1);
    goto GIOCATORE2;
  }
  if(state_3 == 1 || state_3 == 2) {
    goto GIOCATORE1;
  }
}
int casella_4 = digitalRead(A3);
if(casella_4 == 0) {
  if(state_4 = 0) {
    state_4 = 1;
    delayMicroseconds(1);
    goto GIOCATORE2;
  }
  if(state_4 == 1 || state_4 == 2) {
    goto GIOCATORE1;
  }
}
goto GIOCATORE1;
//
//
//
//FINE PROGRAMMA GIOCATORE1
//
//
//
GIOCATORE2:
casella_1 = digitalRead(A0);
if(casella_1 == 0) {
  if(state_1 = 0) {
    state_1 = 2;
    delayMicroseconds(1);
    goto GIOCATORE1;
  }
  if(state_1 == 1 || state_1 == 2) {
    goto GIOCATORE2;
  }
}
casella_2 = digitalRead(A1);
if(casella_2 == 0) {
  if(state_2 = 0) {
    state_2 = 2;
    delayMicroseconds(1);
    goto GIOCATORE1;
  }
  if(state_2 == 1 || state_2 == 2) {
    goto GIOCATORE2;
  }
}
casella_3 = digitalRead(A2);
if(casella_3 == 0) {
  if(state_3 = 0) {
    state_3 = 2;
    delayMicroseconds(1);
    goto GIOCATORE1;
  }
  if(state_3 == 1 || state_3 == 2) {
    goto GIOCATORE2;
  }
}
casella_4 = digitalRead(A3);
if(casella_4 == 0) {
  if(state_4 = 0) {
    state_4 = 2;
    delayMicroseconds(1);
    goto GIOCATORE1;
  }
  if(state_4 == 1 || state_4 == 2) {
    goto GIOCATORE2;
  }
}
goto GIOCATORE2;
//
//
//
//FINE PROGRAMMA GIOCATORE2
//
//
//
}

L’errore ‘Jump to label GIOCATORE2’

PROGRAMMA.ino: In function 'void loop()':
PROGRAMMA:183: error: jump to label 'GIOCATORE2'
PROGRAMMA:158: error: from here
PROGRAMMA:164: error: crosses initialization of 'int casella_4'
PROGRAMMA:183: error: jump to label 'GIOCATORE2'
PROGRAMMA:147: error: from here
PROGRAMMA:164: error: crosses initialization of 'int casella_4'
PROGRAMMA:153: error: crosses initialization of 'int casella_3'
PROGRAMMA:183: error: jump to label 'GIOCATORE2'
PROGRAMMA:136: error: from here
PROGRAMMA:164: error: crosses initialization of 'int casella_4'
PROGRAMMA:153: error: crosses initialization of 'int casella_3'
PROGRAMMA:142: error: crosses initialization of 'int casella_2'

Grazie! :slight_smile:

Potrebbe essere che dichiarando le variabili in mezzo al codice e non in testa o globali il compilatore non sappia quando inizializzarle e crearle siccome hai una serie di goto che si incrociano.

Io ti sconsiglio l'uso di tutti questi goto.
Sarebbe meglio creare una variabile globale "di stato" che permetta di eseguire parti diverse di codice distinguendolo attraverso il suo valore e uno switch enorme.

switch(stato) {
  case GIOCATORE1:
    ... codice giocatore 1
      break;
  case GIOCATORE2:
     ... codice giocatore2
    break;
}

Poi dentro al codice puoi settare stato=GIOCATOREx
essendo tutto in una loop() alla riesecuzione, lui entra nello switch giusto.
stato potrebbe essere una int e i valori GIOCATORE1, GIOCATORE2 delle costanti con i valori 1 e 2

Grazie per la dritta!
Sono alle prime armi con l’arduino, e non conosco tanti comandi quindi non so tantomeno come ottimizzare i programmi…
Intanto che cercavo di capire come sistemare la situazione, ho pensato alle tue parole… da quel che ho capito, il problema potrebbe derivare dal fatto che il programma ha tanti “int” da inizializzare, ma altrettanti ‘goto’ a dare fastidio…
Quindi ho pensato: e se mettessi gli ‘int’ nel loop del ‘millis’, in modo che siano sempre e comunque in esecuzione?
L’idea:

void loop() {
unsigned long tempo = millis();
tempo = 0;
if(tempo > 0 && tempo <= 10) {
  leds_1();
}
azzera(); // USCITE TUTTE = 0
if(tempo > 10 && tempo <= 20) {
  leds_2();
}
azzera(); // USCITE TUTTE = 0
if(tempo > 20 && tempo <= 30) {
  leds_3();
}
azzera(); // USCITE TUTTE = 0
if(tempo > 30 && tempo <= 40) {
  leds_4();
}
azzera(); // USCITE TUTTE = 0
[b]int casella_1 = digitalWrite(A0);[/b]
int casella_2 = digitalWrite(A1);
int casella_3 = digitalWrite(A2);
int casella_4 = digitalWrite(A3);
///
///
GIOCATORE1:
if([b]casella_1[/b] == 0) {
  if(state_1 = 0) {
    state_1 = 1;
    delayMicroseconds(1);
    goto GIOCATORE2;
  }
  if(state_1 == 1 || state_1 == 2) {
    goto GIOCATORE1;
  }
}
goto GIOCATORE1;
//
//
//
//FINE PROGRAMMA GIOCATORE1
//
//
//
GIOCATORE2:
---CODICE---

Potrebbe dare meno problemi?
Praticamente metto gli ‘int’ nel millis poi quando mi serve una variabile ‘casella_n’ la prelevo… vorrei provare a tenere tutti i ‘goto’… sai… non è che abbia tanta dimestichezza con arduino haha :slight_smile:
Comunque… se proprio proprio non è possibile mantenerli, proverò a studiare la tua dritta :slight_smile:

Per i goto, ho solo ipotizzato visto i msg d'errore.
Di solito in C NON si usano i goto. Ci sono molti programmatori C che urlerebbero dal dolore a vedere anche un solo goto :grin:

Io ti consiglio di ottimizzare il codice usando lo switch.
Ne migliorerebbe anche la lettura del codice. Sinceramente il codice che hai postato, a causa di quei goto, è veramente difficile da capire/leggere. E' quel che si chiama "spaghetti code". Come un piatto di spaghetti, la pasta si intreccia e non si capisce dove inizia ogni spaghetto.

Per le variabili usate nella loop() sinceramente puoi tranquillamente metterle tra le variabili globali, assieme alle state_x.
Inoltre se leggi dei pin digitali possono essere byte (unsigned char) ovvero 8 bits invece di int (16 bits).
Anche le state_x possono essere byte (valori da 0 -255)

nid69ita:
Ci sono molti programmatori C che urlerebbero dal dolore di vedere anche un solo goto :grin:

Diciamo pure che usare i goto in quel modo è da linciaggio :grin:

Per migliorare la lettura del codice, usa per gli stati degli enum:

enum STATO_CASELLA {
  SPENTA=0,
  DAGIOCATORE1,     // per il compilatore vale 1
  DAGIOCATORE2    // per il compilatore vale 2
 };

STATO_CASELLA state_1 = SPENTA;
STATO_CASELLA state_2 = SPENTA;
STATO_CASELLA state_3 = SPENTA;
STATO_CASELLA state_4 = SPENTA;

Nel codice puoi usare assegnazioni del tipo state_1=DAGIOCATORE1;

Ancora per semplificare il codice:

void leds_1() {
  switch(state_1)
  { case 0:    // SPENTA
    digitalWrite(2,LOW);
    digitalWrite(3,LOW);
    break;
  case 1:   // se usi enum puoi mettere DAGIOCATORE1 invece di 1
    digitalWrite(2,HIGH);
    digitalWrite(3,LOW);
    break;
  case 2:
    digitalWrite(2,LOW);
    digitalWrite(3,HIGH);
    break;
  }
}

Grazie per tutte le dritte, veramente! Mi hai fatto scoprire 5 comandi haha :grin:
Ho provato a mettere gli 'int' come ti ho detto, e non mi ha dato errori di compilazione.. appena posso lo provo anche in pratica.
comunque sia, proverò anche a seguire il tuo consiglio.. mi rendo conto io stesso che è piuttosto confusionario, ma ho utilizzato il 'goto' sia perchè non sapevo usare altri comandi, sia perchè mi sembrava il più semplice, efficace e semplice da usare.. in fondo mi basta mettere un "label:" e poi un semplice "goto label;" haha :grin:
Ne ho di cose da imparare!
grazie ancora!

P.S. Mi scuso per aver scritto quell'insalatiera di goto :grin:

nid69ita:
Ci sono molti programmatori C che urlerebbero dal dolore a vedere anche un solo goto :grin:

Urla strazzianti!!

Ok, ho vaporizzato i 'goto' :grin:

// state_n = STATO ATTUALE DELLA CASELLA
//           0 = SPENTA
//           1 = DEL GIOCATORE 1
//           2 = DEL GIOCATORE 2
//----------------------------------------
//
// PIN = 2 --> CASELLA1 - state_1 == 1
//       3 --> CASELLA1 - state_1 == 2
//       4 --> CASELLA2 - state_2 == 1
//       5 --> CASELLA2 - state_2 == 2
//       6 --> CASELLA3 - state_3 == 1
//       7 --> CASELLA3 - state_3 == 2
//       8 --> CASELLA4 - state_4 == 1
//       9 --> CASELLA4 - state_4 == 2
//       A0 --> INPUT.CASELLA1
//       A1 --> INPUT.CASELLA2
//       A2 --> INPUT.CASELLA3
//       A3 --> INPUT.CASELLA4

int giocatore = 1;
int state_1 = 0;
int state_2 = 0;
int state_3 = 0;
int state_4 = 0;

void azzera() {
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  delayMicroseconds(1);
}

void leds_1() {
  if(state_1 == 0) {
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
  }
  if(state_1 == 1) {
  digitalWrite(2,HIGH);
  digitalWrite(3,LOW);
  }
  if(state_1 == 2) {
  digitalWrite(2,LOW);
  digitalWrite(3,HIGH);
  }
}
void leds_2() {
  if(state_2 == 0) {
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  }
  if(state_2 == 1) {
  digitalWrite(4,HIGH);
  digitalWrite(5,LOW);
  }
  if(state_2 == 2) {
  digitalWrite(4,LOW);
  digitalWrite(5,HIGH);
  }
}
void leds_3() {
  if(state_3 == 0) {
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
  }
  if(state_3 == 1) {
  digitalWrite(6,HIGH);
  digitalWrite(7,LOW);
  }
  if(state_3 == 2) {
  digitalWrite(6,LOW);
  digitalWrite(7,HIGH);
  }
}
void leds_4() {
  if(state_4 == 0) {
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  }
  if(state_4 == 1) {
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW);
  }
  if(state_4 == 2) {
  digitalWrite(8,LOW);
  digitalWrite(9,HIGH);
  }
}

void setup() {
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  Serial.begin(9600);
}

void loop() {
unsigned long tempo = millis();
if(tempo > 0) {
  leds_1;
  azzera;
  delayMicroseconds(1);
  leds_2;
  azzera;
  delayMicroseconds(1);
  leds_3;
  azzera;
  delayMicroseconds(1);
  leds_4;
  azzera;
  delayMicroseconds(1);
}
///
///
int casella_1 = digitalRead(A0);
int casella_2 = digitalRead(A1);
int casella_3 = digitalRead(A2);
int casella_4 = digitalRead(A3);
switch(giocatore) {
  case 1:
  if(casella_1 == 0 && state_1 == 0) {
    state_1 = 1;
    giocatore = 2;
  }
  if(casella_2 == 0 && state_2 == 0) {
    state_2 = 1;
    giocatore = 2;
  }
  if(casella_3 == 0 && state_3 == 0) {
    state_3 = 1;
    giocatore = 2;
  }
  if(casella_4 == 0 && state_4 == 0) {
    state_4 = 1;
    giocatore = 2;
  }
  break;
  ///
  ///
  case 2:
  if(casella_1 == 0 && state_1 == 0) {
    state_1 = 2;
    giocatore = 1;
  }
  if(casella_2 == 0 && state_2 == 0) {
    state_2 = 2;
    giocatore = 1;
  }
  if(casella_3 == 0 && state_3 == 0) {
    state_3 = 2;
    giocatore = 1;
  }
  if(casella_4 == 0 && state_4 == 0) {
    state_4 = 2;
    giocatore = 1;
  }
  break;
}
}

Sembra più funzionale.. e leggibile :grin:

Bueno :slight_smile:

Fresco fresco di test.. non va nulla..
Ho iniziato una specie di 'ricerca guasti'.. ho provato ad usare il 'Serial.print' (con digitalRead su A0,A1,A2,A3) per vedere se l'arduino si accorgeva della pressione dei pulsanti.
Il monitor seriale è una lista di '14151617', che non cambiano nemmeno alla pressione dei pulsanti. Non capisco perchè! Il circuito dei 4 pulsanti è il solito pull-up, quindi nulla di alieno..
Sto seriamente pensando che abbia involontariamente bruciato i 4 pin (anche se non capisco come.. dato che non faccio "esperimenti" strani sui pin e faccio solo cose di cui son sicuro al 100%..). Ho appena cortocircuitato tutti e 4 a massa, "14151617" la risposta.. bruciato, o errore software?

Come hai collegato i 4 pulsantini?
Se ti legge di continuo lo stato premuto forse hai solo fatto un errore di collegamento.

+5V ---> Resistenza pull-up ---> (ponticello che va al pin) ---> pulsante ---> massa
Sul monitor seriale dovrebbe darmi una cosa di questo genere:
(se i pulsanti sono aperti)
1111
1111
1111
ecc.
(se tutti sono chiusi)
0000
0000
0000
ecc.
(se A0 e A3 sono a massa)
0110
0110
0110
ecc.
Il problema è che sul monitor seriale c'è solo:
14151617
14151617
14151617
14151617
14151617
indipendentemente se i pulsanti sono chiusi o aperti..

Nel codice richiami azzera; e non azzera(); :~

Perchè non elimini la pull-up esterna e non usi quella interna con PinMode(xx, INPUT_PULLUP); ?

nid69ita:
Per i goto, ho solo ipotizzato visto i msg d’errore.
Di solito in C NON si usano i goto. Ci sono molti programmatori C che urlerebbero dal dolore a vedere anche un solo goto :grin:

Non sono programmatore ma sto giá urlando. :wink: :wink: :wink:

Il C con le funzioni é strutturato in modo che non serve il GOTO o GOSUB. Credimi NON SERVE. Ci sono pochi casi dove gli informatici usano GOTO perché semplifica il codice. Questo é il caso quando si fanno tnate While una dentro l’altra e si derve uscire del tutto. Ma anche in quel caso puó essere non usato.

Ciao Uwe

Ok sto impazzendo.. non riesco a capire:
Senza cambiare nulla sul circuito dei pulsanti, ho aperto un altra finestra di Arduino per scrivere un programma che mi legga lo stato del pulsanti:

void setup() {
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  Serial.begin(9600);
}
void loop() {
  int pinA0 = digitalRead(A0);
  int pinA1 = digitalRead(A1);
  int pinA2 = digitalRead(A2);
  int pinA3 = digitalRead(A3);
  Serial.print(pinA0);
  Serial.print(pinA1);
  Serial.print(pinA2);
  Serial.println(pinA3);
}

Infatti in questo modo, nel monitor seriale c'era un "1111" che cambiava in "0110", "1100" ecc. a seconda del pulsante che premevo.
A questo punto, senza toccare nè i ponticelli del circuito, nè tantomeno i pulsanti e/o le resistenze, ho caricato il programma del "tris" e aprendo il monitor seriale trovo la dannatissima fila di "14151617"..
Posso immaginare che non sia un problema del circuito dei pulsanti, nè tantomeno dei ponticelli che vanno agli ingressi analogici.. cos'altro può essere?
Aiutatemi vi prego =(

Forse mi son perso qualcosa io, ma non ho capito.

In questo ultimo codice leggi i pin analogici usando analogRead()
Questi pin se interrogati con analogRead() riportano un valore tra 0 e 1023 a seconda della tensione 0-5V letta sul pin.
Sempre su questi pin puoi usare la digitalRead() che ritorna solo 0 oppure 1 senza i valori intermedi.

No leggi bene, sto usando il digitalRead :slight_smile:
Sto usando i pin analogici, perchè voglio preservare i pin da 0 a 13 dell'arduino, dato che nella versione completa del progetto, mi serviranno tante uscite disponibili.
Ho realizzato 4 pull-up, per altrettanti pulsanti, la cui lettura verrà effettuata appunto dai pin A0, A1, A2, A3.
A causa di problemi nel funzionamento del programma del 'tris' (quello con la funzione 'switch'), ho realizzato un altro programmino che funzionasse solo per testare i pull-up (senza 'switch'.. quello che ho postato prima). Con questo programma, aprendo il monitor seriale, vedo una fila di 1111. Ciò che mi aspetto ovviamente!
Però, se provo a caricare il programma del 'tris', scrivendo in mezzo al programma stesso:

Serial.print(casella_1);
Serial.print(casella_2);
Serial.print(casella_3);
Serial.println(casella_4);

Vedo solo:
14151617
14151617
14151617
14151617
14151617
.... ecc.
invece che
1111
1111
1111
1111
... ecc.
Non capisco perchè! Non tocco nulla, metto solo un "Serial.print" in mezzo al programma!
Poi se riprovo a caricare il programma che testa i pull-up, il monitor seriale mi mostra ciò che dovrebbe mostrare.
Non deve mostrare numeri da 0 a 1023, ma solo "1" oppure "0".

Si, ho letto male, sorry :blush:

Comunque se la Serial.print() stampa un 14 per casella_1 vuol dire che in quel momento vale 14.
E lo fa anche per le altre 3 variabili, non può essere un qualcosa di "accidentale"
Dovresti postare tutto il codice per controllare. Puoi allegare lo sketch invece di usare copia/incolla