3.18.2013

Start Module Implement Yourself

RobotChallange 2013 ordered Start Modules for Robot Sumo, which we can just buy for 15 EUR or implement ourselves.

I've implemented that with my own IR Receiver and Arduino IDE, according to Modes Of Operation:



So here is a code example, how to implement it.
UPDATE: 2014.04.04 after RobotChallenge 2014

//IR control PINs
#define RECV ## //Your pin number instead '##'
#define LED ##

//LIMIT COMMAND VALUES
#define MinimumCommandValue 0xC4
#define MaximumCommandValue 0xFE
#define UnderMinimumCommandValue 0x00 ... 0xC3
#define OverMaximumCommandValue 0xFF

//EEPROM ADDRESS
#define StateAddress   0
#define CommandAddress 1

//EEPROM StateValues
#define POWERON 0
#define STARTED 1
#define STOPPED 2
//OVERALL NUMBER OF STATES
#define NumOfStates 2

//THE LIBRARIES YOU NEED
#include <IRLib.h>
#include <EEPROM.h>

//THE STATES YOU NEED TO DECLARE
State powerOnState    = State(powerOnEnter, powerOnUpdate, powerOnExit);
State idleRunState    = State(idleRunUpdate);
State stoppedState    = State(stoppedSafe,stoppedUpdate, NULL);
/*MORE OF YOUR STATES HERE*/

//THE STATE YOU START FROM
FiniteStateMachine stateMachine = FiniteStateMachine(powerOnState);

//VARIABLES
int STOP, STOP2,  START, START2;
byte StateValue, CommandValue;

//INIT IR RECEIVER
IRrecv My_Receiver(RECV);
IRdecode My_Decoder;

void setup(){
/*PUT ALL YOUR SETUPS*/
  pinMode(LED, OUTPUT);
  pinMode(RECV,  INPUT);
//RESTORE THE PROGRAMMED COMMAND VALUE FROM EEPROM
//RESTORE THE STATE VALUE AFTER UNPREDICTED TURN OFF
  RestoreCommandStateValues();
  My_Receiver.enableIRIn();
//RETURN TO THE RESTORED STATE
  ReturnToCurrentState();
}

void loop() {
  check_irrecv_signal();
/*YOUR ESSENTIAL FUNCTIONS*/
  stateMachine.update();

}

void check_irrecv_signal(){
  if (My_Receiver.GetResults(&My_Decoder)) {
    My_Decoder.decode();
//ACCORDING TO THE STATE, CHOOSE COMMANDS
    switch(StateValue){
      case POWERON:
        if(My_Decoder.value == START || My_Decoder.value == START2){
           startCommand();
         }                  
         remoteStopProgramCommands(); break;
      case STARTED: remoteStopProgramCommands(); break;
      case STOPPED: break;
    }
    My_Receiver.resume();      //Prepare to receive the next value 
  }
}

void remoteStopProgramCommands(){
  if(My_Decoder.value == STOP || My_Decoder.value == STOP2) stopCommand(); //Cannot use in switch because STOP is not a constant
  switch(My_Decoder.value){
//THESE ARE POSSIBLE PROGRAMM COMMAND VALUES
    case 0x12C4 ... 0x12FE:
    case 0x1AC4 ... 0x1AFE: programmCommand(); break;
  }
}

void RestoreCommandStateValues(){
  CommandValue = EEPROM.read(CommandAddress);
  switch(CommandValue){
    case UnderMinimumCommandValue:
    case OverMaximumCommandValue:
      CommandValue = MinimumCommandValue;
      EEPROM.write(CommandAddress, CommandValue);
      break;
  }
  makeStartStopValues();
  StateValue = EEPROM.read(StateAddress);
  if(StateValue > NumOfStates){
    StateValue = POWERON;
    EEPROM.write(StateAddress, StateValue);
  }

}

void makeStartStopValues(){
//ACCORDING TO NEW SWEDEN IR REMOTE YOU MAY
//GET 2 DIFFERENT VALUES AT THE SAME BUTTON
//BUT DIFFERENT PUSH TIMES
  STOP = CommandValue + 0x1100;
  STOP2 = CommandValue + 0x1900;
  START = STOP + 1;
  START2 = STOP2 + 1;
}

void ReturnToCurrentState(){
  switch(StateValue){
    case POWERON: break;
    case STARTED: startCommand(); break;
    case STOPPED: stopCommand(); break;
  }
}

void startCommand(){
  StateValue = STARTED;
  EEPROM.write(StateAddress, StateValue);
/*ENABLE DRIVERS HERE*/
  digitalWrite(RXLED, HIGH);
  stateMachine.transitionTo(idleRunState);
}

void stopCommand(){
/*DISABLE DRIVERS HERE*/
  StateValue = STOPPED;
  EEPROM.write(StateAddress, StateValue);
  stateMachine.transitionTo(stoppedState);
}

void programmCommand(){
/*DISABLE DRIVERS HERE*/
  StateValue = POWERON;
  EEPROM.write(StateAddress, StateValue);
  CommandValue = My_Decoder.value & 0x00FE;
  EEPROM.write(CommandAddress, CommandValue);
  makeStartStopValues();
//FLASH THE LED 2 TIMES 500MS
  LED_FLASHING(2, 500);
  stateMachine.transitionTo(powerOnState);
}

/*POWER ON STATE*/ 
void powerOnEnter(){
/*YOUR CODE HERE*/
}
void powerOnUpdate(){
/*YOUR CODE HERE*/
}  
void powerOnExit(){
/*YOUR CODE HERE*/
}

/*IDLE RUN STATE*/  
void idleRunUpdate(){
/*YOUR CODE HERE*/
}

/*STOPPED_SAFE STATE*/
void stoppedSafe(){
  LED_FLASHING(4, 250);
  StateValue = POWERON;
  EEPROM.write(StateAddress, StateValue);
}
/*STOPPED STATE*/
void stoppedUpdate(){
  while(1){
    LED_FLASHING(5, 500);
  }
}