I am using an Arduino Nano with a Loconet interface to provide some indicators and control for the Track Power Status. I have a sketch which works to both control the Track Power Status from push buttons and also display the status using LEDs. I want to add function to this sketch that will display using LEDs when certain Switch Commands are issued. I have found what I think is a suitable subroutine that will do what I want but I cannot determine how to call it correctly.
At line 80 in the attached sketch I correctly see that a switch command has been issued on the Loconet and the routine I think I should use is at line 109. My problem is I don't know how to parse the command to get the parameters to call the routine.
Thanks for help you can give.
Dale Gloer
#include <LocoNet.h>
#define PowerOnPin 3 // Buttons connected to these pins
#define PowerOffPin 4 // GPON GPOFF and ESTOP as well as Clear All Slots
#define EStopPin 5
#define SlotClearPin 2
#define ST_LED_PIN 7
#define DIV_LED_PIN 9
#define LNtxPin 6 // LocoNet Transmit pin (LocoShield uses pin7)
#define PowerOnLEDPin 10 // Assume this pin has a LED+resistor attached...
#define PowerOffLEDPin 11 // Assume this pin has a LED+resistor attached...
#define EStopLEDPin 12 // Assume this pin has a LED+resistor attached...
#define TURNOUT_ADDRESS 44
int turnoutDirection;
// Button press state
// Current
int GPonButton, GPonButton1, GPonButton2;
int GPoffButton, GPoffButton1, GPoffButton2;
int EStopButton, EStopButton1, EStopButton2;
int ClearButton, ClearButton1, ClearButton2;
// Last state processed - helps us ensure we don't repeat commands while a button is held down
int lastGPon = -1;
int lastGPoff = -1;
int lastEStop = -1;
int lastClear = -1;
int ClearIt = 0; // Should we clear slots when we get a slot status packet?
void setup(){
pinMode(PowerOnPin, INPUT_PULLUP);
pinMode(PowerOffPin, INPUT_PULLUP);
pinMode(SlotClearPin, INPUT_PULLUP);
pinMode(EStopPin, INPUT_PULLUP);
pinMode(EStopLEDPin, OUTPUT);
pinMode(PowerOnLEDPin, OUTPUT);
pinMode(PowerOffLEDPin, OUTPUT);
digitalWrite(PowerOnLEDPin, 0); // Power is in an unknown state
digitalWrite(PowerOffLEDPin, 0); //
digitalWrite(EStopLEDPin, 0); // and not estopped
// Configure the serial Pin for 115200 baud
Serial.begin(115200);
Serial.println("LocoNet Controller");
// initialize the LocoNet interface
LocoNet.init(LNtxPin);
}
//////////////////////////////////////////////////////////////////////
void processIncomingLoconetCommand(lnMsg* LnPacket) {
if( LnPacket ) {
//LocoNet.processSwitchSensorMessage(LnPacket);
unsigned char opcode = (int)LnPacket->sz.command;
Serial.println(opcode,HEX);
Serial.println((int)LnPacket);
if (opcode == OPC_GPON) {
Serial.println("Power ON");
digitalWrite(PowerOnLEDPin, 1);
digitalWrite(PowerOffLEDPin, 0);
digitalWrite(EStopLEDPin, 0);
} else if (opcode == OPC_GPOFF) {
Serial.println("Power OFF");
digitalWrite(PowerOnLEDPin, 0);
digitalWrite(EStopLEDPin, 0);
digitalWrite(PowerOffLEDPin, 1);
} else if (opcode == OPC_IDLE) {
digitalWrite(EStopLEDPin, 1);
Serial.println("EStop!");
}
if (opcode == OPC_SW_REQ){
Serial.println("got a switch request");
// Serial.println((int)turnoutAddress);
// Serial.println(turnoutDirection);
// notifySwitchRequest(LnPacket);
}
/* else if (opcode == OPC_SL_RD_DATA) {
if (ClearIt) {
int slot = LnPacket->sd.slot;
int stat = LnPacket->sd.stat;
Serial.print("Clear Slot:"); Serial.print(slot); Serial.print(":"); Serial.println(stat);
if (stat != 0) {
sendOPC_LOCO_SPD(slot, 0); // speed 0
sendOPC_LOCO_DIRF(slot, 0); // F0-4 off, Fwd
sendOPC_LOCO_SND(slot, 0); // F5-8 off
// Don't need to turn off F9 and above because they should go away when track power is turned off...
sendOPC_SLOT_STAT1(slot, 0);
}
}
}
*/
else {
// ignore the message...
}
}
}
////////////////////////////////////////////////////////////////////////////
void notifySwitchRequest( uint16_t Address, uint8_t Output, uint8_t Direction ) {
if(Address == TURNOUT_ADDRESS) {
turnoutDirection = Direction;
if(turnoutDirection == 0) {
digitalWrite(ST_LED_PIN, HIGH);
digitalWrite(DIV_LED_PIN, LOW);
} else {
digitalWrite(ST_LED_PIN, LOW);
digitalWrite(DIV_LED_PIN, HIGH);
}
}
}
//////////////////////////////////////////////////////////////////////////
void send3bytePacket(int opcode, int slot, int spd) {
lnMsg SendPacket;
SendPacket.data[ 0 ] = opcode;
SendPacket.data[ 1 ] = slot;
SendPacket.data[ 2 ] = spd;
LocoNet.send( &SendPacket );
}
void sendOPC_GP(byte on) {
lnMsg SendPacket;
if (on) {
SendPacket.data[ 0 ] = OPC_GPON;
} else {
SendPacket.data[ 0 ] = OPC_GPOFF;
}
LocoNet.send( &SendPacket ) ;
}
void sendOPC_IDLE() {
lnMsg SendPacket;
SendPacket.data[ 0 ] = OPC_IDLE;
LocoNet.send( &SendPacket ) ;
}
void sendOPC_RQ_SL_DATA(int slot) {
send3bytePacket(OPC_RQ_SL_DATA,slot,0);
}
void loop() {
// Check for any received LocoNet packets
while (lnMsg *LnPacket = LocoNet.receive() ) {
processIncomingLoconetCommand( LnPacket );
}
// Debounce logic:
// ...Check for any buttons pushed, delay, read again...
GPonButton1 = digitalRead(PowerOnPin);
GPoffButton1 = digitalRead(PowerOffPin);
EStopButton1 = digitalRead(EStopPin);
ClearButton1 = digitalRead(SlotClearPin);
delay(5);
GPonButton2 = digitalRead(PowerOnPin);
GPoffButton2 = digitalRead(PowerOffPin);
EStopButton2 = digitalRead(EStopPin);
ClearButton2 = digitalRead(SlotClearPin);
// ...identical readings mean we have a good result
if (GPonButton1 == GPonButton2) { GPonButton = GPonButton1 ? 0 : 1; }
if (GPoffButton1 == GPoffButton2) { GPoffButton = GPoffButton1 ? 0 : 1; }
if (EStopButton1 == EStopButton2) { EStopButton = EStopButton1 ? 0 : 1; }
if (ClearButton1 == ClearButton2) { ClearButton = ClearButton1 ? 0 : 1; }
if (lastGPon == -1) {
// need to initialize things the first time thru to ensure buttons don't all fire...
lastGPon = GPonButton;
lastGPoff = GPoffButton;
lastEStop = EStopButton;
lastClear = ClearButton;
} else {
// See if anything has changed since last time thru...
if (GPonButton != lastGPon) { // GP_ON
lastGPon = GPonButton;
if (GPonButton) {
sendOPC_GP(1);
}
ClearIt = 0;
}
if (GPoffButton != lastGPoff) { // GP_OFF
lastGPoff = GPoffButton;
if (GPoffButton) {
sendOPC_GP(0);
}
ClearIt = 0;
}
if (EStopButton != lastEStop) { // E_STOP
lastEStop = EStopButton;
if (EStopButton) {
sendOPC_IDLE();
}
ClearIt = 0;
}
if (ClearButton != lastClear) { // Clear all Slots
lastClear = ClearButton;
if (ClearButton) {
ClearIt = 1;
// query all the slots, let the handler clear things
for (int slot = 0; slot < 120; slot++) {
sendOPC_RQ_SL_DATA(slot);
}
ClearIt = 0; // race condition?
}
}
}
}