не адекватное поведение delay() в конструкторе
- Войдите на сайт для отправки комментариев
Вс, 19/07/2015 - 16:05
Простой пример. Виснет. В сериал ничего не поподает.
Если закомментировать delay() - работает нормально.
Попробовал на разных платках (Nano, Mega, Demilanove...) В раных версиях IDE.
Собственно почему?
class dim_DS18x20 { int _qty; public: dim_DS18x20( void ) {// Конструктор int i; i = 25; delay( 250 ); } }; // end class dim_DS18x20 dim_DS18x20 dimDS; void setup() { Serial.begin( 57600 ); } void loop() { Serial.print( "_qty_DS18x20 = " ); delay( 1000 ); }
Возможно, дело в том, что переменная dimDS описана глобально, значт, Ваш конструктор вызывается ДО полной инициализации. Проверка - перенесите описание в setup. Если заработает, то так и есть.
Возможно, вечером проверю. Но вопрос все равно останется.
Нет такого ограничегния (или я не знаю) на объявления переменных.
Сам этим активно пользуюсь, примеров есть куча, когда переменные объявляются глобально, и не важно кокого типа.
Скажем можно использовать Serial в конструкторе, что для меня менее очевидно, но работает. А в чем уникальность delay() - не понимаю
Скажем можно использовать Serial в конструкторе, что для меня менее очевидно, но работает. А в чем уникальность delay() - не понимаю
Да, если объявлять не глобально, то работает корректно.
Но вопрос остается.
А где у IDE исходники встроенных библитек лежат?
Нет такого ограничегния (или я не знаю) на объявления переменных.
В С++ нет простых переменных, все переменные - объекты. И для всех объектов при их создании вызывается конструктор.
При этом софт Ардуино устроен так, что конструкторы глобальных объектов отрабатывают до инициализации по крайней мере некоторых аппаратных фич.
Сделано это по ошибке или специально - не знаю.
И, соответсвенно, инициализация железа, которую пытается выполнить конструктор, не удается.
Это факт.
Специально для таких случаев принято писать дополнительную функцию инициализации, которую обычно называют begin или init.
Сам этим активно пользуюсь, примеров есть куча, когда переменные объявляются глобально, и не важно кокого типа.
Скажем можно использовать Serial в конструкторе, что для меня менее очевидно, но работает. А в чем уникальность delay() - не понимаю
Так что Ваш конструктор не уникален.
Сам пытался инициализировать дисплей в конструкторе, и так же, как и Вы обломался.
C:\Arduino\arduino-1.6.5-r2\hardware\arduino\avr\cores\arduino
У Вас, видимо начало будет другое.
delay() живёт в файле wiring.c Судя по тексту, он должен работать, если работает функция micros().
micros() находится в том же файле. Ей для работы нужна инициализированная переменная timer0_overflow_count и нормально работающий таймер/каунтер 0.
Чтобы таймерр нормально работал, ему нужно задать делитель частоты, разрешить прерывания и т.п. Эти волшебные пассы делаются в функции init() (в том же файле). Кстати, в начале функции есть комментарий прямо относящийся к теме нашего разговора:
Функция init() вызывается из main() в файле main.cpp ... в общем, дальше сами разбирайтесь.
Общий вывод понятен. При инициализации глобальных переменных, ещё не установлен таймер 0 и потому не работают micros() millis() delay() и т.п.
Вам следует либо глобально объявить указатель, а экземпляр класса создавать в setup(), либо оставить глобальное объявление, но оставить конструктор пустым, а инициализацию перенести в метод типа Init() и вызывать его уже из setup().
to: ЕвгенийП
Спасибо!
Буду смотреть. Еще бы время на это где нибудь найти!
Почитайте эту тему, там есть решение вашей проблемы с delay():
http://arduino.ru/forum/programmirovanie/novichkam-avtomatnoe-programmir...
Скорее сделали так потому, что по другому, не изобретая свой C++ невозможно. Все глобальные переменные создаются ДО вызова функции main(), в которой вызывается init(), которая все инициализирует и разработчики ардуино не могут на это никак повлиять (кроме разве что написать свой компилятор, но зачем?).
Можно было бы, конечно всю инициализацию запихать в конструктор какого-нибудь объекта и объявить глобально переменную, которая бы создалась и как следствие все проинициализировалось бы раньше, чем конструкторы других объектов. А может и нет, не помню, описано-ли в стандарте C++ в какой последовательности должны вызываться конструкторы глобальных объектов. Но все это было бы каким-то грёбаным извращением и ардуино-разработчики решили, что кому надо - может сам извращаться.