HID Numpad With XIAO SAMD21
Greetings everyone, and welcome back.
Here's something fun and useful: an HID Numpad project made completely from scratch using an XIAO expansion board and 3D-printed parts.
The heart of this project is an XIAO SAMD21 development board paired with an XIAO expansion board, which contains an onboard OLED display that we use in this project to show the button press.
The expansion board was intended to be held atop a specially made enclosure that was 3D printed. We have included 12x12mm tactile buttons inside the enclosure.
These buttons are held firmly in place by a holder part that was modeled in Fusion360.
This Instructables covers the entire build process of this device, including wiring and code, so let's get started with the build.
Supplies
These were the materials used in this project:
- XIAO SAMD21 DEV Board
- XIAO Expansion Board
- 3D-printed parts
- 12x12mm Tactile Push Buttons
- Wires for connections
Level 1: XIAO Expansion Board With XIAO SAMD21 M0
An XIAO SAMD21 microcontroller and an XIAO expansion board manufactured by Seeed Studio comprised the heart of this project.
It comes with rich peripherals that include an OLED, RTC, SD Card Sot, passive buzzer, reset/user button, 5V servo connector, and Grove connector for pairing multiple Grove devices with XIAO. It also contains a battery charging IC for intergrading this setup with a lithium cell as a power source.
If you would like to get one for yourself, here is the link to its page.
https://www.seeedstudio.com/Seeeduino-XIAO-Expansion-board-p-4746.html
https://www.seeedstudio.com/Seeeduino-XIAO-3Pcs-p-4546.html
The first step of the project was rather straightforward: we uploaded a test code to the XIAO SAMD21 DEV Board and utilized the expansion board's onboard button, which was attached to D1, to function as a numpad for entering the number 1.
#include <Keyboard.h> //TEST SKETCH
int buttonPin = 1; // Set a button to any pin
void setup()
{
pinMode(buttonPin, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin, HIGH); // Pull the button high
}
void loop()
{
if (digitalRead(buttonPin) == 0) // if the button goes low
{
Keyboard.write('1'); // send a '1' to the computer via Keyboard HID
delay(500); // delay so there aren't a kajillion z's
}
}
After the test, we prepare a much larger sketch that is able to take input from 9 buttons and output numbers through the HID protocol of the SAMD21 microcontroller inside the XIAO.
CODE
Here's the main code used in this build.
#include <Keyboard.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);
int buttonPin1 = 0;
int buttonPin2 = 1;
int buttonPin3 = 2;
int buttonPin4 = 3;
int buttonPin5 = 6;
int buttonPin6 = 7;
int buttonPin7 = 8;
int buttonPin8 = 9;
int buttonPin9 = 10;
void setup()
{
pinMode(buttonPin1, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin1, HIGH); // Pull the bu11tton high
pinMode(buttonPin2, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin2, HIGH); // Pull the bu11tton high
pinMode(buttonPin3, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin3, HIGH); // Pull the bu11tton high
pinMode(buttonPin4, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin4, HIGH); // Pull the bu11tton high
pinMode(buttonPin5, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin5, HIGH); // Pull the bu11tton high
pinMode(buttonPin6, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin6, HIGH); // Pull the bu11tton high
pinMode(buttonPin7, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin7, HIGH); // Pull the bu11tton high
pinMode(buttonPin8, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin8, HIGH); // Pull the bu11tton high
pinMode(buttonPin9, INPUT_PULLUP); // Set the button as an input
digitalWrite(buttonPin9, HIGH); // Pull the bu11tton high
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay();
}
void loop()
{
if (digitalRead(buttonPin1) == 0) // 01
{
Keyboard.write('1');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("1");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin2) == 0) // 02
{
Keyboard.write('2');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("2");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin3) == 0) // 03
{
Keyboard.write('3');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("3");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin4) == 0) // 04
{
Keyboard.write('4');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("4");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin5) == 0) // 05
{
Keyboard.write('5');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("5");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin6) == 0) // 06
{
Keyboard.write('6');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("6");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin7) == 0) // 07
{
Keyboard.write('7');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("7");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin8) == 0) // 08
{
Keyboard.write('8');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("8");
display.display();
delay(500);
}
display.clearDisplay();
if (digitalRead(buttonPin9) == 0) // 09
{
Keyboard.write('9');
display.clearDisplay();
display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(55, 20);
display.println("9");
display.display();
delay(500);
}
display.clearDisplay();
}
This code essentially acts as a simple keypad input system that simulates pressing keys on a keyboard when corresponding physical buttons are pressed. Additionally, it provides visual feedback on the OLED display to indicate which button has been pressed.
We're using the Adafruit SSD1306 OLED Library, which you need to download and install first before uploading this sketch.
Level 2: Design
Level 2 of this project starts with the design, which consists of an XIAO Expansion Board model created first, which is placed on a rectangular body that houses the nine buttons from the inside.
Here's a tip: Make sure to model every component before beginning the design; this ensures simple and easy prototyping.
The XIAO expansion board was mounted from the top side using four M2 screws.
We installed buttons from the inside of the enclosure and created nine square openings for the placement of switches. We have created a switch holder that is secured in place with four M2 screws in order to keep the switches in their place.
Furthermore, we created a lid that closes the device from the rear. This device is elevated from the top by a rectangular extension in the lid, giving it a somewhat slanted aspect.
After the design was completed, we exported all the mesh files of the design and printed them using Ender 3 with a 0.4mm nozzle.
The main body was printed with orange PLA, and the lid and switch holder were both printed using transparent PLA.
Assembly Process: Adding Buttons
For switches, we will be using 12mm x 12mm square tactile push buttons.
- First, we just pick and insert each switch in its designated location one at a time within the main body, placing them all in their slots.
- Next, we add the 3D-printed switch holder in its place and use four M2 screws to make it stationary. This holder will keep all the switches intact in their place.
Wiring Connections
- The GND terminals of each switch are connected to one another using a soldering iron and silver copper wire. For this stage, we stick to the provided wiring diagram.
- Next, we place a connecting wire on each switch; this connecting wire will be added to XIAO's digital pins for switch input.
Final Assembly Process
- The XIAO expansion board is mounted in its proper location using four M2 screws, which are inserted from the top side.
- Next, we begin the last wiring step, which involves aligning the digital pins on the XIAO with the connecting wires on each switch according to the wiring diagram that has been provided. For this procedure, a soldering iron is used.
- Finally, we position the lid on the bottom side and fasten it to the main body with six M2 screws.
The project is fully assembled.
RESULT
Here's the result of this simple yet functional build: a functional HID Numpad that you can use to enter numbers if your laptop lacks a dedicated numpad. You can also modify this project to operate as a macropad by assigning letters or functions to each button in place of numbers.
You are welcome to download and alter this project in any way you see fit, as the code and details are provided.
Leave a comment if you need any help regarding this project. This is it for today, folks.
Thanks to Seeed Studio Fusion for supporting this project.
You guys can check them out if you need great PCB and stencil service for less cost and great quality.
And I'll be back with a new project pretty soon!