Een DCC decoder op basis van een Arduino mini pro voor het tonen van eenvoudige (rood-groen) seinbeelden.
https://www.arduino.cc/en/Main/ArduinoBoardProMini
<FOTO>
<COMPONENTEN>
<BENODIGDE LIBRARIES>
https://github.com/mrrwa/NmraDcc
<CODE>
#include <NmraDcc.h>
#include <EEPROM.h>
#define maxaccessories 4
#if defined(DCC_ACK_PIN)
const int DccAckPin = DCC_ACK_PIN ;
#endif
NmraDcc Dcc ;
DCC_MSG Packet ;
typedef struct {
int address; // Address to respond to
byte mode; // 0=continuous, 1=oneshot, 2=flasher
byte output; // State of accessory: 1=on, 0=off (for internal use only)
int outputPinR; // Arduino output pin Red
int outputPinG; // Arduino output pin Green
byte highlow; // State of outputpin: 1=HIGH, 0=LOW
//boolean finished; // Memory location that says the oneshot is finished
//int durationonMilli; // oneshot or flasher on time in ms
//int durationoffMilli; // oneshot or flasher off time in ms
//boolean isAnalog; // false=digital, true=analog, sends analogValue to out pin.
//byte analogValue; // pulse with modulation (pwm) value that is written to pin. Range: 0 - 255
// goto http://arduino.cc/en/Reference/AnalogWrite to see which pins support analog pwm output
//unsigned long onMilli; // for internal use
//unsigned long offMilli; // for internal use
}
DCCAccessoryAddress;
DCCAccessoryAddress accessory[maxaccessories];
int addr = 0;
int ProgState = 0;
int ProgButton = 11;
int ProgLed = 10;
int ProgAddr = 0;
int EEAddr = 0;
int buttonState;
int lastButtonState = LOW;
long lastDebounceTime = 0;
long debounceDelay = 50;
void(* resetFunc) (void) = 0; //declare reset function at address 0
boolean debounce() // read button status
{
boolean retVal = false;
int reading = digitalRead(ProgButton);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
retVal = true;
}
}
}
lastButtonState = reading;
return retVal;
}
//Turnouts - may not be properly implemented in library, problem with BoardAddress. Must turn off my-address-only check. must be in FLAGS_DCC_ACCESSORY_DECODER mode.
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ){
uint8_t OutputNum = OutputAddr >> 1; //shift over the bits so the outputaddr is 0 to 3
uint8_t StateProper = OutputAddr & 0b00000001; //JMRI puts out the state as the right most bit of pDccMsg->Data[1], the state argument doesnt change in JMRI Turnout.
Serial.print("AccState - ");
Serial.print("Received raw addr: ");
Serial.println(Addr);
if (ProgState == 1)
{
//EEPROM.write(ProgAddr, Addr);
EEPROM.write(ProgAddr,highByte(Addr)); // for integers bigger than 254
EEPROM.write(ProgAddr + 1,lowByte(Addr)); // for integers bigger than 254
Serial.print("--> Nieuw eerste address toegewezen: ");
Serial.println(Addr);
delay(300);
digitalWrite(ProgLed, LOW);
Serial.println("Reset decoder");
delay(300);
resetFunc(); //call reset
}
for (int i=0; i<maxaccessories; i++)
{
if (Addr == accessory[i].address)
{
if (StateProper == 1 )
{
Serial.print("address enable:");
Serial.println(Addr);
accessory[i].output = 1;
}
else
{
Serial.print("address disable:");
Serial.println(Addr);
accessory[i].output = 0;
}
}
}
}
void setup() {
Serial.begin(9600);
Serial.println("Decoder started");
//EEAddr = EEPROM.read(ProgAddr);
EEAddr = word(EEPROM.read(ProgAddr),EEPROM.read(ProgAddr + 1)); // for integers bigger than 254
Serial.print("--> Address first output: ");
Serial.println(EEAddr,DEC);
// ConfigureDecoderFunctions
accessory[0].address = EEAddr; // DCC address
accessory[0].mode = 0; // Continuous. HIGH until DCC switches the address off again.
accessory[0].outputPinR = 6; // Arduino pin where function is connected to.
accessory[0].outputPinG = 7;
accessory[0].output = 0; // Initial state (0 or 1) of output after startup.
accessory[1].address = EEAddr + 1;
accessory[1].mode = 0;
accessory[1].outputPinR = 8;
accessory[1].outputPinG = 9;
accessory[1].output = 0;
accessory[2].address = EEAddr + 2;
accessory[2].mode = 0;
accessory[2].outputPinR = 13;
accessory[2].outputPinG = 12;
accessory[2].output = 0;
accessory[3].address = EEAddr + 3;
accessory[3].mode = 0;
accessory[3].outputPinR = 15;
accessory[3].outputPinG = 14;
accessory[3].output = 0;
for(int i=0; i<maxaccessories; i++)
{
if (accessory[i].outputPinR)
{
pinMode( accessory[i].outputPinR, OUTPUT );
pinMode( accessory[i].outputPinG, OUTPUT );
// Set initial state (only for mode 0, continuous)
if (!accessory[i].mode && accessory[i].output)
{
digitalWrite(accessory[i].outputPinR, HIGH);
digitalWrite(accessory[i].outputPinG, LOW);
}
else
{
digitalWrite (accessory[i].outputPinR, LOW);
digitalWrite (accessory[i].outputPinG, HIGH);
}
}
}
#if defined(DCCACKPIN)
//Setup ACK Pin
pinMode(DccAckPin,OUTPUT);
digitalWrite(DccAckPin, 0);
#endif
// Setup which External Interrupt, the Pin it's associated with that we're using, disable pullup.
Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 100, FLAGS_DCC_ACCESSORY_DECODER , 0 );
pinMode(ProgLed, OUTPUT);
pinMode(ProgButton, INPUT);
Serial.println("Decoder setup Ready");
}
void loop(){
boolean pressed = debounce();
if (pressed == true) {
Serial.println("Programming mode ");
ProgState = 1;
digitalWrite(ProgLed, HIGH);
}
Dcc.process();
if( addr >= maxaccessories ) addr = 0; // Next address to test
if (accessory[addr].output == 1) //rood
{
if (accessory[addr].mode == 0) accessory[addr].highlow=1; // continuous
}
if (accessory[addr].output == 0) //groen
{
if (accessory[addr].mode == 0) accessory[addr].highlow=0; // continuous
}
if (accessory[addr].highlow == 1)
{
digitalWrite (accessory[addr].outputPinG, HIGH);
digitalWrite (accessory[addr].outputPinR, LOW);
}
else
{
digitalWrite( accessory[addr].outputPinG, LOW);
digitalWrite( accessory[addr].outputPinR, HIGH);
}
addr++;
}
<>
Valentijn
Augustus 2015