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

Для эксперимента нам потребуется:
  • 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","o","ch","q","y","x","e","u",
  "a",
  "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","o","ch","q","y","x","e","u",
  "a",
  "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 отвечающий за чувствительность к свету в скетче приемника.

Источники


Комментарии (10)


  1. aronsky
    17.07.2015 18:25
    -1

    А почему, всё-таки, код Морзе? И, я так понимаю, вы частотную модуляцию для филтрации различных засветов решили не использовать?


    1. nochkin
      17.07.2015 18:49

      Я так понял, что это больше на поиграться и понять как работают эти компоненты. То есть, без особого практического применения.

      А так я бы решал это с инфракрасным спектром и частотной модуляцией. Тем более, что полно приёмников, а мощный IR светодиод можно взять из старого пульта.


      1. barabanus
        18.07.2015 15:22
        +2

        А еще лучше — метод захвата фазы, позволяющий получать сигнал при отношении сигнал-шум меньше одной тысячной (когда шум больше сигнала в тысячу раз). Он позволяет выделять полезный сигнал на больших расстояниях независимо от внешнего освещения.


    1. Syzd Автор
      20.07.2015 11:43

      я о Морзе знаю с детства и это то что я смог быстро опробовать без спецзнаний. Думаю что многим начинающим ардуинщикам будет интересно попробовать данную схему.


  1. ntfs1984
    17.07.2015 22:00

    А чего так сложно?
    UART вполне с этим справится.

    Кстати получается вполне годная беспроводная связь на сотни метров, и днем и ночью работающая. Единственное условие — жесткое крепление.


  1. Spider55
    18.07.2015 09:24

    Чтобы поиграться — самое оно.


  1. radiolok
    18.07.2015 10:22

    Использование аналогового входа тут кстати можно избежать. Схему можно организовать так, чтобы при неосвещенном фоторезисторе на ноге был нуль, а при освещенном — единица. Правда для этого нужно правильно рассчитать сопротивление второго резистора, дабы обеспечивал такие режимы.


    1. Spider55
      18.07.2015 23:37

      или собрать на компараторе


      1. Syzd Автор
        20.07.2015 11:45

        полез в Гугл узнать что это )))


  1. Antex
    20.07.2015 01:15

    Можно модернизировать под код бодо, и вообще сделать аналог rtty :)