Input signal detection

Hi,

I am looking for some ideas on making this signal detection more robust in case of noise.

Example:

  1. Input line is normally pulled high.
  2. Every N seconds it will be held low for X ms which is the “signal” I am looking for.

Below is what I have.

Thanks

volatile byte sigState;
const uint32 sigDurationFilter = 500;
volatile byte sigLOW = false;
volatile byte sigReceived = false;
volatile uint32_t sigStart;

void setup() {
  pinMode(PB2, INPUT);
  attachInterrupt(digitalPinToInterrupt(PB2), sigChange, CHANGE);
}

void signalChange(void) {
  sigState = digitalRead(PB2);
  if(sigState == LOW) {
    sigLOW = true;
    sigStart = micros();
  } else {
    if(sigLOW && ((micros() - sigStart) >= X-sigDurationFilter && (micros() - sigStart) <= X+sigDurationFilter)) {
      sigReceived = true;
      sigLOW = false;
    }
}

void loop() {
  if(sigReceived) {
    sigReceived = false;
  //
  // Valid signal received
  //
  }
}

I would normally run my main loop at fixed time intervals by waiting on elapsed time at the start of each iteration.

This means timers and counters can be based on loop iterations.

I would then use something like this to integrate the incoming signal:

if(SigHi && (SigCounter<SIGMAX)SigCounter++;
if(!SigHi && (SigCounter>0)SigCounter–;

I can then set hysteresis thresholds:

if(SigValid && (SigCounter<SIGLOW))SigValid=0;
if(!SigValid && (SigCounter>SIGHI))SigValid=1;

This means timers and counters can be based on loop iterations.

That’s a terrible way to time things. The loop doesn’t always take the same amount of time to get back to the same spot.

YGator:
Hi,

I am looking for some ideas on making this signal detection more robust in case of noise.

Example:

  1. Input line is normally pulled high.
  2. Every N seconds it will be held low for X ms which is the “signal” I am looking for.

Below is what I have.

Thanks

volatile byte sigState;

const uint32 sigDurationFilter = 500;
volatile byte sigLOW = false;
volatile byte sigReceived = false;
volatile uint32_t sigStart;

void setup() {
  pinMode(PB2, INPUT);
  attachInterrupt(digitalPinToInterrupt(PB2), sigChange, CHANGE);
}

void signalChange(void) {
  sigState = digitalRead(PB2);
  if(sigState == LOW) {
    sigLOW = true;
    sigStart = micros();
  } else {
    if(sigLOW && ((micros() - sigStart) >= X-sigDurationFilter && (micros() - sigStart) <= X+sigDurationFilter)) {
      sigReceived = true;
      sigLOW = false;
    }
}

void loop() {
  if(sigReceived) {
    sigReceived = false;
  //
  // Valid signal received
  //
  }
}

Depending on what board you have, you can use the input capture on Timer1. It has a noise filter bit that you can set that will make it wait until it sees four consecutive clocks at the same level before it triggers.

It only triggers on one edge, but you can set the register to look for the other edge in the interrupt so you effectively get both edges.

Delta_G:
Depending on what board you have, you can use the input capture on Timer1. It has a noise filter bit that you can set that will make it wait until it sees four consecutive clocks at the same level before it triggers.

It only triggers on one edge, but you can set the register to look for the other edge in the interrupt so you effectively get both edges.

Board is ATMega1284 and it looks like the input capture pin is PD6, but the signal is on PB2.

the input capture pin is PD6, but the signal is on PB2

Connect PB2 and PD6 with a wire, and you are good to go.