Close

prototype

A project log for Grove SmartView - A Keyboard Button

A button with display function

makerm0MakerM0 11/25/2022 at 11:160 Comments

I love the feeling of pressing mechanical keys, so I apply mechanical buttons to some projects. But the function of these buttons is not fixed, the way of sticking labels is not easy to remember, in order to solve this problem, I was wondering if I can add a display device to my keys to facilitate real-time indication according to different functions.

During the design process, I came across the activities of SeeedStudio. The designers can design a Grove sensor module for free and have a chance to win more than $300. When designing the Grove sensor I needed to meet their design specifications.

Regarding mechanical buttons, I chose kailh's CHOC series, which is highly satisfying to the overall design.

For the display part, I would have liked to choose an OLED screen, but it requires too many pins to control and cannot meet the grove specification. Then I thought of the WS2812, which only needs 1 pin to control its display content.

Along these lines, I chose the grove digital interface, one pin to detect keys and one pin to control the LED.

During the design process, it was found that the size of the WS2812 was too large to fit enough LEDs within the limited size, so I needed to continue to look for a smaller size. In the end, I found the right component, SK6805-EC15 from OPSCO, and successfully implemented a 5X7 LED matrix.

Due to the size limitations of this project, I chose the Grove 20X40 DIP design out of Grove specification.

The PCB can be ordered on seeed's fusion PCBA service .It consists of two two-layer PCBs.

PCB _motherBoard

PCB_LED

rgbled
rgbled
mainBoard
mainBoard

charging animation

Cistercian Display

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
#define PSTR // Make Arduino Due happy
#endif

uint8_t key1 = 21;
uint8_t key2 = 10;

#define LED_PIN1 20
#define LED_PIN2 9

Adafruit_NeoMatrix matrix1 = Adafruit_NeoMatrix(5, 7, LED_PIN1,
                                                NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
                                                    NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
                                                NEO_GRB + NEO_KHZ800);

Adafruit_NeoMatrix matrix2 = Adafruit_NeoMatrix(5, 7, LED_PIN2,
                                                NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
                                                    NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
                                                NEO_GRB + NEO_KHZ800);
const uint16_t colors[] = {
    matrix1.Color(255, 0, 0), matrix1.Color(0, 255, 0), matrix1.Color(0, 0, 255)};

const uint8_t numberUnits[10][7] = {
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 0
    {0b00000111, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 1
    {0b00000100, 0b00000100, 0b00000111, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 2
    {0b00000100, 0b00000110, 0b00000101, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 3
    {0b00000101, 0b00000110, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 4
    {0b00000111, 0b00000110, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 5
    {0b00000101, 0b00000101, 0b00000101, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 6
    {0b00000111, 0b00000101, 0b00000101, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 7
    {0b00000101, 0b00000101, 0b00000111, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 8
    {0b00000111, 0b00000101, 0b00000111, 0b00000100, 0b00000100, 0b00000100, 0b00000100},
}; // 9

const uint8_t numberTens[10][7] = {
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 0
    {0b00011100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 1
    {0b00000100, 0b00000100, 0b00011100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 2
    {0b00000100, 0b00001100, 0b00010100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 3
    {0b00010100, 0b00001100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 4
    {0b00011100, 0b00001100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 5
    {0b00010100, 0b00010100, 0b00010100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 6
    {0b00011100, 0b00010100, 0b00010100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 7
    {0b00010100, 0b00010100, 0b00011100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 8
    {0b00011100, 0b00010100, 0b00011100, 0b00000100, 0b00000100, 0b00000100, 0b00000100},
}; // 9

const uint8_t numberHundreds[10][7] = {
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 0
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000111}, // 1
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000111, 0b00000100, 0b00000100}, // 2
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000101, 0b00000110, 0b00000100}, // 3
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000110, 0b00000101}, // 4
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000110, 0b00000111}, // 5
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000101, 0b00000101, 0b00000101}, // 6
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000101, 0b00000101, 0b00000111}, // 7
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000111, 0b00000101, 0b00000101}, // 8
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000111, 0b00000101, 0b00000111},
}; // 9

const uint8_t numberThousands[10][7] = {
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100}, // 0
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00011100}, // 1
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00011100, 0b00000100, 0b00000100}, // 2
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00010100, 0b00001100, 0b00000100}, // 3
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00001100, 0b00010100}, // 4
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00001100, 0b00011100}, // 5
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00010100, 0b00010100, 0b00010100}, // 6
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00010100, 0b00010100, 0b00011100}, // 7
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00011100, 0b00010100, 0b00010100}, // 8
    {0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00011100, 0b00010100, 0b00011100},
}; // 9

