I have the NeoKey hooked up to a D1 Mini clone. I am wanting to be able to send MQTT topics based on what key was pressed (and eventually if it was single-tapped, double-tapped, or held) as well as light up the pixels based on MQTT messages it receives. (tied back to Home Assistant as a macro keyboard)
1) My main issue is that it spews MQTT messages when the button is pressed for however long the button is pressed, based on the loop timing. I am looking for it to send a single MQTT message when the key is tapped, and eventually a single MQTT message when tapped, double-tapped, or held.
2) I cant seem to figure out how to have it listen for a color via payload, I think it has something to do with however MQTT packets are coded. Pretty much I am looking to be able to send it "red" or "FF0000" for instance.
I tried a few things. For instance button A sends a bunch of MQTT messages, then HA sends a message to light it red, HA waits 5 seconds, then HA commands the light off. That part works, but again, trying to make it send a single message.
Button B doesnt like anything I send as a payload, it seems to convert it to a brightness of blue or greenish.
Button C I tried making it differentiate between short and long press, but neither works.
Any pointers?
Code attached
NeoKey 1x4, i2c to mqtt, single shot?
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
-
- Posts: 64
- Joined: Mon Jan 05, 2015 10:34 am
NeoKey 1x4, i2c to mqtt, single shot?
- Attachments
-
[The extension ino has been deactivated and can no longer be displayed.]
- dastels
- Posts: 15667
- Joined: Tue Oct 20, 2015 3:22 pm
Re: NeoKey 1x4, i2c to mqtt, single shot?
For the buttons you need something like https://www.arduino.cc/reference/en/libraries/bounce2/ that well let you recognize the press/release edges. Alas that library only works with direct I/O pins. You could subclass Bounce, passing it a pointer to a predicate function and overriding readCurrentState to call that function (rather than reading in input pin). The function would read the NeoKey and pick out the key it's responsible for. I'll get a NeoKey and have a go at it.
Dave
Dave
- dastels
- Posts: 15667
- Joined: Tue Oct 20, 2015 3:22 pm
Re: NeoKey 1x4, i2c to mqtt, single shot?
How's this look for an example:
The updated Bounce2 library is here: https://github.com/dastels/Bounce2
Dave
Code: Select all
/*
DESCRIPTION
====================
Simple example of the Bounce library using the Adafruit NeoKey 1x4 that switches a LED when
a the corresponding key state change (from HIGH to LOW) is triggered (for example when a button is pressed).
*/
#include <Bounce2.h>
#include "Adafruit_NeoKey_1x4.h"
#include "seesaw_neopixel.h"
Adafruit_NeoKey_1x4 neokey;
bool key_A_predicate()
{
return neokey.read() & 0x01;
}
bool key_B_predicate()
{
return neokey.read() & 0x02;
}
bool key_C_predicate()
{
return neokey.read() & 0x04;
}
bool key_D_predicate()
{
return neokey.read() & 0x08;
}
// instantiate the PrediateDebouncer objects
PredicateDebouncer debouncers[4] = { PredicateDebouncer(&key_A_predicate, 5),
PredicateDebouncer(&key_B_predicate, 5),
PredicateDebouncer(&key_C_predicate, 5),
PredicateDebouncer(&key_D_predicate, 5) };
// set a variable to store the led states
int led_states[4] = {LOW, LOW, LOW, LOW};
void setup() {
Serial.begin(9600);
while (!Serial) {
delay(10);
}
Serial.println("Setup started");
if (!neokey.begin(0x30)) { // start matrix
Serial.println("Could not start NeoKeys, check wiring?");
while(1) {
delay(10);
}
}
Serial.println("NeoKey started!");
// led setup
for (uint16_t i = 0; i < 4; i++) {
neokey.pixels.setPixelColor(i, 0x0000FF);
neokey.pixels.show();
delay(100);
neokey.pixels.setPixelColor(i, 0x000000);
neokey.pixels.show();
delay(100);
}
Serial.println("Setup finished");
}
void loop() {
// Update the Bounce instance (you must do this every loop)
for (uint8_t i = 0; i < 4; i++) {
debouncers[i].update();
}
for (uint8_t i = 0; i < 4; i++) {
if (debouncers[i].rose()) {
Serial.print(i);
Serial.println(" was pressed");
uint32_t pixel_colour = neokey.pixels.getPixelColor(i);
neokey.pixels.setPixelColor(i, pixel_colour ^ 0xFF0000); // write the new led state
neokey.pixels.show();
}
}
}
Dave
-
- Posts: 64
- Joined: Mon Jan 05, 2015 10:34 am
Re: NeoKey 1x4, i2c to mqtt, single shot?
That gives me one helluva good start!
Thank you!
I will combine this into my code and go from there.
Thank you!
I will combine this into my code and go from there.
- dastels
- Posts: 15667
- Joined: Tue Oct 20, 2015 3:22 pm
Re: NeoKey 1x4, i2c to mqtt, single shot?
The repo you can drop into the libraries directory in your sketch directory and it will just get pulled in as normal.
The callbacks are another way you might be able to do what you're doing.
Dave
The callbacks are another way you might be able to do what you're doing.
Dave
-
- Posts: 64
- Joined: Mon Jan 05, 2015 10:34 am
Re: NeoKey 1x4, i2c to mqtt, single shot?
Got this far, it took me too long to remember how to go from uint8_t to char...
MQTT seems to be working both directions.
Now to figure out how to "long press", but this will work for now, I will reply back with any improvements.
Code: Select all
// Update the Bounce instance (you must do this every loop)
for (uint8_t i = 0; i < 4; i++) {
debouncers[i].update();
}
for (uint8_t i = 0; i < 4; i++) {
if (debouncers[i].rose()) {
Serial.print(i);
Serial.println(" was pressed");
String i_char = String(i);
client.publish("home/neokey/button", i_char.c_str());
uint32_t pixel_colour = neokey.pixels.getPixelColor(i);
neokey.pixels.setPixelColor(i, pixel_colour ^ 0xFF0000); // write the new led state
neokey.pixels.show();
}
}
Now to figure out how to "long press", but this will work for now, I will reply back with any improvements.
- dastels
- Posts: 15667
- Joined: Tue Oct 20, 2015 3:22 pm
Re: NeoKey 1x4, i2c to mqtt, single shot?
Excellent!
You'll have to save the value of millis() when you detect a press (fell), and compare it with the now-current value when you detect a release (rose). That will tell you how long the key was pressed for.
You'll have to save the value of millis() when you detect a press (fell), and compare it with the now-current value when you detect a release (rose). That will tell you how long the key was pressed for.
Please be positive and constructive with your questions and comments.