Logic issues with sensors and case-break structure

Hello- I am looking for suggestions on the following problem. The program is reading a set of sensors on the I2C buss for a model train layout. I provided the relevant code below. The code works fine. But, what I want to do is have a "null" (no train) detection drive an LED ON when in between two sensors, but not on the rest of the track. The sensing devices provide "0" when no detection, or 2 or 4 or 6 when detected. So, the issue is how to make the LED pin LOW when the train is between the detectors and the data is "0". I have tried numerous if-else constructs within the Case-Break structure, using flags (with various logical comparisons), etc. So far the best I have done is to get the LED to blink in the station position (devData1 = "0".) So, it may be a simple solution, but I cannot seem to generate a solution. Note that the code is non-directional to travel direction, but could be if necessary. The final program structure controls 16 sensors (but each set of 4 are just duplications of the base code with different channel IDs. Thanks in advance.

void loop() {
  // SOUTHWEST STATION and SOUTHEAST STATION detectors SOUTH main line RIR41 detector
  // Loop Functions
  SouthStation();
  /*
    NorthStation();
    NorthMain();
    NorthInner();
  */
}

/* SOUTH STATION detectors 3SW and 2SE  Occupied LED1 Block signal LED2
  Values are 0,2,6/0,4,0, case does not care about direction
  Detects both directions with SwitchCase logic, use flags to note short train */
void SouthStation() {
  devData1 = RIR41.getDetData(0x00);  //No train in the station, devData1 = 0
  switch (devData1) {
    case 0:
      digitalWrite(LED1, HIGH);
      digitalWrite(LED2, HIGH);
      break;

    case 2:
    case 4:
    case 6:
      digitalWrite(LED1, LOW);
      digitalWrite(LED2, LOW);
     break;
  }
}

Your sketch will not compile. There is no setup(). RIR41, LED1, LED2 are not defined. Because of this, the code will not upload to the Arduino, so the Arduino will do nothing.

  1. Are you saying when SouthStation, NorthStation, NorthMain, and NorthInner detectors all report 0 turn the LED on?

  2. You say "the LED" but in your code fragment I see 2 LEDs.

  3. Would you please post your entire sketch.

If I have understood the problem correctly, then it seems to me that in order to determine whether the train is in between two particular sensors, we need to know:

a) which sensor is activated just now
b) which sensor was activated last

For example, if there are 6 sensors and the train has just activated sensor 3 and the last sensor it passed was sensor 2, then it must be heading in the direction of sensor 4. Once it has passed sensor 3, then we can assume that it is now somewhere between sensors 3 and 4.

If the train has activated sensor 3 and it previously passed sensor 4, then it must be travelling in the direction of sensor 2. Once it has passed sensor 3, then we can assume it must be somewhere between sensor 3 and 2.

In each case we can then perform the required action if the train is in-between the two target sensors.

Dunno if this helps, but its just my 2p worth!

Hi The total sketch is over 500 lines of code. It compiles and runs fine. There are 2 LEDs (actually 16), but they are functioning in parallel (so it does not matter, they both respond the same). This part of the code is the decision-making loop for a specific set of sensors. Each set is the same in configuration. Thus, solving 1 solves all. The issues is how to determine the case action(s) when the sensors are detecting zero in two different situations. That is, Case 0 is anywhere outside the station, and Case 0 is also between the sensor sets. This ambiguity is what I am trying to work around.

You'll have to use variables to keep track (see what I did there) of where any trains that are involved might be, based on the history of the sensors as they rise and fall.

Edit: like @BitSeeker sez.

a7

Thanks, you have the idea (except there is no sensor 3...). The values for the Cases are read from the shield memory. I have tried to pick up direction information, but the code did not work. It latched outside the station situation. There is a complex method to extract the timing (pseudo-direction information) of each sensor within the embedded code in the shields, but it will not work if the train stops in the station (the timer code times out).

I used the numbers arbitrarily as an example to illustrate how one might need to track not just the current trigger point (sensor), but the previous one also in order to get a sense of direction as well as location between two given trigger points.

Hi Thanks. I tried to create direction sensing by setting variables, but as expected, the values are lost in the looping. The entire program (4 sets of Case-Break) plus a ton of supporting code loops in about I3mSec. I also tried just using Global variables but again, it was either always ON, or always OFF (after the first pass either sensor 4 to 2 or 2 to 4- it is direction agnostic), or by taking out an "else", the two IF statements (not presently in the code) cycled the LEDs so I would see blinking (not desirable with 16 LEDs blinking at once...).
Do you have a suggestion for retaining variable values within a loop? I did manage around the Arduino coding once in a kind-of-similar situation, but I have forgotten how I pulled this off. I think I just brute-forced it- not elegant but fixed the problem.

Hi Thanks for the reply. No, when the detectors are "empty", the shield reports 0 for any empty detector, and either 2, 4 or 6 for other detectors. The 2 LEDs are working in parallel- one is an indicator light, the other drives a large SSR with an optocoupler. But, they are driven by the same decisions in the code, hence together in the code list. As I mentioned, the code runs fine- it is over 500 lines.... kind of large to post.

Sry, it's time for you to post the (or a) complete sketch, that compiles and runs, and describe carefully (perhaps again) where and how the inputs are coming from and how those inputs, over time, are to be used to develop the outputs.

Without that, it is beyond at least me to imagine what these sensors sense, how they are hooked up to the Arduino and so forth.

Meaningful to you:

/* SOUTH STATION detectors 3SW and 2SE Occupied LED1 Block signal LED2
Values are 0,2,6/0,4,0, case does not care about direction
Detects both directions with SwitchCase logic, use flags to note short train */

Not so much to me.

As for

The total sketch is over 500 lines of code.

I am getting the feeling that you could be looking at many fewer lines with a bit of exploitation of common patterns in the "4 sets of case/breaks" or however you put it.

Do not let the length of your sketch bother you. It won't bother us, and seeing it will help us help you.

TIA

a7

Without posting ALL your code you won't get an answer. 500 lines is nothing.

What would also be useful would be a drawing of your track layout with the stations and sensors noted. A picture is worth a 1000 words. It might help us understand what 3SW and 2SE actually are.

Is there just one train?

Is there only one way to navigate between stations? i.e. are there any parts of the track where the train can take an alternative path?

Does the track loop, or is it point to point?

In this case, 1024 words. :expressionless:

a7

1 Like

Off topic.
Qusetion: What is the difference between a beginner programmer and an advanced programmer?
Answer: The beginner programmer thinks that there are 1000 bytes in 1kB and the advanced programmer thinks that there are 1024 grams in 1kg.

1 Like

There are only 10 kinds of people that get jokes like that.

Programmers and non-programmers.

a7

1 Like

Newbies are prone to vastly over complicating otherwise simple code. A noob might write:

if(digitalRead(buttonPin) == HIGH)
{
   digitalWrite(ledPin,HIGH);
}
else if(digitalRead(buttonPin) == LOW)
{
   digitalWrite(ledPin,LOW);
}

Instead of:
digitalWrite(ledPin,digitalRead(buttonPin));
Or:
bitWrite(PORTB,5,bitRead(PIND,2));

But, I suppose, that comes with time, practice and experience. :smile:

You need to know when devData1 becomes 0 but was previously 2, 4 or 6?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.