6/8 Buttons battery remote node
-
@carywin Certain arduinos such as the pro minis can ONLY do interrupts on pins 2 or 3 from my understanding.
@dbemowsk said in 6/8 Buttons battery remote node:
@carywin Certain arduinos such as the pro minis can ONLY do interrupts on pins 2 or 3 from my understanding.
IIRC, you can do interrupts from other pins too, but each is tied to a separate bank of pins, so you have to do additional testing to determine which specific pin triggered the interrupt. In the case of the voltage divider keypad, that should be no problem.
-
@dbemowsk said in 6/8 Buttons battery remote node:
@carywin Certain arduinos such as the pro minis can ONLY do interrupts on pins 2 or 3 from my understanding.
IIRC, you can do interrupts from other pins too, but each is tied to a separate bank of pins, so you have to do additional testing to determine which specific pin triggered the interrupt. In the case of the voltage divider keypad, that should be no problem.
Here's the link: https://playground.arduino.cc/Main/PinChangeInterrupt
So, in this scenario, it would be:
ISR (PCINT1_vect) pin change interrupt for A0 to A5 -
Here's a revision of the earlier code so that it uses ONLY ONE PIN (namely, A0) on the Arduino. And yes, this does work on a pro mini too, because that's what I tested it on. :)
// Description: // Use just A0 to process the 12 button keypad. // Button press is detected by interrupt set on A0. // Which button was pressed is determined by an analog read of A0. // Note: sleep code borrows from Nick Gammon's Schedule J // Interrupt code borrows from https://playground.arduino.cc/Main/PinChangeInterrupt #include <avr/sleep.h> void pciSetup(byte pin) { *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group } ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here { //no need to do anything beyond just waking up. } void setup() { pinMode(A0,INPUT); pciSetup(A0); Serial.begin(115200); Serial.println("Starting..."); Serial.flush(); } void loop() { uint16_t voltage; set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); // Do not interrupt before we go to sleep, or the // ISR will detach interrupts and we won't wake. noInterrupts (); pciSetup(A0); // turn off brown-out enable in software // BODS must be set to one and BODSE must be set to zero within four clock cycles MCUCR = bit (BODS) | bit (BODSE); // The BODS bit is automatically cleared after three clock cycles MCUCR = bit (BODS); // We are guaranteed that the sleep_cpu call will be done // as the processor executes the next instruction after // interrupts are turned on. interrupts (); // one cycle sleep_cpu (); // one cycle delay(20); //debounce the button voltage=analogRead(A0); //throw out this first result voltage=analogRead(A0); if (voltage>700) { Serial.println(voltage); Serial.flush(); } } -
Here's an improved sketch that gives you the number (rather than the voltage) of the button that was pressed:
// Description: // Use just A0 to process the 12 button keypad. // Button press is detected by interrupt set on A0. // Which button was pressed is determined by an analog read of A0. // Note: sleep code borrows from Nick Gammon's Schedule J // Interrupt code borrows from https://playground.arduino.cc/Main/PinChangeInterrupt #include <avr/sleep.h> int key[12][3] = { //min and max analogRead values for each key in the 3x4 keypad {0,993,1012}, {1,848,865}, {2,834,847}, {3,800,833}, {4,901,914}, {5,884,900}, {6,866,883}, {7,948,969}, {8,930,947}, {9,915,929}, {10,1013,1023}, {11,970,992} }; void pciSetup(byte pin) { *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group } ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here { //no need to do anything beyond just waking up. } int identifyKey(uint16_t voltage) { int i=0; while ((i<12) && ((voltage<key[i][1]) || (voltage>key[i][2]))) { i++; } return i; } void setup() { pinMode(A0,INPUT); pciSetup(A0); Serial.begin(115200); Serial.println("Starting..."); Serial.flush(); } void loop() { uint16_t voltage; set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); // Do not interrupt before we go to sleep, or the // ISR will detach interrupts and we won't wake. noInterrupts (); pciSetup(A0); // turn off brown-out enable in software // BODS must be set to one and BODSE must be set to zero within four clock cycles MCUCR = bit (BODS) | bit (BODSE); // The BODS bit is automatically cleared after three clock cycles MCUCR = bit (BODS); // We are guaranteed that the sleep_cpu call will be done // as the processor executes the next instruction after // interrupts are turned on. interrupts (); // one cycle sleep_cpu (); // one cycle delay(20); //debounce the button voltage=analogRead(A0); //throw out this first result voltage=analogRead(A0); if (voltage>799) { Serial.println(identifyKey(voltage)); Serial.flush(); } } -
@carywin Certain arduinos such as the pro minis can ONLY do interrupts on pins 2 or 3 from my understanding.
-
@dbemowsk said in 6/8 Buttons battery remote node:
@carywin Certain arduinos such as the pro minis can ONLY do interrupts on pins 2 or 3 from my understanding.
IIRC, you can do interrupts from other pins too, but each is tied to a separate bank of pins, so you have to do additional testing to determine which specific pin triggered the interrupt. In the case of the voltage divider keypad, that should be no problem.
-
@wes said in 6/8 Buttons battery remote node:
I'm planning to use some cheap RF remotes and connect a RF receiver to my RPI, which hosts both my gateway and controller.
I finally received the RF remotes and receiver/decoder from eBay and got them set up to talk directly to my controller - they work pretty well: https://youtu.be/9458-3IiG3Y
I did try a OneButton-type approach on a MySensors node, but had lots of malfunctions with long-presses (e.g. fade up 10% per second whilst the button is depressed), where the the "button pressed" message gets through, but the "button released" message is delayed or dropped.
-
@wes said in 6/8 Buttons battery remote node:
I'm planning to use some cheap RF remotes and connect a RF receiver to my RPI, which hosts both my gateway and controller.
I finally received the RF remotes and receiver/decoder from eBay and got them set up to talk directly to my controller - they work pretty well: https://youtu.be/9458-3IiG3Y
I did try a OneButton-type approach on a MySensors node, but had lots of malfunctions with long-presses (e.g. fade up 10% per second whilst the button is depressed), where the the "button pressed" message gets through, but the "button released" message is delayed or dropped.
@wes Maybe your resistors don't have a high enough power rating for the current that's running through them? i.e. holding down the button heats them up and therefore changes their resistance? That might explain the slowness to react as expected after the button is released. After release, they cool off and eventually return within their expected resistance tolerance, at which point the expected behavior finally happens.
-
@NeverDie do you think a NRF5x would be better solution to make a small compact remote control?
@gohan It's hard to answer a question like that in a vacuum, but in general, I do like nRF5x better than nRF24L01 beause of nRF5x's better link budget. I also like LoRa because of its great range and coverage. I have made remotes using each (and I have made posts about them), and they each have their place.