среда, 5 сентября 2018 г.

Азбука Морзе на Arduino


Для обоих скетчей одна схема

светодиод - пин 10
пищалка   - пин 12

кнопка            - пин 8
фоторезистор - пин A0





// *************************************************************************
//
//  ВВОД СИМВОЛОВ АЗБУКИ МОРЗЕ НАЖАТИЕМ КНОПКИ 
//  ИЛИ ПЕРЕКРЫВАНИЕМ ПОПАДАНИЯ СВЕТА НА ФОТОРЕЗИСТОР. 
//
// Добавляем ввод символов через кнопку. Чтобы работать кнопкой а не через фоторезистор
// нужно #define WORK_ON FOTORESISTOR заменить на #define WORK_ON BUTTON
//
// Рабочий вариант с разделением на буквы и слова
// 
//
#define FOTORESISTOR 1
#define BUTTON 2

// #define WORK_ON FOTORESISTOR
#define WORK_ON BUTTON


#define ST_BEGIN           1
#define ST_SIGNAL_ON       2
#define ST_SIGNAL_OFF      3
#define ST_WAIT_SIGNAL_ON  4
#define ST_WAIT_COMMAND    5

const uint16_t  minVolume = 300;      //--  Определяем константу с уровнем входного сигнала отделяющую длительность точек и тире
                                      //--  (принимаются только те сигналы, громкость которых выше указанного уровня)

const uint16_t  min_point_long = 10;  //-- длительность сигнала меньше которого не воспринимается точка 
      uint16_t  point_long = 300;     //-- длительность точки
      uint16_t  next_letter_long = point_long * 3; //-- пауза между буквами 
      uint16_t  word_long = point_long * 7;        //-- пауза между словами
      uint16_t  command_long = point_long * 20;    //-- пауза после которой преходит в режим ввода команд

      uint32_t  tm_sig_start;
      uint32_t  tm_sig_stop;                                      
      uint32_t  tm_pause_start;                                      
      uint32_t  tm_pause_stop;                                      
      uint32_t  signal_long;          //-- длительность сигнала

      uint8_t   varLetter;            //  Объявляем переменную для хранения принятых точек и тире одного символа (бит 0 - точка, бит 1 - тире)
      uint8_t   lenLetter;            //  Объявляем переменную для хранения количества точек и тире в принятом символе
      //bool      flgSignal;          //  Объявляем флаг указывающий на то что была принята хотя бы одна точка или тире
      //bool      flgLetter;          //  Объявляем флаг указывающий на то что был принят символ
      //char*     RUS(char*);         //  Объявляем функцию перевода русских символов из кодировки UTF-8 в кодировку CP866
      char      chrMorze[] = {'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',  '.',  ';',  ',',  ':',  '?',  '!',  '-',  ' ', '\n', '\r'};
      uint8_t   lenMorze[] = {  2,   4,   4,   3,   1,   4,   3,   4,   2,   4,   3,   4,   2,   2,   3,   4,   4,   3,   3,   1,   3,   4,   3,   4,   4,   4,   5,   5,   5,   5,   5,    5,    5,    5,    5,    5,    6,    6,    6,    6,    6,    6,    6,    5,    5,    5};
      uint8_t   varMorze[] = {0x1, 0x8, 0xA, 0x4, 0x0, 0x2, 0x6, 0x0, 0x0, 0x7, 0x5, 0x4, 0x3, 0x2, 0x7, 0x6, 0xD, 0x2, 0x0, 0x1, 0x1, 0x1, 0x3, 0x9, 0xB, 0xC, 0xF, 0x7, 0x3, 0x1, 0x0, 0x10, 0x18, 0x1C, 0x1E, 0x1F,  0x0, 0x2A, 0x15, 0x38, 0x0C, 0x33, 0x21, 0x11, 0x15, 0x0A};

int     state;
String  command;
boolean flg_LF = false;
boolean flg_coma = false;
int     incomingByte = 0;   // переменная для хранения полученного байта

int v1;
int v2;
int zum_on = 0;

int pin_LED = 10;    //-- пин светодиода (+)
int pin_ZUM = 12;    //-- пин пищалки

int pin_RES = A0;    //-- пин фоторезистора )
int pin_KEY = 8; //-- пин кнопки

bool is_active = 0;


void setup(){                                       
    Serial.begin(9600);
    Serial.println("-->  setup()");

    v1 = 0;  //-- сначала запишем в переменную v1 значение 0
    v2 = 10;  //-- сначала запишем в переменную v2 значение 10

    pinMode(pin_LED,OUTPUT);  
    pinMode(pin_ZUM,OUTPUT);  

    varLetter=lenLetter=0;
    state = ST_BEGIN;
    Serial.print(">");
}

void loop(){          

    switch (state) {
      Serial.println(state);
      case ST_BEGIN:
          analogWrite(pin_LED, 0); //-- подадим на светодиод сигнал уровня v2
          tone(pin_ZUM, -1);       //-- подадим на светодиод сигнал уровня v2
#if WORK_ON==FOTORESISTOR
          while(analogRead(pin_RES) < minVolume){delay(10);}
#elif WORK_ON==BUTTON
          while(digitalRead(pin_KEY) == 0) {delay(10);}
#endif
          state = ST_SIGNAL_ON;
        break;
      case ST_SIGNAL_ON:
          tm_sig_start = millis();
          analogWrite(pin_LED, 255); //-- подадим на светодиод сигнал уровня v2
          tone(pin_ZUM, 1000);      //-- подадим на светодиод сигнал уровня v2
#if WORK_ON==FOTORESISTOR
          while(analogRead(pin_RES) > minVolume){delay(10);}
#elif WORK_ON==BUTTON
          while(digitalRead(pin_KEY) == 1) {delay(10);}
#endif
        state = ST_SIGNAL_OFF;
        break;
      case ST_SIGNAL_OFF:
          tm_sig_stop = millis();
          analogWrite(pin_LED, 0); //-- подадим на светодиод сигнал уровня v2
          tone(pin_ZUM, -1);       //-- подадим на светодиод сигнал уровня v2
          signal_long = tm_sig_stop - tm_sig_start;
          //Serial.print(signal_long);
          if(signal_long > point_long) {
            Serial.print("-");
            varLetter<<=1; varLetter|=1;
            lenLetter++;
          } else if(signal_long > min_point_long) {
            Serial.print("*");
            lenLetter++;
            varLetter<<=1; varLetter|=0;
          }
          state = ST_WAIT_SIGNAL_ON;
          break;
      case ST_WAIT_SIGNAL_ON:
          flg_coma = false;
          flg_LF = false;
#if WORK_ON==FOTORESISTOR
          while(analogRead(pin_RES) < minVolume){
#elif WORK_ON==BUTTON
          while(digitalRead(pin_KEY) == 0) {
#endif
            if(!flg_coma && (millis() - tm_sig_stop > next_letter_long)) {
              //Serial.print(",");  //-- конец буквы
              flg_coma = true;
              //  Если принят символ:                                                               //
              bool flg_found = false;
              for(uint8_t i=0; i<46; i++){                                                  // Проходим по всем 46 символам массивов
                if(varLetter==varMorze[i] && lenLetter==lenMorze[i]){                         // Если комбинация точек и тире в varLetter совпала с varMorze[i] и количество точек и тире совпало с lenMorze[i], то...
                    //-- символ найден                  
                    flg_found = true;
                    if(i==44||i==45){ Serial.println();}                                        // Если найденный символ является символом начала '\n' или конца '\r' строки, то прокручиваем ленту на две строки
                    else            { Serial.print(chrMorze[i]);}                           // Если найденный символ не является символом начала '\n' или конца '\r' строки, то просто его выводим на экран (позиция символа на экране смещается автоматически)
                } 
             }
             if(!flg_found) {
                Serial.print("<?>");
             }
              varLetter=lenLetter=0;                                          // Сбрасываем флаги и переменные относящиеся к принятому символу, так как мы его уже вывели
            }
            if(!flg_LF && (millis() - tm_sig_stop > word_long)) {
              Serial.println(""); Serial.print(">"); //-- конец слова
              flg_LF = true;
            }
            if(flg_LF && (millis() - tm_sig_stop > command_long)) {
              Serial.println(""); Serial.println("I am waiting yours command."); //-- конец слова
              Serial.println("     1 - начать передачу");
              Serial.println("     2 - уменьшить скорость передачи");
              Serial.println("     3 - увеличить скорость передачи");
              while (Serial.available() == 0) {
                delay(10);
              }
              state = ST_WAIT_COMMAND;
              break;
            }
            delay(10);
          } 
          if(state != ST_WAIT_COMMAND){ 
               state = ST_SIGNAL_ON;
          }
          break;
      case ST_WAIT_COMMAND:
          while (Serial.available() > 0) {
            // read the incoming:
            command = Serial.readString();
            // say what you got:
            Serial.print("command: ");  Serial.println(command);    
          if(command.charAt(0) == '1') {
            tm_sig_stop = millis();
            Serial.print(">");
            state = ST_BEGIN;
            break;
          } 
          if(command.charAt(0) == '2') {
            point_long += 50;     //-- длительность точки
            next_letter_long = point_long * 3; //-- пауза между буквами 
            word_long = point_long * 7;        //-- пауза между словами
            Serial.print(" point_long = "); Serial.println(point_long);
          } else if(command.charAt(0) == '3') {
            point_long -= 50;     //-- длительность точки
            next_letter_long = point_long * 3; //-- пауза между буквами 
            word_long = point_long * 7;        //-- пауза между словами
            Serial.print(" point_long = "); Serial.println(point_long);
          } else {
          }
          //--  продолжаем принимать команды
          state = ST_WAIT_COMMAND;
          Serial.println(""); Serial.println("I am waiting yours command."); //-- конец слова
          Serial.println("     1 - начать передачу");
          Serial.println("     2 - уменьшить скорость передачи");
          Serial.println("     3 - увеличить скорость передачи");
          break;
        } //-- цикл чтения команд
        break;
    }
}



// *************************************************************************
// 
//  ПЕРЕДАЧА АЗБУКОЙ МОРЗЕ ВВЕДЕННЫХ С КЛАВИАТУРЫ СИМВОЛОВ. 
//
//  Чтение сообщения по сериальному порту и отправка его азбукой Морзе
//    на светодиод и зуммер
// 
// 
const uint16_t  point_long = 100;

char      chrMorze[] = {'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',  '.',  ';',  ',',  ':',  '?',  '!',  '-',  ' ', '\n', '\r'};
uint8_t   lenMorze[] = {  2,   4,   4,   3,   1,   4,   3,   4,   2,   4,   3,   4,   2,   2,   3,   4,   4,   3,   3,   1,   3,   4,   3,   4,   4,   4,   5,   5,   5,   5,   5,    5,    5,    5,    5,    5,    6,    6,    6,    6,    6,    6,    6,    5,    5,    5};
uint8_t   varMorze[] = {0x1, 0x8, 0xA, 0x4, 0x0, 0x2, 0x6, 0x0, 0x0, 0x7, 0x5, 0x4, 0x3, 0x2, 0x7, 0x6, 0xD, 0x2, 0x0, 0x1, 0x1, 0x1, 0x3, 0x9, 0xB, 0xC, 0xF, 0x7, 0x3, 0x1, 0x0, 0x10, 0x18, 0x1C, 0x1E, 0x1F,  0x0, 0x2A, 0x15, 0x38, 0x0C, 0x33, 0x21, 0x11, 0x15, 0x0A};
uint8_t   varLetter;            //  Объявляем переменную для хранения принятых точек и тире одного символа (бит 0 - точка, бит 1 - тире)

int signal_long;
String incoming = "";
int pin_LED = 10;    //-- пин светодиода (+)
int pin_ZUM = 12;    //-- пин пищалки


void setup(){                                       
    Serial.begin(9600);
    Serial.println("--> Hello! Print somting to me.");

    pinMode(pin_LED,OUTPUT);  
    pinMode(pin_ZUM,OUTPUT);  
}

void loop(){                                 

  if (Serial.available() > 0) {
      //-- читаем входную строку
      incoming = Serial.readString();
      //-- печатаем фразу
      Serial.println("");  Serial.println(incoming);         
      //-- по каждому символу в фразе делаем поиск в таблице и передаем точками и тире
      for(int i=0; i<incoming.length(); i++) {
        incoming.toUpperCase();
        //-- ищем букву в массиве всего у нас 49 символов
        for(int j=0; j<49; j++) {                   
          //-- Serial.println(chrMorze[j]);   //-- вывод символа
          if( chrMorze[j] == incoming.charAt(i) ) {
            //-- распознали знак
            String s = String(incoming.charAt(i));
            Serial.print(s); //Serial.print("found ");  Serial.print(varMorze[j]); Serial.print(" "); Serial.print(lenMorze[j]);
            
            //-- если знак пробел, то делаем паузу между словами
            if(incoming.charAt(i) == ' ') {
              Serial.print("   ");
              delay(point_long * 7);   //-- пауза это разделитель между словами длительность 7 точек 
            } else {
              varLetter = varMorze[j];
              
              //-- передаем букву(символ)
              varLetter = varMorze[j];
              for(int k=lenMorze[j]-1; k>=0; k--) {
                uint8_t v = varLetter >> k;
                // Serial.print("k"); Serial.print(k);  Serial.print("v"); Serial.print(v); Serial.println(v & 1);
    
                if( (v & 1) == 0) {              //-- точка
                  signal_long = point_long;  
                  Serial.print("*");
                } else {                         //-- тире
                  signal_long = point_long * 3;  
                  Serial.print("-");
                }
                analogWrite(pin_LED, 255);     //-- включаем сигнал
                tone(pin_ZUM, 1000);       
                delay(signal_long);            //-- сигнал будет длительностью signal_long
                analogWrite(pin_LED, 0);       //-- выключаем сигнал
                tone(pin_ZUM, -1);       
        
                delay(point_long);             //-- задержка между точками и тире одна точка
                Serial.print("");
              }
              delay(point_long * 3);           //-- задержка между буквами 3 точки
              Serial.print(" ");
            }
          } else {
            //-- не распознали знак (но пока не обрабатываем эту ситуацию)    
          }
        }
      }
      Serial.println("");
  }
}


Полный скетч урока по работе с азбукой Морзе на Arduino

end

Комментариев нет:

Отправить комментарий