Author Topic: attachinterrupt not working on ATTiny85  (Read 1086 times)

0 Members and 1 Guest are viewing this topic.

Offline paul_g_787Topic starter

  • Frequent Contributor
  • **
  • Posts: 489
  • Country: gb
attachinterrupt not working on ATTiny85
« on: June 20, 2022, 08:36:57 pm »
Hey. I am hoping someone can help me as I am completely stuck with this problem on the ATTiny85 in the Arduino IDE.

I have built a DIY Xbox 360 USB receiver:
https://techocd.blogspot.com/2014/01/xbox-360-wireless-controller-to-pc-via.html

I have this working great using my Arduino UNO!!! On the UNO this code works perfectly fine.

So now I am trying to slim the device down by using an STTiny85 instead of an Arduino UNO. But I keep getting this error (see attached image).

I have found a few posts online that mention the ATTiny85 does not support attachInterrupt or detachInterrupt. However I cannot find a simple way to replace this part of the code to work with the ATTiny.

Could anyone help me to get this code to work on the ATTIny85?

Here is the code:
The problem is in the function  sleepNow

Code: [Select]
/* Arduino code to communicate with xbox 360 RF module.
Original work by (yaywoop) / additional ideas from Alexander Martinez - modified by dilandou ([url=http://www.dilandou.com]www.dilandou.com[/url], [url=http://www.diru.org/wordpress]www.diru.org/wordpress[/url])
First sends LED initialisation code followed by LED startup animation code, then sleeps until a button press for sync command.
RF module must be powered with 3.3V, two diodes in series with USB 5v will do. Connect the USB wires to a host computer, and the data and serial wires to Arduino.
of course, make sure to have a common ground */

#include <avr/sleep.h>

#define sync_pin 2 //power button repurposed for sync button (pin 5 on the module)
#define data_pin 1 //data line (pin 6 on the module)
#define clock_pin 0 //clock line (pin 7 on module)

int led_cmd[10] =  {0,0,1,0,0,0,0,1,0,0}; //Activates/initialises the LEDs, leaving the center LED lit.
int anim_cmd[10] = {0,0,1,0,0,0,0,1,0,1}; //Makes the startup animation on the ring of light.
int sync_cmd[10] = {0,0,0,0,0,0,0,1,0,0}; //Initiates the sync process.
volatile boolean sync_enable = 0;

void sendData(int cmd_do[]) {
  pinMode(data_pin, OUTPUT);
  digitalWrite(data_pin, LOW);    //start sending data.
  int prev = 1;
  for(int i = 0; i < 10; i++){

    while (prev == digitalRead(clock_pin)){} //detects change in clock
    prev = digitalRead(clock_pin);
      // should be after downward edge of clock, so send bit of data now
    digitalWrite(data_pin, cmd_do[i]);

    while (prev == digitalRead(clock_pin)){} //detects upward edge of clock
    prev = digitalRead(clock_pin);
  }
  digitalWrite(data_pin, HIGH);
  pinMode(data_pin, INPUT);
}

void initLEDs(){
sendData(led_cmd);
delay(50);
sendData(anim_cmd);
delay(50);
}

void wakeUp(){
  sync_enable = 1;
}

void sleepNow() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set sleep mode
  sleep_enable(); //enable sleep bit
  attachInterrupt(0, wakeUp, LOW);
  sleep_mode();
  sleep_disable(); //disable sleep bit
  detachInterrupt(0); // disables interrupt 0 on pin 2
}

void setup() {
  //Serial.begin(9600);
  pinMode(sync_pin, INPUT);
  digitalWrite(sync_pin,HIGH);
  pinMode(data_pin, INPUT);
  pinMode(clock_pin, INPUT);
  delay(2000);

  initLEDs();
//  sendData(sync_cmd);
}

