NeoKey 1x4, i2c to mqtt, single shot?

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
joshatflexcore
 
Posts: 64
Joined: Mon Jan 05, 2015 10:34 am

NeoKey 1x4, i2c to mqtt, single shot?

Post by joshatflexcore »

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
Attachments

[The extension ino has been deactivated and can no longer be displayed.]


User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: NeoKey 1x4, i2c to mqtt, single shot?

Post by dastels »

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

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: NeoKey 1x4, i2c to mqtt, single shot?

Post by dastels »

How's this look for an example:

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();
    }
  }

}
The updated Bounce2 library is here: https://github.com/dastels/Bounce2

Dave

joshatflexcore
 
Posts: 64
Joined: Mon Jan 05, 2015 10:34 am

Re: NeoKey 1x4, i2c to mqtt, single shot?

Post by joshatflexcore »

That gives me one helluva good start!
Thank you!

I will combine this into my code and go from there.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: NeoKey 1x4, i2c to mqtt, single shot?

Post by dastels »

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

joshatflexcore
 
Posts: 64
Joined: Mon Jan 05, 2015 10:34 am

Re: NeoKey 1x4, i2c to mqtt, single shot?

Post by joshatflexcore »

Got this far, it took me too long to remember how to go from uint8_t to char...

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();
        }
      }
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.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: NeoKey 1x4, i2c to mqtt, single shot?

Post by dastels »

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.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”