Large Scale Central

Quick and Dirty ABS on an Arduino

This was just posted on an Arduino list that I’m on. It implements simple Bi-directional ABS using an Arduino Uno. I have it running currently on an Uno clone (Funduino), and it works fine. You’d need one per block. Hoping to get it to compile on a mini or micro.

What program does one need to open the file???

You need to download and install the Arduino IDE - the file is pasted in below. You could also open it with Notepad or something similar.

dave

/*
ABS Signal circuit using the Arduino microcontroller.
This code implements a single section of bi-directional ABS signals using either the Uno or BBLeo boards.
Version 1.0 by Dennis Drury
This code is in the public domain and may be freely copied or modified.

Sig_1

0-
Blk_1 Blk_2 Blk_3

Sig_2

The Flashing Yellow section includes modified code from the Arduino.cc website that is in the public domain
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

*/

// There are six detected blocks
// Blk_1 to Blk_6
int Blk_1 = A5;
int Blk_2 = A4;
int Blk_3 = A3;
int Blk_4 = A2;
int Blk_5 = A1;
int Blk_6 = A0;

// There are six signal outputs
// Sig_1r, Sig_1y, Sig_1g, Sig_2r, Sig_2y and Sig_2g
const int Sig_1r = 6;
const int Sig_1y = 7;
const int Sig_1g = 8;
const int Sig_2r = 9;
const int Sig_2y = 10;
const int Sig_2g = 11;

// There are four internal variables that will change. These are only used for the flashing yellow aspects.
int Sig_1y_f = LOW;
int Sig_2y_f = LOW;
long previousMillis1 = 0;
long previousMillis2 = 0;

// The following variables are the flash rates for the signals. Note these values may need to change depending on the size of your final code and the clock speed of your processor.
// The numbers are slightly different because in my experience no two prototype flashing relays ever flashed at the exact same rate.
long interval1 = 800;
long interval2 = 810;

// The setup routine runs once on bootup or pressing the reset button
void setup() {
// Set up the blocks as inputs
pinMode(Blk_1, INPUT);
pinMode(Blk_2, INPUT);
pinMode(Blk_3, INPUT);
pinMode(Blk_4, INPUT);
pinMode(Blk_5, INPUT);
pinMode(Blk_6, INPUT);
pinMode(Blk_6, INPUT);

// Set up the signals as outputs
pinMode(Sig_1r, OUTPUT);
pinMode(Sig_1y, OUTPUT);
pinMode(Sig_1g, OUTPUT);
pinMode(Sig_2r, OUTPUT);
pinMode(Sig_2y, OUTPUT);
pinMode(Sig_2g, OUTPUT);
}
// This loop runs continously
void loop()
{

// Read block occupancy
Blk_1 = digitalRead(A5);
Blk_2 = digitalRead(A4);
Blk_3 = digitalRead(A3);
Blk_4 = digitalRead(A2);
Blk_5 = digitalRead(A1);
Blk_6 = digitalRead(A0);

// Set signal 1 Green
if (Blk_3 == HIGH && Blk_2 == HIGH && Blk_1 == HIGH)
{
digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1y, HIGH); digitalWrite(Sig_1g, LOW);
}

// Set signal 1 Flashing Yellow
if (Blk_3 == HIGH && Blk_2 == HIGH && Blk_1 == LOW)
{
digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1g, HIGH);
unsigned long currentMillis1 = millis();

if(currentMillis1 - previousMillis1 > interval1)
{
// save the last time you blinked the LED
previousMillis1 = currentMillis1;

// if the LED is off turn it on and vice-versa:
if (Sig_1y_f == LOW)
Sig_1y_f = HIGH;
else
Sig_1y_f = LOW;

// set the LED with the state of the variable:
digitalWrite(Sig_1y, Sig_1y_f);
}
}
// Set signal 1 Yellow
if (Blk_3 == HIGH && Blk_2 == LOW)
{
digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1y, LOW); digitalWrite(Sig_1g, HIGH);
}

// Set signal 1 Red
if (Blk_3 == LOW)
{
digitalWrite(Sig_1r, LOW); digitalWrite(Sig_1y, HIGH); digitalWrite(Sig_1g, HIGH);
}

// Set signal 2 Green
if (Blk_4 == HIGH && Blk_5 == HIGH && Blk_6 == HIGH)
{
digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2y, HIGH); digitalWrite(Sig_2g, LOW);
}

// Set signal 2 Flashing Yellow
if (Blk_4 == HIGH && Blk_5 == HIGH && Blk_6 == LOW)
{
digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2g, HIGH);
unsigned long currentMillis2 = millis();

