Pages: 1 2 [3]   Go Down
Author Topic: Timer2 Interrups REFUSE to work! :(  (Read 5220 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

These ones, according to my fuse calculator sketch:

Code:
Atmega fuse calculator.
Written by Nick Gammon.
Entered programming mode OK.
Signature = 0x1E 0x95 0x0F
Processor = ATmega328P
Flash memory size = 32768
LFuse = 0xE2
HFuse = 0xDA
EFuse = 0xFD
Lock byte = 0xEF
Clock calibration = 0x85
External Reset Disable.................. [ ]
Debug Wire Enable....................... [ ]
Enable Serial (ICSP) Programming........ [X]
Watchdog Timer Always On................ [ ]
Preserve EEPROM through chip erase...... [ ]
Boot into bootloader.................... [X]
Divide clock by 8....................... [ ]
Clock output............................ [ ]
Bootloader size: 2048 bytes.
Start-up time: SUT0: [X]  SUT1: [ ] (see datasheet)
Clock source: calibrated internal oscillator.
Brownout detection at: 2.7V.


Logged


Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My gosh I dont have clue what is up with this stupid timer2.

I have discarded the interrupts for now. It seems it is a different problem.

After uploading an Arduino Pro 8mhz bootloader to the chip, the LED blinks at around 1/2 second pulses (using an UNO board). Going into AVR studio, apparently this sets the fuses to select the crystal on the board as oscillator. Change that to internal, and the LED blinks every second.

However, it seems not to use timer2 whatsoever. Nada. Zilch. And I have no idea why it simply refuses to use any timer asynchronously. Everything seems to base off the internal timer- wther or not there is a timer connected to the TOSC pins or not.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you show a photo of your setup? And your current code.
Logged


Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4092
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I did a project a while back that has some similar features, namely clocking Timer2 from a 32.768kHz crystal, generating an interrupt every 8 seconds, and sleeping in between interrupts:
http://adventuresinarduinoland.blogspot.com/2012/02/high-tech-night-light.html

Code and schematic are on github, see link at the end of the post.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, my setup

I am using an arduino Uno, connected via ICSP to an Amtel MKII programmer (clone) (I should note that the clone seems to work perfectly).

(also, sorry for the blurrycam photos and jumbled wiring. Using a cell phone and the wiring, though jumbled, is working)

Ignore the chip in the breadboard too- that one is fried. Just using it to show the pinout of things. At the moment I am just trying to get this to work on the UNO board before moving to a breadboard

The code i am using is the code you posted on the last page.
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

const byte LED = 8;

//The very important 32.686kHz interrupt handler
ISR (TIMER2_OVF_vect)
{
}

//The interrupt occurs when you push the button
void buttonPress (void)
{
}

void setup()
  {                
  pinMode (LED, OUTPUT);  
  digitalWrite (2, HIGH);  // pull-up

  //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

  attachInterrupt (0, buttonPress, FALLING);
  }

void loop()
  {
  digitalWrite (LED, LOW);
  sleep_mode();   //  Stop everything and go to sleep. Wake up if the Timer2 buffer overflows or if you hit the button
  digitalWrite (LED, HIGH);  
  }

Running that on the UNO seems to work- as long as you are not running off the internal oscillator.


As for the chip itself, I have attached a photo of what the fuse settings are (currently). At this time I was trying a different bootloader which is why the bootloader fuse size is kinda off. Re-burning it to UNO bootloader.Have tried with UNO bootloader, Pro 8mhz bootloader, etc, with and without changing fuse settings to internal oscillator


* photo1.JPG (2110.94 KB, 3264x2448 - viewed 50 times.)

* Screen Shot 2012-10-07 at 2.13.39 PM.png (87.09 KB, 480x552 - viewed 41 times.)
« Last Edit: October 07, 2012, 03:21:26 pm by astroboy907 » Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Last photo, dang forum limitations smiley


* photo.JPG (2675.01 KB, 3264x2448 - viewed 43 times.)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ignore the chip in the breadboard too- that one is fried. Just using it to show the pinout of things. At the moment I am just trying to get this to work on the UNO board before moving to a breadboard

I'm confused now. You aren't using the breadboard? So the point of that photo is?

Quote
At the moment I am just trying to get this to work on the UNO board before moving to a breadboard ...

So we can discard the breadboard, and you are talking about getting the Timer2 to work on a Uno? With or without the 32 KHz crystal?

Quote
Everything seems to base off the internal timer- wther or not there is a timer connected to the TOSC pins or not.

How would you get to those pins on the Uno?
Logged


Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Aha! Finally something...
To test to see if I could actually count using the interrupt, I tried this sketch:
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

const byte LED = 8;
long time;

//The very important 32.686kHz interrupt handler
ISR (TIMER2_OVF_vect)
{time++;}

//The interrupt occurs when you push the button
void buttonPress (void)
{
}

void setup()
  {      
time = 0;    
  pinMode (LED, OUTPUT);  
  digitalWrite (2, HIGH);  // pull-up

  //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
    
    
  attachInterrupt (0, buttonPress, FALLING);
  }

void loop()
  {
  digitalWrite (LED, LOW);
  delay(time);
  sleep_mode();   //  Stop everything and go to sleep. Wake up if the Timer2 buffer overflows or if you hit the button
  digitalWrite (LED, HIGH);  
  delay(time);
  }

An LED on pin 8 blinked really quickly than slowed.

So this proves that the timer is interrupting, however, this was done with the fuses set as
Extended : 0xFE
High : 0xD6
Low : 0xFF (external 8 mHz oscillator)

Edit: To Nick
Sorry, my prototyping process is a bit edgy at the moment. I have not really had any experience actually trying to, well, /professionally/ prototype something.
I am simply using the breadboard to test things I cannot on the UNO board (example, taking off the oscillator, or trying a different speed crystal).

Actually... well, now I see some of my mistakes... Im just gonna move the whole thing to a breadboard and wire up ICSP to that. I have a 16mhz crystal so I can upload fine using ICSP...
The final product I want is an arduino chip that has an RTC running off Timer2 interrupts, whilst using the internal oscillator to run code that the interrupt will eventually trigger
« Last Edit: October 07, 2012, 03:55:20 pm by astroboy907 » Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Whole thing is on a breadboard, still nothing. Asking around for some new chips, etc. IDK whats wrong with this..


-My internal timer seems to work, I can do LED stuff and the timing works without a crystal
-Interrupts *seem* to work when I have the fuses set to use an EXTERNAL oscillator

So I think perhaps something is up when the chip goes into asynchronous timer mode. I'm guessing somehow my chip doesnt get there.

Only think i can find different between your chips and mine in terms of fuses is the clock calibration fuse, which I don't exactly know what that is...
Oh, one more thing, what bootloader did you format your chips on before doing this?
I know this is a pretty weird problem, and I hate to spend a lot of your time on it, but any help would be appreciated greatly.
Thanks!!
« Last Edit: October 08, 2012, 11:06:18 pm by astroboy907 » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't really "format" a chip with a bootloader. I personally just uploaded the sketch, I think (it was 19th September) by using my "sketch uploader" here:

http://www.gammon.com.au/forum/?id=11638

Or maybe it had a bootloader on it. The important thing is, you get your sketch into "low" program memory (where sketches normally go).

If you replicate what I had here:



It should work. Judging by what I posted further up:

Code:
Atmega fuse calculator.
Written by Nick Gammon.
Entered programming mode OK.
Signature = 0x1E 0x95 0x0F
Processor = ATmega328P
Flash memory size = 32768
LFuse = 0xE2
HFuse = 0xDA
EFuse = 0xFD
Lock byte = 0xEF
Clock calibration = 0x85
External Reset Disable.................. [ ]
Debug Wire Enable....................... [ ]
Enable Serial (ICSP) Programming........ [X]
Watchdog Timer Always On................ [ ]
Preserve EEPROM through chip erase...... [ ]
Boot into bootloader.................... [X]
Divide clock by 8....................... [ ]
Clock output............................ [ ]
Bootloader size: 2048 bytes.
Start-up time: SUT0: [X]  SUT1: [ ] (see datasheet)
Clock source: calibrated internal oscillator.
Brownout detection at: 2.7V.

The chip had a bootloader on it, and the fuses are as stated there.

Quote
-Interrupts *seem* to work when I have the fuses set to use an EXTERNAL oscillator

I think you are getting confused. Interrupts work, whether or not you are using the external oscillator.
Logged


Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

FINALLY!!!!!! I dont know exactly what I did, but it works. Odd.
I think I basically had to set the fuses to use the internal oscillator, then proceed to burn a bootloader that makes use of the internal oscillator (I just used the stock "Arduino on a breadboard option")
From there I uploaded the sketch, and it worked

Still not verifying that was exactly what I did, I was basically just messing around, trying to get ANYTHING to work on the chip.

Working on debugging my code currently. It works for the mostpart but by button interrupt stops working after it is used 3 times... Weird.

Thanks so much for your help!!!!

* IMG_1277.MOV (461.3 KB - downloaded 22 times.)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks good, glad it's working now.
Logged


Offline Offline
Newbie
*
Karma: 1
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
Code:
//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
Code:
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
Code:
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
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just use attachInterrupt. You don't need to muck around with ISR(blah) and doing it all yourself. It just gets confusing.

I wouldn't be doing this:

Code:
  Serial.println("Hola!!");

That's likely to be generating interrupts.
Logged


Global Moderator
Offline Offline
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

http://www.gammon.com.au/interrupts
Logged


Pages: 1 2 [3]   Go Up
Jump to: