SPCoast
Railroading on the Southern Pacific Coast

Arduino Loconet Example2

From SPCoast

Jump to: navigation, search

[edit] Arduino demo sketch showing interrupt driven LocoNet TX and RX functionality

This sketch is hardcoded to use ICP pin 8 (port PINB bit PB0) for input from LocoNet via a "usual" LM311 or LM393 comparator circuit:

Loconet Interface Schematic
Loconet Interface Schematic
Arduino + Loconet
Arduino + Loconet
Arduino + Loconet + Activity LEDs
Arduino + Loconet + Activity LEDs

Download the complete sketch as a zip archive

// Copyright 2008, John Plocher and Stefan Bormann, GPL v2.1 or later
 
#include <SoftwareSerial.h>
#include "loconet.h"
#include "ln_interface.h"

#define LED_DCCPOWER  15  // A1
#define LED_PKT       16  // A2
#define LED_IDLE      17  // A3

static LnBuf     LnBuffer ;
static lnMsg     *LnPacket;
static LnBufStats   *LnStats;

void setup(){
    Serial.begin(9600);         // set up Serial library at 9600 bps
    Serial.println("Loconet sniffer "); 
    Serial.println("by John Plocher ");

    pinMode(13, OUTPUT);   ACTIVITY_LED_ON(); ACTIVITY_LED_OFF(); // Flash LEDs
    pinMode( 3, OUTPUT);   ERROR_LED_ON();    ERROR_LED_OFF();    // to show progress
    pinMode(LED_DCCPOWER, OUTPUT);   // A5
    pinMode(LED_PKT,  OUTPUT);   // A6
    pinMode(LED_IDLE, OUTPUT);   // A7
    
    digitalWrite(LED_DCCPOWER, 1);
    digitalWrite(LED_PKT, 1);
    digitalWrite(LED_IDLE, 1);
    
    delay(2000);
    digitalWrite(LED_DCCPOWER, 0);
    digitalWrite(LED_PKT, 0);
    digitalWrite(LED_IDLE, 0);
    
    initLocoNet( &LnBuffer );
    LnStats = getLocoNetBufStats();
}

void printpacket(lnMsg *LnPacket, LnBufStats  *LnStats) {
        char sep;
        unsigned char opcode = (int)LnPacket->sz.command;
        unsigned char opcodefamily = (opcode >> 5);
        int len = -1;
        switch (opcodefamily) {
            case B100:  // 2 data bytes, inc checksum
                       len=2; break;
            case B101:  // 4 data bytes, inc checksum
                       len=4; break;
            case B110:  // 6 data bytes, inc checksum
                       len=6; break;
            case B111:  // N data bytes, inc checksum, next octet is N
                       len = (int)LnPacket->sz.mesg_size; break; 
        }
        Serial.print("Rx: "); 
        Serial.print((int)LnStats->RxPackets, DEC);  
        Serial.print("/"); 
        Serial.print((int)LnStats->RxErrors, DEC);
        Serial.print(" Tx: "); 
        Serial.print((int)LnStats->TxPackets, DEC); 
        Serial.print("/"); 
        Serial.print((int)LnStats->TxErrors, DEC);
        Serial.print(" "); 
        sep = '[';
        for (unsigned char x = 0; x < len; x++) {
            Serial.print(sep); 
            Serial.print("0x");
            Serial.print((int)LnPacket->data[x], HEX);
            sep = ',';
        }
        Serial.println("]");
}

void loop() {  
    LnPacket = recvLocoNetPacket() ;
    digitalWrite(LED_PKT,   0);
    digitalWrite(LED_IDLE,  0);
    
    if( LnPacket ) {
        unsigned char opcode = (int)LnPacket->sz.command;
        switch (opcode) {
          case OPC_GPOFF:
                        digitalWrite(LED_DCCPOWER, 0);
                        break;
          case OPC_GPON:
                        digitalWrite(LED_DCCPOWER, 1);
                        break;
          case OPC_IDLE:
                        digitalWrite(LED_IDLE,  1);
                        break;      
          default:
                        digitalWrite(LED_PKT, 1);          
        }
    }
}