Sie sind auf Seite 1von 6

// Scoreboard Control Program by P.

Clark (Arduino forum handle: Palomar)


//
// Ver. 1.0 10/31/2014
// First release of Scoreboard Control Program
//
// --------------------------------------------------------------------
// A scoreboard was created for the game of Horseshoes.
// Built in two halves, the left half covers courts 1, 2 and 3, while the right
// half covers courts 4, 5 and 6.
// Each half uses one Arduino Nano and is independent of the other half.
// See photo: http://i351.photobucket.com/albums/q452/plclark3/IMJ_4700x.jpg
//
// This sketch is intended for use with the following hardware:
// (one) Arduino USB Nano ATmega328
// (six) 16x32 Dot Matrix Display (DMD) panels
// (six) External switches, normally open, connected to pins A0-A5
//
// The DMD panels are arranged in pairs: 2-across and 3-down.
// Each individual panel displays a 2-digit score, 6 inches high, using the full
// 16-rows of LED's.
//
// The external foot switches are operated by the players themselves.
// When a switch is closed, the corresponding pin goes LOW.
// If switch is released within "delayPeriod" time, the score is incremented by
1.
// If switch is held closed longer than "delayPeriod", the score is repeatedly
// decremented by 1 until the switch is released, or the score reaches zero
.
// If an adjacent pair of switches are closed longer than "delayPeriod", both
// scores are reset to zero.
// When either score of an adjacent pair exceeds "maxScore", both scores are res
et
// to zero.
//
// For anyone attempting to connect a monochrome 16x32 DMD panel to Arduino, the
// following diagram may be helpful. The 16-pin header on the back of the D
MD
// panel is wired to the following pins:
//
// D9 |_1|_2| D6
// GND |_3|_4| D7
// |_5|_6|
// (slot) |_7|_8| D13 (the orientation slot is on the left side of the header)
// |_9|10| D8
// |11|12| D11
// |13|14|
// |15|16|
//
// You must supply 5V power directly to the DMD panel as Arduino cannot provide
// nearly enough current. Lighting up all 512 LED's in a panel with 1/4
// multiplexing takes about 7 amps at 5V.
//
// --------------------------------------------------------------------
#include <SPI.h>
#include <DMD.h>
#include <TimerOne.h>
#include <PLCBigFont.h>
#include <TimedAction.h>
// Operational parameters
int maxScore = 25; // highest score possible
int debounce = 25; // debounce time in millis
unsigned long delayPeriod = 700; // decrement delay period, in mil
lis
unsigned long repeatPeriod = 300; // decrement repeat period, in mi
llis
unsigned long currTime = 0; // current time since start up, i
n millis
unsigned long closedPeriod = 0; // switch-closed period in, milli
s
unsigned long closedTime [] = {0, 0, 0, 0, 0, 0}; // switch-closed time, in mill
is
volatile int interruptFlag = 0; // interrupt flag
int refreshFlag = 0; // refresh flag
int decTimerFlag = 0; // decrement flag
int i = 0; // index for switches and scores
(0 thru 5)
int j = 0; // score pair indicator (0, 2 or
4)
int k = 0; // display column offset (0, 64 o
r 128)
int prevStatus [] = {0, 0, 0, 0, 0, 0}; // prev switch status
int currStatus [] = {1, 1, 1, 1, 1, 1}; // curr switch status
int score [] = {0, 0, 0, 0, 0, 0}; // curr scores
int scoreStatus [] = {0, 0, 0, 0, 0, 0}; // score status for decrementing
// scoreStatus values: 0=switch open, 1=switch closed, 2=switch closed & score d
ecremented
//String PL; // used with Serial.println
// Example: PL = ""; PL = PL + i + " time: " + decTime [i]; Serial.println(PL);
DMD dmd(2,3); // (DISPLAYS_ACROSS, DISPLAYS_DOW
N)
// initialize a timer to perform decrementing
TimedAction decTimer = TimedAction(100,checkDecrement); // do it every 100 mill
is
// --------------------------------------------------------------------
void ScanDMD() // timer interrupt to drive displ
ay refresh
{
dmd.scanDisplayBySPI();
}
// --------------------------------------------------------------------
ISR (PCINT1_vect) // pin change interrupt A0-A5
{
interruptFlag = 1; // set interrupt flag
}
// --------------------------------------------------------------------
void setup ()
{
//Serial.begin(9600);
//Serial.println("Start");
dmd.clearScreen( true ); // clear random pixels on display
dmd.selectFont(MyBigFont); // select large font
// Initialize pin change interrupt (PCINT1_vect)
PCMSK1 = 63; // set interrupt mask for pins A0
-A5
PCIFR |= bit (PCIF1); // clear any outstanding interrup
ts
PCICR |= bit (PCIE1); // enable pin change interrupts
// Initialize DMD interrupt used to refresh the display
// Set period in microseconds to call ScanDMD
// Anything longer than 4000 (4ms) may cause the display to flicker
Timer1.initialize( 5000 );
Timer1.attachInterrupt( ScanDMD );
// set switch pins HIGH
digitalWrite (A0, HIGH); // enable pull-down pin 14
digitalWrite (A1, HIGH); // enable pull-down pin 15
digitalWrite (A2, HIGH); // enable pull-down pin 16
digitalWrite (A3, HIGH); // enable pull-down pin 17
digitalWrite (A4, HIGH); // enable pull-down pin 18
digitalWrite (A5, HIGH); // enable pull-down pin 19
refreshBoard (); // initialize scoreboard to zeros
}
// --------------------------------------------------------------------
void checkSwitches () // check status of switches
{
//Serial.println("");
//Serial.println("checkSwitches");
delay (debounce); // debounce switch contacts
for (i = 0; i <= 5; i++) // quick loop to read pins A0-A5
{
prevStatus [i] = currStatus [i]; // save switch status to prev
currStatus [i] = digitalRead (A0 + i); // read current switch status
// NOTE: an open switch reads HIGH (1); a closed switch reads LOW (0)
}
currTime = millis(); // get current time
for (i = 0; i <= 5; i++) // loop to save switch-closed tim
e
{
if (prevStatus [i] == 1 && currStatus [i] == 0) // if a switch just closed...
{
// Serial.println("switch closed");
closedTime [i] = currTime; // save the time
scoreStatus [i] = 1; // switch is closed
decTimerFlag = 1; // set decTimer flag
// PL = ""; PL = PL + i + " scoreStatus: " + scoreStatus [i]; Serial.println
(PL);
// PL = ""; PL = PL + " decTimer: " + decTimerFlag; Serial.println
(PL);
}
}
refreshFlag = 0; // clear refresh flag
for (i = 0; i <= 5; i++) // loop to increment scores
{
if (prevStatus [i] == 0 && currStatus [i] == 1) // if a switch just opened...
{
// Serial.println("switch opened");
// PL = ""; PL = PL + i + " scoreStatus: " + scoreStatus [i]; Serial.println
(PL);
if (scoreStatus [i] == 1) // but not yet decremented...
{
checkPeriod (); // check switch-closed period
}
scoreStatus [i] = 0; // status is open
// PL = ""; PL = PL + i + " scoreStatus: " + scoreStatus [i]; Serial.println
(PL);
}
}
if (refreshFlag > 0) refreshBoard (); // refresh if a score changed
interruptFlag = 0; // clear interrupt flag
}
// --------------------------------------------------------------------
void checkPeriod () // check switch-closed period
{
//Serial.println("checkPeriod");
closedPeriod = currTime - closedTime [i]; // calculate switch-closed period
//PL = ""; PL = PL + i + " closedPeriod: " + closedPeriod; Serial.println(PL);
if (closedPeriod < delayPeriod) // if closed period < delay perio
d...
{
incrementScore (); // increment the score
refreshFlag = 1; // set refresh flag
}
}
// --------------------------------------------------------------------
void incrementScore () // increment score
{
//Serial.println("incrementScore");
j = (i / 2) * 2; // determine which pair of scores
//PL = ""; PL = PL + i + " score: " + score [i]; Serial.println(PL);
if (score [i] >= maxScore) // if score is at max...
{
score [j] = 0; // reset both scores to zero
score [j + 1] = 0;
}
else
{
score [i] += 1; // else increment score by 1
}
//PL = ""; PL = PL + i + " score: " + score [i]; Serial.println(PL);
}
// --------------------------------------------------------------------
void checkDecrement () // decrement score
{
//Serial.println("");
//Serial.println("checkDecrement");
refreshFlag = 0; // clear refresh flag
decTimerFlag = 0; // clear decTimer flag
currTime = millis(); // get current time
for (i = 0; i <= 5; i = i + 2) // check scores for reset to zero
{
j = i + 1; // i and j are a pair of scores
if (scoreStatus [i] == 2 && scoreStatus [j] == 2) // if both are decrementing.
..
{
score [i] = 0; score [j] = 0; // reset both scores to zero
scoreStatus [i] = 0; scoreStatus [j] =0; // status is open
refreshFlag = 1; // set refresh flag
}
}
//i = 0;
//PL = ""; PL = PL + i + " scoreStatus: " + scoreStatus [i]; Serial.println(PL)
;
for (i = 0; i <= 5; i++) // loop to handle decrementing
{
if (scoreStatus [i] > 0) // if switch is closed...
{
decrementScore (); // decrement
decTimerFlag = 1; // set decTimer flag
}
}
//PL = ""; PL = PL + " decTimer: " + decTimerFlag; Serial.println(PL)
;
if (refreshFlag > 0) refreshBoard (); // refresh if a score changed
}
// --------------------------------------------------------------------
void decrementScore () // decrement score
{
//Serial.println("decrementScore");
closedPeriod = currTime - closedTime [i]; // calculate switch-closed period
//PL = ""; PL = PL + i + " scoreStatus: " + scoreStatus [i]; Serial.println(PL)
;
//PL = ""; PL = PL + i + " closedPeriod: " + closedPeriod; Serial.println(PL)
;
// If switch is closed and closedPeriod >= delay period OR
// If score is decremented and closedPeriod >= repeat period...then decrement
if ((scoreStatus [i] == 1 && closedPeriod >= delayPeriod) ||
(scoreStatus [i] == 2 && closedPeriod >= repeatPeriod))
{
// PL = ""; PL = PL + i + " score: " + score [i]; Serial.println(PL);
if (score [i] > 0) score [i] -= 1; // decrement score by 1
// PL = ""; PL = PL + i + " score: " + score [i]; Serial.println(PL);
scoreStatus [i] = 2; // score decremented
refreshFlag = 1; // set refresh flag
closedTime [i] = currTime; // reset the switch-closed time
}
}
// --------------------------------------------------------------------
void refreshBoard () // refresh entire display
{
//Serial.println("refreshBoard");
dmd.clearScreen( true ); // clear display first
for (j = 0; j <= 5; j = j + 2) // display scores in pairs
{
displayPair ();
}
}
// --------------------------------------------------------------------
void displayPair () // display a pair of scores
{
int scoreA = score [j]; // get a pair of scores
int scoreB = score [j + 1];
char scoreA1 = scoreA / 10; // breakdown score to individual
digits
char scoreA2 = scoreA - (scoreA1 * 10);
char scoreB1 = scoreB / 10;
char scoreB2 = scoreB - (scoreB1 * 10);
if (scoreA1 == 0) scoreA1 = 32; // if leading zero, replace with
ASCII blank
else scoreA1 += 48; // else add offset for ASCII zero
scoreA2 += 48; // add offset for ASCII zero
if (scoreB1 == 0) scoreB1 = 32; // if leading zero, replace with
ASCII blank
else scoreB1 += 48; // else add offset for ASCII zero

scoreB2 += 48; // add offset for ASCII zero

k = 32 - (j * 8); // k is the y coordinate (0, 16 o


r 32)
dmd.drawChar( 0, k, scoreA1, GRAPHICS_NORMAL ); // display the scores
dmd.drawChar( 12, k, scoreA2, GRAPHICS_NORMAL );
dmd.drawChar( 42, k, scoreB1, GRAPHICS_NORMAL );
dmd.drawChar( 54, k, scoreB2, GRAPHICS_NORMAL );
}
// --------------------------------------------------------------------
void loop () // main loop
{
if (interruptFlag > 0) checkSwitches (); // check switches after an interr
upt
if (decTimerFlag > 0) decTimer.check(); // check for decrementing
}

Das könnte Ihnen auch gefallen