Looking for guidance with monitoring 2 proximity sensors

Hey all. I'm starting a project and looking for the best and easiest way to monitor 2 proximity signals (magnetic hall sensors), and will let me know when one of the signals stops sending. The signals are High during idle and go LOW during a pulse.

I need to install 3 sensors on a piece of farm machinery.... a 30 ft grain planter to be exact. The first sensor is easy and just lets me know everything is in place and ready. the other 2 sensors are placed monitoring the corners of a square shaft, which will be rotating at the nearly at the same rpm, except when turning a corner, when one shaft will slow down compared to the other. I need to make it where if the chain comes off one of the shafts and it stops rotating, it will turn on a buzzer and and LED, which i have that part figured out.

I already have most of it sketched out, but i'm unsure on how's the best to proceed to watch the 2 signals. I thought about doing a basic timed counter on each shaft, or something similar. I could use a quick example or something to get me started and i should be able to figure it out from there.

Thanks for an help


int rightSideSensor = 2;
int leftSideSensor = 3;
int centerSensor = 4;

int rightRedLed = 5;
int rightGreenLed = 6;
int rightBlueLed = 7;
int leftRedLed = 8;
int leftGreenLed = 9;
int leftBlueLed = 10;

int buzzer = 11;

static bool rightSideRunning = true;
static bool leftSideRunning = true;
static bool centerReady = true;


void setup() {

  Serial.begin(115200);

  pinMode (rightSideSensor, INPUT);
  pinMode (leftSideSensor, INPUT);
  pinMode (centerSensor, INPUT);

  pinMode (rightRedLed, OUTPUT);
  pinMode (rightGreenLed, OUTPUT);
  pinMode (rightBlueLed, OUTPUT);

  pinMode (leftRedLed, OUTPUT);
  pinMode (leftGreenLed, OUTPUT);
  pinMode (leftBlueLed, OUTPUT);
  pinMode (buzzer, OUTPUT);
}

void loop() {

  digitalWrite(rightBlueLed, LOW);
  digitalWrite(leftBlueLed, LOW);
  digitalWrite(rightRedLed, LOW);
  digitalWrite(leftRedLed, LOW);

  if (centerReady == false) {
    centerNotReady()
  }
  else {
    rightGreenLed, HIGH;
    leftGreenLed, HIGH;
  }

    // code for monitoring 2 proximity sensors ?


}



void (centerNotReady) {

  digitalWrite(rightBlueLed, HIGH);
  digitalWrite(leftBlueLed, HIGH);
}



void (rightNotWorking) {

  for (int r = 0, r < 5, r++) {

    digitalWrite (buzzer, LOW);
    delay(100);
    digitalWrite (buzzer, HIGH);
    delay(100);
  }

  digitalWrite(rightRedLed, HIGH);


}

void (leftNotWorking) {

  for (int l = 0, l < 5, l++) {

    digitalWrite (buzzer, LOW);
    delay(100);
    digitalWrite (buzzer, HIGH);
    delay(100);
  }

  digitalWrite(leftRedLed, HIGH);

}

What is "the best"? Good is not usable? I my opinion any working way is good and would be used.
What is working and what is not working? What differs?
Before analyzing the code I would like to see schematics.

Best wasn't the best wording. It doesn't have to be fancy or complicated, but simple and working. I don't have a schematic drawn up yet as it's all in my head at the moment, but can tomorrow. But it's simple. I have 3 crankshaft sensors which are magnetic hall sensors. They have a 5v high signal at all times except when the hall effect is activated and then it pulls it too LOW.

The center sensor is connected to a hydraulic cylinder and detects when the cylinder is closed, and the wheels are in contact with the ground. The shaft the sensors, one for each side, are being installed on are 3/4" square rod/tubing and i planned on it detecting each corner as it rolls around... so 4 pulses per revolution.

i thought about doing a basic counter and if so much time passes without a signal it throws a flag, which seemed the easiest.

Everything else is lights and buzzers, which i don't need help with.

Here's a basic version to illustrate the concept:

Thanks for the link. While i haven't had a chance to try it yet. do you think it would be possible to duplicate most of that code so it's able to monitor 2 signals the same way instead of 1.

