Hardware components | ||||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
A while back I created the project to encodetext into Morse Code.
Then I was transferring messgares with light and sound signals.
In this project I changed the transmitter I previously created to transmit signals using laser module. I also created the receiver which uses laser receiver module to recognise the laser signals and decode them back to text.
The full two part tutorial cna be found here:
Laser Morse code transmitter - simplified version
ArduinoIt sends text implicitly provided in the code. In this example it sends the whole alfabeth with Unit length 300ms
#define Laser_Pin 2
unsigned long Start;
unsigned long End;
unsigned long Signal_Len=0;
unsigned long Pause_Len=0;
void setup() {
Serial.begin(9600);
pinMode(Laser_Pin,INPUT);
attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE);
}
void Signal_change(){
if(digitalRead(Laser_Pin)==1) {
Start=millis();
Pause_Len=Start-End;
}
else {
End=millis();
Signal_Len=End-Start;
}
}
void loop() {
if (Signal_Len>0){
Serial.print("Signal Start:");
Serial.print(Start);
Serial.print(" Signal End:");
Serial.print(End);
Serial.print(" Signal Duration:");
Serial.println(Signal_Len);
Signal_Len=0;
}
if (Pause_Len>0){
Serial.print("Pause Start:");
Serial.print(Start);
Serial.print(" Pause End:");
Serial.print(End);
Serial.print(" Pause Duration:");
Serial.println(Pause_Len);
Pause_Len=0;
}
}
Laser Receiver - Recognising lenth of laser signals and pause durations
ArduinoConnect the Laser Receiver module to Arduino D2
Load this code and open the serial monitor.
Whenever the sensor detect laser signal it will output its length. It also measures the pauses inbetween the signals
Load this code and open the serial monitor.
Whenever the sensor detect laser signal it will output its length. It also measures the pauses inbetween the signals
#define Laser_Pin 2
unsigned long Start;
unsigned long End;
unsigned long Signal_Len=0;
unsigned long Pause_Len=0;
void setup() {
Serial.begin(9600);
pinMode(Laser_Pin,INPUT);
attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE);
}
void Signal_change(){
if(digitalRead(Laser_Pin)==1) {
Start=millis();
Pause_Len=Start-End;
}
else {
End=millis();
Signal_Len=End-Start;
}
}
void loop() {
if (Signal_Len>0){
Serial.print("Signal Start:");
Serial.print(Start);
Serial.print(" Signal End:");
Serial.print(End);
Serial.print(" Signal Duration:");
Serial.println(Signal_Len);
Signal_Len=0;
}
if (Pause_Len>0){
Serial.print("Pause Start:");
Serial.print(Start);
Serial.print(" Pause End:");
Serial.print(End);
Serial.print(" Pause Duration:");
Serial.println(Pause_Len);
Pause_Len=0;
}
}
Laser Code transmittor -full version
ArduinoIn this version you have text input functionality.
It requires OLED display connected to I2C ports A4 and A5.
And 5 key keybord connected to A2
Check how the functionality works in the Youtube videos linked in the project story
It requires OLED display connected to I2C ports A4 and A5.
And 5 key keybord connected to A2
Check how the functionality works in the Youtube videos linked in the project story
// Mario's Ideas
// Text input using OLED display an 5 Key Keyboard and encoding it to Morse Code
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Oled display size
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Array holding all Morse code letter dot dash combinations
char MorseCode[26][6] = {
{'.','-','x','x','x','A'},
{'-','.','.','.','x','B'},
{'-','.','-','.','x','C'},
{'-','.','.','x','x','D'},
{'.','x','x','x','x','E'},
{'.','.','-','.','x','F'},
{'-','-','.','x','x','G'},
{'.','.','.','.','x','H'},
{'.','.','x','x','x','I'},
{'.','-','-','-','x','J'},
{'-','.','-','x','x','K'},
{'.','-','.','.','x','L'},
{'-','-','x','x','x','M'},
{'-','.','x','x','x','N'},
{'-','-','-','x','x','O'},
{'.','-','-','.','x','P'},
{'-','-','.','-','x','Q'},
{'.','-','.','x','x','R'},
{'.','.','.','x','x','S'},
{'-','x','x','x','x','T'},
{'.','.','-','x','x','U'},
{'.','-','-','x','x','W'},
{'.','.','.','-','x','V'},
{'.','-','-','.','x','X'},
{'-','.','-','-','x','Y'},
{'-','-','.','.','x','Z'},
};
//Potentiometer PIN A1
int Keyboard=A2;
// Variables capturing current and newly calculated position on the letter board (9x3 - 27 postions)
int New_X=0;
int Old_X=0;
int New_Y=0;
int Old_Y=0;
// Variable capturing output from Keyboard pin (Values 0 1023)
int Key_read=0;
int Prev_Key_read=1023;
boolean Key_pressed=false;
// String variable holding the text to transmit
String To_Transmit="";
//Unit length
int unit=300;
// Length of the text to transmit
int To_Transmit_Length=0;
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Used for displaying Leter board
char Letters[3][9]={"ABCDEFGHI",
"JKLMNOPQR",
"STUVWXYZ_"};
// Play/Display Morse code representation of the letter
void Play_Letter (char Letter){
// searching in MorseCode array for the corresponding letter
if (Letter=='_') delay(5*unit); else {
for (int j=0; j<26; j++){
if (MorseCode[j][5]==Letter)
// if the right letter is detected run Play_Dot_Dash for . or -
for (int k=0; k<4;k++){
if (MorseCode[j][k]!='x') Play_Dot_Dash(MorseCode[j][k]);
}
}
delay(2*unit);
}
}
// Playing/Displaying . or -
void Play_Dot_Dash(char sign){
if (sign=='.'){
analogWrite(A3, 255);
delay(unit);
analogWrite(A3,0);
delay(unit);
}
if (sign=='-'){
analogWrite(A3, 255);
delay(3*unit);
analogWrite(A3, 0);
delay(unit);
}
}
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
display.display();
// Display filled in rect in the top section of the display when To_Transfer would be output
display.fillRect(0, 0, 128, 15, SSD1306_INVERSE);
display.drawRect(110, 2, 16, 12, SSD1306_BLACK);
display.setTextSize(1);
display.setTextColor(SSD1306_BLACK);
display.setCursor(113,4);
display.println("OK");
display.display();
// Display Letter Board 3 rows 9 character in each row
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
for (int j=0; j<3;j++){
for (int i=0; i<9;i++){
display.setCursor(i*12+2*i+1,j*16+17);
display.println(Letters[j][i]);
delay(10);
display.display();
}
}
// Highlight character A by displaying Inverse rect at first position
display.fillRect(0, 16, 12, 16, SSD1306_INVERSE);
display.display();
}
void Highlight_letter(int X, int X_Old, int Y, int Y_Old){
// When position changes
// Draw the inverse rect in the Old_pos to deactivate the highlight in the old spot
// Draw the inverse rect to Highlite the new spot
// Displaying Inverse rect in a new position to highlight
display.fillRect(X*12+2*X, Y*16 +16, 12, 16, SSD1306_INVERSE);
// Displaying Inverse rect in the old positon to unhighlight
display.fillRect(X_Old*12+2*X_Old, Y_Old*16 +16, 12, 16, SSD1306_INVERSE);
display.display();
}
void loop() {
Key_read =analogRead(Keyboard);
if (Prev_Key_read>1000 and Key_read<1000){
Key_pressed=true;
if (Key_read<10 and Old_X>0) New_X=Old_X-1;
if (Key_read>160 and Key_read<170 and Old_X<9) New_X=Old_X+1;
if (Key_read>25 and Key_read<35 and Old_Y>-1) New_Y=Old_Y-1;
if (Key_read>80 and Key_read<90 and Old_Y<2 ) New_Y=Old_Y+1;
if (Key_read>350 and Key_read<360) {
if (New_Y!=-1){
To_Transmit=To_Transmit + Letters[New_Y][New_X];
To_Transmit_Length++;
display.setTextSize(1);
display.setCursor(3,1);
display.setTextColor(BLACK );
display.fillRect(0, 0, 100, 15, SSD1306_WHITE);
display.println(To_Transmit);
display.display();
}
else{
for (int i=0; i<To_Transmit.length();i++ ){
Play_Letter(To_Transmit.charAt(i));
}
}
}
if (New_Y==-1 and Old_Y==0){
display.fillRect(110, 2, 16, 12, SSD1306_INVERSE);
display.fillRect(Old_X*12+2*Old_X, Old_Y*16 +16, 12, 16, SSD1306_INVERSE);
}
if (New_Y==0 and Old_Y==-1){
display.fillRect(110, 2, 16, 12, SSD1306_INVERSE);
display.fillRect(New_X*12+2*New_X, New_Y*16 +16, 12, 16, SSD1306_INVERSE);
Prev_Key_read=Key_read;
Old_X=New_X;
Old_Y=New_Y;;
}
if ((Old_X!=New_X or Old_Y!=New_Y) and Old_Y!=-1 ){
if (New_Y!=-1 )Highlight_letter (New_X,Old_X,New_Y,Old_Y);
Old_X=New_X;
Old_Y=New_Y;
}
}
display.display();
Prev_Key_read=Key_read;
}
Laser Morse Code Receiverv - simplified verison
ArduinoIt receognises signals decodes them to text and displays the result in Serial Monitor
String rcvd="";
String Message="";
int tol=10;
int unit=300;
#define LaserPin 2
unsigned long Lastrun=0;
unsigned long Start;
unsigned long End;
unsigned long Signal_Len=0;
unsigned long Pause_Len=0;
boolean TransferInProgress=false;
struct MorseCodeSignal{
char Letter;
String Signal;
};
MorseCodeSignal MorseCode[26] = {
{'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',"--.."}
};
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE);
}
void Signal_change(){
if (millis()-Lastrun>10){
if(digitalRead(LaserPin)==1) {
Start=millis();
Pause_Len=Start-End;
if (TransferInProgress==false) {TransferInProgress=true;rcvd="";}
}
else {
End=millis();
Signal_Len=End-Start;
}
Lastrun=millis();
}
}
char Match_Letter(String input){
char Matched_letter;
for (int i=0;i<26;i++){
if(MorseCode[i].Signal==rcvd) Matched_letter=MorseCode[i].Letter;
}
return Matched_letter;
}
void loop() {
if (TransferInProgress){
if (Signal_Len>0){
if(Signal_Len>=(unit- unit/tol) and Signal_Len<=(unit+unit/tol)) {rcvd+='.';}
if(Signal_Len>=(3*unit- unit/tol) and Signal_Len<=(3*unit+unit/tol)) rcvd+='-';
// if(Signal_Len<(unit- unit*tolerance/100) or (Signal_Len>(unit+unit*tolerance/100)and Signal_Len<(3*unit- unit*tolerance/100)) or Signal_Len>(3*unit+unit*tolerance/100) )
Signal_Len=0;
}
if (Pause_Len>0){
if(Pause_Len>(unit- unit/tol) and Signal_Len<(unit+unit/tol)) {;}
if(Pause_Len>(3*unit- unit/tol) and Signal_Len<(3*unit+unit/tol)) {Message+=Match_Letter(rcvd);Serial.print(Match_Letter(rcvd));Serial.print(rcvd);rcvd="";}
//if(Pause_Len>(5*unit- unit*tolerance/100) and Signal_Len<(5*unit+unit*tolerance/100)) {Message+=Match_Letter(rcvd);Message+=" ";Serial.print(Message);Serial.println(rcvd);rcvd="";}
Pause_Len=0;
}
if((millis()-End)>8*unit and TransferInProgress){Serial.print(Match_Letter(rcvd));Serial.println(rcvd);Message+=Match_Letter(rcvd);Serial.println(Message);rcvd="";TransferInProgress=false;Message="";}
}
}
Laser Morse Code Receiver - Full version
ArduinoIt reads Laser Signals , decodes then into text and displays the result on OLED display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/pgmspace.h>
const char alfabeth[] PROGMEM = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
const char morse_A[] PROGMEM = ".-";
const char morse_B[] PROGMEM = "-...";
const char morse_C[] PROGMEM = "-.-.";
const char morse_D[] PROGMEM = "-..";
const char morse_E[] PROGMEM = ".";
const char morse_F[] PROGMEM = "..-.";
const char morse_G[] PROGMEM = "--.";
const char morse_H[] PROGMEM = "....";
const char morse_I[] PROGMEM = "..";
const char morse_J[] PROGMEM = ".---";
const char morse_K[] PROGMEM = "-.-";
const char morse_L[] PROGMEM = ".-..";
const char morse_M[] PROGMEM = "--";
const char morse_N[] PROGMEM = "-.";
const char morse_O[] PROGMEM = "---";
const char morse_P[] PROGMEM = ".--.";
const char morse_Q[] PROGMEM = "--.-";
const char morse_R[] PROGMEM = ".-.";
const char morse_S[] PROGMEM = "...";
const char morse_T[] PROGMEM = "-";
const char morse_U[] PROGMEM = "..-";
const char morse_V[] PROGMEM = "...-";
const char morse_W[] PROGMEM = ".--";
const char morse_X[] PROGMEM = "-..-";
const char morse_Y[] PROGMEM = "-.--";
const char morse_Z[] PROGMEM = "--..";
const char *const morse_code[] PROGMEM = {morse_A, morse_B, morse_C, morse_D, morse_E, morse_F,
morse_G, morse_H, morse_I, morse_J, morse_K, morse_L,
morse_M, morse_N, morse_O, morse_P, morse_Q, morse_R,
morse_S, morse_T, morse_U, morse_V, morse_W, morse_X,
morse_Y, morse_Z};
char buffer[5];
#define OLED_RESET -1// Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
String rcvd="";
String Message="";
char Matched_Letter;
int tol=10;
int unit=300;
#define LaserPin 2
int letter_index=-1;
unsigned long Lastrun=0;
unsigned long Start;
unsigned long End;
unsigned long Signal_Len=0;
unsigned long Pause_Len=0;
boolean TransferInProgress=false;
struct MorseCodeSignal{
char Letter;
String Signal;
};
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
display.fillRect(0,0,128,16,SSD1306_WHITE);
display.display();
}
void DrawSequence(int index, String instr){
int offset_X;
int offset_Y;
offset_X=9+int(index/6)*43;
offset_Y=17+(index-int(index/6)*6)*8;
display.fillRect(offset_X-2,offset_Y,2,6,SSD1306_WHITE);
for (int i=0; i<instr.length();i++ ){
if(instr.charAt(i)=='.'){
display.fillRect(offset_X,offset_Y,4,6,SSD1306_WHITE);
display.fillRect(offset_X,offset_Y+2,2,2,SSD1306_BLACK);
offset_X+=4;
}
if(instr.charAt(i)=='-'){
display.fillRect(offset_X,offset_Y,8,6,SSD1306_WHITE);
display.fillRect(offset_X,offset_Y+2,6,2,SSD1306_BLACK);
offset_X+=8;
}
}
display.display();
}
void DrawLetter(int index, char Letter){
int offset_X;
int offset_Y;
offset_X=int(index/6)*43;
offset_Y=16+(index-int(index/6)*6)*8;
display.setCursor(offset_X,offset_Y);
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.println(Letter);
display.display();
}
void DrawMessage(String TextIn){
if (TextIn.length()>0){
display.fillRect(0,0,128,16,SSD1306_WHITE);
display.setCursor(3,1);
display.setTextSize(2);
display.setTextColor(SSD1306_BLACK);
display.println(TextIn);
display.display();
}
}
void Signal_change(){
if (millis()-Lastrun>10){
if(digitalRead(LaserPin)==1) {
Start=millis();
Pause_Len=Start-End;
if (TransferInProgress==false) {TransferInProgress=true;rcvd="";}
}
else {
End=millis();
Signal_Len=End-Start;
}
Lastrun=millis();
}
}
char Match_Letter(String input){
char Matched_letter;
String Sequence;
for (int i = 0; i < 26; i++) {
strcpy_P(buffer, (char *)pgm_read_word(&(morse_code[i]))); // Necessary casts and dereferencing, just copy.
Sequence=buffer;
if (Sequence==input) Matched_letter=pgm_read_byte_near(alfabeth+i);
}
return Matched_letter;
}
void loop() {
if (TransferInProgress){
if (Signal_Len>0){
if(Signal_Len>=(unit- unit/tol) and Signal_Len<=(unit+unit/tol)) {rcvd+='.';DrawSequence(letter_index,rcvd);}
if(Signal_Len>=(3*unit- unit/tol) and Signal_Len<=(3*unit+unit/tol)) {rcvd+='-';DrawSequence(letter_index,rcvd);};
// if(Signal_Len<(unit- unit*tolerance/100) or (Signal_Len>(unit+unit*tolerance/100)and Signal_Len<(3*unit- unit*tolerance/100)) or Signal_Len>(3*unit+unit*tolerance/100) )
Signal_Len=0;
}
if (Pause_Len>0){
if(Pause_Len>(unit- unit/tol) and Signal_Len<(unit+unit/tol)) {;}
if(Pause_Len>(3*unit- unit/tol) and Signal_Len<(3*unit+unit/tol)) {
Matched_Letter=Match_Letter(rcvd);
Message+=Matched_Letter;
DrawMessage(Message);
Serial.print(Matched_Letter);
DrawLetter(letter_index,Matched_Letter);
display.display();
Serial.println(rcvd);
rcvd="";
letter_index++;
Matched_Letter="";
}
Pause_Len=0;
}
if((millis()-End)>8*unit and TransferInProgress){
Matched_Letter=Match_Letter(rcvd);
Message+=Matched_Letter;
DrawMessage(Message);
display.display();
Serial.print(Matched_Letter);
DrawLetter(letter_index,Matched_Letter);
display.display();
Serial.println(rcvd);
rcvd="";
//letter_index=0;
TransferInProgress=false;
Message="";
Pause_Len=0;
}
}
}
Comments