ATTINY85 pin changed interrupt not always works

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone,

 

since I've bee messing around with my problem for quite some time and couldn't find a solution anywhere I've decided asking for help right now. I just started 3 weeks ago to dig into the tiny85 programming. I built a small send unit consisting of a attiny85 (digispark) and a NRF24L01+ 2.4GHz unit attached with all necessary pins (not 3-pin) from PB0 to PB4. PB5 was set as interrupt pin and should initiate sending some data to the base station by pressing a simple button. So far so good, basically everything is working... except sometimes the interrupt just doesn't show any reaction for some (like 5 to 30) seconds while sometimes it works flawlessly for multiple initiations until it stalls for some seconds while afterwards it continues to work without issues again.

 

I've done a lot of research considering hard and soft pullup, interrupt handling and changing, and checking voltage levels for high and low state at the pin which was not any different between working and non-working state.

 

Since I was working with Arduino's before and got used to the environment I'm using Arduino IDE for programming.

 

Maybe someone can help me out here fixing this issue... I've attached the code for you to have a look.

 

 

The spark has set the following fuses:
Low fuse: 0xe1
High fuse: 0x5d
Extended fuse: 0xfe

 

/******************************* Hardware definition ************************/
//#define PIN_MISO 0
//#define PIN_MOSI 1
//#define PIN_SCK 2
// CE and CSN are configurable
#define PIN_CE 3
#define PIN_CSN 4
// Triggerpin
#define PIN_TRIGGER 5

#include "RF24.h"

RF24 radio(PIN_CE, PIN_CSN);

byte addresses[][6] = {"1Node","2Node"};
unsigned long triggerZeit = 0;
bool b_send=0;

struct sendData
{
  long sendDelay = 0;
  byte IDcode = 99;
}sendData, *psendData;

void setup() {
  GIMSK = 0b00100000;    // turns on pin change interrupts
  PCMSK = 0b00100000;    // turn on interrupts on pin PB5 (count from 0),
  sei();                 // enables interrupts
  pinMode(PIN_TRIGGER, INPUT_PULLUP);
  digitalWrite(PIN_TRIGGER, HIGH);

  // Setup and configure rf radio
  radio.begin(); // Start up the radio
  radio.setAutoAck(1); // Ensure autoACK is enabled
  radio.setRetries(15,15); // Max delay between retries & number of retries
  radio.setPALevel(RF24_PA_HIGH); // Set sending power
  radio.openWritingPipe(addresses[1]); // Write to device address '2Node'
  radio.openReadingPipe(1,addresses[0]); // Read on pipe 1 for device address '1Node'
  radio.stopListening(); // First, stop listening so we can talk.
}

void loop(void){
  while (b_send && ((millis()-triggerZeit)<DEBOUNCE)){
    sendingData();
    randomSeed(millis());
    delay(random(0,100));
  }
  b_send=0;
}

void sendingData(){
  sendData.sendDelay = triggerZeit-millis();
  radio.write(&sendData, sizeof(sendData));
}

ISR(PCINT0_vect)
{
  if (millis()-triggerZeit>DEBOUNCE){
    triggerZeit=millis();
  b_send=1;
  }
}

Thank you so much in advance for all your thoughts spent with this...

sisv

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sisvpfis wrote:

unsigned long triggerZeit = 0;
bool b_send=0;

Since both of these are shared between ISR() and loop(), they should be made volatile!

sisvpfis wrote:

  pinMode(PIN_TRIGGER, INPUT_PULLUP);
  digitalWrite(PIN_TRIGGER, HIGH);

Also the above is curious, as you make the pin an input w/ pull up, then try to set it high???

sisvpfis wrote:

  GIMSK = 0b00100000;    // turns on pin change interrupts
  PCMSK = 0b00100000;    // turn on interrupts on pin PB5 (count from 0),

Learn to avoid "magic numbers" such as these and use self documenting code like this:

GIMSK = (1<<PCIE);

PCMSK = (1<<PCINT5);

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
stack gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jim,

 

thanks for your remarks...

 

As I learned earlier the pullup was once only activated by setting the pin to HIGH... therefore I wanted to see if it might be a problem of floating state - I've simply missed to remove it again when I finished playing with that.

 

The shift sequence was copied form the first source that I found and I understood instantly how it worked, so I didn't give it much of a thought. I'll memorize your self documenting way of programming that so thanks for that.

 

The volatile variables are a useful hint that I didn't come across yet, an I changed it in the code.  Unfortunately it doesn't fix the problem either... the first try already failed at the second push and took about 15 seconds to "resurrect" (the tiny doesn't restart!)

 

Are there any further things that I can look into? Fuses?

Speed shouldn't be the problem with this small code and run-time considering the fuses, right?

 

 

Thanks again for hints and help!

sisv

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You may need to include the interrupt header

#include <avr/interrupt>

at the top of your program as well as enable interrupts as the last instruction of your setup() function

sei();                 // enables interrupts

 

Jim

edit, you already have that!

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
stack gold/silver https://www.onegold.com/join/713...

 

 

 

 

Last Edited: Fri. Jul 12, 2019 - 07:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jim,

 

thanks again for looking into this!

 

Concerning the sei() function...

...enable interrupts as the last instruction of your setup()

is it crucial where I call the function during setup process? Surely after the definition of the pin change and pin choice but after that? Or should it really be called at the end of setup() or even during runtime in the code? uhm... the latter surely not.

 

Could you explain to me, why or how the inclusion of <avr/interrupts.h> changes the behaviour while the code compiles without any warnings without the header?

I just read through the avr-libc dokumentation concerning interrupts. There is a own defninition of sei() and ISR included that - not much of a surprise... I think I will have a look at the .cpp file the Arduino IDE generates out of my code and see what the research leads to concerning the headers... 

 

Maybe I will give it a try at sunday.

 

 

Meanwhile... have a nice weekend!

sisv

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why do you even need interrupts on the pin? You poll the status in loop(), so why not just read the pin state and debounce it in your loop()?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Kartman,

 

thanks for your thought... but since the timing of this use is crucial (the trigger may just be active for 1/1000 of a second or less) I consider the interrupt to be necessary for saving the triggered time as a minimum inside the ISR. Yet I've meanwhile considered to try to just save the time inside the ISR and do the debounce in loop() - I'm not sure If you meant it that way!? Maybe that helps to eliminate the "lag".

 

I'try later that day...

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Jim & Kartman,

 

I think the Issue can be seen as solved, but I dont't yet understand why it didn't work that way!

 

The important change was hidden in Kartmans hint to try to do everything in the loop except setting the send bit - you were right, I just kinda did check for debounce twice the way I programmed it. I changed it to just set the bit and the time inside the ISR without checking for debounce and voila that did the trick. Still left is a big BUT... since I don't check the set time for debounce anymore another triggerevent can change the time while sending the data which could result in sending permanently. But I will find a way around that much easier! :)

 

Yet I didn't understand why the if-loop was the problem inside ISR (Jim, the header sadly didn't change anything I also tried that). Can anyone give an explanation why this massive ISR "blackout" happens due to a if-loop?

 

Thanks everyone for helping me out!

sisv

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe it was a ‘volatile’ issue. You must declare variables shared between the isr and main line code as volatile.
Eg: volatile bool b-send = false;