Simulateous usage of PCINT0 and TIMER0_OVF Interrupts

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So interrupts seem to be a bit simple, yet tricky.  I am trying to do something which I am not sure if it is possible.

 

So I am working with ATTiny85 and trying to use a momentary switch on PB0 (aka PCINT0) to toggle operating modes.

On PB1-PB4 I have a cheap stepper motor that I am writing to looping through states to rotate it.

 

Now two modes I am trying to work out.

   Mode 1:  Continous Stepper operation

   Mode 2:  10 mins on Stepper, 50 mins sleep.

 

Idea is using the momentary switch on PCINT0_vect to toggle modes.

 

Now - the following works in different code setups..

   1) use SLEEP_MODE_PWR_DOWN and PB0 to wake ATTiny85 ISR(PCINT0_vect)

   2) use SLEEP_MODE_IDLE to put the ATTiny85 to sleep using Timer0 overflows ISR(TIMER0_OVF_vect) and wake up after a duration of time.

 

Having problem doing the following:

   1)  Breaking out of continuous Stepper loop with PCINT0_vect -> seems to multi-trigger the interrupt like 4x which flips the mode 4x . 

             I'm wondering if this is tripping up because I am writing out PORTB for stepper, but also simultaneously using Pin Change Interrupt on PB0

   2)  Trying to break out of sleep_mode() with PCINT0_vect / Pin change on PB0 -> I'm not sure if this is possible.

            I think this is because when it is in sleep_mode using timer0 overflow interrupt .. it just isn't possible to break out with Pin Change Interrupt.

 

Or maybe simply.. I am doing too much with the same PortB and need to jump up to a bigger AVR.  I do have a few ATMega328Ps laying around that I could use too.. 

 

idk.. any thoughts here?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How are you denouncing the switch on int0?

 

also are you accidentally changing the state of the PB0 while writing to PB for the stepper motor pins, IIRC even when configured as inputs writing to the pin can trigger the pin change interrupt.

 

I am sure one of the forum experts will be along shortly to conform or reject this & probably also request some code examples

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi IPguru,

I have found code from two different use-cases and combined them..  So basically stepper would be connected to PB1-4, however for dev/test I have LED's on those ports and SW on BP0.  LED's show me digital output is working the way it should, but also at times use PB1-4 LED's to help me show where I am in my code.

 

My brain at the moment is cooked.  I've tried tweaking this a few dozen different ways..  But if I can get this working.. this would be useful in a few different use-cases.

 

#define DELAY 10 //3 lower value = higher motor speed
#define F_CPU 1000000
#include <avr/io.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>

uint8_t lookup[] = {0b10001, 0b11001, 0b01001, 0b01101, 0b00101, 0b00111, 0b00011, 0b10011}, i; //pin states packed in array because making 8 nested if-else is just awful.

uint16_t t;
volatile uint16_t cont=0; //volatile: just making sure the compiler doesn't optimize this away
unsigned char temp;
volatile uint16_t mode=1;

ISR(PCINT0_vect) {
	// Pin Change Interrupt Request 0
	if(mode==0){
		mode=1;
		PORTB = 0b01101;   //  Flipping on middle LED's to show switching to mode 1
	} else {
		mode=0;
		PORTB = 0b10011;  //  Flipping on outside LED's to show switching to mode 0
	}
	_delay_ms(2000);            // Pause so can see LEDs
	t = 25500;               // Next to lines are if button is pressed while in spin() for loops.  This basically cancel out of spin() and return to main loop.
	i = 9;
}

ISR(TIMER0_OVF_vect){
	cont++;
}

void spin()
{
	for(t = 0; t < 25000; t++){ //25000 = 10 min / (DELAY * 8) = number of cycles
		for(i = 0; i < 8; i++){ //single full-step cycle
			PORTB = lookup[i];
			_delay_ms(DELAY);
		} // cycle
	} // 10 min
	PORTB = 0b00001;
} //spin

