#define not behaving as expected.

Hi,

I’m writing a very short sketch to test a library I’ve written. I want to write the sketch to work slightly differently depending on whether or not a display is available. Basically I want the output to go either to the screen (i.e. Serial.print) or to an LCD display if I happen to have one at the time I run the test. I’m trying to use the #define precompiler directive to include or exclude the code relevant to the LCD display.

Here’s the sketch (as shown here it compiles fine)…

#include <stdlib.h>                        // needed for 'free'
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"                       // replacement for "WProgram.h" - required for versions after to 1.0.1
#else
#include "WProgram.h"                      // needed for 'Serial' - required for earlier versions
#endif
#include <Wire.h>                          // Library to control I2C comunications
#include <avr/pgmspace.h>                  // Needed for PROGMAN stuff
#include <ProgmemConst.h>                  // Global progmem constants
#include <HallPulseCounter.h>              // Rev-counter library based on hall-effect probe (required by propr).
#include <PropAnemometer.h>                // Airspeed based on hall-effect probe.

#define LCD_AVAILABLE                      // defined only if there's an LCD display available

#ifdef LCD_AVAILABLE
#include <LiquidCrystal.h>                    // Controls access to the LCD display
const int rs=8,en=9,d4=10,d5=11,d6=12,d7=13;  // Pin definitions for LCD
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);    // Display
#endif




int airspeed = 0;                          // Airspeed in cm/sec
int rpm = 0;                               // Propeller speed in revolutions per minute.

PropAnemometer Anemom1;                

void setup() 
{
  Serial.begin(115200); // start serial communication at 9600bps 
  Serial.println("##################################################################");
  Serial.println("####################     START     ###############################");
  Serial.println("##################################################################");
  
#ifdef LCD_AVAILABLE
  lcd.begin(16, 2);                        // Initialise the LCD with 2 rows of 16 characters
#endif 
  
  Anemom1.begin(2);  // Connect hall sensor to pin 2 (interrupt 0)
  
  attachInterrupt(1,isr0,FALLING);
  
}

void loop() 
{
  airspeed = Anemom1.getAirspeed();
  rpm = Anemom1.getFreq();

  Serial.print("airspeed <");  Serial.print(airspeed);  Serial.print("> (cm/sec), freq=<");  Serial.print(rpm); Serial.print("> (rpm)" );
  delay(100); // wait for half a second
}


/**************************************************************************
  Interrupt service routine 0.
**************************************************************************/
void isr0()
{
  Anemom1.recPulse();
}

The problem comes if I decide I want to run the sketch without an LCD screen. I comment out the line

#define LCD_AVAILABLE

and then get the error…
error: ‘isr0’ was not declared in this scope.

There are some easy work-arounds for this, but still I’d like to know what I’m doing wrong if anyone can spot it.

Thanks

What does the output from the per-compiler show?

Mark

What does the output from the per-compiler show?

Not sure I understand the question, but if I compile the above code I get.....
Binary sketch size: 18,926 bytes (of a 258,048 byte maximum)

If I comment out the line ...
#define LCD_AVAILABLE

I get the error message listed in my original posting.

thanks

Ah, I'm not sure the IDE keeps the output. The output od the per-complier is feed to the compiler (well really the C++ translator).

With g-cc you should be able to look at the pre-complier output. You can just run the pre-complier on its own. Then you can see what your #defines have really done.

Mark

You can just run the pre-complier on its own. Then you can see what your #defines have really done

Now we're getting technical, but this does sound like a good suggestion. How do I run the pre-compiler on it's own?

thanks

Perhaps the #ifdefs are confusing the Arduino's own preprocessor, which generates forward declarations for the functions in your sketch. What happens if you declare:

void isr0();

prior to setup?

The IDE inserts stuff into your sketch, after the first executable statement that it sees. The preprocessor directives are ignored during the detection process. So, it is inserting stuff in the middle of the block for the LCD. When that code no longer gets executed because you comment out the #define for the LCD use, then the IDE-added stuff goes away, too.

Add

byte stupid;

as the first line of your sketch.

What happens if you declare:

void isr0();

prior to setup?

