Лазерная связь между двумя Arduino кодом Морзе

от автора

Почему лазерный луч, а не радиосвязь? Ради фана. С целью обеспечения секретности, радиопередачи перехватывают все кому не лень, а перехватывать вспышки света не догадаются, к тому же нужно встать в направлении передачи луча. Возможно использовать там, где радиосвязь невозможна из-за сильных помех.

Для эксперимента нам потребуется:

  • 2 Arduino;
  • 1 Фоторезистор (или LDR) VT90N — компонент, меняющий сопротивление в зависимости от количества света падающего на него. В полной темноте он имеет максимальное сопротивление в сотни килоом, а по мере роста освещённости сопротивление уменьшается до десятков килоом:

  • 1 лазерный модуль KY-008:

  • 2 сопротивления: 220 Ом для передатчика,10 кОм для приемника.

Передатчик

Передатчик подключается как самая простая схема в Ардуине (Blink), можно поморгать код Морзе и обычным светодиодом, но на небольшое расстояние, для передачи на метровые расстояния придется воспользоваться лазером. Лазер можно взять или из лазерной указки или купить в магазине специальный модуль для Ардуино с 3 контактами:


Схема подключения лазера к Ардуино:

Так как KY-008 part не нашлась в fritzing на схеме пришлось использовать RGB светодиод, подписав ноги S и “-“, S пин подключаем к 13 ноге, минус к GND (земле).

Для передачи данных воспользуемся кодом Морзе — способ представления букв алфавита последовательностью длинных («тире») и коротких («точка») сигналов. Конечно, при передаче кодом Морзе нет коррекции ошибок, но для тестовой передачи можно обойтись и без нее. Так как мы все равно знаем последовательность передаваемых символов.

В коде скетча указываем на каком контакте будет подаваться морзянка, 13 нога (как для большинства blink.ino скетчей моргания светодиодом), второй параметр отвечает за скорость передачи (24 слов в минуту), 3 параметр 1 для beep звукового сигнала и 0 для PTT (переключение пина в HIGH и LOW). Если заглянуть в код Morse.cpp то увидим что для третьего параметра 1 – beep используется как аналоговый выход запись на пин:

analogWrite(_pin, 128);
delay(_dashlen);
analogWrite(_pin, 0);
delay(_dotlen);
а для 0 – используется как цифровой выход
digitalWrite(_pin, HIGH);
delay(_dashlen);
digitalWrite(_pin, LOW);
delay(_dotlen);

В нашем случае используем код: Morse morse(13, 24, 0);

Для работы скетча необходима библиотекой morze.zip автора Erik Linder. Скетч передатчика простой:

скетч передатчика

// Author Erik Linder // Released 2011 under GNU GPLv3 // // Usage: morse( <pin number>, <speed WPM>, <1=beep, 0=PTT> ) //        sendmsg( "<text-to-send>" ) //  #include <Morse.h>  // Use pin 13 (built-in LED of Arduino 2009) Morse morse(13, 24, 1);  void setup() {  }  void loop() {   morse.sendmsg("HELLO WORLD!");   delay (2000); }  

Заливаем скетч, система готова к передаче данных.

Приемник

Собираем схему приемника, ничего сложного, фоторезистор одна нога с 5V вторая нога аналоговый порт A0, резистор 10 кОм — одна нога GND («земля»), вторая нога A0:

скетч приемника

