Hi all,
I've got a small circuit with a joystick and button attached. I've got a PCINT on 2 Analog pins (for the joystick) and one digital (for the button) and a dummy program that just prints the joystick values to Serial on each interrupt.
It "half works"
The button causes a PCINT every time but the Joystick only causes an interrupt when I move it in the "increase" direction.
That is:
Joystick centered and force interrupt via the button gives me 333, 327.
If I push the joy down I get an interrupt and 331, 660
If I push the joy left I get and interrupt and 607, 326
But if I push the joy up: no interrupt so I push the button to force one and I get 331, 0 (roughly expected values)
If I push the joy right: no interrupt. If I force one with the button: 0, 326 (again, what I expect)
(I also get a second interrupt when the joy goes back from down to center and left to center)
I've tried searching about reliability of PCINT on analog pins but haven't found anything useful.
Any suggestions ?
In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless
If the code exceeds the 9000 character inline limit then attach it to a post
Thanks. I didn't think the sketch was relevant - it is doing everything I expect except triggering interrupts when the joystick moves in certain ways.
I'll trim down the sketch and post the minimal code to demo the issue.
Minimal code to reproduce.
Note if I use 3.3V I get the reproducible behavior described above.
If I use 5V the interrupt triggering for the joystick is different. If I push up once and return to center I get 1 interrupt - pushing up again won't trigger another PCINT but then pushing down (and back to center) gets one interrupt.. I can't get another down interrupt but pushing up will trigger an interrupt again.
#include <avr/sleep.h>
// ISR for analog pins
ISR(PCINT1_vect)
{
}
// ISR for digital pins
ISR(PCINT2_vect)
{
}
//
// Both ISRs do nothing. They just allow the code to wakeup.
//
void setup() {
Serial.begin(9600);
Serial.println("Started");
// pin3 is DCINT19. It Has button connected to trigger PCINT
pinMode(3, INPUT_PULLUP);
// PCICR bit PCIE2 gets us pins D0-D7
PCICR |= 0x04;
// bit PCIE1 for analog inputs
PCICR |= 0x02;
// PCMSK2 bit 3 = PCINT19 = D3
PCMSK2 |= 0x08;
// PCMSK1 bit 0 is a0, bit 1 is a1
PCMSK1 |= 0x03;
delay(500);
}
void loop() {
Serial.println("top of loop()");
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
// Now we're asleep. When an interrupt is triggered we should wake and carry on from here
// disable interrupts (interferes with serial comms)
// cli();
sleep_disable();
int x = analogRead(0);
int y = analogRead(1);
Serial.println(String(x) + ", " + String(y));
delay(200);
// enable interrups
// sei();
}
JCA34F:
Pin Change Interrupts work on digital pins, Which Arduino?
Uno.
All the docs I found says it works on analog or digital pins. I'm wondering if there is some kind of threshold that needs to be set so it knows how much change on an analog pin is required to trigger a PCINT.
I'm a software guy not a hardware guy so don't laugh too hard.
Thinking out loud: can I somehow convert the analog signal into a digital one. e.g. I get a known state (high or low) when the analog voltage is say <1 or > 4. Alternatively 2 digital ones: one for "joy=high" and one for "joy=low".
Answering my own question incase it is of use to anyone else. You can use a voltage comparator. I've done a proof of concept with an LM339.
Basically if one identified input (inverting) is greater than the other then the output goes to ground (else it is floating).
You can use a couple of resistors to do a voltage divider to get a reference voltage.
Pot -> inverting input. Reference (say 4.5 v) to other input: Output goes to GND if pot > 4.5
Reference (say 0.5v) to inverting. Pot to other. Output goes to GND if 0.5 > Pot (aka Pot < 0.5)
Comparators are very handy - you often see beginners struggling without realizing
such components exist and are often the perfect answer! You can think of them as
very fast programmable 1-bit ADCs if you want, but that misses out the hysteresis
that's often needed in practice for clean switching.
Some microcontrollers have built-in comparator(s). Hint.