Здравствуйте Возникла проблема с библиотекой и примерами для IMU-сенсора. Вылезают такие ошибки при компиляции: Код (Text): In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis331dlh.cpp:3:0: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h: In member function 'int16_t LIS331DLH_TWI::readAxis(uint8_t)': C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp:3:0: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h: In member function 'int16_t LIS3MDL_TWI::readAxis(uint8_t)': C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ Sketch uses 5 364 bytes (18%) of program storage space. Maximum is 28 672 bytes. Global variables use 395 bytes (15%) of dynamic memory, leaving 2 165 bytes for local variables. Maximum is 2 560 bytes. Нет возможности проверить, так-как отсутствует датчик. Такие ошибки выползают в каждом примере из библиотеки для IMU-сенсора Прошу ответить как можно скорее С чем это связано? Как это можно исправить? Будет ли это влиять на работу датчика и возможность считывать показания?
Попробуйте Arduino IDE 1.6.X. К примеру на версии 1.6.1 у меня проблем не возникло. А вот на версиях 1.0.X ошибки были, но другие.
Поставил в настройках вывод всех ошибок при компиляции. Код (Text): In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/troyka-imu.h:3:0, from accel.ino:4: C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis3mdl.h:7:0: warning: "RANGE_4" redefined [enabled by default] #define RANGE_4 0 ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/troyka-imu.h:1:0, from accel.ino:4: C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis331dlh.h:8:0: note: this is the location of the previous definition #define RANGE_4 1 ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/troyka-imu.h:3:0, from accel.ino:4: C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis3mdl.h:8:0: warning: "RANGE_8" redefined [enabled by default] #define RANGE_8 1 ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/troyka-imu.h:1:0, from accel.ino:4: C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis331dlh.h:9:0: note: this is the location of the previous definition #define RANGE_8 2 ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/troyka-imu.h:3:0, from accel.ino:4: C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis3mdl.h:31:23: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float x_cal = 0; ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis3mdl.h:32:23: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float y_cal = 0; ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master/lis3mdl.h:33:23: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float z_cal = 0; ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis331dlh.cpp: In member function 'int16_t LIS331DLH_TWI::readAxis(uint8_t)': C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis331dlh.cpp:112:30: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default] Wire.requestFrom(_addr, 1); ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis331dlh.cpp:3:0: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis331dlh.cpp:122:30: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default] Wire.requestFrom(_addr, 1); ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis331dlh.cpp:3:0: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp:5:0: C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.h:31:23: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float x_cal = 0; ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.h:32:23: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float y_cal = 0; ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.h:33:23: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float z_cal = 0; ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp: In member function 'int16_t LIS3MDL_TWI::readAxis(uint8_t)': C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp:161:30: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default] Wire.requestFrom(_addr, 1); ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp:3:0: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp:171:30: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default] Wire.requestFrom(_addr, 1); ^ In file included from C:\Users\RusmenPRO\Documents\Arduino\libraries\Troyka-IMU-master\lis3mdl.cpp:3:0: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int) uint8_t requestFrom(int, int); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t) uint8_t requestFrom(uint8_t, uint8_t); ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring.c: In function 'init': C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring.c:318:3: warning: #warning Timer 2 not finished (may not be present on this CPU) [-Wcpp] #warning Timer 2 not finished (may not be present on this CPU) ^ C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring.c:327:3: warning: #warning Timer 2 not finished (may not be present on this CPU) [-Wcpp] #warning Timer 2 not finished (may not be present on this CPU) ^ Sketch uses 9 038 bytes (31%) of program storage space. Maximum is 28 672 bytes. Global variables use 414 bytes (16%) of dynamic memory, leaving 2 146 bytes for local variables. Maximum is 2 560 bytes.
Ошибки которые отображаются, не должны быть в принципе. Как будто, у Вас 1 и та же библиотека лежит в разных местах. Я сейчас попробую скачать 1.6.5, а Вы удалите данную библиотеку, со всех папок, более подробно, тут - http://forum.amperka.ru/threads/Работа-с-библиотеками.4253/. И заново добавьте, не забывайте закрывать Arduino IDE перед удалением и пользуйтесь обычным добавлением библиотеки, которое описано тут - http://wiki.amperka.ru/программирование:библиотеки. UPD. Как оказалось, у меня 1.6.1 не был настроен на отображение подробной информации. Сейчас получил такие же предупреждения, как у Вас в 1 посте. Нужно время, чтобы глянуть библиотеки.
Проблема в том, что во включаемых файлах для акселерометра и компаса, которые включены в основной включаемый файл библиотеки, объявлены одинаковые макроопределения RANGE_4 и RANGE_8. Причем с разными значениями. У меня на каком-то варианте скетча вылезло. Кажется, когда использовал директивы условной компиляции. Для решения вопроса я переименовал их во включаемом файле акселерометра, добавив к ним префикс, хотя, наверное, правмльнее было бы сделать соответствующие параметры enum, макроопределения переделать в enum, а определения самих перечислений перенести внутрь классов. А на предупреждения (warning) внимание можно не обращать. Если я правильно понял, что написано по англицки, то оно некритично и обращено к тем, кто вдруг захочет поменять параметры компилятора.
Версию 1.6.5 скачать не смог, интернет сейчас у меня, отвратительный, но нашел 1.6.5 r2 Сам был удивлен одинаковыми define. При компиляции получил не мало предупреждений. Подумал, ну не может Амперка сделать такой код, видимо, я что-то не понимаю. Затем добавил в функцию классов begin (в классы lis331dlh и lis3mdl) Serial.print(). Код (Text): Serial.print("lis331dlh - "); Serial.println(RANGE_4); И Код (Text): Serial.print("lis3mdl - "); Serial.println(RANGE_4); Полученный результат Все работает, но понять по чему не смог. Следовательно необходимо использовать библиотеку: Код (Text): #include <troyka-imu.h> Все как в примере IMU. И не обращать внимание на замечания о RANGE_4 и RANGE_8. Если они Вас смущают, сделать как сделал geher. На этом я не остановился, интересно, почему он так работает. Сделал простой пример, вот он Код (Text): #include "t1.h" void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: SPrint(); } Код (Text): #ifndef T1_H #define T1_H #include "t3.h" #include "t2.h" #endif Код (Text): #ifndef T2_H #define T2_H #define RANGE_4 0 #define RANGE_8 1 #define RANGE_12 2 #define RANGE_16 3 #define SPrint() Serial.print("T2 - "); Serial.println(RANGE_8); #endif Код (Text): #ifndef T3_H #define T3_H #define RANGE_4 0 #define RANGE_8 10 #define RANGE_12 20 #define RANGE_16 30 #define SPrint() Serial.print("T2 - "); Serial.println(RANGE_8); #endif В данном примере, все работает как я ожидал, define переписываются в зависимости от порядка include. Буду дальше разбираться, любопытно жуть. Этим займусь ближе к вечеру. По другому предупреждению Wire.requestFrom(_addr, 1). Вот все варианты данной функции Код (Text): uint8_t requestFrom(uint8_t, uint8_t); uint8_t requestFrom(uint8_t, uint8_t, uint8_t); uint8_t requestFrom(int, int); uint8_t requestFrom(int, int, int); Я изучил их, и сделал тестовый пример, чтобы понять куда пойдет компилятор. Код (Text): // библиотека для работы I²C //#include <Wire.h> // библиотека для работы с модулями IMU //#include <troyka-imu.h> void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: uint8_t adr = 10; FuncA(adr, 1); Serial.print("1 sizeof - "); Serial.println(sizeof(1)); Serial.print("1U sizeof - "); Serial.println(sizeof(1U)); delay(1000); } void FuncA(int a, int b) { Serial.println("Fun - int"); } void FuncA(uint8_t a, uint8_t b) { Serial.println("Fun - uint8_t"); } Вообще кода мы вызываем функцию и передаем константу/литерал 1, то всегда думал, что передаем int, но лишний раз проверил, поэтому использовал sizeof. Узнал об этом когда-то из данного материяла - http://lord-n.narod.ru/download/books/walla/programming/Spr_po_C/02/0209.htm. Итак, если мы просто передаем 1 (int), будет предупреждение и будет вызвана функция FuncA(int a, int b), а если передаем 1U (uint), то предупреждения не будет и будет вызвана функция FuncA(uint8_t a, uint8_t b). Вероятнее всего это связано с неявным преобразованием. Опять же, можно легко исправить, найти данную функцию - int16_t LIS331DLH_TWI::readAxis(uint8_t reg), в ней Wire.requestFrom(_addr, 1); заменить на Wire.requestFrom(_addr, 1u);. Или явно преобразовать к нужному типу, так будет еще лучше. И т.д., где будет возникать данное замечание. По следующем замечаниям: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] float x_cal = 0; Пишет, что инициализация не статичных переменных, возможна лишь в С++ 11 версии. И предлагает запустить компилятор с дополнительными настройками. Но им присвоены 0-ли, даже если не инициализировать, они будут 0-ями. Если напрягает, можно убрать инициализацию или запустить компилятор с требуемыми настройками. Но лучше, просто объявить а в конструкторе класса просто присвоить значения. Но рекомендую, ни чего не трогать. Общий вывод для RusmenPRO эти предупреждения не опасны. Но всегда смотрите и изучайте предупреждения. Вроде ни чего не забыл, если где-то ошибся, надеюсь более опытные меня поправят. Вам удачи, а мне теперь не спать и разбираться.
Все работает внутри класса, поскольку перед объявлением класса включается заголовочный файл с соответствующими макроопределениями. Некорректная ситуация возникает при использовании этих констант непосредственно из скетча. Какое у них тогда будет значение? Логично предположить, что последнее, определенное в соответствии с порядком включения заголовочных файлов. Но для класса, определенного в соответствии с этим порядком первым, эти константы будут уже некорректными. Почему предлагает запустить? А как же -std=gnu++11 [enabled by default]? Я не нашел, чтобы этот параметр явно задавался бы где-либо кроме Teensy. Т.е.логично предположить, что оно как раз по умолчанию и все нормально.
Там код переделывать нужно. Либо макросы переименовать, чтобы не пересекались, либо внутри класса объявить enum и т.о. спрятать константы в пространство имен класса.
Вот этого пока не понимаю, просто не достаточно знаний в С++, когда-то работал на C#, но там ни когда не пользовался define. Сейчас пытаюсь разобраться. Вы правы, если по какой-то причине необходимо использовать эти define в коде самого скетча, то да их нужно минимум переименовать. Или переделать, на те же enum и т.д. Сам подход мне тоже не понравился. Да написано, по умолчанию. Но вот у меня, не используется данный параметр, к примеру Нет ни одного параметра -std=gnu++11, хоть он и по умолчанию, как и в файле platform.txt. А вот, после установки вручную данного параметра. И предупреждение исчезает. Если где-то ошибся, прошу меня поправить, Вы все таки более опытны, чем я.
Сделал простенький тест на предмет инициализации полей класса. Код (Text): class a { public: int x=101; int y=234; a() {}; ~a() {}; int q() {return(x+y);}; }; void setup() { Serial.begin(9600); } void loop() { a b; Serial.println(b.q()); Serial.println(b.x); Serial.println(b.y); Serial.println("-----"); delay(3000); } Предупреждения про "non-static data member initializers" идут, но инициализация тем не менее происходит правильно. Логически мысля (но необязательно правильно), могу объяснить это так: Если явно не задано иное, то действует то самое умолчание -std=gnu++11. Но поскольку оно явно не задано, компилятор предупреждает, что оно будет работать, но если задать данному параметру какое-то другое значение, то могут быть проблемы. Если же явно задать значение параметра, при котором оно будет работать, то компилятор полагает, что программист знает, что делает, потому предупреждений нет.
А логика-то и не работает. Добавил в параметры компилятора -std=c++98 (пробовал и -std=gnu++98, "левые" тоже пробовал - их не принимает). Предупреждения идут, но инициализация все равно происходит правильно. При добавлении вместо других -std=c++11 предупреждения пропадают, но поведение программы не меняется никак.
Так же попробовал, да, параметр вроде верен. Да и подставить ерунду, то же не получится, компилятор напомнит. Для С это работает, брал из списка, тут - https://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html#SEC7. Взял iso9899:1990, сразу ошибки и компиляция не возможна. Мне кажется, логика правильная, просто уже поздно, и где-то ошибаемся.
А мне кажется, что вы не совершенно не тем способом проблему решаете. Вместо того, чтобы поправить код, пытаетесь ублажить компилятор. инициализация не статических членов класса -> нафиг, убрать все в конструктор класса неявное приведение типов -> нафиг, дописать везде суффиксы или явное приведение типа пересекающиеся макросы RANGE_x -> нафиг, убрать в enum внутри класса другие короткие макросы -> нафиг, дописать везде префикс модуля, как для x_TWI_ADDRESS или убрать в enum макрос используется только в .cpp -> нафиг, убрать внутрь .cpp и забыть
Разумеется об этом говорил и geher и я. Просто столкнулся с непонятным поведением и хотел разобраться, а как все это работает и почему. Разобраться в нюансах definde внутри класса, в сообщениях компилятора и в его поведении. Просто очень любознательный и вечно попадаю на территорию профессионалов (компиляторы и т.д.), хотя сам простой любитель и мне там не место. Увы сейчас нет времени, надо возвращаться к работе, надеюсь будет время вернутся. Еще раз спасибо geher, за наводки.
Не корысти ради, и не ради приведения кода в "классово правильный" (в обоих смыслах) вид, а исключительно во имя нездорового любопытства. Проверил на "обычном" (в смысле не AVR) gcc под линуксом на x86. Поведение такое же. В зависимости от выбора параметра -std=xxx либо ругается на неправильный параметр (что говорит о том, что параметр может принимать только известные компилятору значения), либо выдает предупреждение (когда параметр задан как c++98 или какой другой или вообще не задан), либо ничего не выдает (если с++11 или gnu++11). Программа притом работает абсолютно неизменно с правильно работающей инициализацией. В итоге так и не понял, в чем глубокий смысл предупреждения про "non-static data member initializers". Если бы оно было логично сделано, при включении того же c++98 оно должно перестать работать вообще, ибо это одна из предыдущих версий стандарта, где такое предусмотрено не было. Иначе зачем вообще этот параметр, если все равно работают вещи из нового стандарта? Или я что-то неправильно понимаю? Что вообще имеется ввиду? Только возможное отсутствие поддержки в других компиляторах? Тогда должно ругаться и при -std=c++11. Если неопределенное поведение, то и ругаться надо на возможное неопределенное поведение. В сети пишут всякое, но внятного ответа не видно.
Все верно, если установить только стандарт, ни чего не меняется. И это натолкнуло меня на мысль, что где-то должен быть параметр следовать стандарту или что-то вроде. У данного компилятора, есть тьма опций в принципе и в частности настройки предупреждений - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options. Вот те, что проверил -Wpedantic -pedantic -pedantic-errors -Wpedantic не поддерживает проверку ISO, не пропустил requestFrom, но по стандарту только предупреждение. -pedantic не поддерживает проверку ISO, не пропустил requestFrom, но по стандарту только предупреждение. -pedantic-errors этот ни чего не пропустит и стандарт соблюдет и т.д. Код (Text): C:\Users\Admin\Documents\Arduino\libraries\Troyka-IMU-master/lis3mdl.h:31:23: error: non-static data member initializers only available with -std=c++11 or -std=gnu++11 float x_cal = 0; Возможно есть какой-то параметр рассчитанный только на соблюдения стандарта. Гляну завтра, там читать и читать (плюс их и моя безграмотность усложняют задачу, они не знают русского, а я плохо анг.), сходу не увидел, но должен быть. Список стандартов - https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html UPD. На свежую голову, как говорится. -Werror - Все предупреждения превращаются в ошибки. -Werror= Превращаем определенные предупреждения в ошибки. -Wfatal-errors Первая ошибка и компиляция будет остановлена. -Wpedantic -pedantic Казалось бы во оно, но увы они выдают лишь предупреждения. -pedantic-errors Толком понять разницу между -Werror и pedantic я не смог. Она есть, но это пока не понимаю. В их описании еще встречается такая запись, которая может похоронить проверку версий. Да и с параметром -pedantic-errors, не скомпилируется даже такой код Код (Text): void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: } Но это совершено другая история.