Interrupt routine not picking up

I have tried to use pin based interrupts before. Was working on an anemometer (wind speed), The device pulsed 8 times per rotation. I was trying to count pulses over time, but the interrupt would never catch. I ended up removing the library and code for my I2C_LCD and the interrupt worked. Not sure what in the LCD code was the problem, I was not calling any of it from the interrupt routine.

I am now working on an Arduino controller for a small radio transmitter. It has a pin that goes low when the radio senses a signal. I have tried to use that to make sure I don't try to transmit when someone else is. Right now, all I am doing, for testing, is turning on an LED to show that there is a signal. I know there are easier ways to do this but right now, I am testing the interrupt feature.

/*
  debug.ino

  A simple sketch that configure a DRA818V and scan all the frequencies in the 
  range 134-174 MHz with a step of 12.5 kHz. 3 pins of the arduino are 
  used (PD, RX and TX) (CAUTION the DRA818 runs @3.3v). Configure the 3 macros
  and customize the DRA818::configure(...) call to your needs.

  Define the macro DRA818_DEBUG in DRA818.h and recompile to activate the
  debug functions of the library.
  
  Here is a sample output from the serial connection:

  Booting ...
  initializing I/O ... done
  initializing DRA818 ... DRA818: log serial connection active
  DRA818::handshake
  -> AT+DMOCONNECT
  <- +DMOCONNECT:0
  Returned value=1
  DRA818::group
  -> AT+DMOSETGROUP=0,145.5000,145.5000,0000,4,0000
  <- +DMOSETGROUP:0
  Returned value=1
  DRA818::volume
  -> AT+DMOSETVOLUME=8
  <- +DMOSETVOLUME:0
  Returned value=1
  DRA818::filters
  -> AT+SETFILTER=1,1,1
  <- +DMOSETFILTER:0
  Returned value=1
  done
  Starting ... 
  Scanning frequency 134.0000 kHz ...DRA818::scan
  -> S+134.0000
  <- S=1
  Returned value=0
 
  Scanning frequency 134.0125 kHz ...DRA818::scan
  -> S+134.0125
  <- S=1
  Returned value=0

    I'm using a digital pin (D10) to crontrol the PD pin of the DRA818. 
  It's not mandatory, you can just let the PD pin of the DRA818 
  to HIGH and free an arduino digital pin.


  Copyright (c) 2017, Jerome LOYET

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <stdio.h>
#include <SoftwareSerial.h>
#include "DRA818.h" // uncomment the following line in DRA818.h (#define DRA818_DEBUG)

/* Used Pins */
#define SIG     2   // Indicates signal is being received
#define PD      7   // to the DRA818 PD pin
#define RX      3   // arduino serial RX pin to the DRA818 TX pin
#define TX      4   // arduino serial TX pin to the DRA818 RX pin
#define PTT     5   // PTT pin 
#define TONE    8   // makes tone to transmit
#define LED     9   // LED to show signal being received (pin SIG)

bool tx = false;
float freq;
void txon();
void txoff();
int stime;
SoftwareSerial *dra_serial; // Serial connection to DRA818
DRA818 *dra;                // the DRA object once instanciated
                // the next frequency to scan

void setup(){
  Serial.begin(9600); // for logging

  Serial.println("Booting ...");

  Serial.print("initializing I/O ... ");  
  dra_serial = new SoftwareSerial(RX, TX);  // Instantiate the Software Serial Object.
  Serial.println("done");                   // Power control of the DRA818
  pinMode(PD, OUTPUT);                      // sleep pin
  digitalWrite(PD,HIGH);                    // Set to not sleep
  pinMode(PTT, OUTPUT);                     // Push to talk
  digitalWrite(PTT, HIGH);                  // Set to receive
  pinMode(SIG, INPUT);
  pinMode(LED, OUTPUT);                     // LED signaling a signal being received
  digitalWrite(LED, tx);

  Serial.print("initializing DRA818 ... ");
  /*
   * Configure DRA818V using 145.500 MHz, squelch 4, volume 8, no ctcss, 12.5 kHz bandwidth, all filters activated
   * We add the &Serial parameter to tell the DRA object where to log its debug information (to the builtin serial)
   *
   * Alternative call:
   *  dra = new DRA818(dra_serial, DRA818_VHF);
   *  dra->set_log(&Serial);
   *  dra->handshake();
   *  dra->group(DRA818_12K5, 145.500, 145.500, 0, 4, 0);
   *  dra->volume(8);
   *  dra->filters(true, true, true);
   */
  dra = DRA818::configure(dra_serial, DRA818_VHF, 145.500, 145.500, 4, 8, 0, 0, DRA818_12K5, true, true, true, &Serial);
  if (!dra) {
    Serial.println("\nError while configuring DRA818");
  }
  freq = DRA818_VHF_MIN;

  Serial.println("done");

  Serial.println("Starting ... ");
  delay(500);
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(SIG), txon, FALLING);
  attachInterrupt(digitalPinToInterrupt(SIG), txoff, RISING);
}

