Программирование классами на arduino
- Войдите на сайт для отправки комментариев
Вс, 14/05/2017 - 20:13
Я программировал в основном на C# и немного на QT, поэтому привык пользоваться классовой архитектурой, но в ардуине столкнулся со следующей проблемой. Попытался написать класс с использованием интерфейса 12C для вывода текстовых данных на дисплей размерностью "20*4", при компиляции ошибок не выдает но и дисплей не инициализирует. Прошу не судить строго на низкоуровневых языках опыта практически нет. Вот код
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//класс дисплея
//###############################################################
class Tdisplay{
public:
LiquidCrystal_I2C *lcd; // создаем указатель на дисплей
Tdisplay();//конструктор класса(а также инициализация дисплея)
void set_text(char* maintext);//установка текста (незаконченна)
void test(); // проверка работы класса
};
//////////////////////////////////////////////////////////////
void Tdisplay::set_text(char* maintext){ //недоделанный метод
}
void Tdisplay::test(){
lcd->setCursor(0, 1);
// Выводим на экран количество секунд с момента запуска ардуины
lcd->print(millis()/1000);
}
Tdisplay::Tdisplay(){
lcd =(0x3F,20,4);//инициализируем указатель
lcd->init();
lcd->backlight();// Включаем подсветку дисплея
lcd->print("iarduino.ru");//вывод тестового текста
lcd->setCursor(8, 1);
lcd->print("LCD 1602");
}
// Конец класса дисплея
//#############################################################
Tdisplay display;//инициализирую свой класс дисплея
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
display.test();// вывод тестовой надписи
}
У меня Ваш код не компилится (1.6.7)
1. с адресом I2C не промазали?
2. если в инициализации помигать подсветкой, мигает?
Пока покопаюсь
Ну что делать. Мы тут не пишим на высокоуровневых языках типа ДОЛЛАР,АКЦИИ,ФЬЮЧЕРСЫ и прочее.
ПС:https://goo.gl/JsmLc5
...привык пользоваться классовой архитектурой, но в ардуине столкнулся со следующей проблемой.
...но и дисплей не инициализирует.
Вы всерьез считаете, что использование классов автоматичекси гарантирует Ваши программы от ошибок?
ПС:https://goo.gl/JsmLc5
моих знаний не хва :(
lcd = new LiquidCrystal_I2C (0x27,16,2);
не работает. Эх, придется ждать решения :(
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C *lcd; void setup() { lcd = new LiquidCrystal_I2C(0x27, 20, 4); lcd->init(); lcd->backlight(); lcd->setCursor(0, 0); lcd->print("Hello, world!"); } void loop() { }Компилируется прекрасно.
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C *lcd; void setup() { lcd = new LiquidCrystal_I2C(0x27, 20, 4); lcd->init(); lcd->backlight(); lcd->setCursor(0, 0); lcd->print("Hello, world!"); } void loop() { }Компилируется прекрасно.
ага. прям здорово. но не работает.
UPD: сорри. забыл что у меня на стенде backlight на PWM висит :)
Ваш код работает. Все тоже самое в классе ТС - не хочет работать
А адрес lcd какой в сканере?
А адрес lcd какой в сканере?
Не буду оффтопичать. ждем ТС
привык пользоваться классовой архитектурой
Стесняюсь спросить, Вы марксист?
Так тоже компилируется
#include <Wire.h> #include <LiquidCrystal_I2C.h> class Cl_display { private: LiquidCrystal_I2C *lcd; // создаем указатель на дисплей public: Cl_display() {}; void setup(); void work(); }; void Cl_display::setup() { lcd = new LiquidCrystal_I2C(0x27, 20, 4); lcd->init(); lcd->backlight(); } void Cl_display::work() { lcd->setCursor(0, 0); lcd->print("Hello, world!"); } Cl_display Display; void setup() { Display.setup(); Display.work(); } void loop() { }Дисплей без класса подключаеться и работает прекрасно. Но как только переношу в класс то программа просто компилируеться но не работает.
Адрес LSD в сканере 0x3F (без класса все работает)
lcd =newLiquidCrystal_I2C(0x3F, 20, 4); - инициализация предложенная выше не помогла, все компилируеться но не работает.Можно конечно передать в конструктор моего класса уже проинициалицированный в setup указатель на дисплей. Но все таки интересно возможно ли полностью вынести инициализацию дисплея в класс?
Не . В конструктор инициализацию перенести нельзя. Вы же не запускаете программу на обесточенном компьюте, что бы включили а программа оп и работает без загрузки.
Да, alexseyF, при программировании для Ардуино не следует забывать о следующем:
Когда Вы пишете программу для ПК, то эта программа вправе ожидать, что к моменту ее старта (и, соответственно, к моменту инициализации используемых ею объектов) уже и ядро ОС и все драйвера загружены и готовы к работе.
В Ардуино скетч начинает работать сразу, и никакой разницы с точки зрения порядка инициализации между прикладными классами и классами библиотек (которые играют роль драйверов) нет. Поэтому инициализация статических переменных (объектов) происходит тогда, когда система еще не полн6остью готова к работе.
Поэтому, вопреки академическим рекомендациям и практике программирования на ПК, в Ардуино принято оставлять собственный конструктор класса пустым. Точнее, использовать его только в том случае, когда хорошо представляешь, зачем это нужно. А реальную инициализацию переменной класса осуществлять в методе init() или begin(), вызываемым из setup(). Но или так, как продемронстрировал qwone: статическим объявляется не сам класс, а указатель на него, а память под него выделяется (и проводится инициализация) опять-таки из setup(), т.е. только тогда, когда вся "системная" игициализация заведомо отработала.
Спасибо друзья вот такой код сработал
#include <Wire.h> #include <LiquidCrystal_I2C.h> //класс дисплея //############################################################### class Tdisplay{ public: LiquidCrystal_I2C *lcd; // Устанавливаем дисплей Tdisplay();//конструктор класса void set_text(char* maintext);//установка текста void test(); void setup(); }; ////////////////////////////////////////////////////////////// void Tdisplay::set_text(char* maintext){ } void Tdisplay::test(){ lcd->setCursor(0, 1); // Выводим на экран количество секунд с момента запуска ардуины lcd->print(millis()/1000); } void Tdisplay::setup(){ lcd = new LiquidCrystal_I2C (0x3F,20,4);// (0x3F,20,4); lcd->init(); lcd->backlight();// Включаем подсветку дисплея lcd->print("iarduino.ru"); lcd->setCursor(8, 1); lcd->print("LCD 1602"); } Tdisplay::Tdisplay(){ } // Конец класса дисплея //############################################################# Tdisplay display; void setup() { // put your setup code here, to run once: display.setup(); } void loop() { // put your main code here, to run repeatedly: // Устанавливаем курсор на вторую строку и нулевой символ. display.test(); }Можно ли перенести инициализацию дисплея в сам конструктор класса не используя метод setup()
Всем большое спасибо вопрос снят.
39// Конец класса дисплеяне занимайся самообманом - конец класса дисплея у тебя здесь:
15};Либо, если будешь работать с классом динамически
TDisplay *display;
то можно инициализацию делать и в конструкторе, потому что создание экземпляра класса в сетап будет происходить в заданное время, после того как вся run-time инициализация уже отработала
P.S. я тоже сторонник классов, у мня даже каждая релюха или трехцветный LCD классом описан. Памяти жрёть больше, канеш, но камни меньше 328p я не пользую, а туда все влазит с запасом. И код получает единообразие.
Например
class TRelay { private: // const char *fontext = "Relay On"; // const char *fofftext = "Relay Off"; bool finverted; bool fstate; byte fpin; public: TRelay(byte pin); // Номер пина на котором реле, по умолчанию уровень включения HIGH TRelay(byte pin, bool inverse); // Если реле включается низким уровнем inverse = true void On(void); // включить реле void Off(void); // выключить реле. Уровень включения определяется finverted const char *ToString(void); // отдает строку "ON" или "OFF" bool State(); // отдает правильное состояние реле, независимо от уровня включения HIGH или LOW };