Код не запустится, если Serial Monitor не открыт

Мой код работает отлично, пока последовательный порт открыт. Однако если я подключу его к внешнему источнику питания или даже если я просто попытаюсь запустить его, подключенным к компьютеру, с закрытым последовательным монитором, ничего не произойдет. Мой проект не нуждается в последовательном взаимодействии, он будет работать самостоятельно вдали от компьютеров. Он у меня здесь, чтобы помочь мне отладить.

Кажется, камнем преткновения является if (morseInput.available()) в строке 63.

Вот все, включая библиотеки, которые я использую:

Morse EnDecoder.h

#ifndef MorseEnDecoder_H
#define MorseEnDecoder_H

#if (ARDUINO <  100)
#include <WProgram.h>
#else
#include <Arduino.h> 
#endif

#define MORSE_AUDIO true
#define MORSE_KEYER false
#define MORSE_ACTIVE_LOW true
#define MORSE_ACTIVE_HIGH false


class morseDecoder
{
public:
morseDecoder(int decodePin, boolean listenAudio, boolean morsePullup);
void decode();
void setspeed(int value);
char read();
boolean available();
int AudioThreshold;
long debounceDelay;     // время устранения дребезга. Держитесь значительно ниже dotTime!!
boolean morseSignalState;  
private:
int morseInPin;         // Входной контакт Морзе
int audioSignal;
int morseTablePointer;
int wpm;                // Скорость слова в минуту
long dotTime;           // длительность точки Морзе в мс
long dashTime;
long wordSpace;
boolean morseSpace;     // Флаг, предотвращающий получение нескольких пробелов
boolean gotLastSig;     // Флаг, что последний полученный сигнал Морзе декодируется как точка или тире
boolean morseKeyer;
boolean lastKeyerState;
boolean morseAudio;
boolean activeLow;
long markTime;          // таймеры для отметки и пробела в сигнале Морзе
long spaceTime;         // E=MC^2 ;p
long lastDebounceTime;  // последний раз, когда входной контакт был переключен
long currentTime;       // Текущее (со знаком) время
char decodedMorseChar;  // Последний декодированный символ Морзе
};


class morseEncoder
{
public:
morseEncoder(int encodePin);
void encode();
void setspeed(int value);
void write(char temp);
boolean available();
int morseSignals;       // количество сигналов Морзе для отправки в одном символе Морзе
char morseSignalString[7];// Сигнал Морзе для одного символа в виде временной строки ASCII из точек и тире
private:
char encodeMorseChar;   // ASCII-символ для кодирования
boolean sendingMorse;
int wpm;                // Скорость слова в минуту
long dotTime;           // длительность точки Морзе в мс
long dashTime;
long wordSpace;
int morseSignalPos;
int sendingMorseSignalNr;
long sendMorseTimer;
long lastDebounceTime;
long currentTime;
protected:
int morseOutPin;
virtual void setup_signal();
virtual void start_signal(bool startOfChar, char signalType);
virtual void stop_signal(bool endOfChar, char signalType);
};


#endif

Morse EnDecoder.cpp

/*          MORSE ENDECODER

- Morse encoder / decoder classes for the Arduino.

Copyright (C) 2010-2012 raron

GNU GPLv3 license:

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Details: http://raronoff.wordpress.com/2010/12/16/morse-endecoder/

#include "MorseEnDecoder.h"


// Таблица двоичного дерева кода Морзе (таблица дихотомического поиска)

// ITU с большинством знаков препинания (но без неанглийских символов - пока)
const int morseTreeLevels = 6; // Минус верхний уровень, а также максимальное количество. сигналов Морзе
const int morseTableLength = pow(2,morseTreeLevels+1);
const char morseTable[] PROGMEM =
" ETIANMSURWDKGOHVF*L*PJBXCYZQ!*54*3***2&*+****16=/***(*7***8*90*"
"***********?_****\"**.****@***'**-********;!*)*****,****:*******\0";

morseDecoder::morseDecoder(int decodePin, boolean listenAudio, boolean morsePullup)
{
morseInPin = decodePin;
morseAudio = listenAudio;
activeLow = morsePullup;

if (morseAudio == false)
{
pinMode(morseInPin, INPUT);
if (activeLow) digitalWrite (morseInPin, HIGH);
}

// Некоторые начальные значения
wpm = 13;
AudioThreshold = 700;
debounceDelay = 20;
dotTime = 1200 / wpm;       // длительность точки Морзе в мс
dashTime = 3 * 1200 / wpm;
wordSpace = 7 * 1200 / wpm;

morseTablePointer = 0;

morseKeyer = LOW;
morseSignalState = LOW;
lastKeyerState = LOW;

gotLastSig = true;
morseSpace = true;
decodedMorseChar = '\0';

lastDebounceTime = 0;
markTime = 0;
spaceTime = 0;
}


void morseDecoder::setspeed(int value)
{
wpm = value;
if (wpm <= 0) wpm = 1;
dotTime = 1200 / wpm;
dashTime = 3 * 1200 / wpm;
wordSpace = 7 * 1200 / wpm;
}

boolean morseDecoder::available()
{
if (decodedMorseChar) return true; else return false;
}

char morseDecoder::read()
{
char temp = decodedMorseChar;
decodedMorseChar = '\0';
return temp;
}

void morseDecoder::decode()
{
currentTime = millis();

// Читаем сигналы Морзе
if (morseAudio == false)
{
// Чтение ключа Морзе (цифрового)
morseKeyer = digitalRead(morseInPin);
if (activeLow) morseKeyer = !morseKeyer;

// Если переключатель изменился из-за шума или нажатия:
if (morseKeyer != lastKeyerState) lastDebounceTime = currentTime; // сбрасываем таймер

// устранение дребезга ключа Морзе
if ((currentTime - lastDebounceTime) > debounceDelay)
{
  // на каком бы месте ни было показание, оно существует уже давно
  // чем задержка устранения дребезга, поэтому примите ее за фактическое текущее состояние:
  morseSignalState = morseKeyer;

  // знак дифференциации и пространственное время
  if (morseSignalState) markTime = lastDebounceTime; 
  else spaceTime = lastDebounceTime;
}
} else {
// Чтение аудиосигнала Морзе
audioSignal = analogRead(morseInPin);
if (audioSignal > AudioThreshold)
{
  // Если это новый сигнал Морзе, сбрасываем таймер сигнала Морзе
  if (currentTime - lastDebounceTime > dotTime/2)
  {
    markTime = currentTime;
    morseSignalState = true; // в данный момент есть сигнал Морзе
  }
  lastDebounceTime = currentTime;
} else {
  // если это новая пауза, сбрасываем пространство-время
  if (currentTime - lastDebounceTime > dotTime/2 && morseSignalState == true)
  {
    spaceTime = lastDebounceTime; // не слишком далеко от последнего полученного звука
    morseSignalState = false;     // Больше нет сигнала
   }
 }
}


// Декодируем азбуку Морзе
if (!morseSignalState)
{
  if (!gotLastSig)
  {
    if (morseTablePointer < morseTableLength/2-1)
    {
    // если пауза превышает половину точки, узнать, какой импульс сигнала (точка/тире) получен последним
    if (currentTime - spaceTime > dotTime/2)
    {
      // если сигнал длится более 1/4 dotTime, воспринимаем его как импульс Морзе
      if (spaceTime-markTime > dotTime/4)
      {
        morseTablePointer *= 2;  // идем на один уровень вниз по дереву
        // если сигнал меньше половины тире, воспринимаем его как точку
        if (spaceTime-markTime < dashTime/2)
        {
           morseTablePointer++; // указать на узел для точки
           gotLastSig = true;
        }
        // иначе, если сигнал находится между половиной тире и тире + одна точка (1,33 тире), принять за тире
        else if (spaceTime-markTime < dashTime + dotTime)
        {
           morseTablePointer += 2; // указываем на узел для тире
           gotLastSig = true;
        }
      }
    }
  } else { // ошибка, если в одном символе Морзе слишком много импульсов
    //Serial.println("<ОШИБКА: нераспознанный сигнал!>");
    decodedMorseChar = '#'; // знак ошибки
    gotLastSig = true;
    morseTablePointer = 0;
  }
}
// Записываем символ, если пауза длиннее 2/3 тире (2 точки) и символ принят
if ((currentTime-spaceTime >= (dotTime*2)) && (morseTablePointer > 0))
{
  decodedMorseChar = pgm_read_byte_near(morseTable + morseTablePointer);
  morseTablePointer = 0;
}
// Пишем пробел, если пауза длиннее 2/3 слова
if (currentTime-spaceTime > (wordSpace*2/3) && morseSpace == false)
{
  decodedMorseChar = ' ';
  morseSpace = true ; // пробел, записанный флаг
}

} else {
// пока есть сигнал, сбрасываем некоторые флаги
gotLastSig = false;
morseSpace = false;
}

// Сохраняем состояние ключа Морзе для следующего раунда
lastKeyerState = morseKeyer;
}

morseEncoder::morseEncoder(int encodePin)
{
  morseOutPin = encodePin;
  this->setup_signal();

// некоторые начальные значения
sendingMorse = false;
encodeMorseChar = '\0';

wpm = 13;
dotTime = 1200 / wpm;       // длительность точки Морзе в мс
dashTime = 3 * 1200 / wpm;
wordSpace = 7 * 1200 / wpm; 
}

void morseEncoder::setspeed(int value)
{
wpm = value;
if (wpm <= 0) wpm = 1;
dotTime = 1200 / wpm;
dashTime = 3 * 1200 / wpm;
wordSpace = 7 * 1200 / wpm;
}

boolean morseEncoder::available()
{
if (sendingMorse) return false; else return true;
}

void morseEncoder::write(char temp)
{
if (!sendingMorse && temp != '*') encodeMorseChar = temp;
}

void morseEncoder::setup_signal()
{
pinMode(morseOutPin, OUTPUT);
digitalWrite(morseOutPin, LOW);
}

void morseEncoder::start_signal(bool startOfChar, char signalType)
{
digitalWrite(morseOutPin, HIGH);
}

void morseEncoder::stop_signal(bool endOfChar, char signalType)
{
digitalWrite(morseOutPin, LOW);
}

void morseEncoder::encode()
{
currentTime = millis();

if (!sendingMorse && encodeMorseChar)
{
// меняем на заглавную букву, если нет
if (encodeMorseChar > 96) encodeMorseChar -= 32;

// Сканирование символа для отправки в таблицу Морзе
int p;
for (p=0; p<morseTableLength+1; p++) if (pgm_read_byte_near(morseTable + p) == encodeMorseChar) break;

if (p >= morseTableLength) p = 0; // не найден, вместо этого отправляем пробел


// Обратная трассировка пути двоичного дерева
int pNode; // родительский узел
morseSignals = 0;

// Проходим обратный путь от позиции p до вершины таблицы Морзе
if (p > 0)
{
  // строим сигнал Морзе (строка сигнала Морзе в обратном направлении от последнего сигнала к первому)
  pNode = p;
  while (pNode > 0)
  {
    if ( (pNode & 0x0001) == 1)
    {
      // Это точка
      morseSignalString[morseSignals++] = '.';
    } else {
      // Это тире
      morseSignalString[morseSignals++] = '-';
    }
    // Находим родительский узел
    pNode = int((pNode-1)/2);
  }
} else { // Вершина дерева Морса — добавляем верхний символ пробела
  // немного обманываем; пространство слов для «сигнала Морзе»
  morseSignalString[morseSignals++] = ' ';
}

morseSignalString[morseSignals] = '\0';


// начинаем отправку символа
sendingMorse = true;
sendingMorseSignalNr = morseSignals; // Отправляем строку сигнала задом наперед
sendMorseTimer = currentTime;
if (morseSignalString[0] != ' ') this->start_signal(true, morseSignalString[morseSignals-1]);
}


// Отправляем сигналы Морзе на вывод
if (sendingMorse)
{
char& currSignalType = morseSignalString[sendingMorseSignalNr-1];
bool endOfChar = sendingMorseSignalNr <= 1;
switch (currSignalType)
{
  case '.': // Отправляем точку (на самом деле, прекращаем отправку сигнала после «времени точки»)
    if (currentTime - sendMorseTimer >= dotTime)
    {
      this->stop_signal(endOfChar, currSignalType);
      sendMorseTimer = currentTime;
      currSignalType = 'x'; // Отмечаем сигнал как отправленный
    }
    break;
  case '-': // Отправляем тире (то же самое, прекращаем отправку после тире)
    if (currentTime - sendMorseTimer >= dashTime)
    {
      this->stop_signal(endOfChar, currSignalType);
      sendMorseTimer = currentTime;
      currSignalType = 'x'; // Отмечаем сигнал как отправленный
    }
    break;
  case 'x': // Чтобы убедиться, что между сигналами есть пауза
    if (sendingMorseSignalNr > 1)
    {
      // Пауза между сигналами в одной букве
      if (currentTime - sendMorseTimer >= dotTime)
      {
        sendingMorseSignalNr--;
        this->start_signal(false, morseSignalString[sendingMorseSignalNr-1]); // Начинаем отправку следующего сигнала
        sendMorseTimer = currentTime;       // сбрасываем таймер
      }
    } else {
      // Пауза между буквами
      if (currentTime - sendMorseTimer >= dashTime)
      {
        sendingMorseSignalNr--;
        sendMorseTimer = currentTime;       // сбрасываем таймер
      }
    }
    break;
  case ' ': // Пауза между словами (минус пауза между буквами - уже отправлено)
  default:  // На всякий случай, это что-то другое
    if (currentTime - sendMorseTimer > wordSpace - dashTime) sendingMorseSignalNr--;
}
if (sendingMorseSignalNr <= 0 )
{
  // Готовы закодировать больше букв
  sendingMorse = false;
  encodeMorseChar = '\0';
}
}
}

Морс.h

#pragma once
/**
* Генерируйте и отправляйте азбуку Морзе на светодиод или динамик. Разрешить отправку
* неблокирующим способом (путем вызова метода «продолжить отправку»
* время от времени включать/выключать светодиод или соответствующим образом вызывать тональный сигнал/noTone).
*
* Все вводимые данные должны быть в нижнем регистре. Прознаки (СК, КН и т.д.) имеют специальные
* значения символов #define.
*/

