Ecco qua il programma in chiaro:
#include <LocoNet.h>
#include <EEPROM.h>
#define LnTXpin 11 //Receive LocoNet PIN
// Item Number (Art.-Nr.): 63340
#define ARTNR 6334
#define generalAdr 65535 //General-Adresse 0xFFFF
static lnMsg *LnPacket;
static LnBuf LnTxBuffer;
#define maxLNCV 100 //lesbare LNCV
#define dAnz 8 //Anzahl der Eingänge
#define MaxAdr 4096 //höchste nutzbare Adresse
byte dPin[dAnz] = {2, 3, 4, 5, 6, 7, 9, 10};
#define ProgSwPin 12 //Programmiertaster
#define LedPin 13 //status LED
unsigned int dAdr[dAnz];
//Entprellen der Eingänge, LNCV EEPROM:
#define timefalling 21 //LNCV val = 0; Verzögerung der Rückmeldung HIGH -> LOW (BELEGT)
#define defaultfall 0
#define timerising 41 //LNCV val = 200; //Verzögerung der Rückmeldung LOW -> HIGH (FREI)
#define defaultrise 200
#define reportAdr 17 //LNCV val = 1017; //Ausgabe der Zustände der Rückmelder
#define defaultreport 1017
unsigned int dtime[dAnz];
boolean dstate[dAnz];
int count = -1; //Zähler für PIN Abfrage, beginne bei 0
unsigned int LedCount = 0;
boolean SwState = false;
boolean ProgAdr = false;
LocoNetCVClass lnCV;
boolean programmingMode = false;
void setup()
{
Serial.end();
//Serial.begin(57600);
// First initialize the LocoNet interface
LocoNet.init(LnTXpin);
pinMode(ProgSwPin, INPUT_PULLUP);
pinMode(LedPin, OUTPUT);
digitalWrite(LedPin, LOW); //LED off
//Adresse aus LNCV lesen:
unsigned int Adresse = lncv(0);
if (Adresse > (MaxAdr - dAnz)) {
Adresse = 1;
lncv(0,1); //default Values
lncv(timefalling, defaultfall);
lncv(timerising, defaultrise);
lncv(reportAdr, defaultreport);
}
if (lncv(timefalling) > 60000)
lncv(timefalling, defaultfall);
if (lncv(timerising) > 60000)
lncv(timerising, defaultrise);
//Initialisierung der Eingänge
for (int i = 0; i < dAnz; i++) {
//set ADR:
dAdr[i] = Adresse + i; //fortlaufende Adressen
//set default state:
dtime[i] = 0;
dstate[i] = false;
pinMode(dPin[i], INPUT_PULLUP); //Pin auf Eingang & Pullup aktivieren
if (dstate[i] == digitalRead(dPin[i])) { //Vorbelegung setzten!
dstate[i] = true;
//sendSensor(dAdr[i], true); //aktuellen Status senden - ON
digitalWrite(LedPin, HIGH); //LED on
}
}
}
void loop()
{
// Check for any received LocoNet packets
LnPacket = LocoNet.receive();
if( LnPacket )
{
// First print out the packet in HEX
Serial.print("RX: ");
uint8_t msgLen = getLnMsgSize(LnPacket);
for (uint8_t x = 0; x < msgLen; x++)
{
uint8_t val = LnPacket->data[x];
// Print a leading 0 if less than 16 to make 2 HEX digits
if(val < 16)
Serial.print('0');
Serial.print(val, HEX);
Serial.print(' ');
}
// If this packet was not a Switch or Sensor Message then print a new line
uint8_t packetConsumed(LocoNet.processSwitchSensorMessage(LnPacket));
if (packetConsumed == 0) {
Serial.println();
packetConsumed = lnCV.processLNCVMessage(LnPacket);
}
}
//handle programming switch:
if (SwState == false && digitalRead(ProgSwPin) == LOW) {
//down
SwState = true;
}
if (SwState == true && digitalRead(ProgSwPin) == HIGH) {
//up
SwState = false;
ProgAdr = !ProgAdr;
}
//toggle status LED:
LedCount++;
if (LedCount > 1700) {
LedCount = 0;
if (ProgAdr == true) { //Blinken bei Programmierung
digitalWrite(LedPin, !digitalRead(LedPin)); //change
}
else {
digitalWrite(LedPin, LOW); //show LocoNet send feedback Data
}
}
//handle input states:
count++; //nächsten Input Abfragen
if (count >= dAnz) //Max Input prüfen
count = 0; //beim Ersten beginnen
if (dstate[count] != digitalRead(dPin[count])) { //Eingang hat sich geändert?
dtime[count]++;
digitalWrite(LedPin, HIGH); //LED on
if ((dstate[count] == true) && (dtime[count] >= lncv(timefalling))) { //falling (high -> low)
sendSensor(dAdr[count], true); //aktuellen Status senden - ON
dstate[count] = !dstate[count]; //Speicher aktualisieren
dtime[count] = 0;
}
else if ((dstate[count] == false) && (dtime[count] >= lncv(timerising))) { //rising (low -> high)
sendSensor(dAdr[count], false); //aktuellen Status senden - OFF
dstate[count] = !dstate[count]; //Speicher aktualisieren
dtime[count] = 0;
}
}
}
// Rückmeldesonsor Daten senden
void sendSensor(int Adr, boolean state) {
//Adressen von 1 bis 4096 (MaxAdr) akzeptieren
if (Adr <= 0) //nur korrekte Adressen
return;
Adr = Adr - 1;
byte D2 = Adr >> 1; //Adresse Teil 1 erstellen
bitWrite(D2,7,0); //A1 bis A7
byte D3 = Adr >> 8; //Adresse Teil 2 erstellen, A8 bis A11
bitWrite(D3,4, state); //Zustand ausgeben
bitWrite(D3,5,bitRead(Adr,0)); //Adr Bit0 = A0
//Checksum bestimmen:
byte D4 = 0xFF; //Invertierung setzten
D4 = OPC_INPUT_REP ^ D2 ^ D3 ^ D4; //XOR
bitWrite(D4,7,0); //MSB Null setzten
addByteLnBuf( &LnTxBuffer, OPC_INPUT_REP ) ; //0xB2
addByteLnBuf( &LnTxBuffer, D2 ) ; //1. Daten Byte IN2
addByteLnBuf( &LnTxBuffer, D3 ) ; //2. Daten Byte IN2
addByteLnBuf( &LnTxBuffer, D4 ) ; //Prüfsumme
addByteLnBuf( &LnTxBuffer, 0xFF ) ; //Trennbit
// Check to see if we have received a complete packet yet
LnPacket = recvLnMsg( &LnTxBuffer ); //Senden vorbereiten
if(LnPacket ) { //korrektheit Prüfen
LocoNet.send( LnPacket ); // Send the received packet from the PC to the LocoNet
}
}
// This call-back function is called from LocoNet.processSwitchSensorMessage
// for all Switch Request messages
void notifySwitchRequest( uint16_t Address, uint8_t Output, uint8_t Direction ) {
Serial.print("Switch Report: ");
Serial.print(Address, DEC);
Serial.print(':');
Serial.print(Direction ? "Closed" : "Thrown");
Serial.print(" - ");
Serial.println(Output ? "On" : "Off");
unsigned int Adr = lncv(0);
if (ProgAdr == true) {
digitalWrite(LedPin, HIGH); //LED on
Serial.println("neue Adresse!");
Adr = Address;
lncv(0, Address);
lncv(timefalling, defaultfall);
lncv(timerising, defaultrise);
lncv(reportAdr, defaultreport);
//Reset Adressen:
for (int i = 0; i < dAnz; i++) {
//set ADR:
dAdr[i] = Adr + i; //fortlaufende Adressen
}
ProgAdr = false;
}
if (Address == lncv(reportAdr) && Output == 0) {
//alle Eingänge melden:
for (int i = 0; i < dAnz; i++) {
sendSensor(dAdr[i], !dstate[i]); //aktuellen Status senden
}
}
}
// This call-back function is called from LocoNet.processSwitchSensorMessage
// for all Sensor messages
void notifySensor( uint16_t Address, uint8_t State ) {
Serial.print("Sensor: ");
Serial.print(Address, DEC);
Serial.print(" - ");
Serial.println( State ? "Active" : "Inactive" );
}
/**
* Notifies the code on the reception of a read request.
* Note that without application knowledge (i.e., art.-nr., module address
* and "Programming Mode" state), it is not possible to distinguish
* a read request from a programming start request message.
*/
int8_t notifyLNCVread(uint16_t ArtNr, uint16_t lncvAddress, uint16_t,
uint16_t & lncvValue) {
Serial.print("Enter notifyLNCVread(");
Serial.print(ArtNr, HEX);
Serial.print(", ");
Serial.print(lncvAddress, HEX);
Serial.print(", ");
Serial.print(", ");
Serial.print(lncvValue, HEX);
Serial.print(")");
// Step 1: Can this be addressed to me?
// All ReadRequests contain the ARTNR. For starting programming, we do not accept the broadcast address.
if (programmingMode) {
if (ArtNr == ARTNR) {
if (lncvAddress < maxLNCV) {
lncvValue = lncv(lncvAddress);
Serial.print(" LNCV Value: ");
Serial.print(lncvValue);
Serial.print("\n");
return LNCV_LACK_OK;
} else {
// Invalid LNCV address, request a NAXK
return LNCV_LACK_ERROR_UNSUPPORTED;
}
} else {
Serial.print("ArtNr invalid.\n");
return -1;
}
} else {
Serial.print("Ignoring Request.\n");
return -1;
}
}
int8_t notifyLNCVprogrammingStart(uint16_t & ArtNr, uint16_t & ModuleAddress) {
// Enter programming mode. If we already are in programming mode,
// we simply send a response and nothing else happens.
Serial.print("notifyLNCVProgrammingStart ");
if (ArtNr == ARTNR) {
Serial.print("artnrOK ");
if (ModuleAddress == lncv(0)) {
Serial.print("moduleUNI ENTERING PROGRAMMING MODE\n");
programmingMode = true;
return LNCV_LACK_OK;
} else if (ModuleAddress == generalAdr) {
Serial.print("moduleBC ENTERING PROGRAMMING MODE\n");
ModuleAddress = lncv(0);
programmingMode = true;
return LNCV_LACK_OK;
}
}
Serial.print("Ignoring Request.\n");
return -1;
}
/**
* Notifies the code on the reception of a write request
*/
int8_t notifyLNCVwrite(uint16_t ArtNr, uint16_t lncvAddress,
uint16_t lncvValue) {
Serial.print("notifyLNCVwrite, ");
// dumpPacket(ub);
if (!programmingMode) {
Serial.print("not in Programming Mode.\n");
return -1;
}
if (ArtNr == ARTNR) {
Serial.print("Artnr OK, ");
if (lncvAddress < maxLNCV) {
lncv(lncvAddress, lncvValue);
return LNCV_LACK_OK;
}
else {
return LNCV_LACK_ERROR_UNSUPPORTED;
}
}
else {
Serial.print("Artnr Invalid.\n");
return -1;
}
}
/**
* Notifies the code on the reception of a request to end programming mode
*/
void notifyLNCVprogrammingStop(uint16_t ArtNr, uint16_t ModuleAddress) {
Serial.print("notifyLNCVprogrammingStop ");
if (programmingMode) {
if (ArtNr == ARTNR && ModuleAddress == lncv(0)) {
programmingMode = false;
Serial.print("End Programing Mode.\n");
}
else {
if (ArtNr != ARTNR) {
Serial.print("Wrong Artnr.\n");
return;
}
if (ModuleAddress != lncv(0)) {
Serial.print("Wrong Module Address.\n");
return;
}
}
}
else {
Serial.print("Ignoring Request.\n");
}
}
//write LNCV into EEPROM:
void lncv (uint16_t Adr, uint16_t val) {
unsigned int Address = Adr * 2;
EEPROM.update(Address, val & 0xFF); //LSB
EEPROM.update(Address + 1, val >> 8); //MSB
}
//read LNCV from EEPROM
uint16_t lncv (uint16_t Adr) {
unsigned int Address = Adr * 2;
unsigned int val = 0;
val = (EEPROM.read(Address) & 0xFF) | ((EEPROM.read(Address + 1) & 0xFF) << 8); //LSB & MSB
return val;
}
Provato i due boot ma niente.
Il nano marchiato viene riconosciuto sulla COM3, carica il codice con il boot più recente e funziona.
Il nano anonimo viene riconosciuto sulla COM4, carica con l'old bootloader e non funziona.