PinChangeInterrupt Library help please

Hi All,

I am working on a sketch a wrote for an ATtiny85 that basically reads a push button and then generates PWM based on a logarithmic curve…that’s working correctly. At first I was polling the button which works, but seems flaky; i mean yeah it does work but isn’t consistent enough for me, it doesn’t respond the same way every time it is pressed. I don’t think it’s the switch bouncing, I do have a simple debounce in place. I’m fairly certain it has to do with the polling, so I am trying to make it interrupt driven. Here’s my code:

#include <PinChangeInterrupt.h>

//varibles below
int prescalerValMask = 0x07; //Register BALACK MAGIC
int prescalerVal = 0x01;     //for 64KHz PWM
                             //makes delay and such run faster 

byte dimmer_counter = 0;     //set to zero at power up
byte debounce_counter = 0;   //set to zero at power up

int dimmer_step_delay_SLOW = 1200; //Slow Start Delay divide by 256 for mS
int dimmer_step_delay_FAST = 300;  //Fast Start Delay divide by 256 for mS
int dimmer_step_delay;

boolean power_status = false;

int LogCurve[180] = {1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3, //roughly based on inverted natural logarithm
                     4,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,10,10,
                     11,11,12,12,13,13,14,14,15,15,16,16,17,18,
                     18,19,20,20,21,22,23,23,24,25,26,27,27,28,
                     29,30,31,32,33,34,35,36,37,38,39,40,41,42,
                     43,44,45,47,48,49,50,51,53,54,55,57,58,59,
                     61,62,64,65,66,68,69,71,73,74,76,77,79,81,
                     82,84,86,87,89,91,93,95,97,98,100,102,104,
                     106,108,110,112,114,116,119,121,123,125,127,
                     130,132,134,136,139,141,144,146,148,151,153,
                     156,159,161,164,166,169,172,174,177,180,183,
                     185,188,191,194,197,200,203,206,209,212,215,
                     218,221,225,228,231,234,238,241,244,248,251,
                     255};

byte gate_pin = 0;
byte fast_cycle = 1;
byte slow_cycle = 2;
byte button_pin = 3;

void setup() 
{
  TCCR0B &= ~prescalerValMask; //more BLACK MAGIC
  TCCR0B |= prescalerVal;      //more BLACK MAGIC

  pinMode(gate_pin, OUTPUT);       //PWM output
  pinMode(fast_cycle, INPUT_PULLUP); //Short Cycle
  pinMode(slow_cycle, INPUT_PULLUP); //Long Cycle
  pinMode(button_pin, INPUT);        //Normally Open Switch, external pullup
  digitalWrite(gate_pin,0);        //turn off output at power up

  attachPcInterrupt(3,button_press,RISING);

}

void loop() 
{
 cycle_mode(); 
 check_button();
 dimming_cycle();
}

//functions below

void cycle_mode()
{
  if (digitalRead(fast_cycle) == 0)      //Check dimming speed jumper
     {
      dimmer_step_delay = dimmer_step_delay_FAST;
     }
  else if (digitalRead(slow_cycle) == 0)
     {
      dimmer_step_delay = dimmer_step_delay_SLOW;
     }
}

void check_button()
{
  while(digitalRead(button_pin) == 1 && debounce_counter < 50) //.5s debounce cycle
       {
        delay(250);
        debounce_counter++;
       }  
  
  if (debounce_counter == 50 && power_status == false) //the if & else if below is the toggle mechanism
     {
      power_status = true; //set flag and reset counter
      debounce_counter = 0;
     }
  else if (debounce_counter == 50 && power_status == true)
          {
           power_status = false; //set flag and reset counter
           debounce_counter = 0;
          }
}

void dimming_cycle()
{
   while(power_status == true && dimmer_counter < 179) //pull values indexed in LogCurve array and output PWM
        {
         analogWrite(gate_pin,LogCurve[dimmer_counter]); 
         delay (dimmer_step_delay);
         dimmer_counter++;
        } 
   if (power_status == false)
      {
       analogWrite(gate_pin, 0);
       dimmer_counter = 0;
       delay(5000);
      }
}

//ISRs below
void button_press(){} //empty until compile errors figured out

I searched around the forum and found several mentions of the PinChangeInterrupt library and I think I know how to use it. When I try and compile I get a huge number of errors. I haven’t gotten to the point in my knowledge where I can figure out how o fix them and that’s what I need some help with. Here are the messages:

