проблема при создании библиотеки
- Войдите на сайт для отправки комментариев
Сб, 15/11/2014 - 15:16
создаю библиотеки со своими классами, для перехода от стандартной IDE в CodeBlocks
возникла проблема при создании класса, в котором функция в одном из метод вызывает другой метод (в пределах этого же класса). не хочет компилироваться это дело.
Вот метод, в вызове стандартной функции attachInterrupt есть обращения к методам
void my_weather_sensors::setupWeatherInts() { pinMode(ANEMOMETER_PIN,INPUT); digitalWrite(ANEMOMETER_PIN,LOW); // EXTERNAL PULL-UP 10 K USED. Turn on the internal Pull Up Resistor pinMode(RAIN_GAUGE_PIN,INPUT); digitalWrite(RAIN_GAUGE_PIN,HIGH); // Turn on the internal Pull Up Resistor pinMode(VANE_PWR,OUTPUT); digitalWrite(VANE_PWR,LOW); attachInterrupt(ANEMOMETER_INT,anemometerClick,FALLING); attachInterrupt(RAIN_GAUGE_INT,rainGageClick,FALLING); interrupts(); }
void my_weather_sensors::rainGageClick() { long thisTime=micros()-rain_last; rain_last=micros(); if(thisTime>500) { rain_count++;} } void my_weather_sensors::anemometerClick() { long thisTime=micros()-anem_last; anem_last=micros(); if(thisTime>500) { anem_count++; if(thisTime<anem_min) { anem_min=thisTime;} } }
получаем ошибку:
D:\_ARDUINO\_OUTPUT\libraries\my_weater_sensors\my_weather_sensors.cpp: In member function 'void my_weather_sensors::setupWeatherInts()': D:\_ARDUINO\_OUTPUT\libraries\my_weater_sensors\my_weather_sensors.cpp:29: error: argument of type 'void (my_weather_sensors::)()' does not match 'void (*)()' D:\_ARDUINO\_OUTPUT\libraries\my_weater_sensors\my_weather_sensors.cpp:30: error: argument of type 'void (my_weather_sensors::)()' does not match 'void (*)()'
С прерываниями такая магия не сработает - разные типы функций получаются.
В калссах надо работать напрямую с прерываниями AVR как тут
неужели нельзя сделать библиотеку в которой есть функции прерывания без плясок с бубном ????
Maverik, attachInterrupt хочет получить аргумент типа "void (*)()", но weather_sensors::setupWeatherInts() ему не нравится, хотя и выглядит очень похоже на этот тип.
Просто, как у любой функции класса, у weather_sensors::setupWeatherInts() есть один скрытый аргумент - указатель на объект, т.е. на экземпляр класса.
Можно объявить методы-обработчики прерываний как static - думаю всё получится, и attachInterrupt такой указатель спокойно проглотит. Только имей в виду: обращаться из такого обработчика к другим методам и переменным класса будет уже не так легко и удобно.
не работает static
Не работает, или не компилируется?
Работу я конечно не проверю, а скомпилировать сейчас попробовал, всё получилось.
Вот это я имел в виду:
Без static будет выдаваться ошибка, а так - всё нормально.
хорошо Вам, у меня не компилится.
в методах anemometerClick() и rainGageClick() используются переменные volatile, видимо поэтому все равно лезут ошибки типа такого error: invalid use of member 'my_weather_sensors::rain_last' in static member function
если волатильные переменные ради прикола объявить еще и static , лезут ошибки множественного объявления переменной.
печалька...
Maverik, нет, не из-за этого. Это то, о чём я писал раньше:
static функция "не привязана" к какому-то конкретному объекту, то есть она не знает, с каким из объектов типа "my_weather_sensors" ты хочешь работать.
Если такой объект только один, можно его явно указать при обращении к переменным и методам:
Не очень удобно, я согласен.
Ещё хуже, если объектов будет несколько. Придётся перед каждым обращением выбирать нужный объект вручную - про удобство от использования классов можно забыть. :)
Я в таких случаях делаю как-нибудь так:
Если объектов несколько, обработчик прерывания должен уметь как-то определять, с каким из них работать. Тут уж я не подскажу, каждый сам придумывает способ.
Удачи! Оно обязано заработать. :)
спасибо, скомпилировалось, но пока нет возможности проверить и терзают смутные сомнения...
я пока с классами не очень дружу, не могу сообразить.
у меня алгоритм следующий - функции "anemometerClick()" и "rainGaugeClick()" ,скажем так, низкоуровневые, т.е. непосредственно снимают циклически показания с двух погодных датчиков. допустим, создаем экземпляр класса с названием Sensor. для удобства, создаю экземпляр прямо в сpp файле библиотеки.
т.е. речь идет о переменных
сейчас я сделал эти две вышеупомянутые функции методами класса. в этом же классе есть другие методы, которые работают с этими же переменными. соответственно, имена этих переменных я модифицирую так же во всех методах класса, "приписывая" их к этому экземпляру. Так вот, вопросы
первый - достаточно ли одного экземпляра класса если датчики опрашиваются периодически ? вроде функции attachInterrupt() инициализируются только однажды, но фактически если датчики опрашиваются многократно, значит и функция задействуется многократно.
второй - мне нужно периодически вызывать те самые другие методы этого класса из-за пределов класса, и оттуда я уже не могу вызвать экземпляр Serial этих методов, видимо, потому что он пошел для "внутреннего употребления", ведь в нем уже есть переменные этого экземпляра- программа не компилируется, ошибка множественного определения. если снаружи создаю новый экземпляр для вызова методов этого класса - компилируется нормально, но я начинаю терять логику работы программы ))) Ведь эти методы фактически работают с другим экземпляром переменных. не получится ли хрень ??
Ой, Maverik, боюсь я тебя плохому научил. :)
Совсем не "соответственно". Такое явное указание конкретного экземпляра внутри методов класса - это вынужденная мера, и этим лучше не пользоваться, по возможности.
И совсем уж неправильно - принудительно указывать конкретный объект в не статических методах класса. Не "static" методы и без этого знают, с каким экземпляром работать - со своим, конечно. Заставить их работать с "чужим" экземпляром можно, но лучше не надо. Это неправильно, и противоречит всей идеологии работы с классами, идеологии объектно-ориентированного программирования, и т.д.
И уж, точно, приведёт к полной потере логики работы программы. :)
У "static" методов "своего" экземпляра нет, они являются общими для всех экземпляров. Они, вообще-то, мало отличаются от обычных, неклассовых функций. То же самое и с классовыми переменными - "static" переменная будет одна на всех, сколько бы экземпляров класса мы ни создали. То есть, она ведёт себя как глобальная переменная, только спрятана внутри класса.
По поводу вопросов - если честно, не очень я их понял. Конечно, один экземпляр класса может опрашивать датчики сколько угодно раз. И да, конечно методы класса, если они public, можно вызывать "снаружи" - а иначе, зачем бы нам нужен такой класс, который живёт где-то там в себе и не имеет связи с внешним миром.
Соответственно, если мы хотим наоборот, спрятать метод или переменную от посторонних - мы объявляем их как private. Ну это я так, напомнил.
И ещё, ты уже не первый раз пишешь про "ошибку множественного определения", а я так и не понимаю, о чём это. Если можешь написать какой-нибудь пример коротенький, с этой ошибкой - попробую посмотреть, разобраться.
не работает static
Работает. Надо только помнить, что static методы не имеют отношения к экземплярам, поэтому в них можно истпльзовать только static сыойства. Если же нужно использовать свойства и методы экземпляров, то надо где-то брать указательно на экземпляр и доступаться через него.
Я для себя нашел 4 решения:
1. Переменную anem_count делать глобальной в скетче
2. Функцию anemometerClick() так же выносить за пределы класса, в функции записать Sensor1.anem_count++; , а саму anem_count перенести в сектор public: в классе
3. Сделать по примеру Datak
4. Сделать 3 класса: первый содержит основной код с прерываниями, второй сожержит переменные которые будут приращаться (anem_count), третий создает экземпляр первого и второго классов.
4-ый способ не проверял, не было необходимости, но думаю с его помощью все можно уложить в библиотеку с простым её сипользованием.
Для себя выбрал 2ой вариант, так как проверку на запуск нужного прерывания сделал в классе, а процедуры приращения вынес в основной код скетча. Тем самым проверка осуществляется только в момент запуска прерывания, что на мой взгляд жрет меньше процессорных ресурсов.
Соответсвенно процедур с приращениями и проверок в классе столько, сколько создается экземпляров класса.
Как я понял, уложить все в класс нереально :(
P.S. Если кто знает способ - делитесь!