Бегущие огни на Ардуино для сборной модели автомобиля
- Войдите на сайт для отправки комментариев
Доброго дня, уважаемые форумчане!
Мое увлечение программированием Ардуино пришло от хобби сборки масштабных моделей автомобилей. Организация поворотников, ближнего/дальнего света, тормозных сигналов и т.п. с помощью микроконтроллера, это оказалось удивительно просто при наличии минимальных знаний по программированию на С++. Однако, попробовав усложнить себе задачу, я столкнулся с непреодолимой трудностью. В очередную сборную модель автомобиля я решил установить бегущие поворотники. Написал скетч, но вот уже больше месяца бьюсь над проблемой. Задача программы, это последовательное чередование режимов бегущих поворотников через нажатие тактовой кнопки:
- левый поворотник
- правый поворотник
- аварийка
- выкл
Режим каждого бегущего поворотника организован на массиве из четырех пинов, сам скетч полностью рабочий, но если нажимать тактовую кнопку, не дожидаясь 100% пробега до 4-го пина, то следующий режим поворотника или аварийки включится не с array[0], а с того пина, на котором был прерван предыдущий цикл бегущей строки.
Ниже я привожу самый простой вариант скетча, хотя пробовал организовать его через выделение динамической памяти для массива, через организацию класса бегущей строки. Единственный способ, который мне удалось реализовать для нормальной работы бегущих строк с первого пина, это полный программный сброс микроконтроллера void(* resetFunc) (void) = 0, но этот способ лишает меня возможности использовать остальные пины Ардуино для другой светотехники модели.
Подскажите, пожалуйста, что мне нужно изменить в скетче или в моей голове? Может, я неправильно обращаюсь с массивами или с областью видимости?
// Организация бегущих поворотников через функцию changeLed /* нажатием тактовой кнопки включаем режимы: 1. бегущий левый поворотник 2. бегущий правый поворотник 3. бегущая аварийка 4. выключение */ #define BUTTON_1_PIN 2 // номер вывода кнопки 1 boolean lastButton = LOW; // переменные для функции антидребезга boolean currentButton = LOW; int array1[10] {3, 4, 5, 6}; // инициализация массива левого поворотник int array2[10] {A0, A1, A2, A3}; // инициализация массива правого поворотника int ledDelay(100); // инициализация задержки в функции бегущих огней int currentLed(0); // инициализация текущего пина unsigned long pastTime; // прошедшее время для millis unsigned long mill; // переменная для millis int counter = 0; // счетчик режимов кнопки // функция для подавления дребезга boolean debounse(boolean last, int swichPin ) { boolean current = digitalRead(swichPin); if (last != current) { delay(5); current = digitalRead(swichPin); } return current; } // функция бегущих огней void changeLed(int *massive1, int *massive2) { static unsigned long pastTime; // прошедшее время для millis if ((mill - pastTime) > ledDelay) { // если пришло время перейти к следующему светодиоду pastTime = mill; // включаем текущий LED digitalWrite(massive1[currentLed], HIGH); digitalWrite(massive2[currentLed], HIGH); // переходим к следующему пину currentLed ++; // увеличиваем иттерацию по массиву на 6 несуществующих элементов для получения требуемой задержки if (currentLed == 10) { // выключаем все светодиоды for (int i = 0; i < 10; i++) { digitalWrite(massive1[i], LOW); digitalWrite(massive2[i], LOW); } currentLed = 0; } } } // функция сброса левого поворотника void offLeft() { for (int i = 0; i < 10; i++) digitalWrite(array1[i], LOW); } // функция сброса правого поворотника void offRight() { for (int i = 0; i < 10; i++) digitalWrite(array2[i], LOW); } void setup() { for (int pin = array1[0]; pin <= array1[3]; ++pin) pinMode(pin, OUTPUT); for (int pin = array2[0]; pin <= array2[3]; ++pin) pinMode(pin, OUTPUT); pinMode(BUTTON_1_PIN, INPUT); } void loop() { mill = millis(); // один запрос millis() на один цикл // блок управления режимами переключениями поворотников currentButton = debounse(lastButton, BUTTON_1_PIN); if (lastButton == LOW && currentButton == HIGH) // было нажатие кнопки counter++; lastButton = currentButton; // сброс признака клика if (counter == 1) { offRight(); // выключаем правый поворотник, включаем левый changeLed(array1, array2); } if (counter == 2) { offLeft(); // выключаем левый поворотник, включаем правый changeLed(array1, array2); } if (counter == 3) { changeLed(array1, array2); // включаем аварийку } if (counter == 4) { offLeft(); // выключаем все и обнуляем счетчик offRight(); counter = 0; } }
currentLed = 0;
надо поместить в 71 строке
А что это у вас в строках 13 и 14 такое интересное написано? ))
По вопросу - видимо, нужно обнулять currentLed при смене режима
А кто ж за Вас будет с начала-то начинать?
Во все функции offXXX добавьте
и всего делов.
Странные у вас массивы. Если в каждом поворотнике по 4 пина - зачем в массиве обьявлены, и, главное, итерируются по десять элементов??
Далее... вот это называется "левой пяткой за ухом"
итерировать цикл надо по индексу массива, а не по значению... а так у вас полная ерунда выходит
И в догонку - функция changeLed тоже вызывает вопросы. зачем вы ей всегда передаете оба массива поворотников. даже если мигаете только одним?
В общем, код - очередная иллюстрация к мифу "ардуино - это так просто"
А что это у вас в строках 13 и 14 такое интересное написано? ))
А что там такого интересного? Объявления переменных с инициализацией.
... пробовал организовать его через выделение динамической памяти для массива, через организацию класса бегущей строки. Единственный способ, который мне удалось реализовать для нормальной работы бегущих строк с первого пина, это полный программный сброс микроконтроллера void(* resetFunc) (void) = 0....
поражает, сколько всего человек освоил - и динамические переменные, и классы, и программный ресет... вместо того чтобы просто обнулить счетчик
Горе от ума.
А что это у вас в строках 13 и 14 такое интересное написано? ))
А что там такого интересного? Объявления переменных с инициализацией.
Вот это и интересно. Не знал, что можно так инициализировать, в скобочках. В учебниках пишут, что переменные инициализируются присвоением
Скобки это сокращённый конструктора.
Конструктор переменной о_О?
Конструктор значения переменной.
Конструктор переменной о_О?
Да. А чо смешного?
когда ты пишешь int i;
неявно вызывается int i(0);
Да. А чо смешного?
когда ты пишешь int i;
неявно вызывается int i(0);
Я говорил, что смешного? Дед, не наговаривай на меня. Я просто подофигел ))
Конструктор переменной о_О?
Да. А чо смешного?
когда ты пишешь int i;
неявно вызывается int i(0);
Это смотря где напишешь.
Да. В глобалах - точно, в локальных - нинаю.
Строго говоря, в глобалах тоже не так. Там просто чистится вся память, не выделяя из нее отдельные переменные.
А вот инициализация через скобки - да, стандартный прием в Си++.
сегмент инициализированных данных тоже тупо чистится? Там не только нули могут быть.
Строго говоря, в глобалах тоже не так. Там просто чистится вся память, не выделяя из нее отдельные переменные.
А вот инициализация через скобки - да, стандартный прием в Си++.
Нет. Там вызывается конструктор по умолчанию. То есть не int i(0);, а int i();, на самом деле.
Куда ж не нафиг :-)))
сегмент инициализированных данных тоже тупо чистится? Там не только нули могут быть.
На самом деле там переменные разделяются на инициализированные и неинициализированные. В младших адресах размещаются инициализированные, значения которых циклом копируются из PROGMEM, а за ними - неинициализированные, которые так же в цикле обнуляются:
Друзья! Спасибо Вам за оказанную помощь и справедливую критику. Отдельная благодарность уважаемому форумчанину под ником Komandir. Один стейтмент в 71-й строке «currentLed = 0;» решил все проблемы. Обязуюсь учесть все замечания. У меня теперь программа работает, как нужно. Единственное, переход от второго поворотника к аварийке стал немного некорректным, но это я додумаю. Еще раз благодарю всех за помощь, критику и участие!
Все готово! Внес еще маленькое изменение в скетч, и теперь это 100% готовый и корректный вариант. Параллельно постарался учесть все справедливые замечания. Выкладываю результат, может кому-нибудь пригодится.
А фото/видео результата?
Фото будет не информативным, а видео выложить не получается. Боюсь, на этой площадке видеофайлы не поддерживаются.
Гифки вполне себе размещаются
Блин, да нафига макетка то? Модельку с поворотниками хотелось. Или вы думаете, что тут никто не знает, как последовательно 4 светодиода загораются?
Я собираю модели из парворков, они собираются по два, три года. Поэтому, динамические поворотники на моем собранном авто можно будет посмотреть только через пару лет. А пока у меня в коллекции только те модели, тираж которых завершен издательством. На них я организовал самую простую схему светотехники на основе Ардуино.
Я собираю модели из парворков
откуда-откуда, простите?
Прошу прощения, опечатка, конечно речь идет о периодическом издании партворков.
Прошу прощения, опечатка, конечно речь идет о периодическом издании партворков.
если вы думаете, что это я вас троллил за пропущенную букву - но таки нет.
"Партворк" - впервые слышу это слово. хотя калька с английского понятна.
Удивительно, что у кго-то хватает терпение собирать модель, когда каждый месяц выходить в продажу только пара деталей...
Не пойму, какой масштаб там. Питание и электроника "у ей в нутре"?
Масштаб 1:8, и да, вся электронная начинка и питание спрятаны внутри
класс))
На копейке никогда аварийки не было.