// для malloc и free, для операторов создания/удаления
#include <stdlib.h>

// Типы языка Arduino
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#define WPM_DEFAULT 12.0
// ПАРИЖ Измерение WPM: 50; CODEX Измерение WPM: 60 (Википедия: азбука Морзе)
#define DITS_PER_WORD   50
// Передача вдикторMorseSenderв качестве несущейFrequency, чтобы подавить несущую.
#define CARRIER_FREQUENCY_NONE  -1

// Битовые маски: 1 для dah и 0 для dit, в порядке слева направо;
// собственно последовательность начинается после первой единицы (дозорного).
// Благодарим за эту схему Марка ВандеВеттеринга K6HX (brainwagon.org).
typedef int             morseTiming_t;
typedef unsigned char   morseBitmask_t; // см. также MAX_TIMINGS
#define MORSE_BITMASK_HIGH_BIT  B10000000

// страж
#define END             0

// наибольшее количество значений времени, которое понадобится любому устройству; пример: k = вкл, выкл, вкл, выкл, вкл, конец = 5
#define MAX_TIMINGS     15

// Пунктуация и знаки
#define PROSIGN_SK  'S'
#define PROSIGN_KN  'K'
#define PROSIGN_BT  'B'
typedef struct {
char c;
morseBitmask_t timing;
} specialTiming;
const specialTiming MORSE_PUNCT_ETC[] = {
{'.',       B1010101},
{'?',       B1001100},
{PROSIGN_SK,    B1000101},
{PROSIGN_KN,    B110110},
{PROSIGN_BT,    B110001},
{END,       B1},
};

