arduino ошибка условной компиляции в NewLiquidCrystal

sunjob
sunjob аватар
Offline
Зарегистрирован: 18.07.2013

добрый день

есть некий 100% рабочий проект на "ардуине"
используется "стандартный" 16х2 LCD дисплей (в 4х битном режиме)

все ноги проца занятые, решил допилить проект под себя, добавить (и ногами разжиться подключив LCD по I2c):
- энкодер (шаговичек от флопика)
- подключить дисплей с пом-ю I2C 
http://www.ebay.com/itm/New-IIC-I2C-Serial-Interface-Board-Module-For-Ar...

с энкодером проблем нет, а вот с дисплеем ... :о)
точнее не с самим дисплеем а с условной компиляцией

I2C модуль хорошо стыкуется с библиотекой (обновленной LiquidCristall, мой моуль нормально стыкуется только с этой либой) 
https://bitbucket.org/fmalpartida/new-liquidcrystal

тупо заменить код на нужный (это не есть тру)
поэтому хочу сделать более универсальный вариант: лобо стандартное подключение либо I2C...

добавляю примерно следующий код:

// ==> CUT

// определяем переменную для того, что бы собрать I2C-версию
// use I2C LCD interface 
#define LCD_I2C
#define LCD_I2C_ADDR 0x20 // I2C module addres

#ifdef LCD_I2C
#include <Wire.h> // обязательно надо было подключить
#include <LiquidCrystal_I2C.h>
#else
#include <LiquidCrystal.h>
#endif
...
#ifdef LCD_I2C
LiquidCrystal_I2C lcd(LCD_I2C_ADDR, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE); 
#else
LiquidCrystal lcd(PINS_LCD_RS, PINS_LCD_ENABLE, PINS_LCD_DB4, PINS_LCD_DB5, PINS_LCD_DB6, PINS_LCD_DB7);
#endif

// ==> CUT

LCD_I2C - определена, сборка проходит нормально
LCD_I2C - задизеблена, сборка затыкается, причем ошибки валят... я бы сказал "левые"...

глянул "код уже в обертке", можно посмотреть в логах ардуины где он находится, ни чего подозрительного не нашел
потыкавшись нашел закономерность - если переменная в условии #ifdef - не определена, то вываливается "эта самая ошибка"

причем, если воткнуть тот или иной код без "препроцессора" то все соберется нормально
т.е. если вставить код

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(LCD_I2C_ADDR, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE); 

или

#include <LiquidCrystal.h>
LiquidCrystal lcd(PINS_LCD_RS, PINS_LCD_ENABLE, PINS_LCD_DB4, PINS_LCD_DB5, PINS_LCD_DB6, PINS_LCD_DB7);

...

проверял на нескольких версиях ардуины ИДЕ (1.,0.5 , 1.5.2 , ночная сборка... )
коллизии со старой либой "ликвид" - исключены (заменена на новую)

смылс переменной, надеюсь понятен: 
- если она определена, то происходит "I2C сборка"
- если переменная не определена, то "нормальная сборка"

причем, очень странно, тут же в коде есть 
#ifdef BOARD_ARDUINO_MEGA // For ArduinoMega compatibility
#define PINS_FLASH1 56 // Mega pin 56 = Duemilanove 16 (digital pin)
#define PINS_FLASH2 55 // Mega pin 55 = Duemilanove 15 (digital pin)
#define PINS_DEVICE 54 // Mega pin 54 = Duemilanove 14 (digital pin)
#else 
#define PINS_FLASH1 16 //(digital pin)
#define PINS_FLASH2 15 //(digital pin)
#define PINS_DEVICE 14 //(digital pin)
#endif

и с этим собирается нормально 
т.е. простые препроцессорные вкропления обрабатываются нормально, а включение непосредственного кода... увы

пробовал на пустых проектах подключать отработать "условную компиляцию" - все нормально, как только подключаю эту самую новую библиотеку "New LiquidCrystal" - то вываливаются ошибки

выкус ошибок 

Photoduino:511: error: ‘sysexCallback’ was not declared in this scope
Photoduino.ino: In function ‘void loop()’:
Photoduino:522: error: ‘config_init’ was not declared in this scope
Photoduino:523: error: ‘backlight_init’ was not declared in this scope
Photoduino:524: error: ‘device_init’ was not declared in this scope
Photoduino:525: error: ‘controller_run’ was not declared in this scope
config_manager.ino: In function ‘void config_init()’:
config_manager:20: error: ‘config_loadBackup_all’ was not declared in this scope
config_manager:24: error: ‘backlight_toggle’ was not declared in this scope
config_manager:25: error: ‘display_printResetting’ was not declared in this scope
config_manager:30: error: ‘display_printProgressBar’ was not declared in this scope
config_manager:43: error: ‘config_loadDefaults_all’ was not declared in this scope

причем "sysexCallback" - ноги от нее растут из системной библиотеки 
$ARDUINO/libraries/Firmata/

хотя в проекте используется "локальная, упрощенная" ее версия 
FirmataLite.h
FirmataLite.ino

ни каких ссылок на подключение системной библиотеки "Firmata" - ни где нет...

### ADD

