what levels are used to define "rising edge" and other interrupt types?

I couldn't find info on this in the ATmega328 datasheet or by searching Google. Here's my plea for help:

I need to detect transitions on a pin using an Uno R3. The signal will 99% of the time have a level of 2.5V+noise (e.g. a DC signal) and then from time to time there will be some bit stream coming along and the levels will transition between 5V+noise and 0V+noise. The bit rate is around 10kHz and the noise level is low, probably 100mV pk-pk or less. I'd like to assign an interrupt to let me know when the signal leaves the nominal 2.5V level, either rising or falling to the 5V or 0V level. I want to know what the micro considering an interrupt worthy transition.... but I can't find this info anywhere.

I know that the HIGH and LOW levels on a digital pin are (from this post:SORTED Uno digital input high / low voltage levels - #3 by TCWORLD - Microcontrollers - Arduino Forum):
VIL - Input Low Voltage, except XTAL1 and RESET pin:
Vcc = 1.8V - 2.4V MIN = -0.5 MAX = 0.2Vcc
Vcc = 2.4V - 5.5V MIN = -0.5 MAX = 0.3Vcc

VIH - Input High Voltage, except XTAL1 and RESET pins:
Vcc = 1.8V - 2.4V MIN = 0.7Vcc MAX = Vcc+0.5
Vcc = 2.4V - 5.5V MIN = 0.6Vcc MAX = Vcc+0.5

There is a "middle ground" that is neither HIGH nor LOW according to these definitions. Also, there are various types of interrupt modes: LOW, CHANGE, RISING, FALLING, and HIGH.

So, here are some topical questions:

  1. What happens when you try to read a (digital) pin and the signal is in the "middle" voltage range, e.g. not in the HIGH or LOW range?
  2. Does a "rising edge" transition have to pass from the "LOW" state to the "HIGH" state range to trigger an interrupt, or does it just have to leave the "LOW" state, or perhaps just enter the "HIGH" state?
  3. Same as #2 but for FALLING and CHANGE interrupts.. what are they detecting exactly?

Given that I need to detect the transitions away from a 2.5V level, what would you advise to be the best way to handle that using one of the interrupt types. Is there another approach that might work for me, e.g. using an analog pin? Although the transitions in my signal are not super fast (10kHz) I need to do other things in my code so I can't constantly pole the pin (thus the idea to use an interrupt).

Thanks for help and advice on this!

-Charlie

There is a "middle ground" that is neither HIGH nor LOW according to these definitions.

No, there is not. The "middle ground" is hysteresis. The pin remains in the same state as the last transition. If the pin was HIGH before the voltage reaches the "middle ground" then the pin remains HIGH. If the pin was LOW before the voltage reaches the "middle ground" then the pin remains LOW.

You have two choices...

  1. Add some hardware that outputs two signals (e.g. "signal" and "valid") so you can detect each of the three line states.

  2. Use the analog-to-digital converter.

Can't you add a capacitor to filter out the noise?

I seem to recall you can configure an op-amp as a Schmitt trigger, so if you did that it would allow for noise and then transition when a "real" signal came along.

Schmitt trigger - Wikipedia *

LOL, spelling. That's how Wikipedia has it. :slight_smile:

Wow. Given the fact that "Schmitt" is the person's name that's actually offensive.

[quote author=Nick Gammon link=topic=180865.msg1340530#msg1340530 date=1375515118]
Can't you add a capacitor to filter out the noise?[/quote]
No, the noise is broadband and filtering it out would also filter out my signal.

I'd like to see three states I guess, so the Schmitt trigger is not helping.

-Charlie

Thanks for the explanation. I wasn't sure if the digital pins had a Schmitt trigger input, although I have seen that mentioned somewhere before now that you bring it up... I'm rather new to the Arduino platform, so I am still getting familiar with everything.

Regarding the choices you outlined:
RE #1 : that could work. I'll think about how to do it and post something. This might be the best option for me, like a 2-bit input.
RE #2 : since I would like to use an interrupt driven routine, how can I do that using the Analog inputs? Since these are 10-bit, states like "HIGH" and transitions like "RISING EDGE" are doing what... is high just 1111111111 and rising when the LSB turns over? That wouldn't have very good noise immunity! Not sure how to implement interrupts on analog pins (I think you can assign them by coding low level instructions) in and effective way...

-Charlie

I think I have identified a solution for triggering an interrupt when data bits show up in my signal using a window comparator. Conveniently, there is a window comparator breakout board available through Sparkfun and other vendors:

The circuit uses a 358 dual op amp, which should be plenty fast for my needs (click on the "Schematic" link on the product page to see the details). The LOGIC output of the circuit will be HIGH when the input is between the two reference voltages that can be set with onboard potentiometers. This can be used to check if my signal is sitting at the "middle" level, with a dead band around it to accommodate noise on the line.

I can monitor the LOGIC output using one of the Arduino pins, and use the transition from HIGH to LOW to trigger an interrupt. At that point I can start monitoring the line to receive the data bits on another pin. When LOGIC has returned to HIGH for some period of time, I know the data transmission has ended.

Seems to work on paper. Thoughts?

-Charlie

Looks good to me.

To be fair, it was a redirect page. The main page spells it correctly.