Код не запустится, если 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();
}
@user26383, 👍2
Обсуждение1 ответ
Лучший ответ:
Похоже, что в этом коде команды serial.print мешали работе кода, как бы странно это ни звучало. Мне удалось удалить мешающие последовательные команды, и теперь код работает. С несколькими изменениями он должен быть безупречным.
- Как разделить входящую строку?
- Какова максимальная длина провода для последовательной связи между двумя Arduino?
- Последовательная связь между двумя Arduino (запрос и получение)
- Не нашел датчик отпечатков пальцев :( Arduino Mega 2560 Adafruit Fingerprint Sensor
- Модуль SIM808: команда определения местоположения GSM (AT+CIPGSMLOC=1,1) дает неверное значение после выполнения команды отправки сообщения (AT+CMGS=+91xxxxxxxx)
- Как правильно получить MIDI с Arduino, с 6n138?
- Bluetooth-модуль HC-05 не принимает AT-команды
- Сбой Arduino во время последовательной печати без очевидной причины
Мне не нравится
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