if(currentMillis2 - previousMillis2 > interval2)
{
// save the last time you blinked the LED
previousMillis2 = currentMillis2;
// if the LED is off turn it on and vice-versa:
if (Sig_2y_f == LOW)
Sig_2y_f = HIGH;
else
Sig_2y_f = LOW;

// set the LED with the ledState of the variable:
digitalWrite(Sig_2y, Sig_2y_f);
}
}
// Set signal 2 Yellow
if (Blk_4 == HIGH && Blk_5 == LOW)
{
digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2y, LOW); digitalWrite(Sig_2g, HIGH);
}

// Set signal 2 Red
if (Blk_4 == LOW)
{
digitalWrite(Sig_2r, LOW); digitalWrite(Sig_2y, HIGH); digitalWrite(Sig_2g, HIGH);
}
}

thanks, David.

You can read that Andy? I’m impressed (http://www.largescalecentral.com/externals/tinymce/plugins/emoticons/img/smiley-smile.gif)

Daktah John said:

You can read that Andy? I’m impressed (http://www.largescalecentral.com/externals/tinymce/plugins/emoticons/img/smiley-smile.gif)

Jon, I can read it… Yes… Understand it??? NOOOOOO

I’ve got a few questions on the ABS code above. I’m not very familiar with signals but I’m trying to understand this code better. If this stuff is all too obvious then simply ignore this post. I’ve been looking at the NORAC site regarding signals - is there a page here that develops a usable signal scheme and/or recommendations for large scale?

Some additional comments would have helped me to understand the code better. As I understand things there are N different signaling protocols and N1 different ways to build signals. So some description of the signal protocol implemented and the signals used would be helpful.

From looking at the code it appears the signal devices are each three aspects/lights with separate red/yellow/green lights. At least this is how I read the code. Many of the examples I’ve seen use multiple colors in the same position, like two lights that each can be red/yellow/green. In any case the code is turning on various combinations together which tells me the three lights are separate.

In terms of where the signals are the text drawing doesn’t display properly on my screen. From what I can tell the two signals referred to above reside at the intersection point of blocks 1/2/3 and 4/5/6. At this juncture one signal faces E (right) protecting blocks 1/2/3 and the other signal faces West and protects blocks 4/5/6.

The signal algorithm looks three (3) blocks (B) out (at most) and has four states. HIGH=Occupied/ON,LOW=Empty/OFF

Block State -> Signal State

B+1=HIGH, B+2=HIGH, B+3=HIGH => RED=HIGH,YELLOW=HIGH,GREEN=LOW

B+1=HIGH, B+2=HIGH, B+3=LOW => RED=HIGH,YELLOW=BLINKING,GREEN=HIGH

B+1=HIGH, B+2=LOW => RED=HIGH,YELLOW=LOW,GREEN=HIGH

B+1=LOW => RED=LOW,YELLOW=HIGH,GREEN=HIGH

Does this analysis seem correct? Is this a popular/common signal scheme? Is there a particular name for this signal scheme? Or is this just an example?

Seems like there could be more actionable states - like all blocks are clear. Once I understand this better I may try to come up with a simpler two multicolor light signal algorithm.

Thanks,

David

I’ve recently communicated with Dennis Drury with questions about his ABS code for the Arduino. He was nice enough to send me the latest version of the code.

Are there many out there using this code for simple signals? Or some other Arduino-based code for operating signals?

David

/*

ABS Signal circuit using the Arduino microcontroller.

This code implements a single section of bi-directional ABS signals using either the Uno, Leonardo, or ProMini boards.

Version 1.2 by Dennis Drury

Version history

V1.0 Initial Release

V1.1 Added approach lighting

V1.2 Changed pin assignments to better match up with the Pro Mini board.

V1.3 Changed pin assignments to better match up with the Nano board.

This code is in the public domain and may be freely copied or modified.

Sig_1

0-|

------|-------|-------|----------|-------|-------

Blk_1 Blk_2 Blk_3 |-0 Blk_4 Blk_5 Blk_6

Sig_2

The Flashing Yellow section includes modified code from the Arduino.cc website that is in the public domain

http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

*/

// There are six detected blocks

// Blk_1 to Blk_6

int Blk_1 = A1;

int Blk_2 = A2;

int Blk_3 = A3;

int Blk_4 = A4;

int Blk_5 = A5;

int Blk_6 = A6;

// There are six signal outputs

// Sig_1r, Sig_1y, Sig_1g, Sig_2r, Sig_2y and Sig_2g

const int Sig_1r = 4;

const int Sig_1y = 5;

const int Sig_1g = 6;

const int Sig_2r = 7;

const int Sig_2y = 8;

const int Sig_2g = 9;

// There are four internal variables that will change. These are only used for the flashing yellow aspects.

int Sig_1y_f = LOW;

int Sig_2y_f = LOW;

long previousMillis1 = 0;

long previousMillis2 = 0;

// The following variables are the flash rates for the signals.

// Note these values may need to change depending on the size of your final code and the clock speed of your processor.

// The numbers are slightly different because in my experience no two prototype flashing relays ever flashed at the exact same rate.

long interval1 = 800;

long interval2 = 810;

// The setup routine runs once on bootup or pressing the reset button

void setup() {

// Set up the blocks as inputs

pinMode(Blk_1, INPUT_PULLUP);

pinMode(Blk_2, INPUT_PULLUP);

pinMode(Blk_3, INPUT_PULLUP);

pinMode(Blk_4, INPUT_PULLUP);

pinMode(Blk_5, INPUT_PULLUP);

pinMode(Blk_6, INPUT_PULLUP);

// Set up the signals as outputs

pinMode(Sig_1r, OUTPUT);

pinMode(Sig_1y, OUTPUT);

pinMode(Sig_1g, OUTPUT);

pinMode(Sig_2r, OUTPUT);

pinMode(Sig_2y, OUTPUT);

pinMode(Sig_2g, OUTPUT);

}

// This loop runs continously

void loop()

{

// Read block occupancy

Blk_1 = digitalRead(A1);

Blk_2 = digitalRead(A2);

Blk_3 = digitalRead(A3);

Blk_4 = digitalRead(A4);

Blk_5 = digitalRead(A5);

Blk_6 = digitalRead(A6);

// Set signal 1 Green

if (Blk_3 == HIGH && Blk_2 == HIGH && Blk_1 == HIGH) //If approach lighting add “&& Blk_4 == LOW” to if statement

{

digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1y, HIGH); digitalWrite(Sig_1g, LOW);

}

// Set signal 1 Flashing Yellow

if (Blk_3 == HIGH && Blk_2 == HIGH && Blk_1 == LOW) //If approach lighting add “&& Blk_4 == LOW” to if statement

{

digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1g, HIGH);

unsigned long currentMillis1 = millis();

if(currentMillis1 - previousMillis1 > interval1)

{

// save the last time you blinked the LED

previousMillis1 = currentMillis1;

// if the LED is off turn it on and vice-versa:

if (Sig_1y_f == LOW)

Sig_1y_f = HIGH;

else

Sig_1y_f = LOW;

// set the LED with the state of the variable:

digitalWrite(Sig_1y, Sig_1y_f);

}

}

// Set signal 1 Yellow

if (Blk_3 == HIGH && Blk_2 == LOW) //If approach lighting add “&& Blk_4 == LOW” to if statement

{

digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1y, LOW); digitalWrite(Sig_1g, HIGH);

}

