Having never programmed an Arduino, but having some knowledge of the C Language made this task easier for me. Having read and understood the Arduino code linked in the Westbury On Severn site I dug a little deeper into the imported modules and found that the CmdMessenger module had been updated (see code here) and that this tied in nicely with PyCmdMessenger (I had python in mind for the REST API). I’ve included the code below.
/* *
*
* Name: ickleton_scoreboard.pde
* Author: David Jones (drjdev@github.com)
*
* Scoreboard software, based on ideas from https://buildyourownscoreboard.wordpress.com
* Takes input from RPi and outputs information to
* shifter chips to light numbers on a cricket scoreboard
*
* Acknowledgements:
* CmdMessenger.h - https://github.com/thijse/Arduino-CmdMessenger
* */
// CmdMessenger(3) library available from https://github.com/thijse/Arduino-CmdMessenger
#include <CmdMessenger.h>
// Base64 library available from https://github.com/adamvr/arduino-base64
//#include <Base64.h>
// Streaming4 library available from http://arduiniana.org/libraries/streaming/
//#include <Streaming.h>
// Library to control shifters courtesy of http://www.proto-pic.com/Resources/shifter.zip
// Modified to take strings rather than int
#include <ShifterStr.h>
// Setup the field separators for CmdMessenger
char field_separator = ',';
char command_separator = '#';
// Attach a new CmdMessenger object to the default Serial port
CmdMessenger cmdMessenger = CmdMessenger(Serial, field_separator, command_separator);
// set up the char arrays for each scoreboard section
char *batAScore = " ";// = { '\0' };
char *batBScore = " ";//[4] = { '\0' };
char *total = " ";//[4] = { '\0' };
char *wickets = " ";//[2] = { '\0' };
char *overs = " ";//[3] = { '\0' };
char *target = " ";//[4] = { '\0' };
char batAScoreStr[] = "Bat A Score";
char totalScoreStr[] = "Total Score";
char batBScoreStr[] = "Bat B Score";
char wicketsStr[] = "Wickets";
char oversStr[] = "Overs";
char targetScoreStr[] = "Target Score";
// Setup shifters
Shifter shifterSet1(9,2,3,4);
Shifter shifterSet2(6,5,6,7);
// This is the list of recognized commands. These can be commands that can either be sent or received.
// In order to receive, attach a callback function to these events
enum
{
// Commands
kAcknowledge , // Command to acknowledge that cmd was received
kTest1Ack ,
kError , // Command to report errors
kArduinoReady , // Command to confirm Arduino is ready
kTestMode1 , // Command to enter test mode
kUpdateScoreboard , // Command to request update of scoreboard
kScoreboardUpdated , // Command to return updated scores
kGetCurrentScore , // Command to retrieve current score stored on Arduino
kReturnCurrentScore , // Command to return current score stored on Arduino
};
// ------------------ C A L L B A C K S -----------------------
// Commands we send from the Arduino to be received on the PC
// ------------------ C A L L B A C K M E T H O D S -------------------------
void test_mode1()
{
char buf[] = { "Test Mode Set" };
cmdMessenger.sendCmdStart(kTest1Ack);
cmdMessenger.sendCmdArg(buf);
shifterSet1.display("111333222");
shifterSet2.display("445678");
cmdMessenger.sendCmd(kTest1Ack, buf);
//char test_comp[] = { "Test complete" };
//cmdMessenger.sendCmdArg(test_comp);
cmdMessenger.sendCmdEnd();
}
void return_current_score()
{
cmdMessenger.sendCmdStart(kReturnCurrentScore);
cmdMessenger.sendCmdArg(batAScore);
cmdMessenger.sendCmdArg(total);
cmdMessenger.sendCmdArg(batBScore);
cmdMessenger.sendCmdArg(wickets);
cmdMessenger.sendCmdArg(overs);
cmdMessenger.sendCmdArg(target);
cmdMessenger.sendCmdEnd();
}
void update_scoreboard()
{
char scoreStringTop[10] = { '\0' };
char scoreStringBottom[7] = { '\0' };
//Read all score strings
batAScore = cmdMessenger.readStringArg();
total = cmdMessenger.readStringArg();
batBScore = cmdMessenger.readStringArg();
wickets = cmdMessenger.readStringArg();
overs = cmdMessenger.readStringArg();
target = cmdMessenger.readStringArg();
//Bat A Score retrieval
strcpy(scoreStringTop,batAScore);
cmdMessenger.sendCmdStart(kScoreboardUpdated);
cmdMessenger.sendCmdArg(batAScoreStr);
cmdMessenger.sendCmdArg(batAScore);
//Total score retrieval
strcat(scoreStringTop,total);
cmdMessenger.sendCmdArg(totalScoreStr);
cmdMessenger.sendCmdArg(total);
//Bat B Score retrieval
strcat(scoreStringTop,batBScore);
cmdMessenger.sendCmdArg(batBScoreStr);
cmdMessenger.sendCmdArg(batBScore);
shifterSet1.display(scoreStringTop);
memset(scoreStringTop, '\0', 10);
memset(scoreStringBottom, '\0', 7);
//Overs
strcpy(scoreStringBottom, overs);
cmdMessenger.sendCmdArg(oversStr);
cmdMessenger.sendCmdArg(overs);
//Retrieve Wickets
strcat(scoreStringBottom, wickets);
cmdMessenger.sendCmdArg(wicketsStr);
cmdMessenger.sendCmdArg(wickets);
//Target Score
strcat(scoreStringBottom, target);
cmdMessenger.sendCmdArg(targetScoreStr);
cmdMessenger.sendCmdArg(target);
cmdMessenger.sendCmdEnd();
shifterSet2.display(scoreStringBottom);
}
// ------------------ D E F A U L T C A L L B A C K S -----------------------
// Commands we send from the PC and want to recieve on the Arduino.
// We must define a callback function in our Arduino program for each entry in the list below vv.
// They start at the address kSEND_CMDS_END defined ^^ above as 004
/*
messengerCallbackFunction messengerCallbacks[] =
{
update_scoreboard, //004
test_mode, //005
NULL
};
*/
// Its also possible (above ^^) to implement some symetric commands, when both the Arduino and
// PC / host are using each other's same command numbers. However we recommend only to do this if you
// really have the exact same messages going in both directions. Then specify the integers (with '=')
// Called when a received command has no attached function
void OnUnknownCommand()
{
cmdMessenger.sendCmd(kError,"Command without attached callback");
}
// Callback function that responds that Arduino is ready (has booted up)
void OnArduinoReady()
{
cmdMessenger.sendCmd(kAcknowledge,"Arduino ready");
}
// ------------------ E N D C A L L B A C K M E T H O D S ------------------
// Commands we send from the PC and want to receive on the Arduino.
// We must define a callback function in our Arduino program for each entry in the list below.
void attachCommandCallbacks()
{
cmdMessenger.attach(kUpdateScoreboard, update_scoreboard);
cmdMessenger.attach(kTestMode1, test_mode1);
cmdMessenger.attach(kGetCurrentScore, return_current_score);
// Attach callback methods
cmdMessenger.attach(OnUnknownCommand);
}
void setup()
{
// Listen on serial connection for messages from the pc
Serial.begin(115200); // Arduino Uno, Mega, with AT8u2 USB
// Adds newline to every command
cmdMessenger.printLfCr();
// Attach my application's user-defined callback methods
attachCommandCallbacks();
//Initialise display to zeroes.
//First show all 8's to check LEDs
shifterSet1.display("888888888");
shifterSet2.display("888888");
delay(5000);
//Then...
shifterSet1.display("--0--0--0");
shifterSet2.display("-00---");
// Send the status to the PC that says the Arduino has booted
cmdMessenger.sendCmd(kAcknowledge,"Arduino has started!");
}
// ------------------ M A I N ( ) --------------------------------------------
// Timeout handling
long timeoutInterval = 2000; // 2 seconds
long previousMillis = 0;
int counter = 0;
void timeout()
{
// blink
if (counter % 2)
digitalWrite(13, HIGH);
else
digitalWrite(13, LOW);
counter ++;
}
void loop()
{
// Process incoming serial data, if any
cmdMessenger.feedinSerialData();
// handle timeout function, if any
if ( millis() - previousMillis > timeoutInterval )
{
timeout();
previousMillis = millis();
}
// Loop.
}