Components and supplies
Laser Transmitter and Receiver
5 key keyboard
Arduino Nano
Apps and platforms
Arduino IDE 2.0 (beta)
Project description
Code
Laser Receiver - Recognising lenth of laser signals and pause durations
cpp
Connect laser sensor to Arduino, detect & measure
1#define Laser_Pin 2 2unsigned long Start; 3unsigned long End; 4unsigned long Signal_Len=0; 5unsigned long Pause_Len=0; 6void setup() { 7 Serial.begin(9600); 8 pinMode(Laser_Pin,INPUT); 9 attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE); 10} 11void Signal_change(){ 12 if(digitalRead(Laser_Pin)==1) { 13 Start=millis(); 14 Pause_Len=Start-End; 15 } 16 else { 17 18 End=millis(); 19 Signal_Len=End-Start; 20 } 21} 22 23void loop() { 24 if (Signal_Len>0){ 25 Serial.print("Signal Start:"); 26 Serial.print(Start); 27 Serial.print(" Signal End:"); 28 Serial.print(End); 29 Serial.print(" Signal Duration:"); 30 Serial.println(Signal_Len); 31 Signal_Len=0; 32 } 33 if (Pause_Len>0){ 34 Serial.print("Pause Start:"); 35 Serial.print(Start); 36 Serial.print(" Pause End:"); 37 Serial.print(End); 38 Serial.print(" Pause Duration:"); 39 Serial.println(Pause_Len); 40 Pause_Len=0; 41 } 42}
Laser Code transmitter -full version
cpp
Text input with OLED & 5-keyboard,see YouTube demo
1// Mario's Ideas 2// Text input using OLED display an 5 Key Keyboard and encoding it to Morse Code 3 4#include <SPI.h> 5#include <Wire.h> 6#include <Adafruit_GFX.h> 7#include <Adafruit_SSD1306.h> 8 9// Oled display size 10#define SCREEN_WIDTH 128 // OLED display width, in pixels 11#define SCREEN_HEIGHT 64 // OLED display height, in pixels 12 13 14 15// Array holding all Morse code letter dot dash combinations 16char MorseCode[26][6] = { 17 {'.','-','x','x','x','A'}, 18 {'-','.','.','.','x','B'}, 19 {'-','.','-','.','x','C'}, 20 {'-','.','.','x','x','D'}, 21 {'.','x','x','x','x','E'}, 22 {'.','.','-','.','x','F'}, 23 {'-','-','.','x','x','G'}, 24 {'.','.','.','.','x','H'}, 25 {'.','.','x','x','x','I'}, 26 {'.','-','-','-','x','J'}, 27 {'-','.','-','x','x','K'}, 28 {'.','-','.','.','x','L'}, 29 {'-','-','x','x','x','M'}, 30 {'-','.','x','x','x','N'}, 31 {'-','-','-','x','x','O'}, 32 {'.','-','-','.','x','P'}, 33 {'-','-','.','-','x','Q'}, 34 {'.','-','.','x','x','R'}, 35 {'.','.','.','x','x','S'}, 36 {'-','x','x','x','x','T'}, 37 {'.','.','-','x','x','U'}, 38 {'.','-','-','x','x','W'}, 39 {'.','.','.','-','x','V'}, 40 {'.','-','-','.','x','X'}, 41 {'-','.','-','-','x','Y'}, 42 {'-','-','.','.','x','Z'}, 43 }; 44 45//Potentiometer PIN A1 46 int Keyboard=A2; 47 48// Variables capturing current and newly calculated position on the letter board (9x3 - 27 postions) 49 int New_X=0; 50 int Old_X=0; 51 int New_Y=0; 52 int Old_Y=0; 53 54// Variable capturing output from Keyboard pin (Values 0 1023) 55 int Key_read=0; 56 int Prev_Key_read=1023; 57 boolean Key_pressed=false; 58 59// String variable holding the text to transmit 60 String To_Transmit=""; 61 62//Unit length 63 int unit=300; 64 65// Length of the text to transmit 66 int To_Transmit_Length=0; 67 68 69// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) 70 #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) 71 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 72 73 74// Used for displaying Leter board 75char Letters[3][9]={"ABCDEFGHI", 76 "JKLMNOPQR", 77 "STUVWXYZ_"}; 78 79 80// Play/Display Morse code representation of the letter 81void Play_Letter (char Letter){ 82 // searching in MorseCode array for the corresponding letter 83 if (Letter=='_') delay(5*unit); else { 84 for (int j=0; j<26; j++){ 85 if (MorseCode[j][5]==Letter) 86 // if the right letter is detected run Play_Dot_Dash for . or - 87 for (int k=0; k<4;k++){ 88 if (MorseCode[j][k]!='x') Play_Dot_Dash(MorseCode[j][k]); 89 } 90 } 91 delay(2*unit); 92 } 93} 94 95// Playing/Displaying . or - 96 97void Play_Dot_Dash(char sign){ 98 if (sign=='.'){ 99 analogWrite(A3, 255); 100 delay(unit); 101 analogWrite(A3,0); 102 delay(unit); 103 } 104 if (sign=='-'){ 105 analogWrite(A3, 255); 106 delay(3*unit); 107 analogWrite(A3, 0); 108 delay(unit); 109 } 110} 111 112void setup() { 113 Serial.begin(9600); 114 115 // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 116 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64 117 Serial.println(F("SSD1306 allocation failed")); 118 for(;;); // Don't proceed, loop forever 119 } 120 121 // Show initial display buffer contents on the screen -- 122 // the library initializes this with an Adafruit splash screen. 123 display.display(); 124 delay(2000); // Pause for 2 seconds 125 126 // Clear the buffer 127 display.clearDisplay(); 128 display.display(); 129 130 // Display filled in rect in the top section of the display when To_Transfer would be output 131 display.fillRect(0, 0, 128, 15, SSD1306_INVERSE); 132 display.drawRect(110, 2, 16, 12, SSD1306_BLACK); 133 display.setTextSize(1); 134 display.setTextColor(SSD1306_BLACK); 135 display.setCursor(113,4); 136 display.println("OK"); 137 display.display(); 138 // Display Letter Board 3 rows 9 character in each row 139 display.setTextSize(2); 140 display.setTextColor(SSD1306_WHITE); 141 for (int j=0; j<3;j++){ 142 for (int i=0; i<9;i++){ 143 display.setCursor(i*12+2*i+1,j*16+17); 144 display.println(Letters[j][i]); 145 delay(10); 146 display.display(); 147 } 148 } 149 150 // Highlight character A by displaying Inverse rect at first position 151 display.fillRect(0, 16, 12, 16, SSD1306_INVERSE); 152 display.display(); 153 154} 155 156void Highlight_letter(int X, int X_Old, int Y, int Y_Old){ 157 // When position changes 158 // Draw the inverse rect in the Old_pos to deactivate the highlight in the old spot 159 // Draw the inverse rect to Highlite the new spot 160 161 // Displaying Inverse rect in a new position to highlight 162 display.fillRect(X*12+2*X, Y*16 +16, 12, 16, SSD1306_INVERSE); 163 164 // Displaying Inverse rect in the old positon to unhighlight 165 display.fillRect(X_Old*12+2*X_Old, Y_Old*16 +16, 12, 16, SSD1306_INVERSE); 166 167 display.display(); 168} 169 170 171void loop() { 172 Key_read =analogRead(Keyboard); 173 if (Prev_Key_read>1000 and Key_read<1000){ 174 Key_pressed=true; 175 if (Key_read<10 and Old_X>0) New_X=Old_X-1; 176 if (Key_read>160 and Key_read<170 and Old_X<9) New_X=Old_X+1; 177 if (Key_read>25 and Key_read<35 and Old_Y>-1) New_Y=Old_Y-1; 178 if (Key_read>80 and Key_read<90 and Old_Y<2 ) New_Y=Old_Y+1; 179 if (Key_read>350 and Key_read<360) { 180 if (New_Y!=-1){ 181 To_Transmit=To_Transmit + Letters[New_Y][New_X]; 182 To_Transmit_Length++; 183 display.setTextSize(1); 184 display.setCursor(3,1); 185 display.setTextColor(BLACK ); 186 display.fillRect(0, 0, 100, 15, SSD1306_WHITE); 187 display.println(To_Transmit); 188 display.display(); 189 } 190 else{ 191 for (int i=0; i<To_Transmit.length();i++ ){ 192 Play_Letter(To_Transmit.charAt(i)); 193 } 194 } 195 } 196 197 if (New_Y==-1 and Old_Y==0){ 198 display.fillRect(110, 2, 16, 12, SSD1306_INVERSE); 199 display.fillRect(Old_X*12+2*Old_X, Old_Y*16 +16, 12, 16, SSD1306_INVERSE); 200 } 201 if (New_Y==0 and Old_Y==-1){ 202 display.fillRect(110, 2, 16, 12, SSD1306_INVERSE); 203 display.fillRect(New_X*12+2*New_X, New_Y*16 +16, 12, 16, SSD1306_INVERSE); 204 Prev_Key_read=Key_read; 205 Old_X=New_X; 206 Old_Y=New_Y;; 207 } 208 if ((Old_X!=New_X or Old_Y!=New_Y) and Old_Y!=-1 ){ 209 if (New_Y!=-1 )Highlight_letter (New_X,Old_X,New_Y,Old_Y); 210 Old_X=New_X; 211 Old_Y=New_Y; 212 } 213 } 214 215 display.display(); 216 Prev_Key_read=Key_read; 217 218}
Laser Morse Code Receiver - Full version
cpp
Reads laser signals, decodes to text,shows on OLED
1#include <Wire.h> 2#include <Adafruit_GFX.h> 3#include <Adafruit_SSD1306.h> 4 5#include <avr/pgmspace.h> 6 7const char alfabeth[] PROGMEM = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; 8 9const char morse_A[] PROGMEM = ".-"; 10const char morse_B[] PROGMEM = "-..."; 11const char morse_C[] PROGMEM = "-.-."; 12const char morse_D[] PROGMEM = "-.."; 13const char morse_E[] PROGMEM = "."; 14const char morse_F[] PROGMEM = "..-."; 15const char morse_G[] PROGMEM = "--."; 16const char morse_H[] PROGMEM = "...."; 17const char morse_I[] PROGMEM = ".."; 18const char morse_J[] PROGMEM = ".---"; 19const char morse_K[] PROGMEM = "-.-"; 20const char morse_L[] PROGMEM = ".-.."; 21const char morse_M[] PROGMEM = "--"; 22const char morse_N[] PROGMEM = "-."; 23const char morse_O[] PROGMEM = "---"; 24const char morse_P[] PROGMEM = ".--."; 25const char morse_Q[] PROGMEM = "--.-"; 26const char morse_R[] PROGMEM = ".-."; 27const char morse_S[] PROGMEM = "..."; 28const char morse_T[] PROGMEM = "-"; 29const char morse_U[] PROGMEM = "..-"; 30const char morse_V[] PROGMEM = "...-"; 31const char morse_W[] PROGMEM = ".--"; 32const char morse_X[] PROGMEM = "-..-"; 33const char morse_Y[] PROGMEM = "-.--"; 34const char morse_Z[] PROGMEM = "--.."; 35 36const char *const morse_code[] PROGMEM = {morse_A, morse_B, morse_C, morse_D, morse_E, morse_F, 37 morse_G, morse_H, morse_I, morse_J, morse_K, morse_L, 38 morse_M, morse_N, morse_O, morse_P, morse_Q, morse_R, 39 morse_S, morse_T, morse_U, morse_V, morse_W, morse_X, 40 morse_Y, morse_Z}; 41 42char buffer[5]; 43#define OLED_RESET -1// Reset pin # (or -1 if sharing Arduino reset pin) 44Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET); 45 46String rcvd=""; 47String Message=""; 48char Matched_Letter; 49int tol=10; 50int unit=300; 51#define LaserPin 2 52int letter_index=-1; 53 54unsigned long Lastrun=0; 55 56unsigned long Start; 57unsigned long End; 58unsigned long Signal_Len=0; 59unsigned long Pause_Len=0; 60 61boolean TransferInProgress=false; 62 63struct MorseCodeSignal{ 64 char Letter; 65 String Signal; 66}; 67 68 69 70 71void setup() { 72 Serial.begin(9600); 73 attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE); 74 75 // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 76 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64 77 Serial.println(F("SSD1306 allocation failed")); 78 for(;;); // Don't proceed, loop forever 79 } 80 81 display.display(); 82 delay(2000); // Pause for 2 seconds 83 84 // Clear the buffer 85 display.clearDisplay(); 86 display.fillRect(0,0,128,16,SSD1306_WHITE); 87 88 89 display.display(); 90} 91 92void DrawSequence(int index, String instr){ 93 int offset_X; 94 int offset_Y; 95 offset_X=9+int(index/6)*43; 96 offset_Y=17+(index-int(index/6)*6)*8; 97 display.fillRect(offset_X-2,offset_Y,2,6,SSD1306_WHITE); 98 for (int i=0; i<instr.length();i++ ){ 99 if(instr.charAt(i)=='.'){ 100 display.fillRect(offset_X,offset_Y,4,6,SSD1306_WHITE); 101 display.fillRect(offset_X,offset_Y+2,2,2,SSD1306_BLACK); 102 offset_X+=4; 103 } 104 if(instr.charAt(i)=='-'){ 105 display.fillRect(offset_X,offset_Y,8,6,SSD1306_WHITE); 106 display.fillRect(offset_X,offset_Y+2,6,2,SSD1306_BLACK); 107 offset_X+=8; 108 } 109 } 110 display.display(); 111} 112 113void DrawLetter(int index, char Letter){ 114 int offset_X; 115 int offset_Y; 116 offset_X=int(index/6)*43; 117 offset_Y=16+(index-int(index/6)*6)*8; 118 display.setCursor(offset_X,offset_Y); 119 display.setTextSize(1); 120 display.setTextColor(SSD1306_WHITE); 121 display.println(Letter); 122 display.display(); 123} 124 125void DrawMessage(String TextIn){ 126 if (TextIn.length()>0){ 127 display.fillRect(0,0,128,16,SSD1306_WHITE); 128 display.setCursor(3,1); 129 display.setTextSize(2); 130 display.setTextColor(SSD1306_BLACK); 131 display.println(TextIn); 132 display.display(); 133 } 134} 135 136void Signal_change(){ 137 if (millis()-Lastrun>10){ 138 if(digitalRead(LaserPin)==1) { 139 Start=millis(); 140 Pause_Len=Start-End; 141 if (TransferInProgress==false) {TransferInProgress=true;rcvd="";} 142 } 143 else { 144 End=millis(); 145 Signal_Len=End-Start; 146 } 147 148 Lastrun=millis(); 149 } 150} 151 152char Match_Letter(String input){ 153 char Matched_letter; 154 String Sequence; 155 for (int i = 0; i < 26; i++) { 156 strcpy_P(buffer, (char *)pgm_read_word(&(morse_code[i]))); // Necessary casts and dereferencing, just copy. 157 Sequence=buffer; 158 if (Sequence==input) Matched_letter=pgm_read_byte_near(alfabeth+i); 159 } 160 return Matched_letter; 161} 162 163void loop() { 164 165 if (TransferInProgress){ 166 if (Signal_Len>0){ 167 if(Signal_Len>=(unit- unit/tol) and Signal_Len<=(unit+unit/tol)) {rcvd+='.';DrawSequence(letter_index,rcvd);} 168 if(Signal_Len>=(3*unit- unit/tol) and Signal_Len<=(3*unit+unit/tol)) {rcvd+='-';DrawSequence(letter_index,rcvd);}; 169 // 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) ) 170 171 Signal_Len=0; 172 } 173 if (Pause_Len>0){ 174 175 if(Pause_Len>(unit- unit/tol) and Signal_Len<(unit+unit/tol)) {;} 176 if(Pause_Len>(3*unit- unit/tol) and Signal_Len<(3*unit+unit/tol)) { 177 Matched_Letter=Match_Letter(rcvd); 178 Message+=Matched_Letter; 179 DrawMessage(Message); 180 Serial.print(Matched_Letter); 181 DrawLetter(letter_index,Matched_Letter); 182 display.display(); 183 Serial.println(rcvd); 184 rcvd=""; 185 letter_index++; 186 Matched_Letter=""; 187 } 188 Pause_Len=0; 189 } 190 if((millis()-End)>8*unit and TransferInProgress){ 191 Matched_Letter=Match_Letter(rcvd); 192 Message+=Matched_Letter; 193 DrawMessage(Message); 194 display.display(); 195 Serial.print(Matched_Letter); 196 DrawLetter(letter_index,Matched_Letter); 197 display.display(); 198 Serial.println(rcvd); 199 rcvd=""; 200 //letter_index=0; 201 TransferInProgress=false; 202 Message=""; 203 Pause_Len=0; 204 } 205 } 206}
Laser Morse code transmitter - simplified version
cpp
Sends coded text: entire alphabet with 300ms unit
1#define Laser_Pin 2 2unsigned long Start; 3unsigned long End; 4unsigned long Signal_Len=0; 5unsigned long Pause_Len=0; 6void setup() { 7 Serial.begin(9600); 8 pinMode(Laser_Pin,INPUT); 9 attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE); 10} 11void Signal_change(){ 12 if(digitalRead(Laser_Pin)==1) { 13 Start=millis(); 14 Pause_Len=Start-End; 15 } 16 else { 17 18 End=millis(); 19 Signal_Len=End-Start; 20 } 21} 22 23 24void loop() { 25 if (Signal_Len>0){ 26 Serial.print("Signal Start:"); 27 Serial.print(Start); 28 Serial.print(" Signal End:"); 29 Serial.print(End); 30 Serial.print(" Signal Duration:"); 31 Serial.println(Signal_Len); 32 Signal_Len=0; 33 } 34 if (Pause_Len>0){ 35 Serial.print("Pause Start:"); 36 Serial.print(Start); 37 Serial.print(" Pause End:"); 38 Serial.print(End); 39 Serial.print(" Pause Duration:"); 40 Serial.println(Pause_Len); 41 Pause_Len=0; 42 } 43}
Laser Morse Code Receiverv - simplified verison
cpp
Decodes signals to text and displays in Serial Mon
1String rcvd=""; 2String Message=""; 3int tol=10; 4int unit=300; 5#define LaserPin 2 6 7unsigned long Lastrun=0; 8 9unsigned long Start; 10unsigned long End; 11unsigned long Signal_Len=0; 12unsigned long Pause_Len=0; 13 14boolean TransferInProgress=false; 15 16struct MorseCodeSignal{ 17 char Letter; 18 String Signal; 19}; 20 21MorseCodeSignal MorseCode[26] = { 22 {'A',".-"}, {'B',"-..."}, {'C',"-.-."}, {'D',"-.."}, {'E',"."}, 23 {'F',"..-."}, {'G',"--."}, {'H',"...."}, {'I',".."}, {'J',".---"}, 24 {'K',"-.-"}, {'L',".-.."}, {'M',"--"}, {'N',"-."}, {'O',"---"}, 25 {'P',".--."}, {'Q',"--.-"}, {'R',".-."}, {'S',"..."}, {'T',"-"}, 26 {'U',"..-"}, {'V',"...-"}, {'W',".--"}, {'X',"-..-"}, {'Y',"-.--"}, 27 {'Z',"--.."} 28 }; 29 30 31void setup() { 32 Serial.begin(9600); 33 attachInterrupt(digitalPinToInterrupt(2), Signal_change,CHANGE); 34} 35 36void Signal_change(){ 37 if (millis()-Lastrun>10){ 38 if(digitalRead(LaserPin)==1) { 39 Start=millis(); 40 Pause_Len=Start-End; 41 if (TransferInProgress==false) {TransferInProgress=true;rcvd="";} 42 } 43 else { 44 End=millis(); 45 Signal_Len=End-Start; 46 } 47 48 Lastrun=millis(); 49 } 50} 51 52char Match_Letter(String input){ 53 char Matched_letter; 54 for (int i=0;i<26;i++){ 55 if(MorseCode[i].Signal==rcvd) Matched_letter=MorseCode[i].Letter; 56 } 57 return Matched_letter; 58} 59 60void loop() { 61 62 if (TransferInProgress){ 63 if (Signal_Len>0){ 64 if(Signal_Len>=(unit- unit/tol) and Signal_Len<=(unit+unit/tol)) {rcvd+='.';} 65 if(Signal_Len>=(3*unit- unit/tol) and Signal_Len<=(3*unit+unit/tol)) rcvd+='-'; 66 // 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) ) 67 68 Signal_Len=0; 69 } 70 if (Pause_Len>0){ 71 72 if(Pause_Len>(unit- unit/tol) and Signal_Len<(unit+unit/tol)) {;} 73 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="";} 74 //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="";} 75 Pause_Len=0; 76 } 77 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="";} 78 } 79}
Documentation
Transmitter Connectivity
How to connect all components
diag2_FgspltGC9X.png
Transmitter Connectivity
How to connect all components
diag2_FgspltGC9X.png
Receiver connectivity
How to connect components
diag1_ZFzjK6s3m3.png
Comments
Only logged in users can leave comments