Sure, you just have to make sure each timer has its own unique variables.

Hey. i had to take a break from working on this project, but i'm needing to starting working on it so i can get it going soon. But i had a question about creating unique variables for the other timer. I don't quite understand the code to start with. You listed an analog input to be used with the timer. but i thought that if i used a particular timer. Say Timer1 and Timer2, i would need to use the pins associated with the timers?

uint32_t timer1AccValue;
uint32_t const timer1Preset = 1500; // 1.5 seconds
uint32_t timer1PreviousMillis;
uint32_t timer1CurrentMillis;

// uint32_t timer12AccValue;
// uint32_t const timer2Preset = 1500; // 1.5 seconds
// uint32_t timer2PreviousMillis;
// uint32_t timer2CurrentMillis;

bool isTimer1Active;
//  bool isTimer2Active;

bool isFirstPass;      //  not called anywhere in the following code????

const byte enablePin = A3; // A0-A5 can be used as digital inputs
const byte externalLED = A0;





void setup() {
  Serial.begin(115200);
  
  pinMode(enablePin, INPUT_PULLUP); 
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(externalLED, OUTPUT);

 
  Serial.print("\n\nTimer  Timer\n");
  Serial.println(" Acc   Done");
 
  displayFunction(timer1CurrentMillis - timer1PreviousMillis, isTimer1Active);
  delay(1000);
}

void loop() {

  bool newTriggerPulse;
  static bool buttonWasPressedLastTime;

  bool isButtonPressed = (bool) !digitalRead(enablePin);     
  timer1CurrentMillis = millis();



 if (isButtonPressed && !buttonWasPressedLastTime){ 
      newTriggerPulse = true;
  }
  else {
    newTriggerPulse = false;
  }

  buttonWasPressedLastTime = isButtonPressed;


 
  if (newTriggerPulse)                     
  {
    timer1PreviousMillis = timer1CurrentMillis;
    isTimer1Active = true;
  }
  else {                                                              
    if (timer1CurrentMillis - timer1PreviousMillis >= timer1Preset) { 
      isTimer1Active = false;
    }
  }



  digitalWrite(LED_BUILTIN, isTimer1Active);                                
  digitalWrite(externalLED, isTimer1Active);

  displayFunction(timer1CurrentMillis - timer1PreviousMillis, isTimer1Active);
}                                                                         



void displayFunction(unsigned long timer1, bool timedOut) {

                                                                          
  Serial.print(timer1);
  Serial.print("\t");
  Serial.print(timedOut);
  Serial.println();
}

I used an analog input merely to illustrate that A0-A5 can accept digital inputs just like D2-D13.  Think of them as digital inputs with the enhanced ability to also take analog signals.  There is no particular pin associated with the timers.  The programmer is free to use any digital-input-capable pin desired - or even an internally generated signal if it serves your purpose.

ok. i mostly understand that. So i can could use the uint32_t with both signals? Just with different variable names? I guess what i'm confused about is, do they both use the same timer? Or do i need to do something different to attach one signal to timer1 and the other signal on timer2?

Thanks

Yes.  uint32_t is a variable type.

No, the act of declaring separate variables and arranging them in a certain way is what creates the two timers.   It's not a hardware timer like the processor's Timers 0, 1, and 2.

Show an example of what you mean.

Your first 2 replies explained most of my confusion. I've used hardware timers a few times in the past, which confused me on this because they are usually pin specific. And is the first time using the variable uint32_t

one final question for today. At the bottom of the example, shown below. This is the only section that calls timer1, both in the function, and the variable to be serial printed. how is timer1 calculated as a variable? It doesn't seem to be called anywhere else in the previous code, so i thought it was timer1.... as in the hardware timer, which started the confusion. The displayFunction in the setup is just substracting 2 millis values. is it that value that is calculated as timer1 in what i shown?

void displayFunction(unsigned long timer1, bool timedOut) {

                                                                          
  Serial.print(timer1);
  Serial.print("\t");

Don't know if this answers your question but, timer1 in the displayFunction is a local variable.

The value of timer1CurrentMillis - timer1PreviousMillis is calculated and the result is passed to the function which assigns the value so passed to its own variable timer1.  timer1 exists nowhere else in the code.  You could make eleven timers, or any unsigned 32-bit integers really, and pass each one's value to the display function and they would each go into timer1.  Of, course, if this were the case you'd want to change the name of the variable to something more generic like, timerValue.

ok. that's what i thought, but i've never seen that before and was unsure how it was done.

thanks for your help.

Sounds like a simple speed switch, what is the minimum shaft rotation speed (RPM)? If the chain did come off, would the shaft stop or keep rolling as the machine moved over the ground?

Sorry for the late reply. i've been busy and haven't been on here. I'm unsure about the minimum rpm, but normally it won't be very slow... except at startup. The wheels are connected to the shaft via chain and sprockets. so when it's rolling, the shaft is spinning, but when the chain comes off the shaft stops.

I think i pretty much have the code worked out, but i have to make a couple more adjustments. but i need an actual spinning shaft so i can do some tests so i can finish it up.

Hey. So i've been able to get the code about 95% done, but i ran into a problem and having a hard time trying to resolve it.

Once it's running, it works perfectly until one of sides encounters a problem, and then runs an alarm that doesn't go away until it's reset. But i need to be able to stop both sides without triggering the alarm, because this will be stopped and starting all the time. and i can't get it to stop before an alarm goes off.

const byte rightSideSensor = 2;
const byte leftSideSensor = 3;
const byte centerSensor = 4;

int rightRedLed = 5;
int rightGreenLed = 6;
int rightBlueLed = 7;
int leftRedLed = 9;
int leftGreenLed = 10;
int leftBlueLed = 8;

int buzzer = 11;

uint32_t const timer1Preset = 1000; // 1.5 seconds
uint32_t timer1PreviousMillis;
uint32_t timer1CurrentMillis;
bool isTimer1Active;

uint32_t const timer2Preset = 1000; // 1.5 seconds
uint32_t timer2PreviousMillis;
uint32_t timer2CurrentMillis;
bool isTimer2Active;

auto rightCounter = 0;
auto leftCounter = 0;

bool rightBuzzed = true;
bool leftBuzzed = true;

static bool isRightTimerStopped = false;
static bool isLeftTimerStopped = false;




void setup() {

  Serial.begin(115200);

  pinMode (rightSideSensor, INPUT_PULLUP);
  pinMode (leftSideSensor, INPUT_PULLUP);
  pinMode (centerSensor, INPUT_PULLUP);

  pinMode (rightRedLed, OUTPUT);
  pinMode (rightGreenLed, OUTPUT);
  pinMode (rightBlueLed, OUTPUT);

  pinMode (leftRedLed, OUTPUT);
  pinMode (leftGreenLed, OUTPUT);
  pinMode (leftBlueLed, OUTPUT);

  pinMode (buzzer, OUTPUT);
  digitalWrite(buzzer, HIGH);


  digitalWrite(rightRedLed, HIGH);
  delay(250);
  digitalWrite(rightRedLed, LOW);

  digitalWrite(rightGreenLed, HIGH);
  delay(250);
  digitalWrite(rightGreenLed, LOW);

  digitalWrite(rightBlueLed, HIGH);
  delay(250);
  digitalWrite(rightBlueLed, LOW);

  digitalWrite(leftRedLed, HIGH);
  delay(250);
  digitalWrite(leftRedLed, LOW);

  digitalWrite(leftGreenLed, HIGH);
  delay(250);
  digitalWrite(leftGreenLed, LOW);

  digitalWrite(leftBlueLed, HIGH);
  delay(250);
  digitalWrite(leftBlueLed, LOW);



  digitalWrite(buzzer, LOW);
  delay(100);
  digitalWrite(buzzer, HIGH);


Serial.println("************************** STARTING*********************");
}

void loop() {

  digitalWrite(rightBlueLed, LOW);
  digitalWrite(leftBlueLed, LOW);
//  digitalWrite(rightRedLed, LOW);
//  digitalWrite(leftRedLed, LOW);


  bool rightNewTriggerPulse;
  bool leftNewTriggerPulse;

  static bool rightSensorLastTime;
  static bool leftSensorLastTime;


  bool rightSensorActivated = (bool) !digitalRead(rightSideSensor);
  timer1CurrentMillis = millis();

  bool leftSensorActivated = (bool) !digitalRead(leftSideSensor);
  timer2CurrentMillis = millis();

  bool centerSensorActivated = (bool) !digitalRead(centerSensor);


  if (rightSensorActivated && !rightSensorLastTime) {
    rightNewTriggerPulse = true;
   }
  else {
    rightNewTriggerPulse = false;
     }

  rightSensorLastTime = rightSensorActivated;



  if (leftSensorActivated && !leftSensorLastTime) {
    leftNewTriggerPulse = true;
    
      }
  else {
    leftNewTriggerPulse = false;
   
  }

  leftSensorLastTime = leftSensorActivated;




  if (rightNewTriggerPulse)
  {
    timer1PreviousMillis = timer1CurrentMillis;
    isTimer1Active = true;
    ++rightCounter;
  }
  else {
    if (timer1CurrentMillis - timer1PreviousMillis >= timer1Preset) {
      isTimer1Active = false;
      isRightTimerStopped = true;
      }
  }



  if (leftNewTriggerPulse)
  {
    timer2PreviousMillis = timer2CurrentMillis;
    isTimer2Active = true;
    ++leftCounter;
  }
  else {
    if (timer2CurrentMillis - timer2PreviousMillis >= timer2Preset) {
      isTimer2Active = false;
      isLeftTimerStopped == true;
       }
  }



  if (centerSensorActivated == true) {
    
    digitalWrite(rightGreenLed, LOW);
    digitalWrite(leftGreenLed, LOW);

//    digitalWrite(rightRedLed, LOW);
//    digitalWrite(leftRedLed, LOW);

    digitalWrite(rightBlueLed, HIGH);
    digitalWrite(leftBlueLed, HIGH);
  }
  else {
    
    digitalWrite(rightGreenLed, HIGH);
    digitalWrite(leftGreenLed, HIGH);
  }

if (isRightTimerStopped == true && isLeftTimerStopped == true){         //attempt to stop without alarms.

  digitalWrite(rightGreenLed, HIGH);
  digitalWrite(leftGreenLed, HIGH);
}


else {

if  (isTimer1Active == false && isTimer2Active == false){
  rightCounter = 0;
  leftCounter = 0;
}

if (rightCounter >=2 && leftCounter >=2){ 

  if (isTimer1Active == true && isTimer2Active == false) {
    leftNotWorking();
  }

  if (isTimer1Active == false && isTimer2Active == true) {
    rightNotWorking();
  }
}


}

}



void rightNotWorking() {

  digitalWrite(leftGreenLed, LOW);
  digitalWrite(rightGreenLed, LOW);
  digitalWrite(rightBlueLed, LOW);
  digitalWrite(rightRedLed, HIGH);

buzz();

  return;
}

void leftNotWorking() {

  digitalWrite(rightGreenLed, LOW);
  digitalWrite(leftGreenLed, LOW);
  digitalWrite(leftBlueLed, LOW);
  digitalWrite(leftRedLed, HIGH);

buzz();

  return;
}


void buzz(){

  if (rightBuzzed == true){
    
  digitalWrite(buzzer, LOW);
  delay(1000);
  digitalWrite(buzzer, HIGH); 
  rightBuzzed = false; 
  }

  if (leftBuzzed == true){
    
  digitalWrite(buzzer, LOW);
  delay(1000);
  digitalWrite(buzzer, HIGH); 
  leftBuzzed = false; 
  
}
}

What problem?

Maybe it would be simpler to monitor that the chains are on the sprockets and alarm off of that.

on my way home i thought of what i need to do. Instead of having an alarm at the moment the shaft stops, which is what i'm doing now, and having problems with. I need to have a little wiggle room and say after 4 missed pulses in a row then it's time for an alarm. that way there's a little room for error but know when there's an actual problem.

my first instinct was to monitor the chain or the sprocket itself. But with it's design being out in the open, the sensor would eventually get knocked off by the felled chain, or a tree branch, or a curious cow. so we're installing the sensors where they're protected