Naming pins is not working and I don't know why

I'm working on a very short sketch just to test out the hardware. I named the pins as follows:

const int D0 = 3;

const int D1 = 4;

const int D2 = 5;

const int D3 = 6;

const int D4 = 7;

const int D5 = 8;

const int D6 = 9;

const int D7 = 9;

const int PG1 = A0;

const int PA1 = A1;

const int PB1 = A2;

const int PG2 = A3;

const int PA2 = A4;

const int PB2 = A5;

When I name them like this the compiler pukes errors like there's no tomorrow over the two pin names PB1 and PB2. Here's the error messages I get:

C:\Users\norms\Dropbox\Arduino\Sketches\Nano_Supermini\Nano_Supermini.ino:14:11: error: expected unqualified-id before numeric constant
const int PB1 = A2;
^
C:\Users\norms\Dropbox\Arduino\Sketches\Nano_Supermini\Nano_Supermini.ino:17:11: error: expected unqualified-id before numeric constant
const int PB2 = A5;

Now if I change the pin names from PB1 to PinB1 and PB2 to PinB2 the compiler is happy as a clam. I'm clueless fellers. Any knowledge you could impart would be helpful. Thanks!

I don't understand the error message, but PB1 and PB2 are already defined names for pins on port B.

If you must, you can probably

# undef PB1
# undef PB2

before you make yours.

a7

PB1 and PB2 are defined as numbers, which gets substituted by the pre-processor before the code is compiled, resulting in a numeric value to the left of the equal sign instead of a legal variable name.

Okay, but: WHY? :face_with_raised_eyebrow:
Why use such generic names like "D0," "D1," etc.?

First, they might conflict with "internal" names (as happened with PB1 and PB2), and second, they make the code less readable (for you and others like... well... us! :wink:).
Don't do it!

PS: pin numbers can be represented by "byte", there's no need to use "int" because a single unsigned byte is enough and saves some RAM (useful for smaller boards line UNO R3).

+1. The general rule is don't swim upstream.

You can use black wire for Vcc and red for GND, but it's no a good idea. Even b*mb makers can't do it, it's always the red wire one must cut.

I was too subtle when I shared my opinion along with a solution… I've always argued for letting people have the knowledge and leave things to their judgement:

Can the millis() be reset to zero?

I was also too lazy to say that that beginning looks awfully like an array is called for, I've typed this or a variation of it many times:

When I bump into an obscure (to me) elsewhere defined identifier, I just make it my own one way or another as @nstobert did in the workaround she tried.

Live with it. :expressionless:

a7

You need to use the IDE to do a Tools/Auto Format then Edit/Copy for Forujm then in a reply just paste it.
Off the top of my bald head, names like you are using are very likely going to clash with reserved names.
Every board (you have not told us which) has a pins definition, add the following to the top of your sketch

#include <Arduino.h>
#include <pins_arduino.h>

do a clean compile. If that means commenting ot failing lines do it. Once clean. highlight the pins statement Right Click/Goto definition. Now a RO tab will open and you can see the reserved pins.

There are other ways to see the needed information but this is how I do it.

i name the pins for their purpose, preface the name with "Pin", capializing it because it's a constant

for example

const byte PinKey    = A2;
const byte PinBrkA   =  8;
const byte PinBrkB   =  9;
const byte PinDirA   = 12;
const byte PinDirB   = 13;
const byte PinPwmA   =  3;
const byte PinPwmB   = 11;
const byte PinBut    = 10;
const byte PinLed    =  4;
const byte PinTrig   =  9;
const byte PinEcho   = 10;
const byte PinServo  =  2;
const byte PinDht    =  7;
const byte PinBuzzer =  8;

you can use #if/#elseif/#endif to define pin values for different hardware

Thanks David and alto777, I never knew any of what you just told me. So two questions:

  1. From what I'm reading in these responses, you should never use a numeric digit in a pin name, correct? So for instance from my original post, The general opinion is that I shouldn't name the first pins as D0, D1, etc. What if I name them DATA1, DATA2, etc? I guess that using the 0, 1, 2, etc is also verboten? Thing is, in other of my sketches, I used numerals in pin names and never had an issue. A couple examples are: "int ttposition13" and "int nibble1"

  2. Is there somewhere where all the pin naming rules are put? I mean where can I read a document or web page that defines all this? I get what you guys are trying to tell me but it comes in bursts and pieces. For instance, alto777 above states that PB1 and PB2 are already defined names for pins on port B. How do you know this? And I have no idea what port B is. That's what I mean when I say is there a document that tells you all the pin naming rules. I would think stuff like this would be called out in the software documentation somewhere. Any info will be appreciated.

Nothing is verboten. You can use any legal identifier for any purpose.

int broccoli;
int mars;

The point about appending a digit

int broccoli0;
int broccoli1:
int broccoli2:
int broccoli3:
int broccoli4;
int broccoli5:

isn't that you can't, it's that there are language features that make working with N of something much easier and convenient.

Arrays

and

Loops.

They make your code easier to write, get right and modify or enhance.

Here's six of those in one array variabke

int broccoli[6];

Referring to one of them can then be done using an index, the index can change as a loop runs; you will like what you will be able to do with them I promise.

Read the two articles linked above, they are fairly gentle introductory level. Keep asking questions!

