tl;dr What is the difference between these two lines of code?
GIMSK |= (1 << PCIE); (PCIE is defined as 5)
GIMSK |= 0x00100000;
These two lines of code, which I understand to be functionally identical, behave differently on an ATiny85. I don’t THINK the rest of the program will be needed, but I’ve included it at the end of the post just in case.
This one works (interrupts are enabled and function)
GIMSK |= (1 << PCIE);
This one does not work (interrupts are not enabled and do not function)
GIMSK |= 0x00100000;
According to iotn85.h from ATTinyCore:
GIMSK, used in both, is defined as:
#define GIMSK _SFR_IO8(0x3B)
PCIE, which identifies the bit in GIMSK that needs to be modified, is defined as:
#define PCIE 5
It must be something obvious, what am I overlooking? I’ve been using this method to modify registers for years, I even tested it with PCMSK on this project without issue.
For those who are curious, I’m using the PC interrupt for a level switch in the reservoir to prevent the pump from running dry. This way, the pump will be shut off NOW when the water gets low, and even with a power outage the interrupt will trigger on a reboot and keep the pump from starting.
//lower moisture readings correlate to an increase in soil moisture
//a dry sensor in open air reads ~520, a sensor submerged in water reads ~204
#include <avr/io.h>
#include <avr/interrupt.h>
#define INTERRUPT_PIN PCINT0 // This is PB1 per the schematic
#define INT_PIN PB0 // Interrupt pin of choice: PB1 (same as PCINT1) - Pin 6
#define PCINT_VECTOR PCINT0_vect // This step is not necessary - it's a naming thing for clarit
// reference mouisture reading used as a dry soil threshold
const int dry = 350;
//reference mousture reading used as a wet soil threshold
const int wet = 276;
unsigned long waterTimeLast = millis();
unsigned long waterTimeNow;
// hours * minutes/hour * seconds/minute * milliseconds/second
const int waterInterval = 6 * 60 * 60 * 1000;
const int pumpPin = 4;
const int soilSensor = A1;
const int ledPin = 1;
// used to account for millis() rollover
int rollOverFlag = 0;
int moisture = 0;
const int levelSwitchOutPin = 3; //provides a current sink to pull the levelSwitchInt pin LOW when the reservior is at LLL
const int levelSwitchIntPin = 0; //pc interrupt capable pin
void lights(int num);
void water();
void setup() {
pinMode(pumpPin, OUTPUT);
pinMode(soilSensor, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(pumpPin, LOW);
digitalWrite(ledPin, LOW);
//get the reservior level interrupt set up now in case the board resets while the level is low
pinMode(levelSwitchOutPin, OUTPUT);
//provides a current sink to pull the levelSwitchInt pin LOW when the reservior is at LLL
digitalWrite(levelSwitchOutPin, LOW);
//attachInterrupt(digitalPinToInterrupt(levelSwitchIntPin), level_ISR, CHANGE);
cli(); // Disable interrupts during setup
PCMSK |= (1 << INTERRUPT_PIN); // Enable interrupt handler (ISR) for our chosen interrupt pin
GIMSK |= (1 << PCIE); // Enable PCINT interrupt in the general interrupt mask
//GIMSK |= 0x00100000;
pinMode(INT_PIN, INPUT_PULLUP); // Set our interrupt pin as input with a pullup to keep it stable
sei(); //last line of setup - enable interrupts after setup
moisture = analogRead(soilSensor);
water();
}
void loop() {
waterTimeNow = millis();
//this will handle millis() rolling over by resetting waterTimeLast and watering now with rollOverFlag
if (waterTimeNow < waterTimeLast) {
waterTimeLast = waterTimeNow;
waterTimeNow = millis();
rollOverFlag = 1;
}
if ((waterTimeNow - waterTimeLast >= waterInterval) || (rollOverFlag == 1)) {
moisture = analogRead(soilSensor);
// if soil is above dry threshhold
if (moisture > dry) {
water();
}
waterTimeLast = waterTimeNow;
rollOverFlag = 0;
}
}
void lights(int num) {
for (int i = 0; i <= num; i++) {
digitalWrite(ledPin, HIGH);
delay (250);
digitalWrite(ledPin, LOW) ;
delay (250);
}
}
// 1) water for two seconds
// 2) wait for 30 seconds for water to absorb into the soil
// 3) take mouisture reading
// 4) repeat until soil is below wet threshold
void water () {
while (moisture >= wet) {
digitalWrite(pumpPin, HIGH);
delay(2000);
digitalWrite(pumpPin, LOW);
delay (30000);
moisture = analogRead(soilSensor);
}
}
//this interrupt is triggired when the water level in the reservior is at LLL
ISR(PCINT_VECTOR)
{
//turn the pump off to prevent running dry
digitalWrite(pumpPin, LOW);
//turn on the onboard LED as a visual indicator that the board is held in the interrupt state
digitalWrite(ledPin, HIGH);
//hold here until reservior is refilled and the level switch goes high again
while (digitalRead(levelSwitchIntPin)==0);
//turn the LED off before we exit
digitalWrite(ledPin, LOW);
}