Hackster is hosting Impact Spotlights: Industrial Automation. Watch the stream live on Thursday!Hackster is hosting Impact Spotlights: Industrial Automation. Stream on Thursday!
rajdakin
Published © MIT

Morse Encoder & Displayer

This project encodes serial messages into Morse code, and displays the characters on an LCD screen at the same time.

IntermediateShowcase (no instructions)7,232
Morse Encoder & Displayer

Things used in this project

Story

Read more

Schematics

Fritzing file

This is the sketch of this project. Use it with Fritzing.

Code

Arduino file

Arduino
Copy and paste it into your Arduino project editor to use it
#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

#define BUZZER 11

#define SMALLER_DELAY 128

PROGMEM const uint8_t morse_code_a_z[26] = {
  0b01100000, // A .-
  0b10010101, // B -...
  0b10011001, // C -.-.
  0b10010100, // D -..
  0b01000000, // E .
  0b01011001, // F ..-.
  0b10100100, // G --.
  0b01010101, // H ....
  0b01010000, // I ..
  0b01101010, // J .---
  0b10011000, // K -.-
  0b01100101, // L .-..
  0b10100000, // M --
  0b10010000, // N -.
  0b10101000, // O ---
  0b01101001, // P .--.
  0b10100110, // Q --.-
  0b01100100, // R .-.
  0b01010100, // S ...
  0b10000000, // T -
  0b01011000, // U ..-
  0b01010110, // V ...-
  0b01101000, // W .--
  0b10010110, // X -..-
  0b10011010, // Y -.--
  0b10100101, // Z --..
};

void send_bit(const bool& dash) {
  lcd.print(dash ? '-' : '.');
  analogWrite(BUZZER, 63);
  delay((dash ? 3 : 1) * SMALLER_DELAY);
  digitalWrite(BUZZER, LOW);
  delay(1 * SMALLER_DELAY);
}

uint8_t hpos = 0;

void send_char(const char& c) {
  // Send the character to the LCD
  lcd.setCursor(hpos++, 0);
  lcd.print(c);
  
  // Position the cursor to the next line to start the .- sequence
  lcd.setCursor(0, 1);
  lcd.print("     ");
  lcd.setCursor(0, 1);
}

void print_number(const char& number) {
  if (!isDigit(number)) return;

  send_char(number);
  
  uint8_t num = number - '0';
  for (uint8_t i = 0 ; i < 5 ; i++) {
    if (num == i) num += 10;
    
    if (num < 6 + i) send_bit(false);
    else send_bit(true);
  }
}

void print_character(char character) {
  if (!isAlpha(character)) return;

  if (isLowerCase(character)) character += 'A' - 'a';

  send_char(character);

  uint8_t code = morse_code_a_z[character - 'A'];
  while (code != 0) {
    switch (code >> 6) {
      case 0:
      break;
      case 1:
      send_bit(false);
      break;
      case 2:
      send_bit(true);
      break;
      case 3:
      Serial.print("Error while printing character: ");
      Serial.println(character);
      Serial.print("Got 3 in the 2 leftmost bits of code ");
      Serial.println(code, BIN);
      break;
      default:
      Serial.print("Error while printing character: ");
      Serial.println(character);
      Serial.print("Got ? in the 2 leftmost bits of code ");
      Serial.println(code, BIN);
    }
    code <<= 2;
  }
}

void print_whitespace() {
  send_char(' ');
  delay(3 * SMALLER_DELAY);
}

void print_char(const char& character) {
  if (isWhitespace(character)) print_whitespace();
  else if (isAlpha(character)) print_character(character);
  else if (isDigit(character)) print_number(character);
  else if (isPunct(character)) { send_char(character); delay(1 * SMALLER_DELAY); }
  else if (character == '\0') {}
  else if (character == '\1') { /* This happens at the end of every string, don't know why */ }
  else {
    Serial.print("Error: unknown character ");
    Serial.print(character);
    Serial.print(" (0b");
    Serial.print((uint8_t)character, BIN);
    Serial.println(")");
    send_char('?');
    analogWrite(BUZZER, 63);
    delay(4 * SMALLER_DELAY);
    digitalWrite(BUZZER, LOW);
    delay(1 * SMALLER_DELAY);
  }
  
  delay(2 * SMALLER_DELAY);
}

void print_string(const char* characters, int len = 15) {
  for (uint8_t pos = 0 ; pos <= len ; pos++) {
    print_char(characters[pos]);
  }
}

void reset_LCD() {
  hpos = 0;

  lcd.clear();
  lcd.noCursor();
  lcd.setCursor(0, 0);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
  lcd.begin(16, 2);
  reset_LCD();

  pinMode(BUZZER, OUTPUT);
}

char* readStr() {
  uint8_t idx = 0;
  char* str = (char*)malloc(128 * sizeof(char));
  
  while (Serial.available() && idx < 128) {
    str[idx] = Serial.read();
    idx++;
    delay(2);
  }
  for ( ; idx < 128 ; idx++) {
    str[idx] = '\0';
  }

  return str;
}

void serialEvent() {
  while (Serial.available()) {
    char* string;
    Serial.setTimeout(-1);
    string = readStr();
    Serial.print("Received: ");
    Serial.println(string);
    
    char substr[16];
    for (uint8_t c = 0 ; c < 128 && string[c] != '\0' && string[c] != '\r' && string[c] != '\n' ; c += 16) {
      for (uint8_t offset = 0 ; offset < 15 ; offset++) {
        if (string[c + offset] != '\0' && string[c + offset] != '\r' && string[c + offset] != '\n') {
          substr[offset] = string[c + offset];
        } else {
          substr[offset] = '\0';
        }
      }

      reset_LCD();
      print_string(substr);
    }

    free((void*)string);
  }
  lcd.setCursor(0, 1);
  lcd.print("     ");
  lcd.setCursor(0, 0);
}

void loop() {
}

Credits

rajdakin
0 projects • 1 follower
Contact

Comments

Please log in or sign up to comment.