Nano interrupts

Hi all,

Can you have a look at this code and see why it does not work. (used on a nano)

volatile int pwm_value = 0;
volatile int prev_time = 0;
 
void setup() {
  Serial.begin(250000);
  // when pin D2 goes high, call the rising function
  pinMode(2, INPUT);  
  attachInterrupt(0, rising, RISING);
}
 
void loop() {
  delay(10000);
  Serial.println(pwm_value);
}
 
void rising() {
  attachInterrupt(0, falling, FALLING);
  prev_time = micros();
}
 
void falling() {
  attachInterrupt(0, rising, RISING);
  pwm_value = micros()-prev_time;
}

Thanks Steve

I think that you need to enable (attach) the interrupt before an interrupt will be recognized. As it is, an interrupt must be generated to enable an interrupt, but there are no interrupts enabled until an interrupt occurs. See Catch 22.
Make one ISR that detects rising or falling edge with StateChangeDetection and attach the interrupt in setup().

An int is too small for your counters which have values based on micros(). Use unsigned long instead.

see why it does not work.

What does it do ?

If you want to know the time between the signal on the pin falling and rising again a more normal technique would be to use a CHANGE interrupt and test the state of the pin in the ISR, possibly using direct port manipulation, but digitalRead() would work, to establish whether the interrupt was caused by a falling or rising pin state.

Thanks for the reply groundFungus, but in setup I attach the interrupt does this not enable it?

void setup() {
  Serial.begin(250000);
  // when pin D2 goes high, call the rising function
  pinMode(2, INPUT);  
  [b]attachInterrupt(0, rising, RISING);[/b]
}

@6v6gt

I don't think this is the problem, I added a Serial.println("test"); to both the rise and fall interrupts and they never printed :frowning:

Steve

Sorry, I don't know why I did not see that. :-[ Yes, that enables it. Serial print depends on interrupts, interrupts are disabled in an ISR, so print won't work right.

If you are running on a nano, i do not think that you can attach it to 0.
Only ping 2 and 3 are allowed ; attachInterrupt() - Arduino Reference

Also us digitalPinToInterrupt(pin) which is recommended above the pin number

attachInterrupt(digitalPinToInterrupt(2), rising, RISING);

. . .
@6v6gt

I don't think this is the problem, I added a Serial.println("test"); to both the rise and fall interrupts and they never printed :frowning:
. . .

This:

volatile int prev_time = 0;
. . .
prev_time = micros();

will blow up if your program runs for more than 0.032 seconds.
As has been said, you cannot use serial print in an ISR.
If you are still having problems, strip the whole thing back to a very basic sketch with a simple ISR, triggered by an on CHANGE interrupt which increments a counter. Print the counter in the loop() every one second or so. If you can't get that working, then something more fundamental is going wrong.

If you having a floating input on pin D2 you have to add a pulldown resistor.
Easier is to set ping 2 to input and enable the pullup resistor.

When connecting D2 to GND the signal falls, on disconnection the signal rises.

Tested it with the code below and works on my nano

volatile int pwm_value = 0;
volatile int prev_time = 0;
 
void setup() {
  Serial.begin(57600);
  Serial.println("Started");
  // when pin D2 goes high, call the rising function
  pinMode(2, INPUT_PULLUP);  
  attachInterrupt(0, rising, RISING);
}
 
void loop() {
  delay(1000);
  Serial.println(pwm_value);
}
 
void rising() {
  attachInterrupt(digitalPinToInterrupt(2), falling, FALLING);
  prev_time = micros();
}
 
void falling() {
  attachInterrupt(digitalPinToInterrupt(2), rising, RISING);
  pwm_value = micros()-prev_time;
}