Go Down

Topic: Arduino and Railway Modelling (Read 6815 times) previous topic - next topic

johnbet

I am trying to set up control of light functions (individual led's) via DCC Digital Command Control) and an Arduino.

Basically i am trying to create a variety of functions controlled by an on (high) - off (low) situation at a given pin.

The functions I am seeking are

A - Simple On/Off
B - Fade on to a set brightness and stay on until switched off and then fade off.
C - Flicker on (neon effect) to a set brightness and stay on until switched off and then switch off.
D - Flash.
E - Double Flash.
F - Strobe.
G - Random Flicker.

I appreciate there are sketches around showing how to pulse a led but i am struggling to find suitable ones for these situations.

Can anyone assist or point me in the direction of answers please.

Many thanks in anticipation.


GrooveFlotilla

You've described seven conditions, but a single digital pin can only exist in one of two states.
Are you expecting the seven effects to take place sequentially?
Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.

johnbet

Hi

No i would use separate pins or indeed separate arduino's

Thank You

GrooveFlotilla

All those effects could be produced by modification of the blink without delay example code that comes with the Arduino IDE.
You could cover the whole lot in a single sketch.
Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.

johnbet

I appreciate A, D, E and F are easily achieved by varying the blink sketch, but would very much welcome some pointers on the others.

I am not very experienced in coding arduino's.

Are you suggesting one sketch with a sort of selection menu?

Many thanks.

GrooveFlotilla

The technique set out in blink without delay simply shows how to perform simple actions at different times.
It doesn't matter if the action turns a thing on or writes a different PWM value, so blinks and fades are all easy to perform.
So, an array (or arrays) could store simple mnemonics for the actions and durations.

I wasn't recommending anything as complex as a menu - you could store options/scripts in EEPROM.
Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.

johnbet

Hi Thank you for your continued interest and support.

I have achieved all the variations of controlling the led with the blink with delay sketch apart from fade on and fade off and flicker on and flicker off.

I have read that the use of delay should be avoided so i will try and achieve the same using the blink without delay options.

I am not familiar with how to create arrays so I am still somehwta stumped .

Please bear in mind I am a relative novice so this is all fairly new to me.

Thank you.

PaulRB

Start by getting an Arduino circuit working with dcc and simple on/off led switching. Post that sketch here and we can suggest code to change the simple on/off into the patterns you want.

johnbet

Ok will do - may take me a while to get back to you but will do as soon as i can.

PaulRB

Ask of you get stuck with that code also. Google seemed to find some suitable DCC Arduino code when I did a quick search.

The patterns you want are all possible, so don't worry about that. I assume you will want to be able to configure one of those effects to any pin, in a fixed way. That should be easy enough. However, the fading, and perhaps the flickering may need to be done using an Arduino PWM pin (often marked with a ~).

johnbet

#10
Mar 05, 2017, 11:55 am Last Edit: Mar 05, 2017, 12:05 pm by johnbet
Hi again

I have attached the sketch that I am using.

You will see that the DCC signal is input via Pin 2 via an optocoupler. I have done that and achieved success.

However each Pin is only set to be on or off (high or low) and it's getting the right code to get each pin to achieve the desired effect as in first post.

Each 'Arduino' is given an 'address' so it is quite possible to have several or many as desired each with several outputs.

The trigger at the DCC controller for the layout is effectively a push button via a mouse clicking on an icon.

I am not sure why the guy doesn't use pins 9, 10, 11 and 12 but I assume I could use these.

I understand what you say about PWM but if it is necessary to use PWM then that is not a problem as I could just use more 'Arduino's" and 'Addresses".

Eventually I may well use ATTiny 85 Development board due to their size. They have less outputs but that would not be an issue.

Each Item be it a switching point, light signal, carriage light or building light could have its own 'Arduino/ATTiny 85'

I am confused with lines 89-101 of the code as ideally I would like to control each pin individually whereas he seems to four lines of three Func's only but this may be something to do with the DCC signal.

The guy has several other sketches on his site (all ok for public domain) and there may be a more appropriate one than this one.

Please let me know if you need any thing further

Many thanks for your help.

PS

I have also attached a sketch he has for the ATTiny 85

Here is the link to the website for the sketches

https://rudysmodelrailway.wordpress.com

the Sketches are in the Software page - takes a bit of delving to find them.

johnbet

I noticed I have included the ATTiny sketch twice  - here is the Arduino sketch

PaulRB

You can edit your previous posts, including adding/removing attachments. You should not do this when it would make the thread confusing for others reading it, but in cases like this it is fine.

Also, unless the code is very long, it is better to paste it into the post using code tags, rather than attaching .ino files. Many people read the forum on phones & tablets which cannot open a .ino attachment.

ATTiny sketch:
Code: [Select]
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DCC Function Decoder
// Author: Ruud Boer - September 2015
// This sketch turns an ATtiny USB board into a DCC function decoder for F0 - F12
// Output pins used: 3-19 (14-19 = A0-A5)
// The DCC signal is optically separated and fed to pin 2 (=Interrupt 0).
// Optocoupler schematics: www.rudysmodelrailway.wordpress.com/software
// Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: GOTO lines 15 - 28 to configure some data!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int decoderAddress = 1830; // This is the decoder address, change into the number you want.
#define F0_pin 1 // Define the output pin for every Function number in use
#define F1_pin 0 // Available pin numbers: 0,1,3,4,5
#define F2_pin 0
#define F3_pin 0
#define F4_pin 0
#define F5_pin 0
#define F6_pin 0
#define F7_pin 0
#define F8_pin 0
#define F9_pin 0
#define F10_pin 0
#define F11_pin 0
#define F12_pin 0
/* F13-F28 commented out
#define F13_pin 0
#define F14_pin 0
#define F15_pin 0
#define F16_pin 0
#define F17_pin 0
#define F18_pin 0
#define F19_pin 0
#define F20_pin 0
#define F21_pin 0
#define F22_pin 0
#define F23_pin 0
#define F24_pin 0
*/

#include <DCC_Decoder.h>                      // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define kDCC_INTERRUPT 0

byte Func[4]; //0=L4321, 1=8765, 2=CBA9, 3=F20-F13, 4=F28-F21
byte instrByte1;
int Address;

boolean RawPacket_Handler(byte pktByteCount, byte* dccPacket) {
  Address=0;
  if (!bitRead(dccPacket[0],7)) { //bit7=0 -> Loc Decoder Short Address
    Address = dccPacket[0];
    instrByte1 = dccPacket[1];
  }
  else if (bitRead(dccPacket[0],6)) { //bit7=1 AND bit6=1 -> Loc Decoder Long Address
    Address = 256 * (dccPacket[0] & B00000111) + dccPacket[1];
    instrByte1 = dccPacket[2];
  }

  if (Address==decoderAddress) {
    byte instructionType = instrByte1>>5;
    switch (instructionType) {
      case 4: // Loc Function L-4-3-2-1
        Func[0]=instrByte1&B00011111;
      break;
      case 5: // Loc Function 8-7-6-5
        if (bitRead(instrByte1,4)) {
          Func[1]=instrByte1&B00001111;
        }
        else { // Loc Function 12-11-10-9
          Func[2]=instrByte1&B00001111;
        }
      break;
      /*  F13-F28 commented out
      case 6: // Future Expansions
        switch (instrByte1&B00011111) {
          case B00011110: // Loc Function F13-F20
            Func[3]=dccPacket[pktByteCount-1];
          break;
          case B00011111: // Loc Function F21-F28
            Func[4]=dccPacket[pktByteCount-1];
          break;
        }
      break;
      */
    }
    if (Func[0]&B00010000) digitalWrite(F0_pin,HIGH); else digitalWrite(F0_pin,LOW);
    if (Func[0]&B00000001) digitalWrite(F1_pin,HIGH); else digitalWrite(F1_pin,LOW);
    if (Func[0]&B00000010) digitalWrite(F2_pin,HIGH); else digitalWrite(F2_pin,LOW);
    if (Func[0]&B00000100) digitalWrite(F3_pin,HIGH); else digitalWrite(F3_pin,LOW);
    if (Func[0]&B00001000) digitalWrite(F4_pin,HIGH); else digitalWrite(F4_pin,LOW);
    if (Func[1]&B00000001) digitalWrite(F5_pin,HIGH); else digitalWrite(F5_pin,LOW);
    if (Func[1]&B00000010) digitalWrite(F6_pin,HIGH); else digitalWrite(F6_pin,LOW);
    if (Func[1]&B00000100) digitalWrite(F7_pin,HIGH); else digitalWrite(F7_pin,LOW);
    if (Func[1]&B00001000) digitalWrite(F8_pin,HIGH); else digitalWrite(F8_pin,LOW);
    if (Func[2]&B00000001) digitalWrite(F9_pin,HIGH); else digitalWrite(F9_pin,LOW);
    if (Func[2]&B00000010) digitalWrite(F10_pin,HIGH); else digitalWrite(F10_pin,LOW);
    if (Func[2]&B00000100) digitalWrite(F11_pin,HIGH); else digitalWrite(F11_pin,LOW);
    if (Func[2]&B00001000) digitalWrite(F12_pin,HIGH); else digitalWrite(F12_pin,LOW);
  }
}

void setup() {
  DCC.SetRawPacketHandler(RawPacket_Handler); // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  DCC.SetupMonitor( kDCC_INTERRUPT );         // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  DCC.loop();   // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}

PaulRB


Arduino sketch:
Code: [Select]
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DCC Function Decoder
// Author: Ruud Boer - September 2015
// This sketch turns an Arduino into a DCC function decoder for F0 - F12
// Output pins used: 3-19 (14-19 = A0-A5)
// The DCC signal is optically separated and fed to pin 2 (=Interrupt 0).
// Optocoupler schematics: www.rudysmodelrailway.wordpress.com/software
// Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: GOTO lines 15 - 28 to configure some data!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int decoderAddress = 1830; // This is the decoder address, change into the number you want.
#define F0_pin 13 // Define the output pin for every Function number in use
#define F1_pin 14 // Available pin numbers: 3 - 19
#define F2_pin 15
#define F3_pin 16
#define F4_pin 17
#define F5_pin 18
#define F6_pin 19
#define F7_pin 3
#define F8_pin 4
#define F9_pin 5
#define F10_pin 6
#define F11_pin 7
#define F12_pin 8
/* F13-F28 commented out
#define F13_pin 0
#define F14_pin 0
#define F15_pin 0
#define F16_pin 0
#define F17_pin 0
#define F18_pin 0
#define F19_pin 0
#define F20_pin 0
#define F21_pin 0
#define F22_pin 0
#define F23_pin 0
#define F24_pin 0
*/

#include <DCC_Decoder.h>                      // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define kDCC_INTERRUPT 0

byte Func[4]; // 0=L F4-F1, 1=F9-F5, 2=F12-F9, 3=F20-F13, 4=F28-F21
byte instrByte1;
int Address;

boolean RawPacket_Handler(byte pktByteCount, byte* dccPacket) {
  Address=0;
  if (!bitRead(dccPacket[0],7)) { //bit7=0 -> Loc Decoder Short Address
    Address = dccPacket[0];
    instrByte1 = dccPacket[1];
  }
  else if (bitRead(dccPacket[0],6)) { //bit7=1 AND bit6=1 -> Loc Decoder Long Address
    Address = 256 * (dccPacket[0] & B00000111) + dccPacket[1];
    instrByte1 = dccPacket[2];
  }

  if (Address==decoderAddress) {
    byte instructionType = instrByte1>>5;
    switch (instructionType) {
      case 4: // Loc Function L-4-3-2-1
        Func[0]=instrByte1&B00011111;
      break;
      case 5: // Loc Function 8-7-6-5
        if (bitRead(instrByte1,4)) {
          Func[1]=instrByte1&B00001111;
        }
        else { // Loc Function 12-11-10-9
          Func[2]=instrByte1&B00001111;
        }
      break;
      /* F13-F28 commented out
      case 6: // Future Expansions
        switch (instrByte1&B00011111) {
          case B00011110: // Loc Function F13-F20
            Func[3]=dccPacket[pktByteCount-1];
          break;
          case B00011111: // Loc Function F21-F28
            Func[4]=dccPacket[pktByteCount-1];
          break;
        }
      break;
      */
    }
    if (Func[0]&B00010000) digitalWrite(F0_pin,HIGH); else digitalWrite(F0_pin,LOW);
    if (Func[0]&B00000001) digitalWrite(F1_pin,HIGH); else digitalWrite(F1_pin,LOW);
    if (Func[0]&B00000010) digitalWrite(F2_pin,HIGH); else digitalWrite(F2_pin,LOW);
    if (Func[0]&B00000100) digitalWrite(F3_pin,HIGH); else digitalWrite(F3_pin,LOW);
    if (Func[0]&B00001000) digitalWrite(F4_pin,HIGH); else digitalWrite(F4_pin,LOW);
    if (Func[1]&B00000001) digitalWrite(F5_pin,HIGH); else digitalWrite(F5_pin,LOW);
    if (Func[1]&B00000010) digitalWrite(F6_pin,HIGH); else digitalWrite(F6_pin,LOW);
    if (Func[1]&B00000100) digitalWrite(F7_pin,HIGH); else digitalWrite(F7_pin,LOW);
    if (Func[1]&B00001000) digitalWrite(F8_pin,HIGH); else digitalWrite(F8_pin,LOW);
    if (Func[2]&B00000001) digitalWrite(F9_pin,HIGH); else digitalWrite(F9_pin,LOW);
    if (Func[2]&B00000010) digitalWrite(F10_pin,HIGH); else digitalWrite(F10_pin,LOW);
    if (Func[2]&B00000100) digitalWrite(F11_pin,HIGH); else digitalWrite(F11_pin,LOW);
    if (Func[2]&B00001000) digitalWrite(F12_pin,HIGH); else digitalWrite(F12_pin,LOW);

    /*//Print DCC packet bytes for testing purposes
    for (byte n=0; n<5; n++) {
      Serial.print(Func[n],BIN);
      Serial.print(" ");
    }
    Serial.println(" ");
    */
  }
}

void setup() {
  Serial.begin(38400);
  DCC.SetRawPacketHandler(RawPacket_Handler); // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  DCC.SetupMonitor( kDCC_INTERRUPT );         // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  for (byte n=3; n<20; n++) pinMode(n,OUTPUT);
}

void loop() {
  DCC.loop();   // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}

PaulRB

I have modified the Arduino sketch to fade up and down DCC F7 = Arduino pin 3. I can't test it for you, so if you get an error messages, post them in code tags.

Code: [Select]
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DCC Function Decoder
// Author: Ruud Boer - September 2015
// This sketch turns an Arduino into a DCC function decoder for F0 - F12
// Output pins used: 3-19 (14-19 = A0-A5)
// The DCC signal is optically separated and fed to pin 2 (=Interrupt 0).
// Optocoupler schematics: www.rudysmodelrailway.wordpress.com/software
// Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: GOTO lines 15 - 28 to configure some data!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int decoderAddress = 1830; // This is the decoder address, change into the number you want.
#define F0_pin 13 // Define the output pin for every Function number in use
#define F1_pin 14 // Available pin numbers: 3 - 19
#define F2_pin 15
#define F3_pin 16
#define F4_pin 17
#define F5_pin 18
#define F6_pin 19
#define F7_pin 3
#define F8_pin 4
#define F9_pin 5
#define F10_pin 6
#define F11_pin 7
#define F12_pin 8
/* F13-F28 commented out
  #define F13_pin 0
  #define F14_pin 0
  #define F15_pin 0
  #define F16_pin 0
  #define F17_pin 0
  #define F18_pin 0
  #define F19_pin 0
  #define F20_pin 0
  #define F21_pin 0
  #define F22_pin 0
  #define F23_pin 0
  #define F24_pin 0
*/

#include <DCC_Decoder.h>                      // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define kDCC_INTERRUPT 0

byte Func[4]; // 0=L F4-F1, 1=F9-F5, 2=F12-F9, 3=F20-F13, 4=F28-F21
byte instrByte1;
int Address;

boolean RawPacket_Handler(byte pktByteCount, byte* dccPacket) {
  Address = 0;
  if (!bitRead(dccPacket[0], 7)) { //bit7=0 -> Loc Decoder Short Address
    Address = dccPacket[0];
    instrByte1 = dccPacket[1];
  }
  else if (bitRead(dccPacket[0], 6)) { //bit7=1 AND bit6=1 -> Loc Decoder Long Address
    Address = 256 * (dccPacket[0] & B00000111) + dccPacket[1];
    instrByte1 = dccPacket[2];
  }

  if (Address == decoderAddress) {
    byte instructionType = instrByte1 >> 5;
    switch (instructionType) {
      case 4: // Loc Function L-4-3-2-1
        Func[0] = instrByte1 & B00011111;
        break;
      case 5: // Loc Function 8-7-6-5
        if (bitRead(instrByte1, 4)) {
          Func[1] = instrByte1 & B00001111;
        }
        else { // Loc Function 12-11-10-9
          Func[2] = instrByte1 & B00001111;
        }
        break;
        /* F13-F28 commented out
          case 6: // Future Expansions
          switch (instrByte1&B00011111) {
            case B00011110: // Loc Function F13-F20
              Func[3]=dccPacket[pktByteCount-1];
            break;
            case B00011111: // Loc Function F21-F28
              Func[4]=dccPacket[pktByteCount-1];
            break;
          }
          break;
        */
    }
    if (Func[0]&B00010000) digitalWrite(F0_pin, HIGH); else digitalWrite(F0_pin, LOW);
    if (Func[0]&B00000001) digitalWrite(F1_pin, HIGH); else digitalWrite(F1_pin, LOW);
    if (Func[0]&B00000010) digitalWrite(F2_pin, HIGH); else digitalWrite(F2_pin, LOW);
    if (Func[0]&B00000100) digitalWrite(F3_pin, HIGH); else digitalWrite(F3_pin, LOW);
    if (Func[0]&B00001000) digitalWrite(F4_pin, HIGH); else digitalWrite(F4_pin, LOW);
    if (Func[1]&B00000001) digitalWrite(F5_pin, HIGH); else digitalWrite(F5_pin, LOW);
    if (Func[1]&B00000010) digitalWrite(F6_pin, HIGH); else digitalWrite(F6_pin, LOW);
    //if (Func[1]&B00000100) digitalWrite(F7_pin,HIGH); else digitalWrite(F7_pin,LOW);
    if (Func[1]&B00001000) digitalWrite(F8_pin, HIGH); else digitalWrite(F8_pin, LOW);
    if (Func[2]&B00000001) digitalWrite(F9_pin, HIGH); else digitalWrite(F9_pin, LOW);
    if (Func[2]&B00000010) digitalWrite(F10_pin, HIGH); else digitalWrite(F10_pin, LOW);
    if (Func[2]&B00000100) digitalWrite(F11_pin, HIGH); else digitalWrite(F11_pin, LOW);
    if (Func[2]&B00001000) digitalWrite(F12_pin, HIGH); else digitalWrite(F12_pin, LOW);

    /*//Print DCC packet bytes for testing purposes
      for (byte n=0; n<5; n++) {
      Serial.print(Func[n],BIN);
      Serial.print(" ");
      }
      Serial.println(" ");
    */
  }
}

void fadeF7() {
  static unsigned long lastFadeTimeF7 = 0;
  static int fadeLevelF7 = 0;

  if (millis() - lastFadeTimeF7 > 10) {
   
    lastFadeTimeF7 = millis();
   
    if (Func[1]&B00000100) {
      if (fadeLevelF7 < 255) analogWrite(F7_pin, ++fadeLevelF7);
      }
    else {
      if (fadeLevelF7 > 0) analogWrite(F7_pin, --fadeLevelF7);
    }
  }
}

void setup() {
  Serial.begin(38400);
  DCC.SetRawPacketHandler(RawPacket_Handler); // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  DCC.SetupMonitor( kDCC_INTERRUPT );         // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  for (byte n = 3; n < 20; n++) pinMode(n, OUTPUT);
}

void loop() {
  DCC.loop();   // Comment for 123d Test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  fadeF7();
}

Go Up