int LDR_Pin = A0; //analog pin 0 int led = 13;  // 10k between GND and A0 // LDR between 5V and A0  #define MORSE_EMPTY   0 // Этими символами мы будем обозначать точки и тире. #define MORSE_DOT     '*' #define MORSE_DOT2     '+' #define MORSE_TIRE    '-' // Максимальная длина символа азбуки Морзе (в точках и тире) #define MAX_MORSE_SYMBOL_LENGTH  8 char* morseSymbol[MAX_MORSE_SYMBOL_LENGTH]; unsigned int morseSymbolLen; char* newMorseSignal; // Новый введенный сигнал - точка или тире.  // Таблица кодов Морзе. N-ный элемент кода соответствует n-ному символу раскладки. char* code[] = {   "*-","-***","*--","--*","-**","*","***-","--**","**","*---",   "-*-","*-**","--","-*","---","*--*","*-*","***","-","**-",   "**-*","****","-*-*","---*","----","--*-","-*--","-**-","**-**","**--",   "*-*-",   "*----","**---","***--","****-","*****","-****","--***","---**","----*","-----",   "......","*-*-*-","---***","-*-*-","-*--*-","*----*","*-**-*","-****-","-**-*","**--**","--**--",   "-***-","********","*--*-*","**-*-",   "" };  // Кириллическая раскладка. char* layoutCyrillic[] = {   "а","б","в","г","д","е","ж","з","и","й",   "к","л","м","н","о","п","р","с","т","у",   "ф","х","ц","ч","ш","щ","ы","ь","э","ю",   "я",   "1","2","3","4","5","6","7","8","9","0",   ".",",",":",";","(","\'","\"","-","/","?","!",   " *DELIMITER* "," *ERR* ","@"," *END* ",   ""   }; // Латинская раскладка. char* layoutLatin[] = {   "a","b","w","g","d","e","v","z","i","j",   "k","l","m","n","o","p","r","s","t","u",   "f","h","c","ö","ch","q","y","x","é","ü",   "ä",   "1","2","3","4","5","6","7","8","9","0",   ".",",",":",";","(","\'","\"","-","/","?","!",   " *DELIMITER* "," *ERR* ","@"," *END* ",   "" };  char** currentLayout; char** newLayout;   void setup(){   Serial.begin(9600);   pinMode(led, OUTPUT);      morseSymbolLen = 0;      newMorseSignal = MORSE_EMPTY;    } int counter_high = 0; int counter_low = 0; int i; void loop(){    int LDRReading = analogRead(LDR_Pin);    if (LDRReading >= 800){   counter_high++ ;    if ( counter_low > 0 ){   //  Serial.print("Low\t");  //   Serial.print(counter_low); //     Serial.print("\n");    }    if ( counter_low > 1200) {     //  for (i = 0; i< morseSymbolLen; i++) {          // Serial.print( currentLayout[i]);     // }     sendMorseSymbol();     morseSymbolLen=0;       Serial.println();     //currentLayout[0]=" ";     //currentLayout[1]=" ";     //currentLayout[2]=" ";     //currentLayout[3]=" ";     //currentLayout[4]=" ";     //currentLayout[5]=" ";     //currentLayout[6]=" ";     //currentLayout[7]=" ";     //currentLayout[8]=" ";     //morseSymbolLen=0;   }      counter_low=0;      digitalWrite(led, HIGH);       } else { //   Serial.print(".");   counter_low++;   if ( counter_high > 0 ){ //      Serial.print("High\t");   //   Serial.print(counter_high);    }   if ( (counter_high < 1200 ) &&( counter_high >350)){ //      Serial.print(counter_high);     Serial.print(".");     newMorseSignal="*";     morseSymbol[morseSymbolLen++] = newMorseSignal;    // currentLayout[morseSymbolLen]=".";    // morseSymbolLen=morseSymbolLen+1;   }   if ( counter_high > 1200 ){  //         Serial.print(counter_high);         Serial.print("-");         newMorseSignal="-";         morseSymbol[morseSymbolLen++] = newMorseSignal;        // currentLayout[morseSymbolLen]="-";        //     morseSymbolLen=morseSymbolLen+1;   }        counter_high=0;       digitalWrite(led, LOW);    }    } void sendMorseSymbol() {   boolean est;   int i, j;   est=-1;   if (morseSymbolLen < 1) {     return;   }       Serial.print(morseSymbolLen);           // Символ из таблицы кодов Морзе соответствует введенному символу.       //  Отправим символ на компьютер.     String str1;     String strm;     str1="";     for (i=0;i<morseSymbolLen;i++){        str1=str1+morseSymbol[i];     }    //  Serial.print(code[6]);                               for (i=0;i<56;i++){       String str2(code[i]);                  if (str1.compareTo(str2)==0){         //Serial.print(str1);        // Serial.print("est");        Serial.print(str2);        est=true;       break;       }        }       if (est!=-1){       Serial.print(layoutLatin[i]);           }       morseSymbolLen = 0;       return;     }  

Приемник с LCD экраном

Полученные данные выводятся в COM порт, это конечно здорово, но не наглядно и требует наличие включенного компьютера. Поэтому подключаем 2 строчный экран с I2C подключением:

Для экрана SDA подключаем ногу arduino UNO A5, SCL – A4, VCC экрана к 5V, GND к GND:

Добавляем в скетче приемника receiver.ino строки отвечающие за вывод на 2 строчный LCD экран. Можно теперь уйти в поле с компактным приемником и прочитать сообщение прямо с LCD экрана.

скетч приемника с LCD экраном

