Thank you for your great advices. I tried the analogComp library without success. I read differents informations and wasn't sure if AIN0 and AIN1 are tied to either D6 and D7 or A6 and A7 on the atmega 328p. According to the datasheet, I think it is the analog ports. Anyway, even if I don't add any wires, by activating the ACSR flag the interrupt is always triggered (#), like so (I reversed Up and Down values from the initial code):
SLEEP
*###########Right (381;513)
**##########Down (518;513)
*##########Up (518;519)
##########Left (518;513)
##########Up (518;513)
##########Left (518;513)
##########Up (518;513)
*##########Right (518;513)
**##########Down (518;513)
##########Down (518;513)
**##########Right (518;513)
**##########Down (517;513)
*
SLEEP
Unfortunatly, the analog compare interrupt is only triggered when the IC is awake. This is the (stripped) code with ACSR enabled;
#include <avr/sleep.h>
const byte XPIN = A1;
const byte YPIN = A2;
const byte CPIN = A3;
const unsigned int wakeTimeout = 5000;
unsigned long previousWakeTimeout;
ISR (PCINT1_vect) { sleep_disable(); Serial.print("*"); } // handle pin change interrupt for A0 to A5
ISR (ANALOG_COMP_vect) { sleep_disable(); Serial.print("#"); }
void setup ()
{
Serial.begin(9600); delay(100);
pinMode(XPIN, INPUT);
pinMode(YPIN, INPUT);
pinMode(CPIN, INPUT);
//Disable the digital input buffers to avoid excessive current at midrange signal levels
DIDR1 = (1<<AIN1D) | (1<<AIN0D);
// Setup the voltage comparator
ACSR =
(0<<ACD) | // Analog Comparator: Enabled
(1<<ACI) | // Analog Comparator Interrupt Flag: Clear Pending Interrupt
(1<<ACIE); //| // Analog Comparator Interrupt: Enabled
/*
(0<<ACBG) | // Analog Comparator Bandgap Select: AIN0 is applied to the positive input
(0<<ACO) | // Analog Comparator Output: Off
(0<<ACIC) | // Analog Comparator Input Capture: Disabled
(1<<ACIS1) | (1<ACIS0); // Analog Comparator Interrupt Mode: Comparator Interrupt on Rising Output Edge
*/
PCMSK1=(1<<PCINT9)|(1<<PCINT10)|(1<<PCINT11); //add interrupt of pins A1, A2, A3
PCIFR|= bit (PCIF1); // clear any outstanding interrupts
PCICR|= bit (PCIE1); // enable pin change interrupts for A0 to A5
Serial.print("Idle x;y value: ("); Serial.print(analogRead(XPIN)); Serial.print(";"); Serial.print(analogRead(YPIN)); Serial.println(")");
}
void loop ()
{
if (millis() - previousWakeTimeout >= wakeTimeout)
{
previousWakeTimeout = millis();
Serial.println(""); Serial.println("SLEEP"); delay(50);
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_mode ();
}
readInput();
}
void readInput()
{
if (digitalRead(CPIN) == 0) { rf_sendString("Click"); }
else if (analogRead(YPIN) > 700) { rf_sendString("Up"); }
else if (analogRead(YPIN) < 400) { rf_sendString("Down"); }
else if (analogRead(XPIN) > 700) { rf_sendString("Left"); }
else if (analogRead(XPIN) < 400) { rf_sendString("Right"); }
}
void rf_sendString(char str[10])
{
previousWakeTimeout = millis();
Serial.print(str);
Serial.print(" ("); Serial.print(analogRead(XPIN)); Serial.print(";"); Serial.print(analogRead(YPIN)); Serial.println(")");
delay(100);
}
Finally, I noticed that:
XPIN + GND = Right + *Interrupt
XPIN + VCC = Left
YPIN + GND = Down + *Interrupt
YPIN + VCC = Up
When enabled, altough the analog comparator is triggered everytime, it won't get the IC out of sleep. I also tried to power the joystick with an external source and it did not help. Worst case scenario, I'll add a tilt switch. But I would really like to get it to work properly, or at least understand what is going on!
EDIT: I found out that
When the arduino is in SLEEP_MODE_PWR_DOWN the only way to wake it is with either a watchdog timer interrupt, a level interrupt on pins 2 or 3, or a Pin Change interrupt (see ATmega328 datasheet Table 10-1, including note 3, on pg. 38).
(Arduino Playground - HomePage)
and
AC can be a wake up source in idle mode by generating an interrupt.
(http://www.avrfreaks.net/forum/analog-comparator-wakeup-source)
So in the end the best solution might be to add a watdog interrupt to wake the arduino 10 times a second or so.. What do you think?