#defines are being overwritten

I am replacing an antique 10 pin dot matrix printer with an arduino. The following code does not work as expected:

// #INCLUDES
/*     none   */

#define PINCOUNT 10
#define PIN1 22
#define PIN2 24
#define PIN3 26
#define PIN4 28
#define PIN5 30
#define PIN6 32
#define PIN7 34
#define PIN8 36
#define PIN9 38 
#define PIN10 40
#define STROBEP      25
#define STROBER      27
#define PRINTSTART   29

int pins[] = { PIN1, PIN2, PIN3, PIN4, PIN5, PIN6, PIN7, PIN8, PIN9, PIN10 };

void setup( void ) {

  pinMode( MOTORSENSE, INPUT );   //raised by board when its time to print
  pinMode( STROBEP, OUTPUT );      //set low to trigger
  pinMode( STROBER, OUTPUT );
  
  Serial.begin( 9600 );
  
  for( int c = 0; c < PINCOUNT; c++ ) {
    pinMode( pins[c], INPUT_PULLUP );

    //for debugging only:
    Serial.println( pins[c] );
    //end debugging

  }
}

void loop( void ){ ; }

This code prints:
1 //I expected 22 as per '#define PIN1 22' and 'pins={PIN1 ... PIN10}'
2
3
4
5
6
36 //these last 3 are correct.
38
40

Suspecting that maybe PIN1 (etc) was defined elsewhere, I renamed all the #defines as LPRPIN1 (etc), which yielded the same problem again. It took me a while (and several beers) to figure out that if I #defined the pins as '#define FOO1 22' (etc) instead it worked as expected.

On further reflection, I know now that it was silly to try and define things like PIN1 in an environment designed for a board that it covered with PINs of its own, but I really don't understand this behaviour, especially since I have not included anything that may overwrite my defines.

Even though I have solved the immediate issue, I still don't understand the problem. Can anyone shed some light on whats happening here?

This is Arduino 1.0.6 on an Mega 2560

Thank you

PINCOUNT ?

portpins.h

AWOL: Good eye, thank you. I correct my example code. In the real code, that line does exist, it just got overlooked when I copied & pasted it here.

portpins.h is definitely where they are being redefined. Odd that it does this without being specifically #included, and without throwing a preprocessor warning.

Odd that it does this without being specifically #included

Arduino.h is added to your sketch. It includes a lot of other stuff which can include other stuff. Just because YOU don't explicitly include it doesn't mean a lot.

and without throwing a preprocessor warning.

Why should it? Lots of people do really bizarre stuff with preprocessor directives that should be done with const variables and real functions. The preprocessor should not need to warn you that you have pointed the gun at your foot, and that you have your finger inside the trigger guard.

Your code doesn't compile. If I can't compile it, I can't debug it.

 error: 'MOTORSENSE' was not declared in this scope

Why should it? Lots of people do really bizarre stuff with preprocessor directives that should be done with const variables and real functions.

Yes, but ... explain this:

#define PIN1 42
#define PIN1 43

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  Serial.println (PIN1);
  }  // end of setup

void loop () { }

With verbose compiling turned on, I get the warning:

sketch_jan20c.ino:2:1: warning: "PIN1" redefined
sketch_jan20c.ino:1:1: warning: this is the location of the previous definition

However if I comment out the line:

#define PIN1 43

There is no warning! However it prints 1 as the PIN1 value. So it warns on one redefinition, but not a different one.

This is the output from the IDE pre-processing:

#line 1 "sketch_jan20c.ino"
#define PIN1 42
#define PIN1 43

#include "Arduino.h"
void setup ();
void loop ();
#line 4
void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  Serial.println (PIN1);
  }  // end of setup

void loop () { }

If you add this to the start of the sketch you get the warning:

#include <Arduino.h>

I'm guessing here the the IDE "helpfully" throws away all warnings from Arduino.h (if it is included by the IDE, not if you include it yourself).

and without throwing a preprocessor warning.

Why should it?

I usually get warnings (or errors) when I try to redefine preprocessor symbols; I have to explicitly #undefine them in order to redefine them. In fact, I still do using 1.0.6, but not 1.5.8. Looks like a feature (or bug) in the new version of avr-g++

var/folders/jz/5yb8f2hr8xjcpf0059bsfz4r0000gn/T/build2187848003437947663.tmp/Blink.cpp -o /var/folders/jz/5yb8f2hr8xjcpf0059bsfz4r0000gn/T/build2187848003437947663.tmp/Blink.cpp.o 
Blink.ino:3:1: warning: "PIN1" redefined
In file included from /Applications/arduino/Arduino-1.0.6.app/Contents/Resources/Java/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/include/avr/io.h:334,
                from /Applications/arduino/Arduino-1.0.6.app/Contents/Resources/Java/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/include/avr/pgmspace.h:82,

(OK, this is really odd. I get the "redefined" warnings out of the 1.5.8 compiler SOMETIMES (like if I put together a simple test case), but not other times. :frowning: )

but not other times. :frowning: )

Perhaps it depends on the randomSeed() value. :smiley:

This is what is known as "namespace pollution." Generally the closer to the programmer you are, the more common names should be not used.

For example, it would be very bad form for a library (or IDE!) to redefine or declare a global "i" variable. The Arduino (or AVR!) folks did not take this to heart, so they used PIN1, when they should have used AVR_PIN1 or ARD_PIN1, to help prevent collisions.

Apple is pretty good about this, All their names in the API's start with NS (for "NextStep" so it is unlikely for you to rename a function.

bcrawford:
I am replacing an antique 10 pin dot matrix printer with an arduino. The following code does not work as expected:

Suspecting that maybe PIN1 (etc) was defined elsewhere, I renamed all the #defines as LPRPIN1 (etc), which yielded the same problem again. It took me a while (and several beers) to figure out that if I #defined the pins as '#define FOO1 22' (etc) instead it worked as expected.

On further reflection, I know now that it was silly to try and define things like PIN1 in an environment designed for a board that it covered with PINs of its own, but I really don't understand this behaviour, especially since I have not included anything that may overwrite my defines.

Even though I have solved the immediate issue, I still don't understand the problem. Can anyone shed some light on whats happening here?

This is Arduino 1.0.6 on an Mega 2560

Thank you

I usually lead my defines with an underscore to prevent that problem... especially with blatantly obvious ones like "SS" and "MISO". I also use lower case and split up names... like this:

#define _miso_pin 7
#define _mosi_pin 6
#define _sck_pin 5

... kinda like that.

Just be careful, that variable names starting with an underscore and an upper-case letter are reserved by the Standard (also identifiers containing adjacent underscores). So, for example, this is reserved:

__PRETTY_FUNCTION__

Thus you would not want to call your pin:

_SCK

I've always avoided using an underscore at the start of my defines for this very reason. I can imagine, in the scenario given by the OP, I'd have felt confident using PIN1 as one of my own. Surely any native functions are going to use _PIN1 or even PIN1

Would it perhaps be an idea to mention PIN1 through to PIN7 in a keywords.txt file somewhere?

If you were to start typing and see:
#define PIN1 22
it would serve as some warning. After all, if I tried
#define Serial1 "Corn flakes"
my mistake would be obvious.

Would it perhaps be an idea to mention PIN1 through to PIN7 in a keywords.txt file somewhere?

Maybe. In general, having Arduino document everything in avr-libc, and everything in the Atmel .h files, is a huge and hopeless undertaking :frowning:

Interestingly, the following generates a warning:

#include <avr/io.h>
#define PIN1 12
int main() {return 1;}

But THIS does NOT generate a warning:

#define PIN1 12
#include <avr/io.h>
int main() { return 1; }

See reply #7.

Yeah, but this is completely skipping the IDE and anything to do with the Arduino. (Note that I'm compiling foo.c and bar.c, but I only ever get the warning from foo.c)

BillW-MacOSX-2<9976> more foo.c

#include <avr/io.h>
#define PIN1 12
int main() { return 1; }

BillW-MacOSX-2<9977> more bar.c

#define PIN1 12
#include <avr/io.h>
int main() { return 1; }

BillW-MacOSX-2<9978> avr-gcc --version

avr-gcc (GCC) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

BillW-MacOSX-2<9979> avr-gcc -mmcu=atmega8 -c foo.c bar.c

foo.c:2:1: warning: "PIN1" redefined
In file included from /usr/local/CrossPack-AVR-20100115/lib/gcc/avr/4.3.3/../../../../avr/include/avr/io.h:408,
from foo.c:1:
/usr/local/CrossPack-AVR-20100115/lib/gcc/avr/4.3.3/../../../../avr/include/avr/portpins.h:71:1: warning: this is the location of the previous definition

BillW-MacOSX-2<9980> /usr/local/CrossPack-AVR-20121207/bin/avr-gcc -mmcu=atmega8 -c foo.c bar.c

foo.c:2:0: warning: "PIN1" redefined [enabled by default]
/usr/local/CrossPack-AVR-20121207/lib/gcc/avr/4.6.2/../../../../avr/include/avr/portpins.h:71:0: note: this is the location of the previous definition

BillW-MacOSX-2<9981> /usr/local/CrossPack-AVR-20121207/bin/avr-gcc --version

Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

BillW-MacOSX-2<9982> /Applications/arduino/Arduino-1.5.8.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-gcc --version

avr-gcc (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

BillW-MacOSX-2<9983> /Applications/arduino/Arduino-1.5.8.app/Contents/Resources/Java/hardware/tools /avr/bin/avr-gcc -c -mmcu=atmega8 foo.c bar.c

foo.c:2:0: warning: "PIN1" redefined [enabled by default]
#define PIN1 12
^
In file included from /Applications/arduino/Arduino-1.5.8.app/Contents/Resources/Java/hardware/tools/avr/avr/include/avr/io.h:606:0,
from foo.c:1:
/Applications/arduino/Arduino-1.5.8.app/Contents/Resources/Java/hardware/tools/avr/avr/include/avr/portpins.h:71:0: note: this is the location of the previous definition
#define PIN1 1
^

Interesting.