void loop(){
  //Serial.println("Sleeping.");
  sleepNow();
  delay(200);
  if(sync_enable==1) {
    //Serial.println("Syncing.");
    sendData(sync_cmd);
    sync_enable = 0;
  }
}
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: attachinterrupt not working on ATTiny85
« Reply #1 on: June 21, 2022, 01:17:03 am »
I do not know Arduino, but you are getting an ISR created that does not exist for your mcu. Comment out the second line below (WInterrupts.c) so the macro does not creat an ISR for INT1_vect.
Code: [Select]
#else

IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)

I would assume there is a 'special' version of arduino for a tiny85 that specifically deals with its hardware, but the above fix may be fine.
 

Offline floobydust

  • Super Contributor
  • ***
  • Posts: 6995
  • Country: ca
Re: attachinterrupt not working on ATTiny85
« Reply #2 on: June 21, 2022, 02:00:46 am »
I have these snippets of my ATtiny85 and '328 sleep code from years ago. I never use "attach interrupt", just the reserved labels for them. Note for min. current draw I had to shut off the A/D and BOD. The code is not pretty but works. Wakes up due to a pin (ignition key or pushbutton) interrrupt. I was testing on '328 Uno and the final H/W is Tiny 85, so I left both MCU-specific routines in the source, just commented it out as not needed.
Code: [Select]
//------------------------------------------------------------------------
void SleepSession328(void) {
   // http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
   // configure and enter sleep mode, only pin change interrupt (ign switch or pushbutton press) wakes us
   ADCSRA &= ~(1 << ADEN); // shutoff ADC
   MCUCR |= (1 << BODS); // disable BOD 328P only, override fuses for sleep
   // config and enable pin-change interrupts
   cli(); // disable global interrupts as we are reconfiguring them
   PCMSK2 |= (1 << PCINT21) | (1 << PCINT23); // unmask pin-change int for D5, D7- the switch inputs
   PCIFR &= ~(1 << PCIF2); // clear flag for any outstanding pin-change interrupt 2 flag PCINT[23:16] for D0-D7
   PCICR |= (1 << PCIE2); // enable pin-change interrupt group2
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   sleep_enable();
   // sleep_bod_disable(); // time limited, have to try
   sei();        // re-enable global interrupts, sleep is set up now
   DEBUG_PRINTLN("** SLEEP **"); delay(100); // to empty serial buffer
   sleep_cpu();  // go to sleep
   //----------------------  W A K E  ---------
   /* Upon waking, the program will continue from here. */
   sleep_disable();       // now that we've woken up, stay up; 
   // BOD is automatically turned on after sleep,, A/D left off
   PCICR &= ~(1 << PCIE2); // disable pin-change interrupt group2, left pcmsk alone
   DEBUG_PRINTLN("** WAKE **");
}
//------------------------------------------------------------------------
void  SleepSession(void) {  // Tiny85
   // http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
  // configure and enter sleep mode, only pin change interrupt (ign switch or pushbutton press) wakes us
  ADCSRA &= ~(1 << ADEN); // shutoff ADC if it was on and save power ~0.3mA at 5V;
  // not sure if BOD (fuse) is used, analog comparator if used may need to disconnect too to save power.

  // config and enable pin-change interrupts
  cli(); // disable global interrupts as we are reconfiguring them
  PCMSK = 0b00011000;    // allow pin-change interrupts on pins PB3, PB4- the switch inputs; Interrupt unmask
  GIMSK |= (1 << PCIE);  // enable pin-change interrupts; Interrupt source
  // not sure if timer interrupts happenin on Arduino with Attiny85

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  // sleep_bod_disable(); // time limited, have to try
  sei();        // re-enable global interrupts, sleep is set up now
  //state = sSLEEPING;
  DEBUG_PRINTLN("** SLEEP **"); delay(100); // to empty serial buffer
  sleep_cpu();  // go to sleep
 
  //----------------------  W A K E  ---------
  // Upon waking due to Pin Change Interrupt, program execution will continue from here.
  sleep_disable();       // now that we've woken up, stay up;
  // disable further pin-change interrupts, so no spurious interrupt
  GIMSK &= ~(1 << PCIE);  // turn off pin-change interrupts off
  DEBUG_PRINTLN("** WAKE **");
}

