Go Down

Topic: Segnapunti 2 digits x 2 players (Read 126 times) previous topic - next topic

Nanni1972

Buongiorno a tutti,
Sono molto neofita di arudino, soprattuto per quanto riguarda la programmazione.
vorrei costruire un segnapunti da 0-99 per 2 giocatori utilizzando un 4x7 segmenti display e due pulsanti per ogni giocatore, uno per incrementare di 1 punto e l'altro per decrementare di 1 punto.
Ho gia' construito, grazie ad un esempio trovato su internet una versione per un solo giocatore utilizzando un 2 x 7 segmenti display.

Ma sarebbe possibile comandare con un solo arduino Nano un 4x7 essendo che mi servirebbero solo 2 pin in piu per comandare le due digit e 2 pin per i due pulsanti del giocatore 2?

Come dovrei modificare il codice che ho usato per la versione 1 giocatore?

Grazie per l'aiuto che potete darmi.


fabpolli

Buona sera,
essendo il tuo primo post nella sezione Italiana del forum, nel rispetto del nostro regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie. :)

Nanni1972

Scusami ma non sapevo della presentazione.
fatta nella sezione apposita.
Grazie

fabpolli

Allora, per riuscire a gestire tutto con la nano ci si riesce senza particolari problemi. Nel codice che hai a disposizione ci sono già indicati (anche se commentati) i due pin per gestire la terza e quarta cifra.
Per gestire i due pulsanti che ti servono puoi usare due pin analogici che possono essere utilizzati come digitali senza problemi.
Per gestire il tutto dovrai duplicare le due funzioni che usi per gestire i due pulsanti e adattarle per leggere e gestire i due nuovi pulsanti.
Per la parte di visualizzazione dei due punteggi tu adesso usi il display delle unità e delle decine per visualizzare da 0 a 99. L'altro punteggio che per logica è separato, nel display in realtà corrisponde alle cifre delle centinaia e delle migliaia, quindi per visualizzare i due punteggi ti basterà moltiplicare per 100 il valore del secondo giocatore e sommarlo al punteggio del primo e visualizzare tutto assieme ;)

Nanni1972

grazie mille per il tuo aiuto.
Io avevo pensato di sommare 100 al valore del player1. Perche' se seguo il tuo aiuto non mi sembra giusto. Per esempio se il pl1 ha un punteggio di 12 se moltiplico x 100 = 1200 + 12 = 1212

In ogni caso ho provato a scrivere il codice, ma quando confermo di usare 4 digits con questa operazione:
int numberOfDigits = 4;

Mi appare un 6 sul digit3!

E poi non riesco (conosco) come scrivere il codice per moltiplicare e/o sommare 100 al valore di Pl1.

Questo e' quello che ho provato a fare che ovviamente non funziona:

Code: [Select]

#include <SevSeg.h>

//Create an instance of the object.
SevSeg myDisplay;

//Create global variables
unsigned long timer;
int deciSecond = 0;
 bool bPress = false;
const int IncbuttonPin = A1;
const int DecbuttonPin = A2;
const int Incbutton2Pin = A3;
const int Decbutton2Pin = A4;

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses

int IncbuttonState = 0;         // current state of the button pl 1
int lastIncbuttonState = 0;     // previous state of the button pl 1

int DecbuttonState = 0;         // current state of the button pl 1
int lastDecbuttonState = 0;     // previous state of the button pl 1

int Incbutton2State = 0;         // current state of the button pl 2
int lastIncbutton2State = 0;     // previous state of the button pl 2

int Decbutton2State = 0;         // current state of the button pl 2
int lastDecbutton2State = 0;     // previous state of the button pl 2

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
  int displayType = COMMON_CATHODE; //Your display is either common cathode or common anode

   pinMode( IncbuttonPin ,INPUT_PULLUP);
   pinMode( DecbuttonPin ,INPUT_PULLUP);

   pinMode( Incbutton2Pin ,INPUT_PULLUP);
   pinMode( Decbutton2Pin ,INPUT_PULLUP);
  /*
  //This pinout is for a regular display
   //Declare what pins are connected to the digits
   int digit1 = 2; //Pin 12 on my 2 digit display
   int digit2 = 3; //Pin 9 on my 2 digit display
   int digit3 = 4; //Pin 8 on my 2 digit display
   int digit4 = 5; //Pin 6 on my 2 digit display
   
   //Declare what pins are connected to the segments
   int segA = 6; //Pin 11 on my 2 digit display
   int segB = 7; //Pin 7 on my 2 digit display
   int segC = 8; //Pin 4 on my 2 digit display
   int segD = 9; //Pin 2 on my 2 digit display
   int segE = 10; //Pin 1 on my 2 digit display
   int segF = 11; //Pin 10 on my 2 digit display
   int segG = 12; //Pin 5 on my 2 digit display
   int segDP= 13; //Pin 3 on my 2 digit display
   */
//This pinout is for OpenSegment PCB layout
  //Declare what pins are connected to the digits
  int digit1 = 2; //Pin 7 on my 2 digit display
  int digit2 = 3; //Pin 8 on my 2 digit display
  int digit3 = 4;
  int digit4 = 5;

  //Declare what pins are connected to the segments
  int segA = 6; //Pin 10 on my 2 digit display
  int segB = 7; //Pin 9 on my 2 digit display
  int segC = 8; //Pin 1 on my 2 digit display
  int segD = 9; //Pin 4 on my 2 digit display
  int segE = 10; //Pin 3 on my 2 digit display
  int segF = 11; //Pin 6 on my 2 digit display
  int segG = 12; //Pin 5 on my 2 digit display
  int segDP= 13; //Pin 2 on my 2 digit display
 

  int numberOfDigits = 4; //Do you have a 1, 2 or 4 digit display?

  myDisplay.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP);
 
  myDisplay.SetBrightness(100); //Set the display to 100% brightness level

  timer = millis();
}

void loop() {
  // put your main code here, to run repeatedly:
IncbuttonState = digitalRead(IncbuttonPin);
DecbuttonState = digitalRead(DecbuttonPin);
Incbutton2State = digitalRead(Incbutton2Pin);
Decbutton2State = digitalRead(Decbutton2Pin);

    checkIncButtonPress();
   checkDecButtonPress();
   checkIncButton2Press();
    checkDecButton2Press();
  //Example ways of displaying a decimal number
  char tempString[10]; //Used for sprintf
  sprintf(tempString, "%2d", buttonPushCounter); //Convert deciSecond into a string that is right adjusted
  //sprintf(tempString, "%d", deciSecond); //Convert deciSecond into a string that is left adjusted
  //sprintf(tempString, "%04d", deciSecond); //Convert deciSecond into a string with leading zeros
  //sprintf(tempString, "%4d", deciSecond * -1); //Shows a negative sign infront of right adjusted number
  //sprintf(tempString, "%4X", deciSecond); //Count in HEX, right adjusted

   
  //Produce an output on the display
  myDisplay.DisplayString(tempString, 0); //(numberToDisplay, decimal point location)

  //Other examples
  //myDisplay.DisplayString(tempString, 0); //Display string, no decimal point
  //myDisplay.DisplayString("-23b", 3); //Display string, decimal point in third position

 

  delay(5);
}

 void checkIncButtonPress()
{
   // compare the IncbuttonState to its previous state
  if (IncbuttonState != lastIncbuttonState) {
    // if the state has changed, increment the counter
    if (IncbuttonState == LOW) {
      // if the current state is HIGH then the button went from off to on:
      bPress = true;
      buttonPushCounter++;
      if( buttonPushCounter > 99) buttonPushCounter =0 ;
      Serial.println("on");
     
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastIncbuttonState = IncbuttonState;

}
void checkDecButtonPress()
{
   // compare the IncbuttonState to its previous state
  if (DecbuttonState != lastDecbuttonState) {
    // if the state has changed, increment the counter
    if (DecbuttonState == LOW) {
      // if the current state is HIGH then the button went from off to on:
      bPress = true;
      buttonPushCounter--;
      if( buttonPushCounter < 0) buttonPushCounter =0 ;
      Serial.println("on");
     
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastDecbuttonState = DecbuttonState;




 void checkIncButton2Press()
{
   // compare the Incbutton2State to its previous state
  if (Incbutton2State != lastIncbutton2State) {
    // if the state has changed, increment the counter
    if (Incbutton2State == LOW) {
      // if the current state is HIGH then the button went from off to on:
      bPress = true;
      buttonPushCounter+100;
      if( buttonPushCounter > 9900) buttonPushCounter -1000 ;
      Serial.println("on");
     
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastIncbutton2State = Incbutton2State;

}
void checkDecButton2Press()
{
   // compare the Decbutton2State to its previous state
  if (Decbutton2State != lastDecbutton2State) {
    // if the state has changed, increment the counter
    if (Decbutton2State == LOW) {
      // if the current state is HIGH then the button went from off to on:
      bPress = true;
      buttonPushCounter-100;
      if( buttonPushCounter < 0) buttonPushCounter =0 ;
      Serial.println("on");
     
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastDecbutton2State = Decbutton2State;

}

fabpolli

Allora hai correttamente duplicato le funzioni per gestire i due pulsanti aggiuntivi, ma hai utilizzato una sola variabile (buttonPushCounter) per gestire entrambe i punteggi.
Ti consiglio di usare due variabili distinte una per il punteggio di un giocatore e una per il punteggio del secondo. In questo modo le quattro funzioni per i pulsanti saranno identiche a meno di incrementare/decrementare una variabile contatore differente.
Poi nel loop usi una terza variabile (punteggioTotale ad esempio) che conterrà i due punteggi e che usarei nella sprintf.
punteggioTotale conterrà il punteggio del giocatore 1 moltiplicato 100 sommato al punteggo del giocatore 2. La moltiplicazione si fa banalmente con *
Infine dovrai modificare il secondo parametro della snprintf perché attualmente gli chiedi di convertire il numero in una stringa con due posizioni, a te ne servono 4.
Prova ad apportare le modifiche e se non ti è chiaro qualcosa siamo qui ;)


Datman

#6
Sep 24, 2019, 02:49 pm Last Edit: Sep 24, 2019, 06:07 pm by Datman
Per quel poco che deve fare è di una complicazione mostruosa!...
Anziché usare una libreria, che sembra non semplificare molto le cose, farei molto più istruttivamente a mano... Inoltre, così facendo, sai esattamente che cosa fa senza incognite e puoi modificarlo a tuo piacimento
Ti occorrono due contatori per i punteggi e una tabella dei caratteri, poi fai la scansione dei quattro display e invii a ciascuno il suo carattere.

Per dei display ad anodo comune, collegando i catodi agli I/O da 0 a 7, puoi usare questa funzione con una tabella di conversione a 7 segmenti, che fa apparire il valore di n sul display attivo:
Code: [Select]
void display()
{
switch(n)      // Anodo comune
               // D 76543210
  {            //  dpGFEDCBA (0: segmento acceso)
  case 0:
  PORTD|=0b01000000;  // Spegne i segmenti a 1
  PORTD&=0b11000000; // Accende i segmenti a 0
  break;

  case 1:
  PORTD|=0b01111001;
  PORTD&=0b11111001;
  break;

  case 2:
  PORTD|=0b00100100;
  PORTD&=0b10100100;
  break;

  case 3:
  PORTD|=0b00110000;
  PORTD&=0b10110000;
  break;

  case 4:
  PORTD|=0b00011001;
  PORTD&=0b10011001;
  break;

  case 5:
  PORTD|=0b00010010;
  PORTD&=0b10010010;
  break;

  case 6:
  PORTD|=0b00000010;
  PORTD&=0b10000010;
  break;

  case 7:
  PORTD|=0b01111000;
  PORTD&=0b11111000;
  break;

  case 8:
  PORTD|=0b00000000;
  PORTD&=0b10000000;
  break;

  case 9:
  PORTD|=0b00010000;
  PORTD&=0b10010000;
  break;
  }

PORT è un'istruzione molto importante, perché ti permette di impostare tutti i bit di una porta con una sola istruzione, in un attimo e in maniera perfettamente contemporanea (cosa che, in alcuni casi, è indispensabile).
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

Datman

#7
Sep 24, 2019, 03:03 pm Last Edit: Sep 24, 2019, 03:52 pm by Datman
Nel loop, oltre al rilevamento della pressione dei pulsanti e al conteggio dei due punteggi punti_A e punti_B, metti un contatore dispAttivo da 1 a 4 che viene incrementato ciclicamente di uno ogni giro di loop: questo valore identificherà il catodo del display da pilotare e la cifra da far comparire.
Code: [Select]
switch(dispAttivo)
  {
  case 1:
  n=punti_A/10;
  digitalWrite(digit4, HIGH); // Disattiva il display precedente.
  if(n!=0) digitalWrite(digit1, LOW); // Attiva il display solo se il valore è diverso da zero.
  break;

  case 2:
  n=punti_A%10;
  digitalWrite(digit1, HIGH);
  digitalWrite(digit2, LOW);
  break;

  case 3:
  n=punti_B/10;
  digitalWrite(digit2, HIGH); // Disattiva il display precedente.
  if(n!=0) digitalWrite(digit3, LOW); // Attiva il display solo se il valore è diverso da zero.
  break;

  case 4:
  n=punti_B%10;
  digitalWrite(digit3, HIGH);
  digitalWrite(digit4, LOW);
  break;
  }
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

Go Up