Partial Home Assistant Control of Mr. Robot Badge Mk. 2
Once I had Mr Robot Badge Mk. 2 up and running on Arduino, I thought: what about Home Assistant? After all, ESPHome is built on compiling ESP8266 Arduino Core code using PlatformIO command-line tools. The challenging part of ESPHome is always that initial firmware flash, which I'm already set up to do, and after that I could do updates wirelessly.
I started easy: getting badge buttons to be recognized as binary sensors in Home Assistant.
binary_sensor:
- platform: gpio
pin:
number: 0
mode:
input: true
pullup: true
inverted: true
name: "Left"
filters:
- delayed_on_off: 20ms
- platform: gpio
pin:
number: 16
mode:
input: true
inverted: true
name: "Down"
filters:
- delayed_on_off: 20ms
- platform: gpio
pin:
number: 15
mode:
input: true
pullup: true
name: "Right"
filters:
- delayed_on_off: 20ms
- platform: gpio
pin:
number: 13
mode:
input: true
pullup: true
inverted: true
name: "Up"
filters:
- delayed_on_off: 20ms
- platform: gpio
pin:
number: 12
mode:
input: true
pullup: true
inverted: true
name: "A"
filters:
- delayed_on_off: 20ms
- platform: gpio
pin:
number: 14
mode:
input: true
pullup: true
inverted: true
name: "B"
filters:
- delayed_on_off: 20ms
Piece of cake! Now on to the more interesting (and more challenging) part: using the LEDs. I followed ESPHome examples to create a custom component. This exposed a single custom output that treated the entire array as a single color (monochromatic) dimmable light.
C header file with custom class declaration:
#include "esphome.h"
#include "Adafruit_IS31FL3741.h"
using namespace esphome;
class MrRobotBadgeFloatOutput : public Component, public FloatOutput
{
Adafruit_IS31FL3741 ledArray;
public:
void setup() override
{
ledArray.begin();
ledArray.setLEDscaling(0x3F); // 25% of max
ledArray.setGlobalCurrent(0x3F); // 25% of max
ledArray.enable(true); // bring out of shutdown
}
void write_state(float state) override
{
int8_t value = state * 128; // 50% of max
ledArray.fill(value);
}
};
YAML:
output:
- platform: custom
type: float
lambda: |-
auto badge_float = new MrRobotBadgeFloatOutput();
App.register_component(badge_float);
return {badge_float};
outputs:
id: badge_float
light:
- platform: monochromatic
name: "Badge Lights"
output: badge_float
Tada! I'm back at the same test I had using Arduino, lighting up all the pixels to highlight problematic LEDs.

The next step in this progression is to expose the entire 18x18 array as individually addressable pixels. Doing so would allow using ESPHome's display rendering engine to draw text and graphics, much as Adafruit GFX does. I found the Addressable Light base class but I got stuck trying to make it happen. I've had no luck finding examples on how to implement a custom addressable light, and didn't get much of anywhere bumping my head in the dark. Digging through existing Addressable Light implementations on GitHub, I've found many object classes that may or may not be required to implement my own addressable light.
- AddressableLightDisplay (inherits from DisplayBuffer)
- AddressableLight (inherits from LightOutput)
- AddressableLightEffect (inherits from LightEffect)
- AddressableLightWrapper (inherits from AddressableLight)
- AddressableLightTransformer
- AddressableLightState
I imagine there's an architecture diagram somewhere that describes how these components interact, but my search has come up empty so far and there's not much in the way of code comments. Most of the online discussions about addressable LED pixels in Home Assistant are centered around WLED, which as of this writing does not support the IS31LF3741 control chip. I'm going to put further exploration on hold until I have more experience with ESPHome custom components to understand their object hierarchy.