//------------------------------------------------------------------------
ISR (PCINT0_vect) { // Pin Change Interrupt for Tiny85
// GIFR automatically cleared here; hope timers don't use them
//clear the pin change interrupt, good to wake and run now; or no change if spurious interrupt
// do nothing here, other than wake up and resume Main
// old code: GIMSK &= ~(1 << PCIE);  // We are awake, no more Pin Change interrupts; mask them off
}
//------------------------------------------------------------------------
ISR (PCINT2_vect) { // '328 Uno Pin Change Interrupt for D0-D7
// GIFR automatically cleared here; hope timers don't use them
//clear the pin change interrupt, good to wake and run now; or no change if spurious interrupt
// do nothing here, other than wake up and resume Main
// old GIMSK &= ~(1 << PCIE);  // We are awake, no more Pin Change interrupts; mask them off
// who woke us up?
   ign.wake = digitalRead(IgnSwitchPin); //
   PB.wake  = !digitalRead(Power_ButtonPin); //
}
« Last Edit: June 21, 2022, 02:08:36 am by floobydust »
 

Offline paul_g_787Topic starter

  • Frequent Contributor
  • **
  • Posts: 489
  • Country: gb
Re: attachinterrupt not working on ATTiny85
« Reply #3 on: June 21, 2022, 02:14:22 pm »
I do not know Arduino, but you are getting an ISR created that does not exist for your mcu. Comment out the second line below (WInterrupts.c) so the macro does not creat an ISR for INT1_vect.
Code: [Select]
#else

IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)

I would assume there is a 'special' version of arduino for a tiny85 that specifically deals with its hardware, but the above fix may be fine.

I commented out that line as you said and it solved my error, but now I have another error (see screenshot).

it says attachInterrupt / detachInterrupt may need some more work for this CPU (case 1)
 

Offline paul_g_787Topic starter

  • Frequent Contributor
  • **
  • Posts: 489
  • Country: gb
Re: attachinterrupt not working on ATTiny85
« Reply #4 on: June 21, 2022, 02:53:19 pm »
Alright it seems to work fine regardless of that final error??

I have just tested the device and it is working great now!

Attached an image of the modded board. Just plug it into USB and install the official Microsoft Driver. Press button to pair controllers. It works with up to 4 controllers.

The ATTiny85 is just listening for the button press (blue wire) and sending the pairing command via serial (yellow wire data, brown wire clock) to the board to make it go into pairing mode.
And the code also sends the startup LED animation command at power-up yo make it mimic the Xbox 360 power up sequence.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: attachinterrupt not working on ATTiny85
« Reply #5 on: June 21, 2022, 04:53:49 pm »
Quote
but now I have another error
If you look at the code where the error says there is a problem, it shows they assume the mcu has an INT1 so although the warning is harmless you could simply do as they do for the INT2 case and change-
Code: [Select]
    #else
      #warning detachInterrupt may need some more work for this cpu (case 1)
to
Code: [Select]
    #elif defined(INT1)
      #warning detachInterrupt may need some more work for this cpu (case 1)
There is also a 'EXTERNAL_NUM_INTERRUPTS' define which defaults to 2 which could also be changed to suit the tiny85. Also harmless until you try to use '1' for attachInterrupt, Eventually if you use the tiny85 for more things, you may want to look into getting a version specifically for a tiny85 series, which I assume there is.
 

Offline paul_g_787Topic starter

  • Frequent Contributor
  • **
  • Posts: 489
  • Country: gb
Re: attachinterrupt not working on ATTiny85
« Reply #6 on: June 21, 2022, 06:06:14 pm »
For those interested here is a quick schematic of my mod board and the pinout diagram from the internet.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf