Кодировщик Морзе работает не так, как ожидалось на Arduino UNO
Я начну с того, что у меня нет большого опыта работы с Arduino и программирования на C. У меня есть клон Elegoo Arduino UNO.
Недавно я пытался создать кодировку Морзе, которая преобразует текст в азбуку Морзе, а затем мигает светодиодом для передачи кода Морзе. Код выглядит следующим образом
#define OUT_PIN 8
#define END_PIN 7
const short dot_time = 200; // Time LED is ON for dot
const short dash_time = dot_time*3; // Time LED is ON for dash
const short same_letter_space = dot_time; // Time LED is OFF between dots/dashes of the same letter
const short letter_space = dot_time*3; // Time LED is OFF between letters
const short word_space = dot_time*5; // Time LED is OFF between words
const char letter_separator[] = "_";
const char word_separator[] = "/";
typedef struct {
char * morse;
char letter;
}morse_pair;
morse_pair morse_table_letters[] = {{".-", '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'}};
morse_pair morse_table_digits[] = {{"-----", '0'}, {".----", '1'}, {"..---", '2'}, {"...--", '3'}, {"....-", '4'}, {".....", '5'}, {"-....", '6'}, {"--...", '7'}, {"---..", '8'},//
{"----.", '9'}};
char test_text[] = "aaa";
morse_pair letter_encoder(char letter){
int letter_value = (int) letter;
if(letter_value >= 97){
//lowercase
return morse_table_letters[letter_value-97];
}
else if (letter_value>=65){
//uppercase
return morse_table_letters[letter_value-65];
}
else {
//digits
return morse_table_digits[letter_value];
}
}
char* word_to_morse(char* word, size_t len){
Serial.print("Encoding word: ");
Serial.println(word);
size_t len_morse = 0;
char* letters[len];
for(size_t l=0;l<len;l++){
letters[l] = letter_encoder(word[l]).morse;
len_morse += strlen(letters[l])+1;
}
char* morse_string = malloc(len_morse*sizeof(char));
for(size_t l=0;l<len;l++){
strcat(morse_string, letters[l]);
if(l<len-1){
strcat(morse_string, letter_separator);
}
}
strcat(morse_string, word_separator);
Serial.print("Result: ");
Serial.println(morse_string);
return morse_string;
}
char* text_to_morse(char* text){
Serial.print("Encoding text: ");
Serial.println(text);
size_t len = strlen(text);
char* text_morse = malloc((4*len+len)*sizeof(char));
char* swp = text;
for(char* ewp = text;ewp!=(text+len);ewp++){
if(*(ewp+1)==' ' || *(ewp+1) == '\0'){
char * wtm = word_to_morse(swp, ewp-swp+1);
strcat(text_morse, wtm);
swp=ewp+2;
free(wtm);
}
}
Serial.print("Result: ");
Serial.println(text_morse);
return text_morse;
}
void morse_to_pin(char* text_morse){
Serial.println("Playing with pins");
size_t len = strlen(text_morse);
for(size_t l=0;l<len;l++){
char letter = text_morse[l];
Serial.println(letter);
if(letter == '.'){
digitalWrite(OUT_PIN, HIGH);
delay(dot_time);
}
else if(letter=='-'){
digitalWrite(OUT_PIN, HIGH);
delay(dash_time);
}
else if(letter=='_'){
digitalWrite(OUT_PIN, LOW);
delay(letter_space);
}
else if(letter=='/'){
digitalWrite(OUT_PIN, LOW);
delay(word_space);
}
else {
digitalWrite(OUT_PIN, LOW);
delay(same_letter_space);
}
}
}
void start_comm(){
Serial.println("Start comm.");
digitalWrite(END_PIN, HIGH);
delay(2000);
digitalWrite(END_PIN, LOW);
}
void end_comm(){
Serial.println("End comm.");
digitalWrite(END_PIN, HIGH);
delay(500);
digitalWrite(END_PIN, LOW);
delay(500);
digitalWrite(END_PIN, HIGH);
delay(500);
digitalWrite(END_PIN, LOW);
}
void setup(){
Serial.begin(9600);
pinMode(OUT_PIN, OUTPUT);
pinMode(END_PIN, OUTPUT);
}
void loop ()
{
start_comm();
delay(1000);
char* ttm = text_to_morse(test_text);
morse_to_pin(ttm);
free(ttm);
delay(1000);
end_comm();
delay(1000);
}
Часть кода, которая преобразует текст в строку Морзе, ведет себя правильно при запуске на ноутбуке, но когда я загружаю ее на Arduino, UNO ведет себя странно, и индикатор Морзе вообще не мигает.
ОБНОВЛЕНИЕ:
кажется, что Arduino UNO просто запускает только функции start_comm
и end_comm
, как будто между ними ничего нет. Он изменил поведение и не всегда ведет себя одинаково, прежде чем напечатать какой-то мусор на последовательный монитор, но теперь он просто пропускает весь код между двумя упомянутыми выше функциями.
@luigi, 👍1
Обсуждение1 ответ
Лучший ответ:
Я вроде как решил эту проблему, я неправильно использовал malloc и получал доступ к неинициализированным битам, что приводило к неопределенному поведению. Приведенный ниже код должен работать правильно
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OUT_PIN 8
#define END_PIN 7
const short dot_time = 200; // Time LED is ON for dot
const short dash_time = dot_time * 3; // Time LED is ON for dash
const short same_letter_space = dot_time; // Time LED is OFF between dots/dashes of the same letter
const short letter_space = dot_time * 3; // Time LED is OFF between letters
const short word_space = dot_time * 5; // Time LED is OFF between words
const char letter_separator[] = "_";
const char word_separator[] = "/";
const char unkown_letter[] = "?";
typedef struct {
char * morse;
char letter;
} morse_pair;
const morse_pair morse_table_letters[] = {{".-", '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'}
};
const morse_pair morse_table_digits[] = {{"-----", '0'}, {".----", '1'}, {"..---", '2'}, {"...--", '3'}, {"....-", '4'}, {".....", '5'}, {"-....", '6'}, {"--...", '7'}, {"---..", '8'},//
{"----.", '9'}
};
const char* letter_encoder(char letter) {
int letter_value = (int) letter;
if (letter_value >= 97 && letter_value <= 122) {
//lowercase
return morse_table_letters[letter_value - 97].morse;
}
else if (letter_value >= 65 && letter_value <= 90) {
//uppercase
return morse_table_letters[letter_value - 65].morse;
}
else if (letter_value>=48 && letter_value<=57) {
//digits
return morse_table_digits[letter_value].morse;
}
else {
//Boh
return unkown_letter;
}
}
void word_to_morse(char* morse_word, char* word, int len) {
Serial.print("Encoding word: ");
Serial.println(word);
for (int l = 0; l < len; l++) {
strcat(morse_word, letter_encoder(word[l]));
if (l < len - 1) {
strcat(morse_word, letter_separator);
}
}
strcat(morse_word, word_separator);
Serial.print("Word result: ");
Serial.println(morse_word);
}
void text_to_morse(char* morse_text, char* text, int len) {
Serial.print("Encoding text: ");
Serial.println(text);
char* swp = text;
int morse_len = 0;
for (char* ewp = text; ewp != (text + len); ewp++) {
if (*(ewp + 1) == ' ' || *(ewp + 1) == '\0') {
int w_len = ewp - swp + 1;
char * morse_word = (char*) malloc((5*w_len+w_len)*sizeof(char));
strcpy(morse_word, "");
word_to_morse(morse_word, swp, w_len);
morse_len += strlen(morse_word);
Serial.print("Word result: ");
Serial.println(morse_word);
Serial.print("Word len: ");
Serial.println(morse_len);
strcat(morse_text, morse_word);
swp = ewp + 2;
free(morse_word);
}
}
morse_text = (char*) realloc(morse_text, ++morse_len*sizeof(char));
Serial.print("Text result: ");
Serial.println(morse_text);
}
void morse_to_led(const char* text_morse, int len) {
Serial.println("Flashing morse with pins");
for (int l = 0; l < len; l++) {
char letter = text_morse[l];
Serial.println(letter);
switch(letter){
case '.':
digitalWrite(OUT_PIN, HIGH);
delay(dot_time);
break;
case '-':
digitalWrite(OUT_PIN, HIGH);
delay(dash_time);
break;
case '_':
digitalWrite(OUT_PIN, LOW);
delay(letter_space);
break;
case '/':
digitalWrite(OUT_PIN, LOW);
delay(word_space);
break;
default:
digitalWrite(OUT_PIN, LOW);
delay(same_letter_space);
break;
}
}
}
void start_comm() {
Serial.println("Start comm.");
digitalWrite(END_PIN, HIGH);
delay(dash_time);
digitalWrite(END_PIN, LOW);
}
void end_comm() {
Serial.println("End comm.");
digitalWrite(END_PIN, HIGH);
delay(dot_time);
digitalWrite(END_PIN, LOW);
delay(dot_time);
digitalWrite(END_PIN, HIGH);
delay(dot_time);
digitalWrite(END_PIN, LOW);
}
void setup() {
Serial.begin(9600);
pinMode(OUT_PIN, OUTPUT);
pinMode(END_PIN, OUTPUT);
}
void loop ()
{
//Start
start_comm();
delay(2000);
//Convert
char test_text[] = "test";
int len = strlen(test_text);
char * morse_text = (char*) malloc((5*len+len)*sizeof(char));
strcpy(morse_text, "");
text_to_morse(morse_text, test_text, len);
morse_to_led(morse_text, strlen(morse_text));
free(morse_text);
delay(2000);
//End
end_comm();
delay(2000);
}
- Arduino синтаксический анализ строки с использованием sscanf
- Объяснить функцию pulseIn с помощью arduino и ультразвукового датчика
- Проблемы с Serial.read()
- Node.js не может распознавать символы из последовательного порта
- GPS автономный робот
- Создание формулы
- Arduino зуммер кодовая последовательность не срабатывает
- Проблема с измерением времени в цикле for
Итак, как именно функция "text_to_morse ()" ведет себя в Uno? Печатает ли он правильный текст Морзе? Если нет: что это на самом деле печатает? Нам нужно сузить круг источников ошибок здесь, @chrisl
@chrisl вы правы, я обновлю, как только смогу, и приведу пример, @luigi
"ведет себя правильно при запуске на моем ноутбуке, но" не на "моем Arduino UNO". вы используете " malloc ()", он работает на вашем ноутбуке, потому что у вашего ноутбука много памяти, но в Arduino только 2 кб оперативной памяти. Вы должны проверить, успешно ли ваша "malloc ()" выделила память в куче с помощью " if (text_morse != NULL) { // остальная часть вашего кода};", или лучше не использовать статическую выделенную память, чем динамическую выделенную память., @hcheung