Author Topic: SPI Conflict between RFM69 and SD library  (Read 28753 times)

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #15 on: February 14, 2016, 07:29:28 PM »
I'm still banging my head on the wall over this one. My "workaround" didn't work in long run, whole micro-controller freezes when radio signal comes in while it's playing WAV file from SD Card.
Felix as you suggested, I was able to figure out how to disable correct interrupt and it works with SD card
Code: [Select]
detachInterrupt(digitalPinToInterrupt(2));
But to get Radio working again I need enable it, and so far I couldn't figure out how to do it...
In your library it ran during init:
Code: [Select]
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
I've tried running this from my sketch:
Code: [Select]
attachInterrupt(digitalPinToInterrupt(2), radio.isr0(), RISING);
But it gives me error:
RFM69.h:122:17: error: 'static void RFM69::isr0()' is protected

Is there any way I can attach interrupt within my program?

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: SPI Conflict between RFM69 and SD library
« Reply #16 on: February 15, 2016, 08:23:19 AM »
Just call radio.initialize() again.  It will reattach its own interrupt.  You could also simply mask and unmask interrupt 2.  A simple DAGS will provide code for this.

Tom

TD22057

  • NewMember
  • *
  • Posts: 26
  • Country: us
Re: SPI Conflict between RFM69 and SD library
« Reply #17 on: February 15, 2016, 11:29:03 AM »
Just a coding note:
isr0 is a static function - you don't need the 'radio' variable instance to access it or call it.  In your attachInterrupt code, you want to pass the function, not call it and pass the return value.  So:

Code: [Select]
// WRONG:
attachInterrupt(digitalPinToInterrupt(2), radio.isr0(), RISING);
// RIGHT:
attachInterrupt(digitalPinToInterrupt(2), RFM69::isr0, RISING);

Of course it's still protected.  But if you wanted to inherit from RFM69, you can do something like this and then call the add/del methods to take care of the interrupt.

Code: [Select]
class MyRFM69 : public RFM69 {
public:
   // Pass through constructor
   MyRFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN,
           bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM)
      : RFM69(slaveSelectPin, interruptPin, isRFM69HW, interruptNum) {
   }

   void enableInterrupt() {
      attachInterrupt(_interruptNum, RFM69::isr0, RISING);
      }
   void disableInterrupt() {
      detachInterrupt(_interruptNum);
   }
};

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #18 on: February 15, 2016, 03:53:57 PM »
Just call radio.initialize() again.  It will reattach its own interrupt.  You could also simply mask and unmask interrupt 2.  A simple DAGS will provide code for this.

Thanks Tom!  I actually am calling radio.initialize() every time after Audio finished playing. I think I'm also have call radio.encrypt() as well, so I'm doing it just in case. 
I'm not sure I understand what do you mean by unamsk interrupt? And what is DAGS?

Code: [Select]
// ==================================================
// -- Turns off radio and keeps track of it's status
void turnOffRadio() {
 if (!isRadioPresent) return;
 //radio.Sleep();
 if (radioOn) {
   //radio.sleep();
   radioOn=false;
  putstring_nl ("Radio Off!");
  delay (5);
  detachInterrupt(digitalPinToInterrupt(2));
 }
}

// ====================================================================
// -- Re-initializes radio after it was diabled by interrupt function
void reEnableRadio() {
  if (!isRadioPresent) return;
  if (radioOn) return;
  if (isInMenu) return;
  if (soundAlarm[0] || soundAlarm[1]) return;
  if (wave.isplaying) return;
  if (isInQMenu) return;
  putstring_nl("Re-enable Radio");
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
  radio.encrypt(KEY);
  radioOn=true;
  radio.sleep();
  card.init(); // Reset SD Card
}

So before playing audio I call turnOffRadio() function.  reEnableRadio() is running in main loop, and once it sees it can do it's thing it reinitialize radio (and SD card).  This seems to work pretty well, but probably uses unnecessary resources.

TD22057, thanks so much for your code! I'll try to add it to the library.

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: SPI Conflict between RFM69 and SD library
« Reply #19 on: February 15, 2016, 04:34:06 PM »
Just call radio.initialize() again.  It will reattach its own interrupt.  You could also simply mask and unmask interrupt 2.  A simple DAGS will provide code for this.

Thanks Tom!  I actually am calling radio.initialize() every time after Audio finished playing. I think I'm also have call radio.encrypt() as well, so I'm doing it just in case. 
I'm not sure I understand what do you mean by unamsk interrupt? And what is DAGS?
DAGS:= 'Do A Google Search'

DAGS "AVR disable INT0" and you will find, among other things:

Code: [Select]
EIMSK &= ~(1 << INT0);

DAGS "AVR Enable INT0" and you will probably find:
Code: [Select]
EIMSK |= (1 << INT0);

This, of course, assumes that you are using a 328P.  If using a Mega the INT# is different and the mask register is different but a simple DAGS will find it for you.


