Помогите со странным поведением Arduino uno

happy_penguin
Offline
Зарегистрирован: 18.10.2018

Доброго времени суток. Прошу, спасите меня от психушки. Начал ваять небольшой проект на Arduino UNO в личных целях (да и поучиться чтобы), программированием владею "со словарем", раньше только светодиодами на ардуинке мигал, да немного с символьными дисплеями баловался.

В процессе написания кода наткнулся на какое-то странное поведение и уже битый час не могу понять даже его причину. Код длинный, так что выложу только проблемную часть. Суть кода: имеется массив строк с командами, для управления освещением. При загрузке нужно посчитать, сколько элементов в массиве, если известно, что последней будет строка "NULL". Для этого я написал 2 версии счетчика. (Вручную вбить, естественно, проще, но в дальнейшем список будет расширяться, так что хотелось бы процесс автоматизировать)

String M_command_list[] = {"PLACEHOLDER", "ON", "OFF", "ALL_ON", "ALL_OFF", "MASK", "NULL"};  //Список нужных команд (PLACEHOLDER - всегда в начале, последняя всегда NULL - для счетчика)
int command_list_size = 0;
int command_list_size_alt = 0;

int CommandListCounter(){       // Первая версия счетчика команд
    int l = 0;
    do{
            l++;    //Да, тут баг, первый элемент массива никогда в счетчик не попадет, но их в массиве будет больше одного, да и ищем мы последний, так что ну его.
            Serial.println(M_command_list[l]);  // Для дебага, смотрим, что попадет в счетчик
    } while(!M_command_list[l].startsWith("NULL"));    //Читаем по очереди строки из массива и ждем NULL
    Serial.print("Command list size: "); Serial.println(l); // Для дебага
    return l;  //возвращаем найденное значение
   
}

void CommandListCounterAlt() {       // Вторая версия счетчика команд
  for (int l = 0; true; l++) {  //Цикл бесконечный, завершается по break
      Serial.println(M_command_list[l]);  // Для дебага, смотрим, что попадет в счетчик
      if (M_command_list[l].startsWith("NULL")) { //Читаем по очереди строки из массива и ждем NULL
          command_list_size_alt = l; //Пишем данные в глобальную переменную
          Serial.print("Alternative command list size: "); Serial.println(l);  // Для дебага, смотрим, что счетчик насчитал
          break; //выходим из цикла
    }
  }
}

void setup() {Serial.begin(9600);
  while (!Serial) {
    ;
  }
command_list_size = CommandListCounter(); // пробуем первый способ
CommandListCounterAlt(); // пробуем второй способ
}

 

Суть проблемы: массив строк неизменен, тем не менее: а) при каждой перезагрузке часть символов в массиве строк заменяется на  пробелы и буквы L (но никода - первый и последний элемент массива). б) в большинстве случаев счетчики игнорируют первый встреченный  NULL и начинают забивать монитор последовательного порта тарабарщиной (которая явно содержит куски данных из других массивов) в) иногда все же (рано или поздно) счетчики останавливаются и выдают значения от 5 до 500 и выше. Каждый - свое. г) в полной версии программы, если убрать из счетчиков вывод на последовательный порт, то это приводит к полному зависанию еще ДО ТОГО(!) как произойдет обращение к счетчикам.

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

mixail844
Offline
Зарегистрирован: 30.04.2012

я бы заменил лист предопределенных команд на 

typedef enum 
{
PLACEHOLDER, 
ON,
OFF,
ALL_ON,
ALL_OFF,
MASK,
LIST_SIZE // всегда должен быть последним элементом enum
}command_t;

и ненадо ничего считать, добавляетете себе команды до LIST_SIZE .LIST_SIZE = "количество потдерживаемых команд"

эконимит место ,вместо String.Вы скорее всего пользуетесь этим набором команд в каком то протоколе команд ,там тоже проканает замена.легче сравнивать.

ежели нужно узнать список потдерживаемых команд(через serial например), тогда либо сопуствующуя документация к девайсу или уже при запросе "какие команды потдерживаються" ,отвечать строками .

а проблема ? у вас нет защиты от выхода за пределы массива.

аллокация памяти для String происходит динамически , и есть вероятность что один или нескольк из элементов массива M_command_list не смогли получить область памяти запрашиваемого размера (так как она уже занета другими массивами в вашем коде) .надеюсь если ЕвгенийП сюда заглянет,то разьяснит и мне и вам,ну или пошлет...читать документацию http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-3-dinamicheskie-i-avtomaticheskie-peremen

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

happy_penguin пишет:

нужно посчитать, сколько элементов в массиве .... Вручную вбить, естественно, проще, но в дальнейшем список будет расширяться, так что хотелось бы процесс автоматизировать)

Так, автоматизируйте

const size_t len = sizeof(M_command_list) / sizeof(M_command_list[0]);

Вот и весь Ваш подсчёт.