Progetto bomba per softair

Ciao a tutti,
ho creato questo sketch per Arduino, per creare una bomba gioco per softair. Il circuito è provvisto di display a 7 segmenti per il conto alla rovescia, partendo da 30s. Per il disinnesco, ci sono da tagliare 4 cavi che portano poi alle seguenti funzioni:

  • morto --> si accende il LED rosso;
  • salvo --> si accendo led verde;
  • fast timer --> il conto alla rovescia si velocizza;
  • non succede niente.
    Passati 30 secondi, oppure dopo gli stati salvo o morto, il circuito può essere resettato per far ripartire il gioco da capo, naturalmente sostituendo prima i cavi interrotti.
    Per rendere lo sketch più realistico, ho introdotto uno shuffle di un array e funzioni, per vedere di mischiare di volta in volta post reset, o avvio, cavi diversi che portano ad eventi diversi. Il problema è che questo non si verifica, i soliti cavi portano sempre ai soliti eventi, rendendo prevedibile il gioco dopo pochi turni di gioco. Non mi riesce a risolvere questo problema. Ho usato anche la funzione randomseed nel setup(), ma non mi ha risolto il problema. Potreste aiutarmi? Di seguito il listato. PS: i tempi di countdown per fare un secondo sono dimezzati, poichè poi vorrei riversare il tutto su un atmega328 per realizzare un circuito standalone senza uso del mio Arduino, con fuse settati per oscillatore interno a 8Mhz. Grazie mille per l'aiuto.
#include <avr/wdt.h>
#include <SevSeg.h>
#define start 11 // pin per start gioco
#define salvo 13 // led per indicare salvo
#define morto 12 // led per indicare morto
SevSeg sevseg; // Crea l'oggetto
unsigned long t0=0; 
unsigned long t1;
int count_down = 30;
byte evento[4] = {0, 1, 2, 3};
byte result[4];
byte temp[4];
int i = 0;
unsigned long contasecondi=500;
int cavo0;
int cavo1;
int cavo2;
int cavo3;
bool start1=false;
int stato=0;
const int inizio=0;
const int gioco=1;
const int morto_stato=2;
const int evento_stato=3;
bool pulsante_inizio;
bool pulsante_reset;
int azione;
void setup() 
{
  MCUSR = 0;
  wdt_disable();
  byte numDigits = 2;
  byte digitPins[] = {2, 3}; // Pin collegati ai digit comuni
  byte segmentPins[] = {4, 5, 6, 7, 8, 9, 10, 11}; // Segmenti A-G + DP
  bool resistorsOnSegments = true; // true se le resistenze sono sui segmenti
  byte hardwareConfig = COMMON_CATHODE; // o COMMON_ANODE
  bool updateWithDelays = false;
  bool leadingZeros = true;
  bool disableDecPoint = true;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
  sevseg.setBrightness(90);
  Serial.begin(9600);
  pinMode(start, INPUT_PULLUP);
  pinMode(salvo, OUTPUT);
  pinMode(morto, OUTPUT);
  randomSeed(analogRead(A5));
  pinMode(A4, INPUT_PULLUP); // pulsante reset
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  pinMode(A3, INPUT_PULLUP);
  int osize = 4;
  for (int k = 0; k < 4; k++) {
    int p = random(osize);
    int estratto = evento[p];
  
    result[i] = estratto;
    i++;
  
    int ti = 0;
    for (int n = 0; n < osize; n++) {    
      if (n != p) {
        temp[ti] = evento[n];
        ti++;
      }    
    }
    osize--;
    for (int x = 0; x < 4; x++) {    
      if (x < osize) {
        evento[x] = temp[x];  
      } else {
        evento[x] = 0;
      } 
    }
  //stampo result x verifica
  for (int x = 0; x < 4; x++) {    
  Serial.println(result[x]);  
  }
}}

void conteggio()
{
sevseg.setNumber(count_down);
sevseg.refreshDisplay();
t1=millis();
  if (((t1-t0) > contasecondi) && (start1 == true))
  {
   count_down--;
   t0=t1;
  }
}

void resettone()
{
  wdt_enable(WDTO_15MS);  // attiva watchdog a 15ms
  while (1) 
  {}            // attende il reset
}