// Set signal 1 Red

if (Blk_3 == LOW) //If approach lighting add “&& Blk_4 == LOW” to if statement

{

digitalWrite(Sig_1r, LOW); digitalWrite(Sig_1y, HIGH); digitalWrite(Sig_1g, HIGH);

}

/*

Uncomment the /* pair to enable approach lighting

// Set signal 1 to Off

if (Blk_4 == HIGH)

{

digitalWrite(Sig_1r, HIGH); digitalWrite(Sig_1y, HIGH); digitalWrite(Sig_1g, HIGH);

}

*/

// Set signal 2 Green

if (Blk_4 == HIGH && Blk_5 == HIGH && Blk_6 == HIGH) //If approach lighting add “&& Blk_3 == LOW” to if statement

{

digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2y, HIGH); digitalWrite(Sig_2g, LOW);

}

// Set signal 2 Flashing Yellow

if (Blk_4 == HIGH && Blk_5 == HIGH && Blk_6 == LOW) //If approach lighting add “&& Blk_3 == LOW” to if statement

{

digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2g, HIGH);

unsigned long currentMillis2 = millis();

if(currentMillis2 - previousMillis2 > interval2)

{

// save the last time you blinked the LED

previousMillis2 = currentMillis2;

// if the LED is off turn it on and vice-versa:

if (Sig_2y_f == LOW)

Sig_2y_f = HIGH;

else

Sig_2y_f = LOW;

// set the LED with the ledState of the variable:

digitalWrite(Sig_2y, Sig_2y_f);

}

}

// Set signal 2 Yellow

if (Blk_4 == HIGH && Blk_5 == LOW) //If approach lighting add “&& Blk_3 == LOW” to if statement

{

digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2y, LOW); digitalWrite(Sig_2g, HIGH);

}

// Set signal 2 Red

if (Blk_4 == LOW) //If approach lighting add “&& Blk_3 == LOW” to if statement

{

digitalWrite(Sig_2r, LOW); digitalWrite(Sig_2y, HIGH); digitalWrite(Sig_2g, HIGH);

}

/*

Uncomment the /* pair to enable approach lighting

// Set signal 2 to Off

if (Blk_3 == HIGH)

{

digitalWrite(Sig_2r, HIGH); digitalWrite(Sig_2y, HIGH); digitalWrite(Sig_2g, HIGH);

}

*/

}