I'm trying to use a coil to sense DCC current (which in this context is similar to AC), to tell me when a certain section of my model train track is occupied. False negatives don't matter, as the program will keep checking until it gets a positive. The coil is wired in as per below:
The blue wire attached to the green wire through the coil goes from the track bus to the section of track in question. The wires from the coil board go to the +5V from the Arudino, the gnd of the arduino and pin A0 of the Arduino. The latter is defined in my code as OCC_PIN.
Whenever it reaches the section of the code where the coil is read, I get a false positive almost immediately. This is what puzzles me, as I've run a test sketch on this coil, in this exact configuration. When I ran it, I saw that it showed a reading of 0 until a loco was placed on the tracks (to complete the circuit).
In the actual program, which automatically switches power to the correct turntable track for the locomotive I'm currently running, I have a function which reads the coil. It returns true if the reading is above a certain threshold, and false otherwise:
boolean readTrack(){
/* Reads the current sensor on the wire between the
* track bus and the relay bank. This will sense if
* there is a locomotive present.
*/
int readVal = analogRead(OCC_SENSOR);
disNumLed(readVal);
if (readVal >= 6){
return true;
} else {
return false;
}
}
The disNumLed function takes a number and displays it on a LED display on the control panel. Now here's where it gets weird. After I put in the line to display the value of readVal, I saw that the value being read wasn't actually the value from the coil. Originally, the readVal variable was being compared to >= 5 in the if statement. When that was the case, the number that was displayed on the LED display changed to 5 after a few calls to the function (from the main loop). After I changed it to 6 (as per the above code), the number that it jumped to was a 6. In all of these cases, there were no locomotives on the track, so it should have been reading 0 for the whole thing, rather than jumping to the exact value required to return a false positive. Given that it's jumping to the comparison value, I suspect this is a problem with the programming somehow, rather than one with the sensor. Can someone please shed some light on what's going on?
Here's the full body of my main loop() function, if that will help. The readTrack() function is only called in the if(arriveMode) if statement.
void loop() {
// put your main code here, to run repeatedly:
//Check if the buttons have been pushed.
clockwButton.tick();
cclockButton.tick();
memButton.tick();
/* Has a loco been selected? If so, and it's not 0, then get the loco track.
* getLocoTrack returns -1 if that loco address isn't in the array of locos
* around the turntable. Need to check for this at some point.
*/
if (baseET.receiveData()){
//We've received data from the base station. A loco has been called.
if ((baseData.controllerID == -1) && (baseData.locoAddress != 0)){
//ControllerID of -1 is used to indicate it's for the staging controller.
//Handset sends out an address of 0 on startup - need to ignore it.
currLoco = baseData.locoAddress; //set the current loco address
/* Check if the locomotive should be in the turntable. -1 from the
* getLocoTrack function indicates it's one of the BVLC locos. I.e.
* it's not the PRM one. If it's equal to the value in locoOut, then
* it's the BVLC loco in staging, and doesn't need any action taken.
*
* Remember, the turntable bridge will be aligned with the exit track
* by default.
*/
currLocoTrack = getLocoTrack(currLoco);
}
}
if ((!arriveMode) && (!departMode)){
//Then we're listening to see if a departure or arrival will occur.
if ((currLocoTrack > 0) && (trackOccupancy[currLocoTrack])){
/*Then we've received an address that's around the turntable, and the
* loco is on its track. Needs to depart.
*
* Also, arriveMode needs to clear these variables at the end to prevent
* false triggering.
*/
departMode = true;
disNumLed(currLoco);
}
if ((currLocoTrack > 0) && (readExit())){
/* Then the incoming loco is valid, and it has tripped the sensor
* on the exit track.
*/
arriveMode = true;
disNumLed(currLoco);
}
}
if (departMode){
/* Then a loco is departing. By this point, we already have the following
* information:
* - Loco address
* - Track number
* - That loco is around the turntable
*/
//Turn on track power, if not already on.
if (!trackPowered) {
setTrackPower(currLocoTrack, true);
}
//Turn off and reset when exit track sensor is tripped.
if (readExit()){
//Turn off power
setTrackPower(currLocoTrack, false);
//Record occupancy status and save it
trackOccupancy[currLocoTrack] = false;
saveOccupancy();
//Turn off LED display
dispLED.clearDisplay(0);
//Exit departure mode
departMode = false;
//Pause to allow loco to clear sensor
progRest();
}
}
if (arriveMode){
/* Then a loco is arriving. By this point, we already have the following
* information:
* - Loco address
* - Track number
* - It is on the turntable bridge.
*/
//Turn on the track power, if it isn't already
if (!trackPowered){
setTrackPower(currLocoTrack, true);
}
//Listen to see if loco has just arrived on the track
if (readTrack() && trackPowered){
//Then the loco has just arrived on the track.
progRest();
/* It's now been 30 seconds since the locomotive arrived.
* Turn off track power and reset.
*/
setTrackPower(currLocoTrack, false);
//Record occupancy status and save it.
trackOccupancy[currLocoTrack] = true;
saveOccupancy();
//Turn off LED display
dispLED.clearDisplay(0);
//Clear variables to prevent false triggering
currLoco = 0;
currLocoTrack = 0;
//Reset flags
arriveMode = false;
}
}
}