void loop(){
  char buf[9];
  if (!dra) return; // do nothing if DRA configuration failed
  digitalWrite(PTT, LOW);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  tone(TONE,700);
  delay(3000);
  digitalWrite(PTT, HIGH);
  noTone(TONE);
  digitalWrite(LED_BUILTIN, LOW);
  delay(5000);
  stime = millis();
  while (stime + 5000 > millis())
  {
    delay(500);
    Serial.print("signal line is: ");
  //  Serial.println(digitalRead(SIG));
    Serial.println(tx);
  }
  //dtostrf(freq, 8, 4, buf);  // convert frequency to string with right precision
  //Serial.print(String("Scanning frequency ") +  String(buf) + String(" kHz ..."));
  /* scan the frequency */
  //if (dra->scan(freq)) Serial.print("Found");
  //Serial.println("");
  
  //freq += 0.0125; //12.5kHz step
  //if (freq > DRA818_VHF_MAX) freq = DRA818_VHF_MIN; // when DRA818_VHF_MAX (174.0) is reached, start over at DRA818_VHF_MIN (134.0)
}


void txon()
{
  tx = true;
  digitalWrite(LED, tx);
}

void txoff()
{
  tx = false;
  digitalWrite(LED, tx);
}

Don't use interrupts unless it is absolutely necessary. Just poll the pin state. You didn't say what caused the headaches you mentioned in the subject line.

You can not have 2 interrupt routines attached to the same pin.

Also, according to your schematic, SIG is pin 2 which is connected to MIC_IN which is an input of the chip, not an output. You would normally connect a microphone to that pin.

Fixed subject line.

Pin 2 is the D2, aka chip pin 8. This goes to SQ (squelch) which goes low when there is a signal on the radio. Pin D8 (chip2) is an output to play a tone to the mic in on the radio.

As for two routines for the same pin, I know there are certain things you can't do in an interrupt routine, I am guessing you can pole the pin in a interrupt routine... right?

aarg: I may ditch the interrupt, the more I think about it... but there was thinking there was a reason I wanted interrupt... but it eludes me now. I think you may be right for my purpose to pole the pin before I need to know. The rest of the questions are to make sure I understand how everything works as I may need interrupts in the future.

Bob

Here is a good reference for that:
https://gammon.com.au/interrupts

I am guessing you can pole the pin in a interrupt routine... right?

It would usually be a bad idea, as it could stall the ISR, which needs to do its job quickly, and return to the main program. Also usually futile, since the ISR already runs when the pin is active, since you set it up that way.

I could call the ISR from based on "change", but the action to take would differ depending on falling or rising change. That would be why I would want to read the pin. I suppose I could set a bool for change and wherever I needed the status of the pin, read it there.

I assume it is likewise not advisable to set an output in in an ISR, correct?

Bob
KG5GTE by the way

No, you could set an output in an ISR, it's done a lot for things like bit banging. The point is, an interrupt isn't the right paradigm for monitoring an input state, unless you have to respond in sub microseconds, to the stimulus.

Especially for a beginner, but a pro also would never undertake an approach that is 10x more complicated than it needs to be.

If you'll excuse some analysis, it seems to me like you're "diving in" to the technical details, prior to a needs and requirements assessment, leading to a high level design. That should precede detailed design decisions such as whether to use interrupts or not, or what to use them for.

1 Like

See, without interrupts, this boils down to "read a pin". :slight_smile: Thus why bother with all that stuff...

Do you understand that loop() runs several thousand times per second (unless you screw that up with delays)? Usually that is more than fast enough to read a medium speed I/O.

Seems to me you only need to check SQ before you go into transmit mode. So why not just check it once then?

Actually, some transceiver IC's have TX blocking on SQ built in. You should check to see whether it can be enabled there. Then you would only need to monitor it.

I agree with just about everything you say. I am not a programer per se, but I guy know knows enough to be dangerous. lol Two replies:

  1. Yes I am jumping in and building/testing in parts because I find much better success when I have tested the parts before putting them together. And also I tend to get into the project and go "ohhh, I could add this feature or that..."
  2. Pertaining to the Interrupt, the reason is so that I don't have to read the status of the pin in several places. This code will eventually play a tune or Morse code message with some pauses to let the radio cool off (not sure what duty cycle it can handle) and my call every 10 minutes. In the pauses I will listen for DTMF codes and change the tune, change the frequency, change the CW speed, and or whatever other shiny feature catches my attention. But you are right in this case that I could just check the status of SQ before transmitting. Some of my other hair brained ideas may have a lot more going on.

I may pick your brain later as to why my original wind speed code would not call the ISR if the LCD code was present. I think using at interrupt to count the tics would be better/faster than dedicating the whole chip to monitoring the clicks for a time, then doing the other tasks.

Thank you for all your help. I have not read through your link on interrupts and it may answer some of my questions, but I will.

Bob

It's a "must read" if you plan on using interrupts.

1 Like

You will eventually discover with that, you have to poll the flags that the ISR sets, in those several places. So you won't gain anything there. Interrupts are disabled inside an ISR which severely limits what you can do in the ISR code. Usually all you can do is capture or emit some data, set some flags, and return.

Besides, what is so terrible about reading a pin in several places? The overhead is almost nothing.

I was not aware that the regulations allow you to broadcast a tune.

There are lots of foxes that do. I don't think I can play copyrighted or commercial tunes. Just because several do, doesn't mean it is legal. I will look into that further as well. Thanks for the heads up.

Bob

Holy cow, it never even occerred to me to read the ATMega328 datasheet. Gonna be a long read but the more I understand the chip, the better and more I can do. And I have already made a few chip only (as opposed to any arduino) devices.

Thanks again for the help and guidance!

Bob

Well, I would be the last to discourage you from reading the data sheet, but I was actually referring to Nick Gammon's site in this case.

1 Like

Lol. I got that and did read the site, but didn't understand all the references. His page referred me to the datasheet.

73,
Thanks again.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.