/*
PB2 (INT0) used for external interrupt.
PB0, PB1, PB2, PB3, PB4, PB5 pin change interrupt.
*/
/*
SREG - AVR Status Register
The AVR Status Register – SREG – is defined as:
Bit 7 6 5 4 3 2 1 0
0x3F I T H S V N Z C SREG
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Init Value 0 0 0 0 0 0 0 0
Bit 7 – I: Global Interrupt Enable
- - - - - - - - - - - - - - - - - - -
GIMSK – General Interrupt Mask Register
Bit 7 6 5 4 3 2 1 0
0x3B – INT0 PCIE – – – – – GIMSK
Read/Write R R/W R/W R R R R R
Init Value 0 0 0 0 0 0 0 0
PCIE bit enables the pin change interrupt.
Setting the pin enables this interrupt.
in addition need to configure the pins to attach to this interrupt.
- - - - - - - - - - - - - - - - - - -
PCMSK – Pin Change Mask Register
Bit 7 6 5 4 3 2 1 0
0x15 – – PCINT5 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0 PCMSK
Read/Write R R R/W R/W R/W R/W R/W R/W
Init Value 0 0 0 0 0 0 0 0
The bits PCINT0 to PCINT5 can to attaches the pin change interrupt to ATtiny85 pins PB0 to PB5.
- - - - - - - - - - - - - - - - - - -
GIFR – General Interrupt Flag Register
Bit 7 6 5 4 3 2 1 0
0x3A – INTF0 PCIF – – – – – GIFR
Read/Write R R/W R/W R R R R R
Init Value 0 0 0 0 0 0 0 0
This register contains the interrupt flag register for both external and pin change interrupt.
This flag bits will be set by hardware when the interrupt occurs.
This bit will be cleared when the controller executes the corresponding interrupt service routine ( ISR ).
*/
#include <avr/io.h>
#include <avr/interrupt.h> // required for ISR(INT0_vect) macro
#include <TinyDebug.h>
#define PIR PB3
#define LED4 PB4
#define timeSeconds 10
// Timer: Auxiliary variables
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;
boolean motion = false;
int randomNum;
ISR (PCINT0_vect) { // Interrupt service routine
digitalWrite(LED4, HIGH);
//PORTB |= (1 << LED4);
randomNum = random(1, 5); // random number 1 to 4
startTimer = true;
lastTrigger = millis();
}
void pin_change_interrupt() {
// GIMSK – General Interrupt Mask Register
// Setting PCIE bit enables the pin change interrupt.
// Also need to configure the pins that will be triggered by this interrupt.
GIMSK |= (1 << PCIE); // enable PCIE (pin change interrupt)
PCMSK |= (1 << PCINT3); // Set which pin will trigger the interrupt
// same as SREG – Status Register: • Bit 7 – I: Global Interrupt Enable
sei(); // 'Set Enable Interrupt': (global) interrupt enable bit, turning on all interrupts that have been configured.
}
void setup() {
Debug.begin();
DDRB |= (1 << LED4); // set PB4 as output(LED)
PORTB |= (1 << PIR); // initialize pullup resistor on button pin PB1, 00000010
pin_change_interrupt();
/*
if analog input pin (pin number) is unconnected, random analog noise will cause the call to randomSeed() to generate
different seed numbers each time the sketch runs. randomSeed() will then shuffle the random function.
*/
randomSeed(analogRead(A0)); // Pin PB5 = ADC0
PORTB &= ~(1 << LED4); // set initial state of LED4 to LOW
}
void loop() {
now = millis(); // Current time
if ((digitalRead(LED4) == HIGH) && (motion == false)) {
Debug.println("MOTION DETECTED!!!");
Debug.print("PIR = "); Debug.println(digitalRead(PIR));
Debug.print("now = "); Debug.print(now); Debug.print(", lastTrigger = "); Debug.println(lastTrigger);
Debug.print("millis = "); Debug.println(millis());
PORTB |= (1 << LED4);
motion = true; // setting 'motion' to true ensures if statement runs only once
}
// Turn off the LED after the number of seconds defined in the timeSeconds variable
if (startTimer && (now - lastTrigger > (timeSeconds*1000))) {
Debug.println("Motion stopped...");
Debug.print("randomNum: "); Debug.println(randomNum);
Debug.print("now: "); Debug.print(now); Debug.print(", lastTrigger: "); Debug.println(lastTrigger);
Debug.print("now - lastTrigger = "); Debug.println(now - lastTrigger);
Debug.print("PIR = "); Debug.println(digitalRead(PIR));
PORTB &= ~(1 << LED4);
startTimer = false;
motion = false;
}
}