// Азбука Морзе (явное объявление времени письма)
const morseBitmask_t MORSE_LETTERS[26] = {
/* a */ B101,
/* b */ B11000,
/* c */ B11010,
/* d */ B1100,
/* e */ B10,
/* f */ B10010,
/* g */ B1110,
/* h */ B10000,
/* i */ B100,
/* j */ B10111,
/* k */ B1101,
/* l */ B10100,
/* m */ B111,
/* n */ B110,
/* o */ B1111,
/* p */ B10110,
/* q */ B11101,
/* r */ B1010,
/* s */ B1000,
/* t */ B11,
/* u */ B1001,
/* v */ B10001,
/* w */ B1011,
/* x */ B11001,
/* y */ B11011,
/* z */ B11100,
};


/**
* Define the logic of converting characters to on/off timing,
* and encapsulate the state of one sending-in-progress Morse message.
*
* Subclasses define setOn and setOff for (for example) LED and speaker output.
*/
class MorseSender {
protected:
const unsigned int pin;
// Методы setOn и setOff будут чисто виртуальными,
// но здесь есть проблемы с компилятором.
// См.: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1167672075.

/**
 * Called to set put the output in 'on' state, during a dit or dah.
 */
virtual void setOn();
virtual void setOff();

/**
 * Called before sending a message. Used for example to enable a
 * carrier. (Noop in the base class.)
 */
virtual void setReady();
virtual void setComplete();

private:
morseTiming_t DIT, DAH;
String message;

// вкл, выкл,..., ожидание, список 0, миллис
morseTiming_t timingBuffer[MAX_TIMINGS+1];

// индекс отправляемого в данный момент символа
unsigned int messageIndex;
// единица измерения времени, отправляемая в данный момент
unsigned int timingIndex;

// когда этот блок синхронизации был запущен
unsigned long lastChangedMillis;

/**
 * Copy definition timings (on only) to raw timings (on/off).
 * @return the number of 'on' timings copied
 */
int copyTimings(morseTiming_t *rawOut,
    morseBitmask_t definition);

/**
 * Fill a buffer with on,off,..,END timings (millis)
 * @return the index at which to start within the new timing sequence
 */
unsigned int fillTimings(char c);

public:
/**
 * Create a sender which will output to the given pin.
 */
MorseSender(unsigned int outputPin, float wpm=WPM_DEFAULT);

/**
 * To be called during the Arduino setup(); set the pin as OUTPUT.
 */
void setup();

/**
 * Set the words per minute (based on PARIS timing).
 */
void setWPM(float wpm);

/**
 * Set the duration, in milliseconds, of a DIT.
 */
void setSpeed(morseTiming_t duration);

/**
 * Set the message to be sent.
 * This halts any sending in progress.
 */
void setMessage(const String newMessage);

/**
 * Send the entirety of the current message before returning. See the "simple"
 * example, which uses sendBlocking to send one message.
 */
void sendBlocking();

/**
 * Prepare to send and begin sending the current message. After calling this,
 * call continueSending repeatedly until it returns false to finish sending
 * the message. See the "speeds" example, which calls startSending and
 * continueSending on two different senders.
 */
void startSending();

/**
 * Switch outputs on and off (and refill the internal timing buffer)
 * as necessary to continue with the sending of the current message.
 * This should be called every few milliseconds (at a significantly
 * smaller interval than a DIT) to produce a legible fist.
 *
 * @see startSending, which must be called first
 * @return false if sending is complete, otherwise true (keep sending)
 */
boolean continueSending();

void *operator new(size_t size);
void operator delete(void* ptr);
};


