DigitalWrite to pin X controls pin Y

Hi,

Since I'm new to this forum, I'll introduce myself briefly. I'm Maarten, living in Belgium and started playing around with Arduino to realise different kinds of home-projects.
Today I encountered some weird behaviour, which is most likely something the experts over here can explain.

Basically I wrote by accident code that writes to digitalPins that don't exist, but still it seems like they are interpreted by Arduino. Needless to say, I know what's wrong, but I was wondering why it behaves the way it behaves. Just being curious :smiley: .

This is the code I use on my Arduino Uno having 13 digital ouputs:

/*
   Test to demonstrate strange behavior when outputting to inexisting pins...

   The circuit:
   - LED 1 (RED) to digital pin 2, with 220 Ohm resistor
   - LED 2 (GREEN) to digital pin 4, with 220 Ohm resistor

*/

void setup() {

  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(30, OUTPUT);
}

void loop() {
  digitalWrite(2, HIGH);
  delay(2000);
  digitalWrite(30, LOW); //Seems to write to pin 2
  delay(5000);
  digitalWrite(4, HIGH);
  delay(2000);
  digitalWrite(22, LOW); //Seems to write to pin 4
  delay(5000);
}

You can figure it out yourself by examining the source code for the Arduino core, which maps the pin numbers to physical pins.

A classic saying in programming is "Garbage In Garbage Out". ditalWrite(30, LOW) is basically "Garbage In" because 30 is an invalid pin. Internally, the Arduino has Input/Output Registers and will reinterpret the pin number you provide the digitalWrite function to mean Pin x of Port y. By providing something which cannot be properly interpreted, Errors in the Translation are occuring.

Like jremington already said, you could examine the coding for the internal digitalWrite function to see exactly what is going wrong. Or you could accept the fact that the Output is wrong because bad Input confused the Interpreter.

maartenvd84:
Arduino Uno having 13 digital ouputs:

There are 20, actually. 0-13 (which is 14 pins), plus the 6 analog inputs (A0-A5) can also be used as digital IO (aliased as pins 14-19).

The pinmode and digitalWrite functions are defined to take an unsigned 8-bit number to represent the pin number. The compiler has no way of knowing which specific numbers are valid inputs to a given function. You could pass it a pin number anywhere between 0 and 255 if you wanted to, and the compiler has know way of knowing if it's bad or not.

So when you compile and upload something manipulating the imaginary pin 30, the function will attempt to execute. However, it's not designed to handle pin numbers outside a certain range, the function will operate improperly. The pinMode, digitalWrite, and digitalRead functions use arrays to store the registers and bit masks needed to manipulate the pins. When you try and use a pin outside of the range, the code will be happily run right past the end of the array and pull out whatever happens to be there. There's no way of predicting what it will find past the end of the array either. It could be another variable's data, or even executable code.

The technical term for this is undefined behavior. Because doing a sanity check on the pin number would take up program space and processing time, the designers decided to leave those situations as undefined because you aren't supposed to be using those pin numbers anyway.

TL;DR, the behavior of using invalid pin numbers is undefined; anything is permitted to happen. Stop worrying about exactly why this happens, fix your pin numbers, and get on with your project.

Thanks guys!

I remember this from the posts:

Garbage In Garbage Out

So true, and perfectly applicable here. Here it was also very clear I was producing garbage. In the original code (which automatically assigned pin numbers, it was less obvious).

Examining the source code for the Arduino core could provide the answer

... but most likely the answer is indeed:

... because doing a sanity check on the pin number would take up program space and processing time, the designers decided to leave those situations as undefined because you aren't supposed to be using those pin numbers anyway.

I'll take the advice of Jiggy-Ninja:

Stop worrying about exactly why this happens, fix your pin numbers, and get on with your project".

:smiley:

The constants NUM_DIGITAL_PINS and NUM_ANALOG_INPUTS are available if you'd like to do your own sanity checking.