No change in behavior.

Add
Code:
byte stupid;
as the first line of your sketch.

No change in behavior.

Luckily the sketch is short and simple enough that commenting and un-commenting the optional bits isn't too time consuming, but still, a more elegant solution would be better.

Thanks

No change in behavior.

Adding an executable statement as the first line SHOULD have had an impact. Post the modified code.

I commented out lines until it compiled (IDE 0.22 today) and it stops throwing errors at this state.
DO you have links to the three libs I commented?

#include <stdlib.h>                        // needed for 'free'
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"                       // replacement for "WProgram.h" - required for versions after to 1.0.1
#else
#include "WProgram.h"                      // needed for 'Serial' - required for earlier versions
#endif
#include <Wire.h>                          // Library to control I2C comunications
#include <avr/pgmspace.h>                  // Needed for PROGMAN stuff
//#include <ProgmemConst.h>                  // Global progmem constants
//#include <HallPulseCounter.h>              // Rev-counter library based on hall-effect probe (required by propr).
//#include <PropAnemometer.h>                // Airspeed based on hall-effect probe.

#define LCD_AVAILABLE                      // defined only if there's an LCD display available

#ifdef LCD_AVAILABLE
#include <LiquidCrystal.h>                    // Controls access to the LCD display
const int rs=8,en=9,d4=10,d5=11,d6=12,d7=13;  // Pin definitions for LCD
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);    // Display
#endif




int airspeed = 0;                          // Airspeed in cm/sec
int rpm = 0;                               // Propeller speed in revolutions per minute.

// PropAnemometer Anemom1;                

void setup() 
{
  Serial.begin(115200); // start serial communication at 9600bps 
  Serial.println("##################################################################");
  Serial.println("####################     START     ###############################");
  Serial.println("##################################################################");

#ifdef LCD_AVAILABLE
  lcd.begin(16, 2);                        // Initialise the LCD with 2 rows of 16 characters
#endif 

  // Anemom1.begin(2);  // Connect hall sensor to pin 2 (interrupt 0)

  attachInterrupt(1,isr0,FALLING);

}

void loop() 
{
  //airspeed = Anemom1.getAirspeed();
  //rpm = Anemom1.getFreq();

  Serial.print("airspeed <");  
  Serial.print(airspeed);  
  Serial.print("> (cm/sec), freq=<");  
  Serial.print(rpm); 
  Serial.print("> (rpm)" );
  delay(100); // wait for half a second
}


/**************************************************************************
 * Interrupt service routine 0.
 **************************************************************************/
void isr0()
{
  // Anemom1.recPulse();
}

Adding an executable statement as the first line SHOULD have had an impact. Post the modified code.

I've just done some re-checking, the changes you suggested DO work - I've been fiddling with the sketch all morning, so the error I thought I saw was a brand new one I'd only just added!

I commented out lines until it compiled (IDE 0.22 today) and it stops throwing errors at this state. 
DO you have links to the three libs I commented?

I haven't posted the links anywhere, but your comments make me realise this may be a version dependent issue. I'm using version 1.0.1 (should have said this in my initial post) If I take your sketch, then it will compile with

#define LCD_AVAILABLE

enabled, but as with my original sketch, I get the error

error: 'isr0' was not declared in this scope

As soon as I comment out #define LCD_AVAILABLE.

the compiler creates the signatures of the functions within the #ifdef (IDE 0.22) which explains the error

#define LCD_AVAILABLE                      // defined only if there's an LCD display available
#ifdef LCD_AVAILABLE 
#include "WProgram.h"
void setup();
void loop();
void isr0();
const int rs=8,en=9,d4=10,d5=11,d6=12,d7=13;  
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);    
// LiquidCrystal lcd(8,9,10,11,12,13);

#endif

workaround is to define void isr0() before setup()

Adding an executable statement as the first line SHOULD have had an impact. Post the modified code.

I added int x=0; at the first line and the Arduino preprocessor places the prototypes just before the first executable statement

#include "WProgram.h"
void setup();
void loop();
void isr0();
int x = 0;

Now this is outside the #ifdef #endif block the prototype of isr0() is always visible.