What needs to be modified

Hello Everyone

I have this sketch from DIY and Digital Railroad to use DIY CT sensors to detect block occupancy on a model railroad. I have built his circuits and they function correctly but I cannot get multiple ones working at the same time on a Nano. Here is the code.

long result; //longer variable storage
int numSamples = 10;//number of readings
int clearcount;//clear test variable
int clearsample = 100;// number of clear samples needed from sensor
int threshold = 550;//ADJUST THIS FOR SENSITIVITY minimum thresold for tripping the sensor
int value;// final read result

void setup(){
  Serial.begin(9600);//starts serial monitor
  pinMode(7,OUTPUT);//indicator LED for occupancy
}

enum OCCUPANCY
{
  ST_OCCUPIED,
  ST_CLEAR,
};//Our occupancy states

OCCUPANCY Occupancy = ST_CLEAR;//default state

void loop(){
  int valA1;
  int result = 0;
  for (int i=1; i < numSamples; ++i){
    valA1 = analogRead(A0);//reads analog pin
    result +=valA1;//adds new reading to variable 'result'
 delay(10);//reading every .01 seconds
  }
 
  value=result/numSamples;//averages readings
    Serial.println(value);//displays average reading

switch (Occupancy)
{
  case ST_OCCUPIED:
  occupied();
  break;//sets up occupied state
  case ST_CLEAR:
  clear1();
  break;//sets up clear state
}
}

void clear1(){
  clearcount=0;//resets the clearcount
  digitalWrite(7,LOW);//keeps LED off for indicator
  if (value < threshold){
    Serial.println("Block is occupied");//displays text
    Occupancy = ST_OCCUPIED;//switches to occupied
  }
}

void occupied(){
  digitalWrite(7,HIGH);//turns on LED indicator
if ((value >threshold) && (clearcount<clearsample)){
  clearcount++;//adds to clear count
}
if ((value < threshold) && (clearcount<clearsample)){
  clearcount=0;//resets the clearcount if a false reading was taken
}
if ((value>threshold) && (clearcount >(clearsample-1))){
  Serial.println("Block is Clear");//displays text
  Occupancy = ST_CLEAR;//changes to clear
}
}

here is what I have thought would work but obviously I have missed something as it does nothing but signal the number 1 sensor

long result; //longer variable storage
int numSamples = 10;//number of readings
int clearcount;//clear test variable
int clearsample = 100;// number of clear samples needed from sensor
int threshold = 550;//ADJUST THIS FOR SENSITIVITY minimum thresold for tripping the sensor
int value;// final read result

void setup() {
  Serial.begin(9600);//starts serial monitor
  pinMode(2, OUTPUT); //indicator LED for occupancy
  pinMode(3, OUTPUT); //indicator LED for occupancy
  pinMode(4, OUTPUT); //indicator LED for occupancy
  pinMode(5, OUTPUT); //indicator LED for occupancy
  pinMode(6, OUTPUT); //indicator LED for occupancy
}

enum OCCUPANCY
{
  ST_OCCUPIED,
  ST_CLEAR,
};//Our occupancy states

OCCUPANCY Occupancy = ST_CLEAR;//default state

void loop() {
  int valA1;
  int valA2;
  int valA3;
  int valA4;
  int valA5;
  int result = 0;
  for (int i = 1; i < numSamples; ++i) {
    valA1 = analogRead(A0);//reads analog pin
    valA2 = analogRead(A1);//reads analog pin
    valA3 = analogRead(A2);//reads analog pin
    valA4 = analogRead(A3);//reads analog pin
    valA5 = analogRead(A4);//reads analog pin

    result += valA1; //adds new reading to variable 'result'
    result += valA2; //adds new reading to variable 'result'
    result += valA3; //adds new reading to variable 'result'
    result += valA4; //adds new reading to variable 'result'
    result += valA5; //adds new reading to variable 'result'

    delay(10);//reading every .01 seconds
  }

  value = result / numSamples; //averages readings
  Serial.println(value);//displays average reading



  switch (Occupancy)
  {
    case ST_OCCUPIED:
      occupied();
      break;//sets up occupied state
    case ST_CLEAR:
      clear1();
      break;//sets up clear state
  }
}

void clear1() {
  clearcount = 0; //resets the clearcount
  digitalWrite(2, LOW); //keeps LED off for indicator
  digitalWrite(3, LOW); //keeps LED off for indicator
  digitalWrite(4, LOW); //keeps LED off for indicator
  digitalWrite(5, LOW); //keeps LED off for indicator
  digitalWrite(6, LOW); //keeps LED off for indicator

  if (value < threshold) {
    Serial.println("Block is occupied");//displays text
    Occupancy = ST_OCCUPIED;//switches to occupied
  }
}

void occupied() {
  digitalWrite(2, HIGH); //turns on LED indicator
  digitalWrite(3, HIGH); //turns on LED indicator
  digitalWrite(4, HIGH); //turns on LED indicator
  digitalWrite(5, HIGH); //turns on LED indicator
  digitalWrite(6, HIGH); //turns on LED indicator

  if ((value > threshold) && (clearcount < clearsample)) {
    clearcount++;//adds to clear count
  }
  if ((value < threshold) && (clearcount < clearsample)) {
    clearcount = 0; //resets the clearcount if a false reading was taken
  }
  if ((value > threshold) && (clearcount > (clearsample - 1))) {
    Serial.println("Block is Clear");//displays text
    Occupancy = ST_CLEAR;//changes to clear
  }
}