a7

I did not. But your workaround was a huge clue, and I kinda suspected those had previously been used elsewhere.

That allowed me to go looking.

There are quite a few things like this that will be mysterious until they aren't, the best thing is to start slow and follow some organized exposition of the material.

There are many online learning sources, try googling

arduino beginning programmer

and just poke around. I usually say something like spend seven minutes on seven plausible looking hits, in less than an hour you will def learn something and with any luck one of them will feel like a place you wanna spend more time. I like the breezy chick that makes everything fun, others like the iced tea guy.

And we here always, usually it is at the time when you have some code and a roadblock. Like a previously defined symbol…

a7

  • That’s easy for he who lays on the beach and posts to the forum.

Alto77 has already answered this point, so I have nothing to add. And I agree that you'd be wise to start learning arrays; they're useful when dealing with multiple identical elements.

There's no "hard and fast rule" about this, other than that you almost always need to make the definition "global," so it's best to place that code outside of the functions.
However, a common rule of thumb is to put all "configuration" definitions (for example, pin numbers and any key values ​​you can use to modify the code, such as timing and intervals, number of elements in the array, etc.) in the first few lines so you can easily identify and modify these values. Nothing more, nothing less.

Hard to say even for more experienced programmers (those definitions depend on the board you're using, and most of the times no one knows exactly all the identifiers used "under the hood"), but just keep in mind my first general rule:

First, they might conflict with "internal" names (as happened with PB1 and PB2), and second, they make the code less readable (for you and others like... well... us! :wink:)

Just make sure the names/symbols are neither too short (P1 and P2 are not "meaningful" compared to "pinBtn1" if it's a variable, or "PIN_BUTTON1" if it's a constant - capitalization is the convention) nor too long (e.g., use "RightMotor" instead of "right_motor_control") and that they are clearly understandable and meaningful not only to you but also to anyone who reads your code (or to you if you're revisiting the code after a few years...).
And use comments often to describe what a certain part of the code or function does.
You'll see, you'll feel much better.
.

Library file pins_arduino.h
There you can see PD0-7, PB0-5 and PC0-6 are already defined.

I think that is a bug. As long as it is not an Arduino function name or C keyword you should be able to use any combination of letters and numbers as a variable name.

No but what PA,PB,PC,PD, etc. designators have been used should be identified in the pinout for your board.

For example for the UNO

I can see that PB, PC, PD are used

Think about this:

const byte pinButtonUp = PB0;    // works, but needs knowledge of hardware
const byte pinButtonDown = PD7;  // works, but needs knowledge of hardware
const byte pinButtonLeft = 6;    // refers to visible marking
const byte pinButtonRight = 5;   // refers to visible marking

EDIT:

const byte pinButtonUp = PB0;    // compiles, but doesn't work
const byte pinButtonDown = PD7;  // works, but I don't know why
const byte pinButtonLeft = 6;    // refers to visible marking
const byte pinButtonRight = 5;   // refers to visible marking

It seems like the compiler ignores the letters.

Please post a sketch where

const byte pinButtonUp = PB0;    // compiles, but doesn't work

compiles but doesn't work.


That sentence is not just simplistic - it’s materially wrong in ways that can actively confuse beginners. There is no bug in sight.

In C++, your own identifiers - such as variable names, function names, and macro names - may contain letters, digits, and underscores, but they cannot start with a digit or be reserved words.

You also cannot use names already defined by included libraries, whether added explicitly by you or supplied automatically by the Arduino environment behind the scenes.

These may include identifiers such as HIGH or, as @nstobert is asking about here, PB1.

a7

Here's the sketch and the disassembled sketch:

const byte pinButtonUp = PB0; // compiles, but doesn't work
const byte pinButtonDown = PD7; // works, but I don't know why
const byte pinButtonLeft = 6; // refers to visible marking
const byte pinButtonRight = 5; // refers to visible marking

void setup() {
Serial.begin(115200);
if (digitalRead(pinButtonUp)) Serial.print("1");
else Serial.print("0");
if (digitalRead(pinButtonDown)) Serial.print("1");
else Serial.print("0");
if (digitalRead(pinButtonLeft)) Serial.print("1");
else Serial.print("0");
if (digitalRead(pinButtonRight)) Serial.print("1");
else Serial.print("0");

}
void loop() {
// put your main code here, to run repeatedly:
}

You see the function digitalRead() called with argument 0, not 8.
(For clarification: colored stuff is added by hand.)

Thanks.

It compiles and works, it just doesn't do what you want, or what you think it should.

That is understandable, it's an easy mistake to make.

PB0, and its siblings PD0 and PC0 are all zero (0) and are bit position constants.

So ppl can write things like

  PORTB |= 1 << PB0;

Wanna guess the value of PC5 or PD3?

All PXN constants are just names for N.

I don't get the value-add here, but it is claimed to make code more readable.

a7

In portpins.h PB0 is defined as PORTB0, suggesting that the name PB0 can be used as name for that pin, like it is used in various documentation.
In avr/iom328P.h names like PORTB0 are defined, for each port as numbers 0 to 7.
So when I used the name PB0, it was replaced by PORTB0 and then by 0, losing info about port-instance.
One more riddle in Arduino IDE.