Remove spikes when using digital interrupt

Is there some way to handling pikes in the input signal when working with interrupts?

I have a digital sensor that is low when not detecting and high when detecting. The arduino is counting the objects. When using a analogue reading i can just not count if the number of sampling (when high) is under a specific number. But using interrupt, counting every time the signal goes from high to low or low to high, will always counts the peaks (with just one or two samplings). Is there any way of filtering that out changing just the software? Those peaks has nothing to do with interferences and is only related to the badly shaped object, so changing the hardware or peripheral (such as cables etc.) won't solve my problem (I mean, maybe I need to change the senors, but that's a later problem in that case).

Will the logic for debouncing switches do what you want?

What is a "pike" ? (apart from a species of fish)

When I saw your title I assumed it was just a typo for "spike" - but clearly that is not the case.

I don't understand why you are considering an analog reading for a digital signal from your sensor?

How often (how many per second) do your "pikes" occur ?

...R

Robin2: What is a "pike" ? (apart from a species of fish)

When I saw your title I assumed it was just a typo for "spike" - but clearly that is not the case.

I don't understand why you are considering an analog reading for a digital signal from your sensor?

How often (how many per second) do your "pikes" occur ?

...R

Yeah it was a combo-typo between peaks and spikes. :)

Well, the spikes are happening now and then just before or after the sensor has detecting the object, e.g. the object will call for the interrupt twice making the miscalculation.

I don't really considering using analogue reading, but I used it to see why the logic counted the number of object wrong. But at the same time I don't know (that's why I asked) how to make the logic not care about spikes, when using digital interrupts.

DrDiettrich: Will the logic for debouncing switches do what you want?

I have tried to read about it but I am not sure if I understand. Do you have any suggestions how to make the approach?

Hi, Can you tell us the type/part number of the sensor and how far you have the sensor from the arduino? What model arduino is it. Have you got the sensor bypassed on its power leads? Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom.... :)

TomGeorge: Hi, Can you tell us the type/part number of the sensor and how far you have the sensor from the arduino? What model arduino is it. Have you got the sensor bypassed on its power leads? Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom.... :)

It's an Uno. I have really tried every thing. I just wondering if there is a way of preventing the interrupt routine for counting if the trigger is just a spike. Or if I can put something in the routine so it understands that the trigger (spike) is not the real object. Like in the same way I can do with analogue reading (if sample>2 => count = count + 1).

Or can I put something between the refsignal from sensor and the arduino to remove spikes (something else than capacitors)?

You really should show us your circuit and let us see the specs for the sensor; makes things a great deal easier.

syntaxterror: You really should show us your circuit and let us see the specs for the sensor; makes things a great deal easier.

And this is an example of an analogue reading:

|500x375

First you see the detection of the object, then a spike. Using a interrupt based program, the interrupt routine would count the spike as an new object.

exemple code:

 const int SensorPin1 = 2;

volatile int scount1 = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(SensorPin1, INPUT_PULLUP);      
  attachInterrupt(0, count1, RISING);  
}

void loop() {
  Serial.println(scount1);

}  

void count1(){              // Interrupt service routine
  scount1 = scount1 + 1;    // Counting 
}

So, the question is how to make the logic ignore the spike?

Have you seen this? Is the sensing frequency within 0-70Hz? How are your power sources connected and grounded? What is your application for this sensor?

If the spike is wide enough, you could use a D flip-flop as a divider?

dlloyd: Have you seen this? Is the sensing frequency within 0-70Hz? How are your power sources connected and grounded? What is your application for this sensor?

Yes, I have been following everything, putting up the system in the right maner. I have also been talking to the manufacturer and they think it is because the object sometimes might move a bit or have partially bad shape of the sensing face. So it is not a interference. In the graph you see that the detections takes 3 samples. Normally it takes between 4 to 10 samlings depending on the velocity. So probably the shape of the object makes the sensor drop to low and back up very fast, detecting it once again for one sampling.

So this happens just ones or twice every 30 detections (objects). And the miscalculation with the interrupt is because of the spike that has only one sampling.

Edit: yes sensing freq. is 70 hz!

Try this as a test ... I've changed INPUT_PULLUP to INPUT so as not to influence the signal and filter (it already pulls up the signal). Also changed to printing at intervals to free up some processor time. Other minor changes.

const int SensorPin1 = 2;
byte printInterval = 500;
unsigned long previous;

volatile unsigned int scount1;

void setup()
{
  Serial.begin(9600);
  pinMode(SensorPin1, INPUT);
  attachInterrupt(0, count1, RISING);
  scount1 = 0;
}

void loop() {
  if (millis() - previous >= printInterval)
  {
    Serial.println(scount1);
    previous = millis();
  }
}

void count1() {             // Interrupt service routine
  scount1++;                // Counting
}

EDIT:

You could also try changing both resistors in your external circuit to 4.7K, or both to 10K (max). With 10K resistors, the RC time constant is 10ms which will limit the maximum signal frequency to somewhere near 100Hz.

Megaman80: I just wondering if there is a way of preventing the interrupt routine for counting if the trigger is just a spike.

Blindingly simple problem, and so often comes up here.

Don't use interrupts!

Completely unnecessary and unprofitable. For this application, you need a de-bounce routine working through polling. If you characterise your input properly here, some such routines can be suggested.

This includes software debounce ...

const int SensorPin1 = 2;
byte printInterval = 500;
byte interruptInterval = 5;
unsigned long previousPrint;
volatile unsigned long previousInterrupt;
volatile unsigned int scount1;

void setup()
{
  Serial.begin(9600);
  pinMode(SensorPin1, INPUT);
  attachInterrupt(0, count1, RISING);
  scount1 = 0;
}

void loop() {
  if (millis() - previousPrint >= printInterval)
  {
    Serial.println(scount1);
    previousPrint = millis();
  }
}

void count1() {       // Interrupt service routine
  if (millis() - previousInterrupt >= interruptInterval)
  {
    scount1++;        // Counting
    previousInterrupt = millis();
  }
}

Paul__B: Blindingly simple problem, and so often comes up here.

Don't use interrupts!

Completely unnecessary and unprofitable. For this application, you need a de-bounce routine working through polling. If you characterise your input properly here, some such routines can be suggested.

Could you clarify what you mean?

What objects do you count (material, shape)?

Can you provide a signal with the input capacitor removed?

Anything configurable with the sensor, except the distance?

Any difference when you modify the measuring distance?

DrDiettrich: (1) What objects do you count (material, shape)?

(2) Can you provide a signal with the input capacitor removed?

(3) Anything configurable with the sensor, except the distance?

(4) Any difference when you modify the measuring distance?

(1) Metal plates rolling by, with a face parallell with the sensor.

(2) No, but before I put it there I had more or less the same input (same miscalculation with intrrupts).

(3) No

(4) No, I get the same result.

I tried all suggestions but with no luck.

When I am using this code it works every time:

int inPin = 2;   
int val = 0;        
int count = 0;
int flag = 0;
int sample= 0;

void setup()
{
  pinMode(inPin, INPUT);      
  Serial.begin(9600); 
}

void loop()
{
  val = digitalRead(inPin);   // read the input pin
  Serial.println(count); 
  
   if(val==HIGH){
    
      sample = sample + 1;
    }
  
  if(sample > 1 && flag == 0){
    count = count + 1;
    flag = 1;
    sample = 0;
  }
  
   if(val == LOW && flag == 1){
     flag = 0;
     sample = 0;
   }
}

Is this the best way of doing this?