/**
* Adapt Morse sending to use the Arduino language tone() and noTone()
* functions, for use with a speaker.
*
* If a carrierFrequency is given, instead of calling noTone, call tone
* with a low frequency. This is useful ex. for maintaining radio links.
*/
class SpeakerMorseSender: public MorseSender {
private:
    unsigned int frequency;
    unsigned int carrFrequency;
protected:
    virtual void setOn();
    virtual void setOff();
    virtual void setReady();
    virtual void setComplete();
public:
    // концерт А = 440
    // средний C = 261,626; высшие октавы = 523,251, 1046,502
    SpeakerMorseSender(
        int outputPin,
        unsigned int toneFrequency=1046,
        unsigned int carrierFrequency=CARRIER_FREQUENCY_NONE,
        float wpm=WPM_DEFAULT);
};


/**
* Sends Morse on a digital output pin.
*/
class LEDMorseSender: public MorseSender {
protected:
    virtual void setOn();
    virtual void setOff();
public:
    LEDMorseSender(int outputPin, float wpm=WPM_DEFAULT);
};


/**
* Sends Morse on an analog output pin (using PWM). The brightness value is
* between 0 and 255 and is passed directly to analogWrite.
*/
class PWMMorseSender: public MorseSender {
private:
    byte brightness;
protected:
    virtual void setOn();
    virtual void setOff();
public:
    PWMMorseSender(int outputPin, float wpm=WPM_DEFAULT, byte brightness=255);
    void setBrightness(byte brightness);
};