Tom
UPDATE:  Of course, it would probably be a BETTER google search if you mention AtMega328P since THAT processor uses the EIMSK register, NOT the GICR register.  Code is corrected above.  :-[

And in the case of the AtMega1284, the INT for the Radio is INT2 so... EIMSK &= ~(1<<INT2);
« Last Edit: February 15, 2016, 04:56:43 PM by TomWS »

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #20 on: February 15, 2016, 04:49:09 PM »
Ah ok! Cool, I'll try to figure it out then from Datasheet :)
I'm using ATmega1284p, so far no easy google results on that one :)

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #21 on: February 15, 2016, 05:32:30 PM »
Thanks again Tom.
Is "INT2" a variable of some sort? Cause it doesn't compile :(
Code: [Select]
EIMSK &= ~(1<<INT2);

'INT2' was not declared in this scope


TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: SPI Conflict between RFM69 and SD library
« Reply #22 on: February 15, 2016, 06:13:33 PM »
Thanks again Tom.
Is "INT2" a variable of some sort? Cause it doesn't compile :(
Code: [Select]
EIMSK &= ~(1<<INT2);

'INT2' was not declared in this scope
You DO have the Moteino Mega selected as your Board in the Tools menu, right?????


Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #23 on: February 15, 2016, 06:25:12 PM »
You DO have the Moteino Mega selected as your Board in the Tools menu, right?????
LOL, no :)
It's my own board, for clocks that I make :)
Bootloader is "Maniacbug" Mighty 1284p
« Last Edit: February 15, 2016, 06:26:43 PM by Lensdigital »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: SPI Conflict between RFM69 and SD library
« Reply #24 on: February 16, 2016, 09:22:13 AM »
If you use my libraries I would suggest using my 1284p core, which was Mighty 1284p based, but I think I had to make some other changes. That gives you a Tools > Boards > MoteinoMEGA option. I had to make this specifically for the 1284p based board I produce.

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #25 on: February 16, 2016, 09:26:54 AM »
If you use my libraries I would suggest using my 1284p core, which was Mighty 1284p based, but I think I had to make some other changes. That gives you a Tools > Boards > MoteinoMEGA option. I had to make this specifically for the 1284p based board I produce.
Thanks Felix, I'll try your bootloader.  Did you base it on any other bootloader or did you write it from scratch?

I see all pins match, except that you have blink routing on D15.  Do you share your source files for this bootloader? I'd like to modify it because I use D15 for my LED Matrix Clock pin...
« Last Edit: February 16, 2016, 09:59:34 AM by Lensdigital »

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #26 on: February 16, 2016, 10:26:39 AM »
I'm not sure what's happening but it's now compiling with INT2...   :o
I think I had wrong board selected or something yesterday :D
Seems to be working so far. 
And here's something interesting I discovered (which you guys probably already knew). It seems that RFM69W "caches" transmission. When Interrupt being off, I send message, and when interrupt turns on in few seconds, it shows that message!  Pretty cool! :)
« Last Edit: February 16, 2016, 10:33:13 AM by Lensdigital »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: SPI Conflict between RFM69 and SD library
« Reply #27 on: February 16, 2016, 11:12:34 AM »
Did you base it on any other bootloader or did you write it from scratch?
Do you share your source files for this bootloader? I'd like to modify it because I use D15 for my LED Matrix Clock pin...

My bootloader is called DualOptiboot (my own naming), it is based on Optiboot. The sources and binary are posted here.

And here's something interesting I discovered (which you guys probably already knew). It seems that RFM69W "caches" transmission. When Interrupt being off, I send message, and when interrupt turns on in few seconds, it shows that message!  Pretty cool! :)
If I understand this correctly, and without digging the MCU datasheets, I think the interrupts are only triggered when they are enabled, even if they happen while they are disabled (interrupt bits will get set in their registers but the handlers will not be called until the interrupt enable registers bits are enabled).

TD22057

  • NewMember
  • *
  • Posts: 26
  • Country: us
Re: SPI Conflict between RFM69 and SD library
« Reply #28 on: February 16, 2016, 11:57:57 AM »
And here's something interesting I discovered (which you guys probably already knew). It seems that RFM69W "caches" transmission. When Interrupt being off, I send message, and when interrupt turns on in few seconds, it shows that message!  Pretty cool! :)

Thanks for posting this.  I'm trying to hack the RFM69 library to understand it better and experiment with a "callback on state change" API and I was actually wondering about that very question yesterday.  So your post saved me a bunch of time - Thanks!

Lensdigital

  • Full Member
  • ***
  • Posts: 155
    • Lensdigital
Re: SPI Conflict between RFM69 and SD library
« Reply #29 on: February 16, 2016, 03:57:07 PM »
Thanks for posting this.  I'm trying to hack the RFM69 library to understand it better and experiment with a "callback on state change" API and I was actually wondering about that very question yesterday.  So your post saved me a bunch of time - Thanks!

Glad it was useful :)
It frustrates me when these issues happen, but on the other hand I'm very happy it happened. I think I learned more about SPI during last couple of weeks than I did in few last years that I've been involved with micro-controllers :)   Couldn't have done this without you guys, really thankful for the interrupt solution!  My code seems to work great now, directing which SPI device can do what and when like a traffic light, so "accidents" don't happen :)  I've been bombarding my clocks with radio transmissions during audio playbacks and so far wasn't able to make them freeze. Very happy :)
« Last Edit: February 16, 2016, 04:02:34 PM by Lensdigital »