C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:50: error: 'NUMBER_PIN_CHANGE_INTERRUPT_HANDLERS' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp: In function 'void attachPcInterrupt(uint8_t, void (*)(), uint8_t)':
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:76: error: 'digitalPinToBitMask' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:80: error: 'CHANGE' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:84: error: 'FALLING' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:88: error: 'RISING' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:104: error: 'pcint' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:105: error: 'NUMBER_PIN_CHANGE_INTERRUPT_HANDLERS' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp: In function 'void detachPcInterrupt(uint8_t)':
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:266: error: 'digitalPinToBitMask' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:274: error: 'pcint' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:275: error: 'NUMBER_PIN_CHANGE_INTERRUPT_HANDLERS' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp: In function 'void detachPcInterrupt(uint8_t, void (*)(), uint8_t)':
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:315: error: 'digitalPinToBitMask' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:319: error: 'CHANGE' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:323: error: 'FALLING' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:327: error: 'RISING' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:337: error: 'pcint' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:338: error: 'NUMBER_PIN_CHANGE_INTERRUPT_HANDLERS' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp: In function 'void PCINTX_common(uint8_t, volatile uint8_t&)':
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:393: error: 'pcint' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\PinChangeInterrupt\PinChangeInterrupt.cpp:394: error: 'NUMBER_PIN_CHANGE_INTERRUPT_HANDLERS' was not declared in this scope

Any advice would be greatly appreciated! Sorry for the long post.

If you got rid of the delay calls in your dimmer routine you wouldn’t need the interrupt.

It looks like you might have an old version of the library. Look and see if it includes wprogram.h If so, change it to arduino.h

Hi Delta_G,

Thanks for the response

I looked for wprogram.h in the library and don’t see it anywhere in the .h or .cpp files, but I didn’t see arduino.h either. Here’s what’s in that section for the libraries:

PinChangeInterrupt.h

#ifndef PinChangeInterrupt_h
#define PinChangeInterrupt_h

#include <inttypes.h>

#include <core_build_options.h>
// rmv #include "wiring_private.h"

PinChangeInterrupt.cpp

#include <wiring.h>
#include <pins_arduino.h>
#include <core_macros.h>

#include <avr/interrupt.h>
#include <avr/io.h>

#include <PinChangeInterrupt.h>

I know there are several different Attiny cores, could I be using the wrong one or rather one that isn’t compatible with the library?

About the delays…I’m not trying to get the button to respond in during dimming_cycle, I’m really trying to get away from polling the switch. But I know delays really aren’t that great in general, are you suggesting that I do something along the lines of using the millis() to check if enough time has passed?

Sorry, I missed that it was a tiny. That arduino.h is my go to solution when I start seeing constants that I know Arduino defines showing up as undefined. You may have an issue somewhere with how the core is included.

Either way, how much of a delay are you seeing between the button push and the code reacting? I can't imagine it would be more than a few microseconds if you don't have any delay in that code. Interrupts are mostly for machines interacting with other machines where things need to happen on the microsecond scale. Or they are for counting events that happen really fast and only last a few microseconds. I can't imagine any human who is able to push a button fast enough to require an interrupt to read it. In the time it takes you to push the button down the loop can poll that button dozens of times.

Have you measured a lag there? How much lag is there?

Well it's not really laggy, and kind of hard to explain.

If you press it button starting the dimming cycle and let it run, when you press it again afterword to turn it off, sometimes it doesn't respond and requires a third press to turn off; still other times it shuts off correctly and the restarts the dimming cycle.

Maybe it's being caused by my debouncing, it is very rudimentary.

I'll mess around with it and post any results.

I would like to figure out how to get the PinChangeInterrupt working anyway...seems very handy.

You mean you press the button to turn it off while it is running that dimming cycle? That's because your dimming code is blocking. While that function is running Arduino is blind to any button presses and that function takes a little while to completer. If you get rid of the delays and embrace the "blink without delay" paradigm then you won't have that problem.

while(power_status == true && dimmer_counter < 179) //pull values indexed in LogCurve array and output PWM
        {
         analogWrite(gate_pin,LogCurve[dimmer_counter]); 
         delay (dimmer_step_delay);
         dimmer_counter++;
        }

I’m talking about this code. That will take some time to count all the way up and complete and the buttons aren’t being read or responded to during that. Instead, write this function so that it checks the time and makes one step and returns. Instead of waiting in that while block, it just gets called over and over stepping its way through. That way, after each step the code runs through the rest of loop and calls your button checking routine.