void evento0()
{
 azione=result[0];
 stato=3;
} 

void evento1()
{
 azione=result[1];
 stato=3;
} 

void evento2()
{
 azione=result[2];
 stato=3;
} 

void evento3()
{
 azione=result[3];
 stato=3;   
} 


void loop() 
{
switch (stato)
  {
    case inizio:
    digitalWrite(morto, LOW); digitalWrite(salvo, LOW);
    sevseg.setNumber(00);
    sevseg.refreshDisplay();
    pulsante_inizio=digitalRead(start);
    if (pulsante_inizio==LOW)
      {
        stato=1;
        start1 = true;
      }
    break;  
    case gioco:
    digitalWrite(morto, LOW); digitalWrite(salvo, LOW);
    conteggio();
    cavo0=digitalRead(A0);
    cavo1=digitalRead(A1);
    cavo2=digitalRead(A2);
    cavo3=digitalRead(A3);
    if (cavo0 == HIGH)
    {
      evento0();
    }
    if (cavo1 == HIGH)
    {
      evento1();
    }
    if (cavo2 == HIGH)
    {
      evento2();
    }
    if (cavo3 == HIGH)
    {
      evento3();
    }
    if (count_down==0)
      {
        stato=2;
        start1 = false;
      }
    break;
    case morto_stato:
    conteggio();
    digitalWrite(morto, HIGH); digitalWrite(salvo, LOW);
    pulsante_reset=digitalRead(A4);
    if(pulsante_reset==LOW)
      {
        resettone();
      }
    break;
    case evento_stato:
    if(azione==0) //morto
      {
        stato=2;
        start1 = false;
        count_down=0;
      }
    if(azione==1) //salvo
      {
        start1=false;
        count_down=0;
        digitalWrite(morto, LOW); digitalWrite(salvo, HIGH);
        pulsante_reset=digitalRead(A4);
        if(pulsante_reset==LOW)
          {
            resettone();
          }
      }
    if (azione==2) //timer fast
      {
       contasecondi=150;
       stato=1; 
      }
    if(azione==3) //non accade niente
      {
        stato=1;
      }      
    break;    
  }  
}
````Usa i tags code per formattare il codice per il forum`

Se si usa la corretta configurazione del file boards.txt e il corretto bootloader per gli 8MHz, i tempi NON cambiano e tutto funziona come si deve.

Certo che se usi le definizioni per una scheda a 16MHz e poi, in realtà, il clock è a 8 MHz ... le cose NON vanno bene e di problemi ne hai svariati (inclusi problemi con la seriale) :roll_eyes:

Guglielmo

Mi sembra alquanto contorto... Inoltre, estratto non serve: usa direttamente result[].
Io leggerei millis()%4 al momento del taglio, annotando i numeri già usciti e facendo una nuova lettura finché non ne esce uno nuovo.

In effetti ho fatto le cose un pò alla rovescia. Ho rifatto adesso tutto con Arduino, e dopo un pò di correzioni aiutato dalle seriale, tutto fila lascio come volevo io. Il codice è venoto fuori un pò macchinoso... ma il suo lo fa. Ripubblico lo sketch corretto. Ciao e grazie.

 
// #include <avr/wdt.h> tolta per usare arduino
#include <SevSeg.h>
#define start 11 // pin per start gioco
#define salvo 13 // led per indicare salvo
#define morto 12 // led per indicare morto
SevSeg sevseg; // Crea l'oggetto
unsigned long t0=0; 
unsigned long t1;
int count_down = 30;
byte evento[3] = {0, 1, 2,};
byte result[3];
byte temp[3];
int i = 0;
unsigned long contasecondi=1000;
int cavo0;
int cavo1;
int cavo2;
int cavo3;
bool start1=false;
int stato=0;
const int inizio=0;
const int gioco=1;
const int morto_stato=2;
const int evento_stato=3;
bool pulsante_inizio;
bool pulsante_reset;
int azione;
void setup() 
{
  // MCUSR = 0; tolta per usare arduino
  // wdt_disable(); tolta per usare arduino
  byte numDigits = 2;
  byte digitPins[] = {2, 3}; // Pin collegati ai digit comuni
  byte segmentPins[] = {4, 5, 6, 7, 8, 9, 10, 11}; // Segmenti A-G + DP
  bool resistorsOnSegments = true; // true se le resistenze sono sui segmenti
  byte hardwareConfig = COMMON_CATHODE; // o COMMON_ANODE
  bool updateWithDelays = false;
  bool leadingZeros = true;
  bool disableDecPoint = true;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
  sevseg.setBrightness(90);
  Serial.begin(9600);
  pinMode(start, INPUT_PULLUP);
  pinMode(salvo, OUTPUT);
  pinMode(morto, OUTPUT);
  randomSeed(analogRead(A5));
  pinMode(A4, INPUT_PULLUP); // pulsante reset
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  pinMode(A3, INPUT_PULLUP);
  Serial.begin(9600);

  int osize = 3;

  for (int k = 0; k < 3; k++) {
    int p = random(osize);
    int estratto = evento[p];
  
    result[i] = estratto;
    i++;
  
    int ti = 0;
    for (int n = 0; n < osize; n++) {    
      if (n != p) {
        temp[ti] = evento[n];
        ti++;
      }    
    }
    osize--;
    for (int x = 0; x < 3; x++) {    
      if (x < osize) {
        evento[x] = temp[x];  
      } else {
        evento[x] = 0;
      } 
    }
  }

  //stampo result x verifica
  for (int x = 0; x < 3; x++) {    
     Serial.println(result[x]);    
  }
  
}
void conteggio()
{
sevseg.setNumber(count_down);
sevseg.refreshDisplay();
t1=millis();
  if (((t1-t0) > contasecondi) && (start1 == true))
  {
   count_down--;
   t0=t1;
  }
}

void resettone()
{
  //wdt_enable(WDTO_15MS);  tolta per usare arduino
  //while (1) tolta per usare arduino
  asm volatile (" nop ");  
  asm volatile (" jmp 0 ");  
            
}

void evento0()
{
 azione=result[0];
 stato=3;
} 

void evento1()
{
 azione=result[1];
 stato=3;
} 

void evento2()
{
 azione=result[2];
 stato=3;
} 

// void evento3()
// {
//  azione=result[3];
// stato=3;   
// } 


void loop() 
{
switch (stato)
  {
    case inizio:
    digitalWrite(morto, LOW); digitalWrite(salvo, LOW);
    sevseg.setNumber(00);
    sevseg.refreshDisplay();
    pulsante_inizio=digitalRead(start);
    if (pulsante_inizio==LOW)
      {
        stato=1;
        start1 = true;
      }
    break;  
    case gioco:
    digitalWrite(morto, LOW); digitalWrite(salvo, LOW);
    conteggio();
    cavo0=digitalRead(A0);
    cavo1=digitalRead(A1);
    cavo2=digitalRead(A2);
    cavo3=digitalRead(A3);
    if (cavo0 == HIGH)
    {
      evento0();
    }
    if (cavo1 == HIGH)
    {
      evento1();
    }
    if (cavo2 == HIGH)
    {
      evento2();
    }
    // if (cavo3 == HIGH)
    // {
     // evento3();
    // }
    if (count_down==0)
      {
        stato=2;
        start1 = false;
      }
    break;
    case morto_stato:
    conteggio();
    digitalWrite(morto, HIGH); digitalWrite(salvo, LOW);
    pulsante_reset=digitalRead(A4);
    if(pulsante_reset==LOW)
      {
        resettone();
      }
    break;
    case evento_stato:
    if(azione==0) //morto
      {
        stato=2;
        start1 = false;
        count_down=0;
      }
    if(azione==1) //salvo
      {
        start1=false;
        sevseg.setNumber(00);
        sevseg.refreshDisplay();
        digitalWrite(morto, LOW); digitalWrite(salvo, HIGH);
        pulsante_reset=digitalRead(A4);
        if(pulsante_reset==LOW)
          {
            resettone();
          }
      }
    if (azione==2) //timer fast
      {
       contasecondi=250;
       stato=1;
      }
    // if(azione==3) //non accade niente
    //   {
      //  stato=1;
     //  }      
    break;    
  }  
}