morse.cpp

// Библиотека отправки кода Морзе

#include <morse.h>


// МорсОтправитель
int MorseSender::copyTimings(
morseTiming_t *rawOut,
morseBitmask_t definition)
{
int t = 0;
boolean foundSentinel = false;
for(morseBitmask_t mask = MORSE_BITMASK_HIGH_BIT;
    mask > 0; mask = mask >> 1)
{
    boolean isDah = (mask & definition) > 0;
    if(!foundSentinel)
    {
        if (isDah) { foundSentinel = true; }
        continue;
    }
    rawOut[2*t] = isDah ? DAH : DIT;
    rawOut[2*t + 1] = DIT;
    t++;
}
return t;
}
unsigned int MorseSender::fillTimings(char c)
{
int t = 0;
unsigned int start = 0;
if (c >= 'a' && c <= 'z')
{
    t = copyTimings(timingBuffer, MORSE_LETTERS[c-'a']);
}
else if (c >= '0' && c <= '9')
{
    int n = c - '0';
    boolean ditsFirst = (n <= 5);
    if (!ditsFirst)
    {
        n -= 5;
    }
    while(t < 5)
    {
        timingBuffer[2*t] = ((t < n) == ditsFirst) ? DIT : DAH;
        timingBuffer[2*t + 1] = DIT;
        t++;
    }
}
else
{
    int s = 0;
    while(MORSE_PUNCT_ETC[s].c != END)
    {
        if(MORSE_PUNCT_ETC[s].c == c)
        {
            t = copyTimings(timingBuffer,
                MORSE_PUNCT_ETC[s].timing);
            break;
        }
        s++;
    }
    if (MORSE_PUNCT_ETC[s].c == END)
    {
        start = t = 1; // начинаем с пробела
    }
}

timingBuffer[2*t - 1] = DAH;
timingBuffer[2*t] = END;

return start;
}

// см. примечание в заголовке о чистой виртуальной реальности
void MorseSender::setOn() {};
void MorseSender::setOff() {};

// значения по умолчанию
void MorseSender::setReady() {};
void MorseSender::setComplete() {};

MorseSender::MorseSender(unsigned int outputPin, float wpm) :
pin(outputPin)
{
setWPM(wpm);
}

void MorseSender::setup() { pinMode(pin, OUTPUT); }

void MorseSender::setWPM(float wpm)
{
setSpeed((morseTiming_t)(1000.0*60.0/(max(1.0, wpm)*DITS_PER_WORD)));
}

void MorseSender::setSpeed(morseTiming_t duration)
{
DIT = max(1, duration);
DAH = 3*DIT;
}

void MorseSender::setMessage(const String newMessage)
{
message = newMessage;

// Принудительно запускаем startSending() перед continueSending().
messageIndex = message.length();

// Если обрабатывалось другое сообщение, убедитесь, что оно корректно остановлено.
if (timingIndex % 2 == 0) {
    setOff();
}
}

void MorseSender::sendBlocking()
{
//Serial.println("Блокировка отправки: ");
//Serial.println(сообщение);
startSending();
while(continueSending());
}

void MorseSender::startSending()
{
messageIndex = 0;
if (message.length() == 0) { return; }
timingIndex = fillTimings(message[0]);
setReady();
if (timingIndex % 2 == 0) {
    setOn();
    //Serial.print("Начиная с on, period=");
} else {
    //Serial.print("Начиная с выключения, продолжительности=");
}
lastChangedMillis = millis();
//Serial.println((int)timingBuffer[timingIndex]);
}

