Morse Code IR Transmitter

Morse Code IR Transmitter

HARDWARE REQUIRED:

  • PICUNO Microcontroller board
  • 1 × HW-489 TR Emission Module
  • Jumper wires
  • USB cable

DESCRIPTION:

This project creates a transmitter that converts text into International Morse Code and sends it as a series of long and short flashes of invisible infrared light. The user can type a message into the Serial Monitor, and the microcontroller will look up each character, translate it to the corresponding dot-dash pattern, and transmit it with precise timing. The transmitted signal can be seen using any smartphone camera, demonstrating the principles of data encoding and wireless signal transmission.

CIRCUIT DIAGRAM:

Morse Code IR Transmitter
  • Connect the GND pin (-) of the IR Emitter module to GND on PICUNO.
  • Connect the VCC pin (+) of the IR Emitter module to 3.3V
  • Connect the Signal pin (S) of the IR Emitter module to GPIO 8.

SCHEMATIC:

IR Emitter Module VCC → 3.3V

IR Emitter Module GND → GND

IR Module Signal → GPIO 8

CODE -- C:

const int IR_PIN = 8;

const int DOT_DURATION = 200;
const int DASH_DURATION = DOT_DURATION * 3;
const int SYMBOL_SPACE = DOT_DURATION;
const int LETTER_SPACE = DOT_DURATION * 3;
const int WORD_SPACE = DOT_DURATION * 7;

// Morse Code Look-up Table
const char* MORSE_CODE[] = {
  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", // A-Z
  "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----." // 0-9
};

void setup() {
  pinMode(IR_PIN, OUTPUT);
  Serial.begin(9600);
  Serial.println("Enter a message to transmit in Morse Code:");
}

void transmit(char* message) {
  for (int i = 0; message[i] != '\\0'; i++) {
    char c = toupper(message[i]);
    const char* morse_pattern;

    if (c >= 'A' && c <= 'Z') {
      morse_pattern = MORSE_CODE[c - 'A'];
    } else if (c >= '0' && c <= '9') {
      morse_pattern = MORSE_CODE[c - '0' + 26];
    } else if (c == ' ') {
      delay(WORD_SPACE);
      continue;
    } else {
      continue; // Ignore unknown characters
    }

    for (int j = 0; morse_pattern[j] != '\\0'; j++) {
      digitalWrite(IR_PIN, HIGH); // Turn IR LED ON
      if (morse_pattern[j] == '.') {
        delay(DOT_DURATION);
      } else { // It's a dash
        delay(DASH_DURATION);
      }
      digitalWrite(IR_PIN, LOW); // Turn IR LED OFF
      delay(SYMBOL_SPACE); // Space between dots/dashes
    }
    delay(LETTER_SPACE - SYMBOL_SPACE); // Space between letters
  }
}

void loop() {
  if (Serial.available() > 0) {
    String message = Serial.readString();
    message.trim();
    if (message.length() > 0) {
      Serial.print("Transmitting: ");
      Serial.println(message);
      
      // Convert String to char array for the function
      char char_buffer[message.length() + 1];
      message.toCharArray(char_buffer, message.length() + 1);
      
      transmit(char_buffer);
      Serial.println("\\nTransmission complete. Enter new message:");
    }
  }
}
const int DOT_DURATION = 200; - This base unit defines the entire timing scheme. A dash is 3 dots long, the space between letters is 3 dots, etc.

const char* MORSE_CODE[] - This array is the "dictionary" that holds the dot-dash patterns for each letter and number.

transmit() - This is the main function. It loops through each character of your message, finds its pattern in the MORSE_CODE array, and then loops through that pattern to flash the IR LED for the correct dot or dash duration.

if (Serial.available() > 0) - The main loop waits for you to type a message into the Arduino IDE's Serial Monitor and press Enter.

CODE -- PYTHON:

from machine import Pin
from time import sleep_ms

ir_pin = Pin(8, Pin.OUT)

DOT_DURATION = 200
DASH_DURATION = DOT_DURATION * 3
SYMBOL_SPACE = DOT_DURATION
LETTER_SPACE = DOT_DURATION * 3
WORD_SPACE = DOT_DURATION * 7

# Morse Code Dictionary
MORSE_CODE_DICT = {
    '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': '.----', '2': '..---', '3': '...--',
    '4': '....-', '5': '.....', '6': '-....", '7': '--...', '8': '---..',
    '9': '----.', '0': '-----'
}

def transmit(message):
    for char in message.upper():
        if char == ' ':
            sleep_ms(WORD_SPACE)
        elif char in MORSE_CODE_DICT:
            pattern = MORSE_CODE_DICT[char]
            for symbol in pattern:
                ir_pin.on()
                if symbol == '.':
                    sleep_ms(DOT_DURATION)
                else: # It's a dash
                    sleep_ms(DASH_DURATION)
                ir_pin.off()
                sleep_ms(SYMBOL_SPACE)
            sleep_ms(LETTER_SPACE - SYMBOL_SPACE)

# --- Main Loop with User Input ---
print("Ready for input.")
while True:
    message = input("Enter a message to transmit: ")
    
    if len(message) > 0:
        print(f"Transmitting: {message.upper()}")
        transmit(message)
        print("Transmission complete.")
        print("-------------------------")
MORSE_CODE_DICT - This dictionary is the core of the translator. It maps each character (the "key") to its dot-dash pattern (the "value").

transmit() - This function takes a message string. It loops through each character, looks up its pattern in the dictionary, and then flashes the IR LED according to the pattern.

ir_pin.on() / ir_pin.off() - These commands turn the IR LED on and off.

sleep_ms() - This function creates the precise delays needed for dots, dashes, and the spaces between letters and words, which is critical for valid Morse code.