#include <LCD.h> #include <LiquidCrystal_I2C.h>  #include <Wire.h> // Define I2C Address where the PCF8574* is #define I2C_ADDR    0x27    // Define LCD Pins #define BACKLIGHT_PIN     3 #define En_pin  2 #define Rw_pin  1 #define Rs_pin  0 #define D4_pin  4 #define D5_pin  5 #define D6_pin  6 #define D7_pin  7   // Initialize LiquadCrystal with pin setup LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);   int pos_lcd,pos_lcd2;     int LDR_Pin = A0; //analog pin 0 int led = 13;  // 10k between GND and A0 // LDR between 5V and A0  // настроить чувствительность фотоэлемента #define LEVEL_LDR    800  #define MORSE_EMPTY   0  // Этими символами мы будем обозначать точки и тире. #define MORSE_DOT     '*' #define MORSE_DASH    '-'     //Длина точки и тире для 24 слов в минуту (wpm) = 150 мс и 700 мс,   // Для 12 wpm = 700 и 1200  #define MORSE_TIME_DOT 150 #define MORSE_TIME_DASH 700  // Максимальная длина символа азбуки Морзе (в точках и тире) #define MAX_MORSE_SYMBOL_LENGTH  8 char* morseSymbol[MAX_MORSE_SYMBOL_LENGTH]; unsigned int morseSymbolLen; char* newMorseSignal; // Новый введенный сигнал - точка или тире.  // Таблица кодов Морзе. N-ный элемент кода соответствует n-ному символу раскладки. char* code[] = {   "*-","-***","*--","--*","-**","*","***-","--**","**","*---",   "-*-","*-**","--","-*","---","*--*","*-*","***","-","**-",   "**-*","****","-*-*","---*","----","--*-","-*--","-**-","**-**","**--",   "*-*-",   "*----","**---","***--","****-","*****","-****","--***","---**","----*","-----",   "......","*-*-*-","---***","-*-*-","-*--*-","*----*","*-**-*","-****-","-**-*","**--**","--**--",   "-***-","********","*--*-*","**-*-",   "" };  // Кириллическая раскладка. char* layoutCyrillic[] = {   "а","б","в","г","д","е","ж","з","и","й",   "к","л","м","н","о","п","р","с","т","у",   "ф","х","ц","ч","ш","щ","ы","ь","э","ю",   "я",   "1","2","3","4","5","6","7","8","9","0",   ".",",",":",";","(","\'","\"","-","/","?","!",   " *DELIMITER* "," *ERR* ","@"," *END* ",   ""   }; // Латинская раскладка. char* layoutLatin[] = {   "a","b","w","g","d","e","v","z","i","j",   "k","l","m","n","o","p","r","s","t","u",   "f","h","c","ö","ch","q","y","x","é","ü",   "ä",   "1","2","3","4","5","6","7","8","9","0",   ".",",",":",";","(","\'","\"","-","/","?","!",   " *DELIMITER* "," *ERR* ","@"," *END* ",   "" };    void setup(){   Serial.begin(9600);      pos_lcd=0;   lcd.begin (16,2);     // Switch on the backlight   lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);   lcd.setBacklight(HIGH);     // Reset cursor to home   lcd.home ();                      // Print Hello World  // lcd.print("GOTOV priem");             pinMode(led, OUTPUT);      morseSymbolLen = 0;      newMorseSignal = MORSE_EMPTY;    } int counter_high = 0; int counter_low = 0; int i; void loop(){    int LDRReading = analogRead(LDR_Pin);    if (LDRReading >= LEVEL_LDR){   counter_high++ ;     if ( counter_low > MORSE_TIME_DASH) {     sendMorseSymbol();     morseSymbolLen=0;   }       counter_low=0;      digitalWrite(led, HIGH);       } else {   counter_low++;    if ( (counter_high < MORSE_TIME_DASH ) &&( counter_high >MORSE_TIME_DOT)){     Serial.print(".");     newMorseSignal="*";     morseSymbol[morseSymbolLen++] = newMorseSignal;   }   if ( counter_high > MORSE_TIME_DASH ){         Serial.print("-");         newMorseSignal="-";         morseSymbol[morseSymbolLen++] = newMorseSignal;    }        counter_high=0;       digitalWrite(led, LOW);    }    } void sendMorseSymbol()  {   boolean est;   int i, j;   est=-1;   if (morseSymbolLen < 1)  	{ 	return; 	}              // Символ из таблицы кодов Морзе соответствует введенному символу.       //  Отправим символ на компьютер.     String str1;     str1="";     for (i=0;i<morseSymbolLen;i++) 	{   	str1=str1+morseSymbol[i]; 	}                 for (i=0;i<56;i++) 	{ 	String str2(code[i]); 	if (str1.compareTo(str2)==0) 		{ 		Serial.print(str2); 		est=true; 		break; 		}        }              if (est!=-1) 	{ 	Serial.print(layoutLatin[i]);    //   Вывод символа на LCD экран 	if (pos_lcd>16 )  		{ 		Serial.print("vtorayStroka"); 		pos_lcd2=pos_lcd-17;   		Serial.print(pos_lcd); 		lcd.setCursor(pos_lcd2,1 ); //Пишем в LCD на 2 строк 		} 	pos_lcd=pos_lcd+1;    	if (pos_lcd>32)  		{ 		lcd.clear(); 		pos_lcd=0; 		} 	lcd.print(layoutLatin[i]);  	lcd.setBacklight(HIGH);     // Backlight on 	}       morseSymbolLen = 0;       return;     }  

Итоги

Данный способ передачи успешно работал у меня как и в комнате вечером на расстоянии 0,5–3 метра, так и вечером на улице на расстоянии 7–14 м. Большие расстояния пока не были опробованы. Передача днем потребует светозащищенной трубы чтобы на фотоэлемент не падал солнечный и дневной свет, а только свет от лазера или нужно поиграться параметром LEVEL_LDR отвечающий за чувствительность к свету в скетче приемника.

Источники

ссылка на оригинал статьи http://geektimes.ru/post/258948/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *