CT Occupied Sensor with Arduino and JMRI part two

In my previous blog i set up an arduino to read a current transformed with no other additional electronics which would update PanlePro via CMRI. For a single sensor this worked all ok, but as soon as I put more than one CT sensor on the system the reads went erratic and i could not get it to work properly. So I searched the internet and found a very good web page that showed how to setup the CT sensor properly link for the site here. This is a basic voltage divider between 5v and GND pins on the arduino to give a center 2.5v to the CT. This allows the CT to be able to swing from 5V to 0V into the analog input of the Arduino. You will also need a burden resistor which I calculated to be 3.3K ohms for what I wanted to read (about 1A). This is the diagram for the setup with 3 CT sensors.

I tried running the program all on the Mega reading the three CT sensors then updating this to the Pc via CMRI but this was really slow and was not picking up the train as it passed through the zones. So, I run the reading of the sensors on a nano Arduino which then turned on an LED if the zone was occupied and this output was read by the Mega via digital inputs. The Mega would then update the Pc via CMRI for PanelPro JMRI sensors. This allows me to have a mimic panel of the layout with LEDs turning on where the track is occupied and I could also control the layout signals with this nano Arduino.

To read the CT sensors I am using the program and library EmonLib which can be found here. The sketch will take a number of reading and then check if the reading is high enough to indicate a track is occupied then turn on the LED and if low enough to not be occupied to turn off the LED. The sketch I am using on the nano is shown below.

 

#include "EmonLib.h"   

EnergyMonitor readOcc1; 
int Occ1LED = 12;                  
EnergyMonitor readOcc2;
int Occ2LED = 11; 
EnergyMonitor readOcc3;
int Occ3LED = 10;
EnergyMonitor readOcc4;

void setup()
{  
  Serial.begin(9600);
  
  readOcc1.current(0, 111.1);
  pinMode(Occ1LED, OUTPUT);
  readOcc2.current(1, 111.1);
  pinMode(Occ2LED, OUTPUT);
  readOcc3.current(2, 111.1);
  pinMode(Occ3LED, OUTPUT);
  readOcc4.current(3, 111.1);
}

void loop()
{  
  double Occ1 = readOcc1.calcIrms(300); 
  Serial.print ("Occ1 = ");
  Serial.print(Occ1); 
  if (Occ1 > 0.89){
    digitalWrite(Occ1LED, HIGH);
  }
  if (Occ1 < 0.40){ digitalWrite(Occ1LED, LOW); } double Occ2 = readOcc2.calcIrms(300); Serial.print(" Occ2 = "); Serial.print(Occ2); if (Occ2 > 0.85){
    digitalWrite(Occ2LED, HIGH);
  }
  if (Occ2 < 0.40){ digitalWrite(Occ2LED, LOW); } double Occ3 = readOcc3.calcIrms(300); Serial.print(" Occ3 = "); Serial.println(Occ3); if (Occ3 > 0.89){
    digitalWrite(Occ3LED, HIGH);
  }
  if (Occ3 < 0.49){
    digitalWrite(Occ3LED, LOW);
  }
  double Occ4 = readOcc4.calcIrms(800);
  
}

In the sketch I have set the amount of times to take a reading to 300 to give me a fairly good reading which is not a truly accurate reading but enough to not be too erratic to cause nuisance triggering of the LED’s with no train on the track. If you increase this number you will get a more accurate reading but the speed of taking a reading drops to the point the program is not usable.
The on/off fresh hold which in my sketch will be about 0.89 for ON and 0.40 for OFF has been setup individually for each CT using the serial monitor. This was due to the CT’s not being the same when reading them and the length of cable was causing a difference in the reading. All this was to read one loco with no attached carriages and no loco lights or stay alive chips. I hope to add loco lights which will make it much easier to detect a loco on the track when stationary. As soon as the train is moving the readings are very high and easy to detect.
The mega sketch shown below just reads the nano pins via the mega digital input pins and if the pin is high it will pass a bit 1 to the PC via CMRI for that occupied address and if the LED is off it will pass bit 0. This works OK but I am finding a lag in the time this is sent to JMRI. This might become a problem with a lot of CT sensors.

#include 
#include 

#define CMRI_ADDR 1
#define DE_PIN 2

Auto485 bus(DE_PIN);
CMRI cmri(CMRI_ADDR, 24, 48, bus);

int Occ1 = 3;
int Occ1Reading;
int Occ2 = 4;
int Occ2Reading;
int Occ3 = 5;
int Occ3Reading;

void setup() {
    Serial.begin(57600);
    pinMode(Occ1, INPUT);
    pinMode(Occ2, INPUT);
    pinMode(Occ3, INPUT);
}

void loop() {
  cmri.process();
  Occ1Reading = digitalRead(Occ1);
  Occ2Reading = digitalRead(Occ2);  
  Occ3Reading = digitalRead(Occ3);
  if (Occ1Reading == 1)
  {
    cmri.set_bit(0, 1);
   }
  if (Occ1Reading == 0)
   {
    cmri.set_bit(0, 0);
   }

   if (Occ2Reading == 1)
   {
    cmri.set_bit(1, 1);
   }
   if (Occ2Reading == 0)
   {
    cmri.set_bit(1, 0);
   }

   if (Occ3Reading == 1)
   {
    cmri.set_bit(2, 1);
   }
   if (Occ3Reading == 0)
   {
    cmri.set_bit(2, 0);
   }


}

The video below shows all this working. Still in the building stage of this and I would like to get JMRI input running faster. However, the nano mimic panel (LEDs) works great and I will be keeping this setup, just need to build more of the layout and start on a mimic panel

1 Comment

  1. David Costin says: Reply

    Did you get any further with this project as I would love to replicate something similar IE current detecting block occupancy sensors to update JMRI?

Leave a Reply