void dispDigital(uint16_t dig, uint16_t color)
{
    uint8_t data[7];
    memset(data, 0, 7);
    for (uint8_t i = 0; i < 7; i++)
    {
        data[i] = numberThousands[dig / 1000][i] | numberHundreds[dig % 1000 / 100][i] | numberTens[dig % 100 / 10][i] | numberUnits[dig % 10][i];
    }

    matrix1.drawBitmap(-3, 0, data, 8, 7, color);
}

void setup()
{
    Serial.begin(115200);
    Serial.println("test");

    matrix1.begin();
    matrix1.setTextWrap(false);
    matrix1.setBrightness(40);
    matrix1.setTextColor(colors[0]);
    matrix1.fillScreen(matrix1.Color(20, 30, 0));
    matrix1.show();

    matrix2.begin();
    matrix2.setTextWrap(false);
    matrix2.setBrightness(40);
    matrix2.setTextColor(colors[0]);
    matrix2.fillScreen(matrix2.Color(20, 30, 0));
    matrix2.show();

    pinMode(key1, INPUT);
    pinMode(key2, INPUT);
}

void loop()
{
    matrix1.fillScreen(matrix1.Color(0, 0, 0));
    dispDigital(9433, matrix1.Color(0, 255, 0));
    matrix1.show();
    delay(3000);

    matrix1.fillScreen(matrix1.Color(0, 0, 0));
    dispDigital(7085, matrix1.Color(0, 255, 0));
    matrix1.show();
    delay(3000);

    matrix1.fillScreen(matrix1.Color(0, 0, 0));
    dispDigital(6859, matrix1.Color(0, 255, 0));
    matrix1.show();
    delay(3000);

    matrix1.fillScreen(matrix1.Color(0, 0, 0));
    dispDigital(4723, matrix1.Color(0, 255, 0));
    matrix1.show();
    delay(3000);

    matrix1.fillScreen(matrix1.Color(0, 0, 0));
    dispDigital(9999, matrix1.Color(0, 255, 0));
    matrix1.show();
    delay(3000);

    for (uint8_t i = 0; i < 10; i++)
    {
        matrix1.fillScreen(matrix1.Color(0, 0, 0));

        dispDigital(i, matrix1.Color(0, 255, 0));

        matrix1.show();
        delay(1000);
    }
    for (uint8_t i = 0; i < 10; i++)
    {
        matrix1.fillScreen(matrix1.Color(0, 0, 0));

        dispDigital(i * 10, matrix1.Color(255, 0, 0));

        matrix1.show();
        delay(1000);
    }
    for (uint8_t i = 0; i < 10; i++)
    {
        matrix1.fillScreen(matrix1.Color(0, 0, 0));

        dispDigital(i * 100, matrix1.Color(0, 0, 255));

        matrix1.show();
        delay(1000);
    }
    for (uint8_t i = 0; i < 10; i++)
    {
        matrix1.fillScreen(matrix1.Color(0, 0, 0));

        dispDigital(i * 1000, matrix1.Color(255, 0, 255));

        matrix1.show();
        delay(1000);
    }
}

short click,long click, double tap, triple tap

#include <Arduino.h>
#include "Button2.h"

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
#define PSTR // Make Arduino Due happy
#endif

#define LED_PIN1 20

Adafruit_NeoMatrix matrix1 = Adafruit_NeoMatrix(5, 7, LED_PIN1,
                                                NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
                                                    NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
                                                NEO_GRB + NEO_KHZ800);

 

#define BUTTON_PIN 21

 

Button2 button;

 

void setup()
{
    Serial.begin(115200);
    delay(50);
    Serial.println("\n\nButton Loop Demo");

    button.begin(BUTTON_PIN);

    matrix1.begin();
    matrix1.setTextWrap(false);
    matrix1.setBrightness(40);
    matrix1.setTextColor(matrix1.Color(255, 255, 0));
    matrix1.fillScreen(matrix1.Color(0, 50, 50));
    matrix1.show();
}

 

void loop()
{
    button.loop();

    if (button.wasPressed())
    {
        matrix1.setCursor(0, 0);
        matrix1.setTextColor(matrix1.Color(random(10,200), random(10,200),  random(10,200)));

        matrix1.clear();
        switch (button.read())
        {
        case single_click:
            matrix1.println("Single");
            break;
        case double_click:
            matrix1.println("Double");
            break;
        case triple_click:
            matrix1.println("Triple");
            break;
        case long_click:
            matrix1.println("Looong");
            break;
        }
        matrix1.show();
    }
}

Discussions