Using arduino and Shift Register (74HC595) for Braille project

Hi! I'm just starting to use shift registers - I bought some 74HC595 chips. My project is a Braille reading control system, and I'm currently using LEDs for testing. I've written some code, but it's not working quite right. I suspect the issue might be related to synchronization between the Latch, CLK, and Data pins.

The program works like this:
It asks for a letter from A to Z.
If the letter is lowercase, it converts it to uppercase.
It checks against the predefined char values I assigned earlier.
Then it sends the binary data to the Data pin, updating the CLK pin each time (at least I think it does).
Finally it updates the Latch pin to display the pattern on the LED matrix.

The problem is that the correct LEDs aren't lighting up properly.

Code:


// Definición de pines
const int dataPin = 1;
const int latchPin = 2;
const int clockPin = 3;

// Mapeo corregido de letras a patrones (ajustado al orden físico de tus LEDs)
const byte patronesLetras[26] = {
  // Bits: LED8 LED7 LED6 LED5 LED4 LED3 LED2 LED1 (orden físico)
  0b00000001, // A
0b00000011, // B
0b00100001, // C
0b01100001, // D
0b01000001, // E
0b00100011, // F
0b01100011, // G
0b01000011, // H
0b00100010, // I
0b01100010, // J
0b00000101, // K
0b00000111, // L
0b00100101, // M
0b01100101, // N
0b01000101, // O
0b00100111, // P
0b01100111, // Q
0b01000111, // R
0b00100110, // S
0b01100110, // T
0b10000101, // U
0b10000111, // V
0b11100010, // W
0b10100101, // X
0b11100101, // Y
0b11000101, // Z
};

void setup() {
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("Sistema listo. Ingrese una letra (A-Z):");
}

void loop() {
  if (Serial.available()) {
    char letra = toupper(Serial.read());
    
    if (letra >= 'A' && letra <= 'Z') {
      byte patron = patronesLetras[letra - 'A'];
      
      Serial.print("Letra: ");
      Serial.print(letra);
      Serial.print(" - Patron: ");
      imprimirBinario(patron);
      Serial.println();
      
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, patron); // Cambiado a LSBFIRST
      digitalWrite(latchPin, HIGH);
      
      delay(2000);
      escribirRegistro(0b00000000);
    }
  }
}

void imprimirBinario(byte valor) {
  Serial.print("0b");
  for (int i = 7; i >= 0; i--) {
    Serial.print(bitRead(valor, i));
  }
}

void escribirRegistro(byte dato) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, dato);
  digitalWrite(latchPin, HIGH);
}
  • What Arduino board are you using ?

If you're using an Uno R3 or a classic Nano, pin 1 is Serial Tx.

Did you input the key correctly?
Did you translate the input to upper case correctly?
Did you translate upper case to LEDs correctly?
Did you wire the 595 correctly?
Did you wire the LEDs correctly?

  • Suggest you use the SPI library.

  • UNO
    SS 10;
    MOSI 11;
    SCK 13;

#include <SPI.h>

//UNO
//SS   10
//MOSI 11
//SCK  13

// Mapeo corregido de letras a patrones (ajustado al orden físico de tus LEDs)
const byte patronesLetras[26] =
{
  // Bits: LED8 LED7 LED6 LED5 LED4 LED3 LED2 LED1 (orden físico)
  0b00000001, // A
  0b00000011, // B
  0b00100001, // C
  0b01100001, // D
  0b01000001, // E
  0b00100011, // F
  0b01100011, // G
  0b01000011, // H
  0b00100010, // I
  0b01100010, // J
  0b00000101, // K
  0b00000111, // L
  0b00100101, // M
  0b01100101, // N
  0b01000101, // O
  0b00100111, // P
  0b01100111, // Q
  0b01000111, // R
  0b00100110, // S
  0b01100110, // T
  0b10000101, // U
  0b10000111, // V
  0b11100010, // W
  0b10100101, // X
  0b11100101, // Y
  0b11000101, // Z
};


//================================================^================================================
//
void setup()
{
  Serial.begin(9600);
  
  Serial.println("Sistema listo. Ingrese una letra (A-Z):");

  SPI.begin();
}


//================================================^================================================
//
void loop()
{
  if (Serial.available() > 0)
  {
    char letra = toupper(Serial.read());

    if (letra >= 'A' && letra <= 'Z')
    {
      byte patron = patronesLetras[letra - 'A'];

      Serial.print("Letra: ");
      Serial.print(letra);
      Serial.print(" - Patron: ");
      imprimirBinario(patron);
      Serial.println();

      transferData(patron);

      delay(2000);
      
      transferData(0);
    }
  }
}


//================================================^================================================
//
void imprimirBinario(byte valor)
{
  Serial.print("0b");
  for (int i = 7; i >= 0; i--)
  {
    Serial.print(bitRead(valor, i));
  }
}


//                                    t r a n s f e r D a t a ( )
//================================================^================================================
//
void transferData(byte data)
{
  digitalWrite(SS, LOW);

  //send the data to the shift register
  SPI.transfer (data);

  //update outputs
  digitalWrite(SS, HIGH);

} //END of   transferData()


//================================================^================================================

Why do you think the problem is the code? Or are you just hoping the problem is the code, so you don't need to post a wiring diagram?

Are you using a real person to help you construct a Braille reading system? Real Braille reading needs an line of many characters and many times both hands are required to actually read the words.

I used the code posted in #1 in the hardware from this project

changing only the # define statements to match the existing wiring. It is a good idea in any case to be off pin 1, perhaps that is your only problem as the simulation works. I did not extensively test it and it is possible, given your description of the problem you have, that the simulation is behaving identically. I see LEDs in synchrony with the printed patterns which seem to be accurately taken from your table.

Do you have bare chips? Have you tried simple code, like what comes out of the box on the project I linked, as a test?

Just in case:

HTH

a7

Here is an adaptation of my Sequencer to form Braille letters and words. Next phase for this would be to enter a sentence, and have it play... flattening and "digitizing" each letter.

// DIO sequencer version 5 - Braille Sequencer

// - char arrays are flat (one long string, no comma separators)
// - edit array elements using (star) "*" for "ON" and (dot) "." for "OFF"
// - each row in an array must be the same length
// https://forum.arduino.cc/t/uno-nano-dio-sequencer/1364441

#include <avr/pgmspace.h> // to offload arrays from RAM to PROGMEM 
byte ledPin[] = {11, 10, 9, 3, 4, 5}; // PWM pins for LEDs. ** Leave pin 2 and 3 for hardware interrupts
int ledCount = sizeof(ledPin) / sizeof(ledPin[0]); // number of LEDs
int loops; // for repeating a sequence
bool firstTime = 1; // flag for printing Loop Time

// Multiply "spacing" times "columns" for total time to complete one loop
unsigned long columnSpacing = 500; // milliseconds per element/column for speed control

const char hello[] PROGMEM = { // single-dimension array of sequenced elements
  //HELLO // elements or columns
  "*****" // LED[0]... sequence[0][0..n]
  "*.**." // LED[1]... sequence[1][0..n]
  "..***" // LED[2]... sequence[2][0..n]
  "....." // LED[3]... sequence[3][0..n]
  "**..*" // LED[4]... sequence[4][0..n]
  "....." // LED[5]... sequence[5][0..n]
};

const char world[] PROGMEM = {
  //2345
  "*...*"
  ".***."
  "*.***"
  ".****"
  "..***"
  "....*"
};

const char space[] PROGMEM = {
  "."
  "."
  "."
  "."
  "."
  "."
};

void setup() {
  Serial.begin(115200); // start serial communications
  for (int i = 0; i < ledCount; i++) // count through LED pins
    pinMode(ledPin[i], OUTPUT); // configure pins for OUTPUT
}

void loop() {
  sequencer(space, sizeof(space) / ledCount);
  sequencer(hello, sizeof(hello) / ledCount);
  sequencer(space, sizeof(space) / ledCount);
  sequencer(world, sizeof(world) / ledCount);
}

void sequencer(char list[], int length) {
  for (int col = 0; col < length; col++) { // count through row length
    for (int row = 0; row < ledCount; row++) { // count through number of LED elements/columns
      switch (pgm_read_byte(&list[row * length + col])) { // locate element row and column location
        case '*': digitalWrite(ledPin[row], HIGH); break; // LED ON
        case '.': digitalWrite(ledPin[row],  LOW); break; // LED OFF
        default: break;
      }
    }
    delay(columnSpacing); // regulate sequence speed
    for (int i = 0; i < ledCount; i++) // space between letters
      digitalWrite(ledPin[i], LOW);
    delay(columnSpacing / 2);
  }
}
diagram.json for wokwi
{
  "version": 1,
  "author": "Anonymous maker",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": 120, "left": 9.1, "attrs": {} },
    {
      "type": "wokwi-resistor",
      "id": "r4",
      "top": 89.8,
      "left": 66.35,
      "rotate": 270,
      "attrs": { "value": "333" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r5",
      "top": 89.8,
      "left": 75.95,
      "rotate": 270,
      "attrs": { "value": "333" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r6",
      "top": 91.2,
      "left": 28.25,
      "rotate": 270,
      "attrs": { "value": "333" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r9",
      "top": 91.2,
      "left": 18.65,
      "rotate": 270,
      "attrs": { "value": "333" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r8",
      "top": 91.2,
      "left": 9.05,
      "rotate": 270,
      "attrs": { "value": "333" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r10",
      "top": 89.8,
      "left": 85.55,
      "rotate": 270,
      "attrs": { "value": "333" }
    },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": -20.4,
      "left": 39.8,
      "rotate": 270,
      "attrs": { "color": "red", "flip": "1" }
    },
    {
      "type": "wokwi-led",
      "id": "led2",
      "top": -1.2,
      "left": 39.8,
      "rotate": 270,
      "attrs": { "color": "red", "flip": "1" }
    },
    {
      "type": "wokwi-led",
      "id": "led3",
      "top": 18,
      "left": 39.8,
      "rotate": 270,
      "attrs": { "color": "red", "flip": "1" }
    },
    {
      "type": "wokwi-led",
      "id": "led4",
      "top": -20.4,
      "left": 73.8,
      "rotate": 90,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-led",
      "id": "led5",
      "top": -1.2,
      "left": 73.8,
      "rotate": 90,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-led",
      "id": "led6",
      "top": 18,
      "left": 73.8,
      "rotate": 90,
      "attrs": { "color": "red" }
    },
    { "type": "wokwi-text", "id": "text1", "top": -9.6, "left": 28.8, "attrs": { "text": "1" } },
    { "type": "wokwi-text", "id": "text2", "top": 9.6, "left": 28.8, "attrs": { "text": "2" } },
    { "type": "wokwi-text", "id": "text3", "top": 28.8, "left": 28.8, "attrs": { "text": "3" } },
    { "type": "wokwi-text", "id": "text4", "top": -9.6, "left": 115.2, "attrs": { "text": "4" } },
    { "type": "wokwi-text", "id": "text5", "top": 9.6, "left": 115.2, "attrs": { "text": "5" } },
    { "type": "wokwi-text", "id": "text6", "top": 28.8, "left": 115.2, "attrs": { "text": "6" } }
  ],
  "connections": [
    [ "r9:1", "nano:10", "white", [ "h0" ] ],
    [ "r6:1", "nano:9", "white", [ "h0" ] ],
    [ "nano:11", "r8:1", "white", [ "v0" ] ],
    [ "r6:2", "led3:A", "green", [ "h-0.3", "v-9.8", "h9.6" ] ],
    [ "r9:2", "led2:A", "green", [ "h-0.3", "v-9.8", "h19.2" ] ],
    [ "r8:2", "led1:A", "green", [ "h-0.3", "v-9.8", "h28.8" ] ],
    [ "r4:2", "led6:A", "green", [ "h-0.3", "v-8.4", "h-28.5" ] ],
    [ "r5:2", "led5:A", "green", [ "h-0.3", "v-8.4", "h-38.1" ] ],
    [ "r10:2", "led4:A", "green", [ "h0", "v-8.4", "h-28.8" ] ],
    [ "nano:GND.2", "led3:C", "black", [ "v-67.2", "h-67.2" ] ],
    [ "led3:C", "led2:C", "green", [ "h0" ] ],
    [ "led2:C", "led1:C", "green", [ "h0" ] ],
    [ "led1:C", "led4:C", "green", [ "h0" ] ],
    [ "led4:C", "led5:C", "green", [ "h0" ] ],
    [ "led5:C", "led6:C", "green", [ "h0" ] ],
    [ "nano:5", "r4:1", "white", [ "v0" ] ],
    [ "nano:4", "r5:1", "white", [ "v0" ] ],
    [ "nano:3", "r10:1", "white", [ "v0" ] ]
  ],
  "dependencies": {}
}

For reference:

Here is version 2... reading from an array... same hardware (diagram.json) setup as Post #9.

// DIO Braille sequencer version 2 - for use with Braille Key (LEDs represent plungers)
// https://forum.arduino.cc/t/using-arduino-and-shift-register-74hc595-for-braille-project/1373221/

#define MONITO 0 // use defined array of characters
// #define MONITOR 1 // use serial monitor for input

char helloWorld[] = "HELLO KITTY WORLD";
int helloWorldSize = sizeof(helloWorld) / sizeof(helloWorld[0]);

byte ledPin[] = {11, 10, 9, 3, 4, 5}; // pins
int ledCount = sizeof(ledPin) / sizeof(ledPin[0]); // number of pins
int playbackRate = 250;

int alphabet[] = {
  //A  B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
  1,   3,  9, 25, 17, 11, 27, 19, 10, 26,  5,  7, 13, 29, 21, 15, 31, 23, 14, 30, 37, 39, 58, 45, 61, 53
};

void setup() {
  Serial.begin(115200); // start serial communications

  for (int i = 0; i < ledCount; i++) // count through LED pins
    pinMode(ledPin[i], OUTPUT); // configure pins for OUTPUT
}

void loop() {
  for (int letter = 0; letter < helloWorldSize; letter++) {
    Serial.print(helloWorld[letter]);
    int letterVal = helloWorld[letter] - 65;
    for (int i = 0; i < 6; i++)
      digitalWrite(ledPin[i], bitRead(alphabet[letterVal], i));
    delay(playbackRate);
    for (int i = 0; i < 6; i++)
      digitalWrite(ledPin[i], LOW);
    delay(playbackRate);
  }
  Serial.println();
  delay(2000);
}

// POSITIONS
// 1 oo 4
// 2 oo 5
// 3 oo 6
// 654321 bit order

// A 000001  F 001011  K 000101  P 001111  U 100101  Z 110101
// B 000011  G 011011  L 000111  Q 011111  V 100111
// C 001001  H 010011  M 001101  R 010111  W 111010
// D 011001  I 001010  N 011101  S 001110  X 101101
// E 010001  J 011010  O 010101  T 011110  Y 111101

// 0 011010  1 000001  2 000011  3 001001  4 011001  5 001011  6 001011  7 011011  8 010011  9 001010

// Number follows 111100 Capital follows 100000
// period         110010 comma           000010
// colon          010010 apostrophe      000100
// question       100110 asterisk/mult   010100
// slash/div      001100 equal           110110
// exclamation    010110 parenthesis     110110
// plus           010110 minus           010010
// openquote      100110 closequote      110100

Version 3 will be Serial Monitor input.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.