int main(void)
{
	ADMUX = ADCSRA = 0;
	DDRB = 0b11110;           // So Setting PB0 to input and PB1-4 as outputs. 
	
	// Set PB0 as interrupt pin and pull it up
	GIMSK |= _BV(PCIE);     // Enable Pin Change Interrupts
	PCMSK |= _BV(PCINT0); // Use PB0 as interrupt pin
	PORTB = _BV(PB0);        // So I need to pull-up PB0

	// Setup Timer Overflow Interrupt
	ACSR = 0b10000000;
	set_sleep_mode(SLEEP_MODE_IDLE);
	TIMSK |= 1<<TOIE0; //overflow interrupt
	
	sei();  // Enable Interrupts

	while (1)
	{
		TCCR0B = 0;           //timer0 stopped
		PRR = 0b00001111;     //disable timer0
		
		spin();               //Spin Stepper for 10 minutes.  If Mode 0 then while loop will keep executing spin() continuously until interrupted by PB0 SW
		
		if(mode==1){                // Mode 1 Cycle is Spin Stepper 10 min then Sleep 50 min;  Mode 2 Cycle is Spin Stepper continuously
			PORTB = 0b11111;    //  Flash All pins PB1-4 Also connected to LEDs..  So I can see it made it to this point
			_delay_ms(2000);    // Just keep ALL LED's lit for a few seconds so I don't miss it.
			PORTB = 0b00001;    //  ok PB1-4 off
			PRR = 0b00001011;   //  enable timer0
			TCCR0B |= 1<<CS02 | 1<<CS00; //1024 prescaler
			cont = 0;          // Init Loop var
			do{
				sleep_mode();  // go back to sleep
			}while(cont < 200);    //11444: number of timer0 overflows @1024 prescaling to wait 50 minutes ** Setting this to a 200 for few minutes for testing.
		} // mode
	} // while
} // main

 

Last Edited: Sat. Feb 11, 2017 - 03:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Weird - the code in the last reply is actually indented, etc.  When I go back to edit it.. it shows up as indented..  Not sure why it is showing up so flat in the thread.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not sure why it is showing up so flat in the thread.

Because you didn't use the CODE button <> to post your code.

How are you denouncing the switch on int0

Maybe he'll use a lawyer....wink

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Because you didn't use the magic <> button. Look in the toolbar when you edit.

 

It's a bad idea to use pushbutton switches on interrupts - switch bounce notwithstanding. Use interrupts if you want to wake the processor or act on microsecond scale events. A pushbutton only happens 20 times a seconds max. You've got a timer overflow isr - read the switch in that, debounce and set/clear the var the tells the rest of the code the button was pressed.

Using for() loops for timing delays is also bad - the optimiser tends to get rid of them. Use timers (preferred) or the _delay functions supplied in the compiler libraries.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:

How are you denouncing the switch on int0

Maybe he'll use a lawyer....wink

damn thought i had corrected that auto-correct :-(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found the magic <code> button :P  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman - Thanks so much for your insight.  Although I have alot of background from my CompEng in College, it's not my day job and moreover am a hobbyist.  That being said... it's been a long week at work. I should have realized what you said.  But instead.. I found myself more staring at the code.. What I should have done is pulled myself up at 50k view.. and realizing what is going on.  Back in the day I used one-shot monostable vibrator circuits on input push buttons to keep things from going crazy on triggers.  It is starting to come back to me now.  LOL - when I say 'back in the day'.. that is prior to microcontrollers and where Linux was ~50 floppy disks of Slackware..

 

Thanks again

-dt

Last Edited: Sat. Feb 11, 2017 - 03:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yeah - that made me laugh too.  LOL I shall denounce that damn switch on int0 :P

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Microcontrollers were around a lot longer before Linux - microcontrollers - 70's, Linux - 90's! 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No kidding.  In college years back in early 90's we were building up TTL based circuits, working on ASICS, FPGAs, VLSI, and Computer Architecture.  For me it wasn't until '95 until I dove into Microchip PIC and MPASM and then later with some M68HC11 stuff.  And I still have my old PICSTART 16B1 DEV board.  moreover as a fun antique than anything.