Missing pulses with Proximity Sensor

Hi,

I'm using a Mega R3 coupled to an inductive proximity sensor (LJ18A3-8-/BX) to try and measure the rotations of a bale wrapping table. It works fine at slow revs (12 - 20rpm), but at full speed misses pulses / counts on the Arduino.

From the central shaft of the table to the point where the sensor and magnet are mounted (table radius) is about 1 meter. The magnet which passes in front of the sensor is roughly 30mm in diameter, and the table rotates at around 60 rpm. As such the sensor is only 'ON' for milli-seconds, but I know it is working at full speed as I can just see the red led flash on each rotation.

The sensor is 6-36 vin, so I'm powering it through a 12v supply and feeding the signal through a voltage divider, before going to the Mega (hand-drawn circuit diagram attached - apologies for quality).

My code is also very basic......

const int pulseRotate = 45;

// Define Variables
int pRotate = 0;
int pRotateLast = 0;
int intRotateCnt = 0;

void setup() {

pinMode(pulseRotate, INPUT);
Serial.begin(9600);

}

void loop() {

  // Read input values
  pRotate = digitalRead(pulseRotate);

  //if (pRotate != pRotateLast) { 
      
      if (pRotate == 0) { intRotateCnt++; } else { } 
      
      //}
      //pRotateLast = pRotate;

  // Print to Serial
  Serial.print("Sensor Output = " );
  Serial.print(pRotate);
  Serial.print("Count = " );
  Serial.println(intRotateCnt);
  
}

I've tried it with and without the outer IF statement to ensure just one count.

Any help would be appreciated with this.

Thanks

Start by increasing the baud rate of the Serial interface to at least 115200 and not printing unnecessary data

You should also change the code to detect when the magnet becomes detected rather than when it is detected

In this case you might consider using an interrupt to detect the pulses.

I'd do something like
volatile count =0;
void interruptroutine()
{
count++;
}

In loop, using millis() for timing read the count, do the calculations, clear the count.

Use millis() for timing instead of delay()

Thanks for the quick reply Helibob.

Not sure how to go about changing the code to detect when the magnet becomes detected though.

Thanks

See the StateChangeDetection example in the IDE

1 Like

Thanks Idahowalker. What effect would using an interrupt have on the rest of my code, as this is part of a larger program? I'll have to do some research on how to implement an interrupt as this is completely new to me.

I've no idea as the rest of the code is missing.

1 Like

Yes, that example works for me too.
We don't know what the maximum rpm is or what type of bale machine it is - straw or cardboard boxes? - but hopefully, it's not in the thousands of rpm.

Whoops.

There are plenty of pulse counting examples out there for Arduino.
You would do well to develop each part of your larger program in separate modules.
A simple Hall sensor would suffice.
Do you have an LED on the Mega to show if the pulses are getting through?
You could also set up another Arduino to generate pulses for you to see if your Mega is behaving properly.

Max rotation speed is no more than 60rpm, but with the sensor magnet being so small it's on for literally a milli-second. My thoughts were that the pulse was too short to be detected. But then the LED on the sensor itself blinks, so the signal must change to low for a milli-second.

I'll try the state change and report back tonight.

If I can get this working reliably I'll start the rest of the coding.

Surely the StateChangeDetection example is no different from what I already have, apart from when the switch is low it counts?

const int pulseRotate = 45;

// Define Variables
int pRotate = 0;
int pRotateLast = 0;
int intRotateCnt = 0;

void setup() {

pinMode(pulseRotate, INPUT);
Serial.begin(9600);

}

void loop() {

  // Read input values
  pRotate = digitalRead(pulseRotate);

  if (pRotate != pRotateLast) { 
      if (pRotate == 0) { intRotateCnt++; } else { } 
      }
      
pRotateLast = pRotate;

  // Print to Serial
  Serial.print("Sensor Output = " );
  Serial.print(pRotate);
  Serial.print("Count = " );
  Serial.println(intRotateCnt);
  
}

The StateChangeDetection example may not give any different results from your current sketch but it is certainly not the same and is the correct way to count pulses when polling for input

Consider the case with your current code where the code ran so fast or the rotation is so slow, that the sensor state was read twice before the magnet got out of range. Then the rotation count would be wrong

I've had a little time tonight to have a play. Using the StateChangeDetection example I have the same issue.

The oscilloscope on the Mega input pin is showing a pulse signal, with the HIGH signal slightly over 5v. If the voltage is over 5v, would this cause the Mega to misread?
IMG_9782

I'm going to try using interrupts tomorrow, but I'm leaning more towards a hardware or wiring issue. Power source comes from a 12v tractor battery which when running produces 14v. The sensors are powered directly from this 12/14v. While the Arduino Vin power is regulated to 9v using an LM350.

I'll try a few things....

  1. Regulate and stabilise input voltages to sensors @ 12v fixed
  2. Run external wire from sensor black, through voltage divider into Arduino input (outside of loom).
  3. Interupts

I finally managed to get this working.

I used an additional voltage reg to smooth out the alternator voltage to a constant 12v. This supply I then ran to the proximity switches. I also put the pulse count code into a function:

  void count_rotations() {
  // read the pushbutton input pin:
  pRotate = digitalRead(pulseRotate);

  if (pRotate != pRotateLast) {
    if (pRotate == LOW) {
      intRotateCnt++;      
    } else {
    }
    delay(50);
  }
  pRotateLast = pRotate;
  }

Then called this function multiple times within the loop, instead of just once at the start of the loop.

Thanks for the input folks,
Jim

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