Nah, I'm back for more....
Ok, so basically I got my code up and mostly running, but this time I am having trouble with the hardware interrupts.
My code:
#include <avr/sleep.h> //Needed for sleep_mode
#include <avr/power.h> //Needed for powering down perihperals such as the ADC/TWI and Timers
//#include <interrupts.h>
#include <avr/interrupt.h>
#define TRUE 1
#define FALSE 0
//Set this variable to change how long the time is shown on the watch face. In milliseconds so 1677 = 1.677 seconds
int show_time_length = 2000;
volatile int show_the_time = FALSE;
//You can set always_on to true and the display will stay on all the time
//This will drain the battery in about 15 hours
int always_on = FALSE;
volatile long seconds = 54;
volatile int minutes = 24;
volatile int hours = 3;
//Careful messing with the system color, you can damage the LEDs if
//you assign the wrong color. If you're in doubt, set it to red and load the code,
//then see what the color is.
#define RED 1
int systemColor = RED;
int display_brightness = 15000; //A larger number makes the display more dim. This is set correctly below.
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//Pin definitions
int hour8 = A4; //Hour 8
int hour4 = A2; //Hour 4
int hour2 = 12; //Hour 2
int hour1 = 10; //Hour 1
int minute32 = A0; //Minute 32
int minute16 = A3; //Minute 16
int minute8 = A1; //Minute 8
int minute4 = 13; //Minute 4
int minute2 = 11; //Minute 2
int minute1 = 9; //Minute 1
int theButton = 2;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//The very important 32.686kHz interrupt handler
//The very important 32.686kHz interrupt handler
ISR (TIMER2_OVF_vect)
{
seconds += 8; //We sleep for 8 seconds instead of 1 to save more power
//seconds++; //Use this if we are waking up every second
if(seconds > 59){
minutes++;
seconds = seconds - 59;
}
if(minutes > 59){
hours++;
minutes = minutes - 59;
}
/*
//Update the minutes and hours variables
minutes += seconds / 60; //Example: seconds = 2317, minutes = 58 + 38 = 96
seconds %= 60; //seconds = 37
hours += minutes / 60; //12 + (96 / 60) = 13
minutes %= 60; //minutes = 36
*/
if(hours > 12) hours -= 12;
}
//The interrupt occurs when you push the button
ISR(INT0_vect){
//When you hit the button, we will need to display the time
//if(show_the_time == FALSE)
show_the_time = TRUE;
}
void setup() {
//To reduce power, setup all pins as inputs with no pullups
for(int x = 1 ; x < 18 ; x++){
pinMode(x, INPUT);
digitalWrite(x, LOW);
}
pinMode(theButton, INPUT); //This is the main button, tied to INT0
digitalWrite(theButton, HIGH); //Enable internal pull up on button
//These pins are used to control the display
pinMode(hour8, OUTPUT);
pinMode(hour4, OUTPUT);
pinMode(hour2, OUTPUT);
pinMode(hour1, OUTPUT);
pinMode(minute32, OUTPUT);
pinMode(minute16, OUTPUT);
pinMode(minute8, OUTPUT);
pinMode(minute4, OUTPUT);
pinMode(minute2, OUTPUT);
pinMode(minute1, OUTPUT);
//Power down various bits of hardware to lower power usage
set_sleep_mode (SLEEP_MODE_PWR_SAVE);
//Shut off ADC, TWI, SPI, Timer1
ADCSRA &= ~ _BV (ADEN); // Disable ADC
ACSR = _BV (ACD); // Disable the analog comparator
DIDR0 = 0x3F; // Disable digital input buffers on all ADC0-ADC5 pins
DIDR1 = _BV (AIN1D) | _BV (AIN0D); //Disable digital input buffer on AIN1/0
power_twi_disable();
power_spi_disable();
power_usart0_disable();
power_timer1_disable();
//Setup TIMER2
/* TCCR2A = 0;
TCCR2B = _BV (CS22) | _BV (CS21) | _BV (CS20);
ASSR = _BV (AS2); // Enable asynchronous operation
TIMSK2 = _BV (TOIE2); // Enable the timer 2 interrupt
*/
TIMSK2 = 0; //stop timer2 interrupts while we set up
ASSR = _BV(AS2); //Timer/Counter2 clocked from external crystal
TCCR2A = 0; //override arduino settings, ensure WGM mode 0 (normal mode)
TCCR2B = _BV (CS22) | _BV (CS21) | _BV (CS20); //prescaler clk/1024 -- TCNT2 will overflow once every 8 seconds
TCNT2 = 0; //start the timer at zero
while (ASSR & (_BV(TCN2UB) | _BV(TCR2AUB) | _BV(TCR2BUB))) {} //wait for the registers to be updated
TIFR2 = _BV(OCF2B) | _BV(OCF2A) | _BV(TOV2); //clear the interrupt flags
TIMSK2 = _BV(TOIE2); //enable interrupt on overflow
//Setup external INT0 interrupt
EICRA = (1<<ISC01); //Interrupt on falling edge
EIMSK = (1<<INT0); //Enable INT0 interrupt
sei(); //Enable global interrupts
//System clock futzing
//CLKPR = (1<<CLKPCE); //Enable clock writing
//CLKPR = (1<<CLKPS3); //Divid the system clock by 256
//Display brightness changes based on color
if(systemColor == RED) {
display_brightness = 4500; //The higher the number, the lower the brightness
}
else {
display_brightness = 1;
}
showTime(); //Show the current time for a few seconds
sei(); //Enable global interrupts
// open the serial port at 9600 bps:
Serial.begin(9600);
Serial.println("Hola!!");
}
void loop() {
if(always_on == FALSE)
Serial.println("Hola!!");
Serial.println("Hola!!");
sleep_mode(); //Stop everything and go to sleep. Wake up if the Timer2 buffer overflows or if you hit the button
if(show_the_time == TRUE || always_on == TRUE) {
/*Serial.print(hours, DEC);
Serial.print(":");
Serial.print(minutes, DEC);
Serial.print(":");
Serial.println(seconds, DEC);*/
showTime(); //Show the current time for a few seconds
//If you are STILL holding the button, then you must want to adjust the time
if(digitalRead(theButton) == LOW){
setTime();
}
show_the_time = FALSE; //Reset the button variable
}
}
void showTime() {
//Here is where we display the time and PWM the LEDs
//Now show the time for a certain length of time
long startTime = millis();
while( (millis() - startTime) < show_time_length) {
lightLeds();
if(display_brightness > 0){ //PWM only if brightness is not full
delayMicroseconds(display_brightness);
}
}
}
void lightLeds() {
//Turns correct outputs on
//Pin assignments
//Minutes
switch(hours) {
case 12:
digitalWrite(hour8, HIGH); // Hour is 12
digitalWrite(hour4, HIGH);
digitalWrite(hour2, LOW);
digitalWrite(hour1, LOW);
break;
// ....
case 1:
digitalWrite(hour8, LOW); // Hour is 1
digitalWrite(hour4, LOW);
digitalWrite(hour2, LOW);
digitalWrite(hour1, HIGH);
break;
}
switch(minutes){
case 59:
digitalWrite(minute32, HIGH); //Minute is 59
digitalWrite(minute16, HIGH);
digitalWrite(minute8, HIGH);
digitalWrite(minute4, LOW);
digitalWrite(minute2, HIGH);
digitalWrite(minute1, HIGH);
break;
// .....
case 1:
digitalWrite(minute32, LOW); //Minute is 1
digitalWrite(minute16, LOW);
digitalWrite(minute8, LOW);
digitalWrite(minute4, LOW);
digitalWrite(minute2, LOW);
digitalWrite(minute1, HIGH);
break;
}
if(display_brightness > 0){ //Only PWM if brightness is not full
delayMicroseconds(display_brightness);
digitalWrite(hour8, LOW); //write pins low to get "dimming" effect
digitalWrite(hour4, LOW);
digitalWrite(hour2, LOW);
digitalWrite(hour1, LOW);
digitalWrite(minute32, LOW);
digitalWrite(minute16, LOW);
digitalWrite(minute8, LOW);
digitalWrite(minute4, LOW);
digitalWrite(minute2, LOW);
digitalWrite(minute1, LOW);
}
}
Heres the problem point
//The interrupt occurs when you push the button
ISR(INT0_vect){
//When you hit the button, we will need to display the time
//if(show_the_time == FALSE)
show_the_time = TRUE;
}
If I have it just set as
ISR(INT0_vect)
The interrupt is only able to be called once or twice, then the arduino seems to not respond to the interrupt anymore.
Setting it to
ISR(EXT_INT0_vect)
seems to fix it, but then the 32khz clock doesn't "tick" forward (perhaps a bit of interrupt clashing here?)
I dont really know what is going on, I have checked most of the code but i don't get what is causing the problem.
I am just using a wire-to-ground to trigger the interrupt, maybe i need to wire in a straight button... I'm not sure. Looks and seems a bit like a debounce issue to me.
I did have to edit my code to fit into the forum, cutting out the time-setting part, and some of the comments. Just ask if you need the full deal, I kept all the loop() code in though