Learn Braille letters with a keypad and six LEDs

Type a letter on the keypad, the way you would on an old mobile phone, and six LEDs light up its Braille dots. Then switch to quiz mode: the LEDs show a mystery letter and you guess it.
  • Level:Intermediate
  • Duration: 1 h
  • Ages 10+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Learn Braille letters with a keypad and six LEDs – EEMENTOR STEM™ lesson

Braille is the writing system that blind and partially sighted people read with their fingertips. Every letter is a small cell of six dots, in two columns of three, and each letter has its own pattern of raised dots. In this lesson six LEDs play the part of the six dots. You type letters on the keypad and the LEDs show their Braille pattern. In quiz mode the UNO shows a random letter, you guess which one it is, and the buzzer tells you if you were right. It is a fun way to learn the alphabet that millions of people read every day, and a first step towards building real aids for people who can't see.

What you'll learn

  • How a Braille cell works: six dots and their numbers
  • How to store the 26 letters as bit patterns in one byte each
  • How to read single bits with bitRead()
  • How to type letters with "multi-tap" on a number keypad

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • 4×4 keypad module (UNO R3 Starter Kit)
  • 6 LEDs and 6 resistors, 220 Ω (UNO R3 Starter Kit)
  • Passive buzzer (UNO R3 Starter Kit)
  • Breadboard and jumper wires (UNO R3 Starter Kit)

The Braille cell

The six dots are numbered: 1, 2 and 3 go down the left column, and 4, 5 and 6 go down the right column. The letter a is only dot 1. The letter b is dots 1 and 2. The letter c is dots 1 and 4, side by side at the top.

Dots Left column Right column
Top row dot 1 dot 4
Middle row dot 2 dot 5
Bottom row dot 3 dot 6

Put the six LEDs on the breadboard in order, dot 1 on the left and dot 6 on the right. The Serial Monitor also draws each letter as a real 2 × 3 cell, so you can see both.

Wiring

Breadboard wiring diagram: Learn Braille letters with a keypad and six LEDs
Breadboard view. Check each connection against the wiring table below.
From To
Keypad R1, R2, R3, R4 UNO pins A0, A1, A2, A3
Keypad C1, C2, C3, C4 UNO pins 10, 8, 7, 6
UNO pins 2, 3, 4 220 Ω resistor, then the long leg of the LEDs for dots 1, 2 and 3
UNO pins 5, 9, 11 220 Ω resistor, then the long leg of the LEDs for dots 4, 5 and 6
Short leg of every LED GND
Passive buzzer + UNO pin 12
Passive buzzer − GND

The keypad is wired the same way as in the keypad safe. Its row pins use A0 to A3, which also work as normal digital pins.

The sketch

In the Arduino IDE, open Library Manager and install Keypad by Mark Stanley and Alexander Brevig.

#include <Keypad.h>

const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {A0, A1, A2, A3};
byte colPins[COLS] = {10, 8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

const int DOT_PINS[6] = {2, 3, 4, 5, 9, 11};   // LEDs for dots 1 to 6
const int BUZZER_PIN = 12;
const unsigned long TAP_TIME = 1000;           // taps closer than this cycle the letters

// Braille letters a to z. Bit 0 is dot 1, bit 1 is dot 2 ... bit 5 is dot 6.
const byte BRAILLE[26] = {
  0b000001, 0b000011, 0b001001, 0b011001, 0b010001,   // a b c d e
  0b001011, 0b011011, 0b010011, 0b001010, 0b011010,   // f g h i j
  0b000101, 0b000111, 0b001101, 0b011101, 0b010101,   // k l m n o
  0b001111, 0b011111, 0b010111, 0b001110, 0b011110,   // p q r s t
  0b100101, 0b100111, 0b111010, 0b101101, 0b111101,   // u v w x y
  0b110101                                            // z
};

// Letters on each number key, like an old mobile phone
const char* LETTERS[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

char lastKey = 0;
int tapCount = 0;
unsigned long lastTap = 0;
char typed = 0;          // the letter you are typing
bool quiz = false;
char mystery = 0;        // the letter the quiz shows
int score = 0, asked = 0;

void showBraille(char letter) {
  byte dots = 0;
  if (letter >= 'a' && letter <= 'z') dots = BRAILLE[letter - 'a'];
  for (int i = 0; i < 6; i++) digitalWrite(DOT_PINS[i], bitRead(dots, i));
}

void drawCell(char letter) {               // draw the cell in the Serial Monitor
  byte dots = BRAILLE[letter - 'a'];
  Serial.print("Letter ");
  Serial.println(letter);
  for (int row = 0; row < 3; row++) {      // dots 1+4, then 2+5, then 3+6
    Serial.print(bitRead(dots, row) ? "  O" : "  .");
    Serial.println(bitRead(dots, row + 3) ? " O" : " .");
  }
  Serial.println();
}

void newQuestion() {
  mystery = 'a' + random(26);
  typed = 0;
  lastKey = 0;
  showBraille(mystery);
  Serial.println("Which letter is this? Type it and press #. Press * for a hint.");
}

void checkAnswer() {
  asked++;
  if (typed == mystery) {
    score++;
    Serial.println("Correct!");
    tone(BUZZER_PIN, 880, 120);
    delay(140);
    tone(BUZZER_PIN, 1320, 200);
  } else {
    Serial.print("Not quite. It was ");
    Serial.println(mystery);
    drawCell(mystery);
    tone(BUZZER_PIN, 220, 400);
  }
  Serial.print("Score: ");
  Serial.print(score);
  Serial.print(" of ");
  Serial.println(asked);
  delay(1200);
  newQuestion();
}

void handleKey(char key) {
  if (key >= '2' && key <= '9') {          // multi-tap typing
    const char* group = LETTERS[key - '0'];
    if (key == lastKey && millis() - lastTap < TAP_TIME) tapCount = (tapCount + 1) % strlen(group);
    else tapCount = 0;
    lastKey = key;
    lastTap = millis();
    typed = group[tapCount];
    tone(BUZZER_PIN, 1500, 15);
    if (quiz) {
      Serial.print("Your answer: ");
      Serial.println(typed);
    } else {
      showBraille(typed);
      drawCell(typed);
    }
  } else if (key == '#' && quiz && typed) {
    checkAnswer();
  } else if (key == '*' && quiz) {
    Serial.print("Hint: it is on key ");
    for (int k = 2; k <= 9; k++) if (strchr(LETTERS[k], mystery)) Serial.println(k);
  } else if (key == 'A') {
    quiz = true;
    score = 0;
    asked = 0;
    Serial.println("Quiz mode");
    newQuestion();
  } else if (key == 'B') {
    quiz = false;
    typed = 0;
    showBraille(0);
    Serial.println("Typing mode: tap a number key to show a letter");
  } else if (key == 'C' && !quiz) {        // show the whole alphabet
    for (char c = 'a'; c <= 'z'; c++) {
      showBraille(c);
      drawCell(c);
      delay(1200);
    }
    showBraille(0);
  } else if (key == '1') {                 // test: all six dots on for a second
    for (int i = 0; i < 6; i++) digitalWrite(DOT_PINS[i], HIGH);
    delay(1000);
    showBraille(quiz ? mystery : typed);
  } else if (key == '0') {                 // clear
    typed = 0;
    lastKey = 0;
    if (!quiz) showBraille(0);
  }
}

void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 6; i++) pinMode(DOT_PINS[i], OUTPUT);
  randomSeed(analogRead(A5));
  Serial.println("Typing mode: tap a number key to show a letter");
  Serial.println("A = quiz, B = typing, C = whole alphabet, 0 = clear, 1 = test LEDs");
}

void loop() {
  char key = keypad.getKey();
  if (key) handleKey(key);
}

Try it

  1. Upload the sketch and open the Serial Monitor at 9600 baud.
  2. Press 2 once: the LED for dot 1 lights, because that is the letter a. Press 2 again quickly for b (dots 1 and 2), and a third time for c (dots 1 and 4).
  3. Wait a second, then press 2 again: you start again at a. Try your name, letter by letter, and watch the cells in the Serial Monitor.
  4. Press C to see the whole alphabet, one letter every second. Notice how the letters k to t are a to j with dot 3 added.
  5. Press A for the quiz. Look at the LEDs, type the letter you think it is and press #. Press * if you need a hint, and B to go back to typing.

How it works

Six dots that are either up or down are exactly six bits: 1 for a raised dot, 0 for a flat one. So every Braille letter fits into one byte, and the whole alphabet is just the 26 bytes in BRAILLE. Read 0b001001, the letter c, from right to left: bit 0 (dot 1) is 1, bits 1 and 2 are 0, bit 3 (dot 4) is 1. bitRead(dots, i) gives you bit number i, so showBraille() needs only one short loop to set all six LEDs.

Louis Braille, who was blind himself, invented the system in 1824 when he was only 15. He built it cleverly: the first ten letters, a to j, only use the top four dots. The next ten, k to t, are the same patterns with dot 3 added, and u, v, x, y and z add dots 3 and 6. The letter w is the odd one out, because French, his language, didn't use it at the time.

Typing letters on a 12-key pad is the same problem old mobile phones had. Multi-tap solves it: each key holds a few letters, and pressing the same key again within a second moves to the next one. The sketch remembers the last key and the time of the last tap to decide whether a tap is "the next letter on this key" or "a new letter".

Try this next

  • Build a real 2 × 3 cell: put the LEDs in a little box in two columns of three, so the pattern looks exactly like Braille.
  • Add the Braille numbers: in Braille, a "number sign" (dots 3, 4, 5 and 6) followed by a to j means 1 to 0.
  • Make the quiz harder: show each letter for only two seconds before switching the LEDs off.
  • Replace the LEDs with small vibration or servo "pins" so that the letters can be felt, not only seen.

Troubleshooting

  • A key does nothing or gives the wrong letter: check the eight keypad wires. Swapped row wires (A0 to A3) or column wires (10, 8, 7, 6) mix the keys up.
  • One LED never lights: turn it round (long leg towards the resistor) and check its resistor. Press 1 to light all six dots as a test.
  • Typing jumps two letters at a time: you pressed the key twice by accident. Wait a second to start a new letter, or press 0 to clear.
  • No sound: check that the buzzer is the passive one (no sticker, you can see the circuit board underneath) and that + goes to pin 12.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

UNO R3 Starter Kit | Arduino IDE Compatible | Free Tutorials $56.00

Shop the kit