PinChangeInterrupt Library

repository·master·Indexed 43 days ago

https://github.com/nicohood/pinchangeinterrupt

A resource-friendly library for AVR microcontrollers that enables rising, falling, or change detection on pins that do not support standard interrupts. It provides high-level functions like attachPinChangeInterrupt and detachPinChangeInterrupt, as well as a LowLevel API for maximum optimization by bypassing function pointer overhead.

Tokens
1.3K
Snippets
5
Records
6
Agent score
5%

What's inside PinChangeInterrupt

  1. How PinChangeInterrupts differ from PinInterrupts

    master

    It is crucial to understand the distinction between standard PinInterrupts and PinChangeInterrupts (PCINTs):

    • PinInterrupts: Dedicated to a single pin. They can detect RISING, FALLING, or CHANGE events directly.
    • PinChangeInterrupts: Triggered for an entire port (a group of pins). Because the hardware only signals that a pin in the port changed, the library must save the port state and compare it to the previous state to determine which pin changed and whether it was a RISING or FALLING edge.

    Performance Note: Because of the detection overhead (comparing port states), PCINTs may be slightly slower (measured in microseconds) than standard PinInterrupts. Avoid using long function calls or Serial.print inside the Interrupt Service Routine (ISR).

  2. Install the PinChangeInterrupt library

    master

    To install the library in the Arduino IDE:

    1. Download the ZIP file from the repository.
    2. Extract the ZIP file.
    3. Rename the extracted folder to remove the -master suffix.
    4. Move the folder to your Arduino libraries directory as described in the official Arduino guide.

    Note: For maximum optimization (using .a linkage), you can install the library into the Arduino core.

    # No specific command provided, follow manual installation steps.
  3. Use the LowLevel API for maximum optimization

    master

    For advanced users requiring the highest performance and smallest code size, the library provides a LowLevel API. This bypasses the standard function pointer overhead used by the high-level API.

    To use it:

    1. Call attachPinChangeInterrupt but omit the function name argument.
    2. Define a global function named PinChangeInterruptEvent(pcint_number) where pcint_number is the exact PCINT number (not the Arduino pin number).

    Warning: This requires precise knowledge of your MCU's PCINT mapping.

    // Attach without providing a function name
    attachPinChangeInterrupt(interruptBlink, CHANGE);
    
    // Define the LowLevel event function using the exact PCINT number
    // Note: 5 is the PCINT number, not the Arduino pin
    void PinChangeInterruptEvent(5)(void) {
      // High-speed logic here
    }
  4. Identify the trigger type in CHANGE mode

    master

    When an interrupt is attached with the CHANGE mode, you can determine if the specific pin transition was RISING or FALLING by calling getPinChangeInterruptTrigger(). This must be called inside the attached interrupt function.

    Warning: Do not call this function outside of the ISR context.

    void myInterruptHandler() {
      uint8_t trigger = getPinChangeInterruptTrigger(digitalPinToPCINT(pinTick));
      if(trigger == RISING) {
        // Handle rising edge
      } else if(trigger == FALLING) {
        // Handle falling edge
      }
    }
  5. Detach, Enable, and Disable PinChangeInterrupts

    master

    You can manage the lifecycle of an interrupt using the following functions:

    • detachPinChangeInterrupt(pin) or detachPCINT(pcint): Stops the interrupt from occurring.
    • disablePinChangeInterrupt(pin) or disablePCINT(pcint): Temporarily disables the interrupt.
    • enablePinChangeInterrupt(pin) or enablePCINT(pcint): Re-enables the interrupt using its previously configured function and mode.
    // Detach
    detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
    detachPCINT(digitalPinToPCINT(pinTock));
    
    // Disable
    disablePinChangeInterrupt(digitalPinToPCINT(pinBlink));
    
    // Enable
    enablePinChangeInterrupt(digitalPinToPCINT(pinTick));
  6. Attach a PinChangeInterrupt

    master

    Use attachPinChangeInterrupt or the abbreviated attachPCINT to enable interrupts on a specific pin. You can use the Arduino pin number by converting it via digitalPinToPinChangeInterrupt or provide the raw PCINT number directly.

    Valid interrupt modes are: RISING, FALLING, or CHANGE.

    Note: The pin must be a valid PCINT pin for your specific microcontroller (see the PCINT table in the documentation).

    // Using Arduino pin number and macro conversion
    attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick), tick, RISING);
    
    // Using the abbreviated PCINT function
    attachPCINT(digitalPinToPCINT(pinBlink), blinkLed, CHANGE);
    
    // Using a raw PCINT number directly
    attachPinChangeInterrupt(5, tock, FALLING);