boolean MorseSender::continueSending()
{
if(messageIndex >= message.length()) { return false; }

unsigned long elapsedMillis = millis() - lastChangedMillis;
if (elapsedMillis < timingBuffer[timingIndex]) { return true; }

timingIndex++;
if (timingBuffer[timingIndex] == END)
{
    messageIndex++;
    if(messageIndex >= message.length()) {
        setOff();
        setComplete();
        return false;
    }
    timingIndex = fillTimings(message[messageIndex]);
}

lastChangedMillis += elapsedMillis;
//Serial.print("Далее");
if (timingIndex % 2 == 0) {
    //Serial.print("(on) ");
    setOn();
} else {
    //Serial.print("(выкл.) ");
    setOff();
}
//Serial.println((int)timingBuffer[timingIndex]);

return true;
}

void *MorseSender::operator new(size_t size) { return malloc(size); }
void MorseSender::operator delete(void* ptr) { if (ptr) free(ptr); }

// СпикерMorseSender

void SpeakerMorseSender::setOn() { tone(pin, frequency); }
void SpeakerMorseSender::setOff() {
if (carrFrequency == CARRIER_FREQUENCY_NONE) {
    noTone(pin);
} else {
    tone(pin, carrFrequency);
}
}
void SpeakerMorseSender::setReady() { setOff(); }
void SpeakerMorseSender::setComplete() { noTone(pin); }
SpeakerMorseSender::SpeakerMorseSender(
int outputPin,
unsigned int toneFrequency,
unsigned int carrierFrequency,
float wpm)
: MorseSender(outputPin, wpm),
frequency(toneFrequency),
carrFrequency(carrierFrequency) {};


// LEDMorseSender

void LEDMorseSender::setOn() { digitalWrite(pin, HIGH); }
void LEDMorseSender::setOff() { digitalWrite(pin, LOW); }
LEDMorseSender::LEDMorseSender(int outputPin, float wpm)
: MorseSender(outputPin, wpm) {};


// ШИММорсОтправитель

void PWMMorseSender::setOn() { analogWrite(pin, brightness); }
void PWMMorseSender::setOff() { analogWrite(pin, 0); }
void PWMMorseSender::setBrightness(byte bright) {
brightness = bright;
}
PWMMorseSender::PWMMorseSender(
    int outputPin,
    float wpm,
    byte bright)
: MorseSender(outputPin, wpm), brightness(bright) {};

И наконец, вот мой код:

#include <avr/pgmspace.h>
#include <MorseEnDecoder.h>
#include <stdio.h>
#include <morse.h>
#define PIN_STATUS  13
#define CPU_RESTART_ADDR (uint32_t *)0xE000ED0C
#define CPU_RESTART_VAL 0x5FA0004
#define CPU_RESTART (*CPU_RESTART_ADDR = CPU_RESTART_VAL);

// Сопоставление контактов
const byte morseInPin = 7;
const byte morseOutPin = 13;
String check = "";
String origin = "SOS";
const int maxItems = 3;
int x;
char myArray[maxItems], curChar;
char nextChar;
int i;
int y;

// Создание экземпляров объектов Морзе
morseDecoder morseInput(morseInPin, MORSE_KEYER, MORSE_ACTIVE_LOW);
morseEncoder morseOutput(morseOutPin);

// Переменные, отвечающие за форматирование вывода
// вставив CR (возврат каретки)
long lastTransmissionTime;
long currentTime;
boolean transmissionEnded = true; // Флаг, обозначающий завершение старой передачи

// Минимальное время паузы передачи для вставки возврата каретки (CR)
// Корректируем в зависимости от скорости Морзе. IE 13 слов в минуту = 646 мс между словами (без CR).
const long transmissionPaused   = 1000; // Подходит для 13 слов в минуту?

LEDMorseSender sender(PIN_STATUS);

void setup()
{
  Serial.begin(9600);
  Serial.println("Morse EnDecoder Geocache");

  // Установка скорости Морзе в словах в минуту
  // Если не установлено, в любом случае по умолчанию будет 13 слов в минуту
  morseInput.setspeed(5);
  morseOutput.setspeed(5);

  lastTransmissionTime = (long)millis();
}

void(* resetFunc) (void) = 0; //объявляем функцию сброса по адресу 0

