Random and unpredictable analog comparator behaviour

I read that you are using a DAC to generate the sine wave signal. DAC outputs can glitch at the output state changes so you should definitely apply some analogue filtering to the DAC output before feeding it into your comparator circuit. This can help with preventing some of the double interrupt triggers that are likely to be occurring.

I would also comment that you really want to be using an external comparator for this type of problem so that you can apply the hysteresis with resistors without the use of a software interaction. This will also allow better problem isolation since you can directly monitor the output of the comparator.

Last comment relates to the type of hysteresis you are using. It is a bit hard to see exactly what scheme you are using but note that what you want is behavior that does this: You want the hysteresis that pulls the threshold voltage in the OPPOSITE direction than the signal is transitioning. So for a rising edge you want the threshold to be a bit higher than the zero point and then when the state changes the threshold gets pulled to a lower level.


The issues with this scenario is there is a time delay between the comparator switching and the interrupt being handled to the point where you switch the "hysteresis" pin.

Your hysteresis band is also rather small for that signal level considering what you are using it for. Especially when I see how much noise is on that square wave on your scope.

With both of those factors in mind, there is a high probability that at certain input levels you will get multiple edges from the comparator before you can handle the first one. Checking to see what the comparator state is during that interrupt handler wont help much since it can be in either state.

Unfortunately you have not detailed in the question how the handler works.

Your handler should however, work something like this.

  1. When the hysteresis value in the high threshold state you should be waiting for a negative edge interrupt.

  2. When said negative edge interrupt arrives, toggle the hysteresis to the low value, wait a few cycles, then clear any pending interrupt and begin waiting for a positive edge interrupt.

  3. When said positive edge interrupt arrives, toggle the hysteresis pin back to the high value, wait a few cycles, clear any pending interrupt and begin waiting for a negative edge interrupt again.

  4. Repeat from step 1.

BTW I'm not too keen on the way you are using the comparator reference as the bias for the signal. That results in a little cross-talk both from the signal to the reference and from the hysteresis to the signal, especially with low frequency signals. Granted with those values that effect should be small, but for purity, a separate bias on the signal would be better.

EDIT: Re your code.

In the else statement you change the interrupt edge before you set the hysteresis.

In neither case do you pause and clear any pending interrupts before returning. (Note, changing the interrupt control register can create interrupts on it's own.)

I do not know if the Atmega does re-entrant interrupts, that is, if a subsequent edge will interrupt the still running handler from the previous edge. If so you need to handle concurrency appropriately.

Not sure what the PORTC part is for, but it probably needs to move into the qualified part.


This effect is similar to contact bounce, and can be mitigated by the same debounce techniques you'd use for pushbuttons.

  • Decide on debounce time Td
  • keep the timestamp of the last edge interrupt in a variable
  • if the time between the current interrupt and the last one is less than Td, ignore the current interrupt