Programming The Arduino

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.
}

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.