void loop()
{
  currentTime = (long)millis();

  // Необходимо вызывать их один раз за цикл
  morseInput.decode();
  morseOutput.encode();

  // ПОЛУЧИТЬ МОРЗУ (ВХОД)
  // Если символ декодирован со входа, запишите его в последовательный порт
  if (morseInput.available())
  {
    char receivedMorse = morseInput.read();
    Serial.print(receivedMorse);
    // Небольшая проверка ошибок
    if (receivedMorse == '#') Serial.println("< ERROR:too many morse signals! >");
    morseOutput.write('#');
    morseOutput.encode();

    //Создаем массив из полученных символов Морзе

    curChar = 0;
    nextChar = receivedMorse;
    curChar += nextChar;
    myArray[i] = curChar;
    check.concat(myArray[i]);
    Serial.println(check);

    //Проверяем ввод и отвечаем
    if (check == origin)      // ХОРОШАЯ РАБОТА!! Ваша награда следующая
    {
      Serial.println("check = origin");
      Serial.println(check);
      sender.setup();
      sender.setWPM(5);
      sender.setMessage(String("help is coming"));
      sender.startSending();
    }
    else if (check == "S") {}
    else if (check == "SO") {}
    else if (check == " SOS") {}
    else if (check.length() > 4)
    {
      delay(100);
      Serial.println("resetting");
      delay(500);
      resetFunc();  //сброс вызова
      delay(100);
    }
    else {}
  }
  sender.continueSending();
}

, 👍2

Обсуждение

Мне не нравится resetFunc(); //вызов сброса — это на самом деле не сбрасывает чип, знаете ли. Он просто переходит к вектору сброса, это что-то еще (аппаратное обеспечение не сбрасывается)., @Nick Gammon

если я просто попытаюсь запустить его, подключив к компьютеру с закрытым последовательным монитором, ничего не произойдет - не пытаясь понять весь ваш код, чего вы ожидаете, этого не произойдет, если вы не видите последовательный выход?, @Nick Gammon

Я хочу, чтобы он запускал код, я не пытаюсь показаться шутливым, но он буквально ничего не запустит, если последовательный монитор не открыт. Предполагается, что он считывает и декодирует ввод кода Морзе с кнопки на цифровом контакте 7, затем он должен сравнить эту строку кода Морзе с другой строкой, и если они совпадают, он должен вывести код Морзе на светодиод., @user26383

Мне в голову пришла идея, которая могла быть виновником. Код может отправлять символ на последовательный монитор после его декодирования (превращает нажатия кнопок в символ). В этом случае он не будет работать без последовательного монитора, но я понятия не имею, как это исправить., @user26383

Можете ли вы указать точную плату, которую вы используете? В качестве примечания: вы можете использовать неинвазивный подход к отладке системы, например https://github.com/rlogiacco/MicroDebug., @Roberto Lo Giacco

Как на Mega, так и на Nano, если вы используете последовательный порт только для вывода, плата не заботится и даже не знает, прослушивает ли кто-нибудь (последовательный монитор или другая программа)., @Edgar Bonet

В настоящее время я использую Mega, потому что она больше и на ней легче тестировать схемы, однако я планирую перевести этот проект на nano, поэтому я пометил обе платы., @user26383

Я использовал вашу библиотеку светодиодов отладки и определил, что без открытого последовательного монитора она пропускает строки 71–116, основной оператор if, который по сути содержит все важные фрагменты кода. Я считаю, что это может быть связано с «morseInput.available», но я не знаю, как это исправить., @user26383

«Предполагается, что он считывает и декодирует код Морзе, вводимый с кнопки на цифровом контакте 7, затем должен сравнивать эту строку кода Морзе с другой строкой, и если они совпадают, он должен выводить код Морзе на светодиод». вы имеете в виду, что он считывает нажатия переключателей через входной контакт, а затем передает те же самые шаблоны на выходной контакт через декодирование/кодирование большого количества кода? Почему? Чего он для этого достигает?, @Nick Gammon


1 ответ


Лучший ответ:

0

Похоже, что в этом коде команды serial.print мешали работе кода, как бы странно это ни звучало. Мне удалось удалить мешающие последовательные команды, и теперь код работает. С несколькими изменениями он должен быть безупречным.

,