есть подозрения что ноги растут как раз из новой библиотеки NewLiquidCrystal
- заменил ее на старую, стандартную, из пакета Arduino
- подправил текст программы, что бы подключались нужные файлы и заменил на соотв. конструкторы...

#include <LiquidCrystal_I2C.h>
-->
#include <LiquidCrystal.h>

и усе собралось, как по маслу с определенной переменной так и с дизебленной

библиотека, которая замещает исходную ардуиновскую - NewLiquidCrystal
https://bitbucket.org/fmalpartida/new-liquidcrystal
i'm use LiquidCrystal_V1.2.1.zip

будем изучать код библиотеки, буть он неладен...
если кто глянет более опытным глазом, будем благодарны (все, кто сталкнется с таким же... :о)

### add

перерыл весь код NewLiquideCristall, все тщетно, придраться не к чему

### пособие по повторению косяков

значит такь, записывайте:
1. библиотека, которая замещает исходную ардуиновскую NewLiquidCrystal
https://bitbucket.org/fmalpartida/new-liquidcrystal
i'm use LiquidCrystal_V1.2.1.zip

2. проект который я "рихтую"
http://sourceforge.net/projects/photoduino/files/firmware/photoduino.shi...

3. мои изменения в патче Photoduino.diff

// cut ==>

319a320,323
>.
> //#define LCD_I2C
> #define LCD_I2C_ADDR 0x20 // I2C module addres
>.
322c326,334
< #include <LiquidCrystal.h> // For LCD Display use.
---
>.
> //#include <LiquidCrystal.h> // For LCD Display use.
> #ifdef LCD_I2C
> #include <Wire.h> // обязательно надо было подключить, непомню уже как до этого дошел :о) !!! но и без него нормально собирается
> #include <LiquidCrystal_I2C.h>
> #else
> #include <LiquidCrystal.h>
> #endif
>.
327a340,343
> //LiquidCrystal lcd(PINS_LCD_RS, PINS_LCD_ENABLE, PINS_LCD_DB4, PINS_LCD_DB5, PINS_LCD_DB6, PINS_LCD_DB7);
> #ifdef LCD_I2C
> LiquidCrystal_I2C lcd(LCD_I2C_ADDR, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);.
> #else.
328a345
> #endif

// cut ==>
 

p.s.
linux slackware 12.2 kernel 2.6.29.6 kde3 trinity
arduino 1.0.5, 1.5.2, nightly_build
проц, озу, диски - по самое неболуй-предостаточно

спасибо
 

tsostik
Offline
Зарегистрирован: 28.02.2013

Ответил в теме на ee.

sunjob
sunjob аватар
Offline
Зарегистрирован: 18.07.2013
sunjob
sunjob аватар
Offline
Зарегистрирован: 18.07.2013

ну, будут идеи почему с "неопределенной константой" вываливается ошибка???

tsostik
Offline
Зарегистрирован: 28.02.2013

Странно, я точно помню, что в пятницу на форума изиелектроникс писал подробный ответ, что происходит, но сейчас его там нет.

К сожалению, все эксперименты остались на работе, поэтому могу только по памяти изложить основные тезисы.

Когда Arduino IDE видит в тексте строчку "#include <LiquidCrystal.h>", то в отличие от "обычного" компилятора он не только включает в текузий файл содержмое указанного хедера, но и добавояет в проект соответствующий хедеру .cpp

При этом на #ifdef он, похоже плюет (что впрочем понятно - формитрование мейкфайла происходит раньше, чем работает препроцессор)

Это случается даже, если написать что-то типа:

#if 0
#include <LiquidCrystal.h>
#endif

В обычных ситацуациях это не создает проблем, так как линкер все равно не включит лишние скомпилированные объектники в итоговый hex, но в данном случае LiquidCrystal.h и LiquidCrystal_I2C.h - это наследники одного базового класса, определенного в LCD.h

Соответственно, одному ктулху ведомо, в какой из двух файлов с одинаковыми функциями лезет линкер за их телом (по идее, должен в первый из встреченых, но я могу и ощибаться, а линкер может иметь свое собственное мнение по этому поводу).

Плюс к этому, какие файлы и в каком порядке будут скармилваться препроцессору/компилятору в случае с ArduinoIDE тоже непонятно.

Так что я бы просто создал Makefile для проекта, тщательно почистил его и компилировал ручками с помощью обычного мейка идущим в составе ардуины avrgcc. Мэйкфайл можно, скорее всего, вытащить из временных файлов, создаваемых IDE.

sunjob
sunjob аватар
Offline
Зарегистрирован: 18.07.2013

"ошибка условной компиляции" устранена, решение следующее:

1. добавляем хедер файл в главный модуль 

#include "inc.h"

2. добавляем в inc.h описания всех функций используемых в проекте (проект состоит из нескольких INO-файлов, подключаемых Arduino-IDE "от балды на автомате" :о)))

ну вообщем то и все... сборка прошла нормально

будем грысть проект далее

п.с. думаю вся проблема в Arduino-IDE, которая некорректно "упаковывает" код (есть такое мнение, не мое, в инете об этом пишут...)

спасибо всем откликнувшимся, удачи