can someone please clue me into what else needs to be modified to get it working
Thanks James

Why not? Explain what you expect to happen, and what happens instead. What does this mean: "does nothing but signal the number 1 sensor"?

Please post a wiring diagram. Hand drawn is fine, Fritzing is not.

His Ct sensor detects a locomitive entering an area on a model railroad and turns an led on, on the circuit board or on your control panel. Then once the loco leaves that area the led goes off after a few seconds . The first sketch works correctly for one sensor. My modified sketch works correctly for the first sensor connected to pin A0 and D2 for the led . None of the other leds on pins D3,4,5,6 come on when a loco is in their area. I have tested each one of the sensors with the first sketch and they operate as they should. So what is missing is in the code and I have no idea what else needs to be modified in it to get all 5 sensors working . I am using a nano to run these sensors, detection input is on pins A0 thru A4 and led output is on pins D2 thru D6.

See above.

Hello
I would start to modify the sketch to use the "moving averages calculation" for each sensor readings to save processing time.

moving averages:
float ETA=0.95; // Set ETA at the beginning, adjust if necessary, can also be at 0.90 or 0.99=> try it out!
meanValue = ETA*(measuredValue) + (1-ETA)*meanValue;

Hello Paul
Thank you for your suggestion I googled moving averages calculation.
I will read more about it hopefully I can get to the point were I fully understand what you have suggested and be able to write code that will work efficiently in the future right now all I know how to do is copy/ paste/ and modify till I get things working
Thanks James

Hello
On the other hand to get a multiple block monitoring function I recommend to take a view into OOP.
This means to make an object per block makes the coding more easy.

Hi,
Haven't you got the diode in the circuit the wrong way around?

Can you post a link to where you got the code and info?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

CT coils are normally biased at mid-rail as the output is AC. This appears to be missing from this circuit, biasing at 5V will mean the CT output will go above 5V and cause damage.

Load (aka burden) resistors for a CT go across the CT secondary. Again I don't see this in the diagram.

Hi,
I found the YouTube

The guy has no idea about how a current transformer works.
The only way it works is because of the DCC signal being basically AC.
And as @MarkT has said 5v bias and no burden resistor, not good for the controller.

Those two series resistors are 2 x 1M Ohm.
In effect the circuit is using the current transformer as an antenna, not a current sensing device.

Tom... :smiley: :+1: :coffee: :australia:

I probably drew the diagram wrong . I assembled the circuit as he described and it works.This maybe not the way it should be done then . I guess I need to do more research before going any further. Since what you guys are telling me they could cause damage.

Why not just use a Hall sensor under the rails and stick a small magnet on the underside of the locomotive?

Here is a way to extend the sketch to handle multiple blocks. Each block needs an analog input pin and an LED indicator pin.

const byte BlockCount = 5;
const int ClearSamplesNeeded = 100;// number of clear samples needed from sensor
const int Threshold = 550; //ADJUST THIS FOR SENSITIVITY minimum thresold for tripping the sensor
const float ETA = 0.95; // Set ETA at the beginning, adjust if necessary, can also be at 0.90 or 0.99=> try it out!

struct BlockStatus
{
  byte inputPin;  // Analog Input Pin
  int averageReading;
  int clearCount;
  bool isOccupied;
  byte LEDIndicatorPin;  // Digital Output Pin
} Blocks[BlockCount] =
{
  {A0, 0, 0, false, 2},
  {A1, 0, 0, false, 3},
  {A2, 0, 0, false, 4},
  {A3, 0, 0, false, 5},
  {A4, 0, 0, false, 6},
};

void setup()
{
  Serial.begin(9600);//starts serial monitor
  for (int i = 0; i < BlockCount; i++)
    pinMode(Blocks[i].LEDIndicatorPin, OUTPUT);
}

void loop()
{
  for (int i = 0; i < BlockCount; i++)
  {
    int reading = analogRead(Blocks[i].inputPin);
    Blocks[i].averageReading = ETA * (reading) + (1 - ETA) * Blocks[i].averageReading;
    if (Blocks[i].averageReading < Threshold)
    {
      // Block reads clear.  Require multiple samples.
      if (Blocks[i].isOccupied)
      {
        Blocks[i].clearCount++;
        if (Blocks[i].clearCount > ClearSamplesNeeded)
        {
          // Finally cleared
          Blocks[i].clearCount = 0;
          Blocks[i].isOccupied = false;
          digitalWrite(Blocks[i].LEDIndicatorPin, LOW);
          Serial.print("Block ");
          Serial.print(i + 1);
          Serial.println(" is now clear.");
        }
      }
    }
    else
    {
      // Block reads OCCUPIED
      if (!Blocks[i].isOccupied)
      {
        // Newly occupied.
        Blocks[i].clearCount = 0;
        Blocks[i].isOccupied = true;
        digitalWrite(Blocks[i].LEDIndicatorPin, HIGH);
        Serial.print("Block ");
        Serial.print(i + 1);
        Serial.println(" is now occupied.");
      }
    }
  }
}
1 Like

Thank you John I will try it out and let everyone know the results
James