Serial.print stop working if analog pins are initialised

Hi,

I'm facing a strange behaviours. The following code works as expected:

#include <Arduino.h>
//Joystick 0
#define Joystick0 0
const u_short js0XPin = 0;
const u_short js0YPin = 1;
const u_short js0ZPin = 2;

void setup() {
  Serial.begin(115200);
  Serial.println("Launching setup");
  
  // pinMode(js0XPin, INPUT);
  // pinMode(js0YPin, INPUT);

  pinMode(js0ZPin, INPUT_PULLUP);
  Serial.println("Jumping to loop");
}

void loop() {
  // put your main code here, to run repeatedly:
  int js0XValue = analogRead(js0XPin);
  int js0YValue = analogRead(js0YPin);
  int js0ZValue = digitalRead(js0ZPin);

  Serial.print("Joystick 0 - X: ");
  Serial.print(js0XValue);
  Serial.print(" Y: ");
  Serial.print(js0YValue);
  Serial.print(" Z: ");
  Serial.println(js0ZValue);  
  
  delay(1000);
}

The monitor shows the read values every second

\--- Terminal on /dev/cu.usbmodem1101 | 115200 8-N-1
--- Available filters and text transformations: debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Launching setup
Jumping to loop
Joystick 0 - X: 786 Y: 768 Z: 1
Joystick 0 - X: 791 Y: 775 Z: 1
Joystick 0 - X: 791 Y: 775 Z: 1
Joystick 0 - X: 792 Y: 775 Z: 1

If I just uncomment the lines where the analog pins are defined as input:

  pinMode(js0XPin, INPUT);
  pinMode(js0YPin, INPUT);

The monitor doesn't show anything but a couple of garbage characters:

--- Terminal on /dev/cu.usbmodem1101 | 115200 8-N-1
--- Available filters and text transformations: debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
�

Assuming an Uno R3, yes, Serial uses pin 0 for Rx, and Pin 1 for Tx.

And, pins 0, 1 and 2 on an Uno R3 don't support analog input.

Did you perhaps mean A0, A1 and A2 rather than 0, 1 and 2?

  • Schematic diagrams are the universal language of electronics.
  • We use schematics to communicate hardware design. All components and connections are illustrated.
  • As always, show us a good schematic of your proposed circuit. Hand drawn schematics are acceptable.

analogRead() makes the assumption that 0 and 1 refer to A0 and A1, but pinMode() and digitalRead() do not, those functions need you to explicitly use A0 and A1.

I forgot to mention the code is for a DUE board. But a similar sample (changing io pins) also happens on ONE

But the point here is.... why Serial.Print stop working?

Hi LarryD,

you are totally right.

I see this this behaviour always independently If I connect a simple sensor or if I connect a joystick (the sample above). That's why I thought schematic was not relevant here. In this specific case the wiring is:

Joystick <-> Arduino DUE
GND      <-> GND (the one closer to 5v)
+5V      <-> 5V
VRx      <-> A0 (analog)
VRy      <-> A1 (analog)
SW       <-> 2 (Digital PWM)

Regards,

This is setting the pins used for Serial to input mode, so you are no longer able to send serial data out of the Tx pin. Change js0XPin and js0YPin to A0 and A1 to eliminate the problem, but as a practical matter there is no need to set an analog pin to input mode before using analogRead().

Yes, you did. But in this case it doesn't matter, as pins 0 and 1 on the DUE are also the Rx and Tx pins for Serial. So what doesn't work on an Uno R3 also doesn't work on a DUE.

Because pin 0 refers to digital pin 0, which is the Serial Rx pin, and pin 1 refers to digital pin 1, which is the Serial Tx pin. Not A0 and A1. Which has been pointed out to you a few times already.

Stop changing pins 0 and 1 from Serial functionality to ordinary inputs and start making progress. If you feel you must set something to inputs, use A0 and A1 in the pinModes. But by default they already come up as inputs, so maybe just leave well enough alone?

Lots of confusion could have been avoided if the first words in your post were "Using Arduino DUE". :smiley:

The alternate to mentioning your board type is posting in an apprpriate category... if one exists.

@jesusglezalv76

1. In the context of ADC, the following code are equivalent:

int y = analogRead(0);   //Ch-0; here, 0 does not mean DPin-0/HPin-0
int y = analogRead(A0); //Ch-0
int y = analogRead(14); //Ch-0

2. It is not desired to configure the directions of the analog lines as inputs. They are automatically inputs during the execution of analogRead() function.

On what logic, the above two code are equivalent when the argument values are different? Experimentally found that both lines acquire signal from Ch-0.

I suspect you already know the answer.
On the Arduino board you are using, A0 is digital pin 14 (likely an UNO/Nano or other atmega328 based board). Therefore, A0 is defined as 14, so using A0 or 14 is interchangeable.
From pins_arduino.h in the avr board package, for standard pinout boards:

#define PIN_A0   (14)
....
static const uint8_t A0 = PIN_A0;

The analogRead() function, in wiring_analog.c of the avr board package, for your particular board, will reduce the value of the argument by 14 if it is equal to or greater than 14, making the analog pin reference start at 0 for A0. This results in A0 or 14 both being the equivalent of 0, and results in digital pin 0 also being a reference to the first analog pin.

#if defined(__AVR_ATmega32U4__)
  if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#endif
  pin = analogPinToChannel(pin);
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
  if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
  if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
  if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif

Note that on other boards where the pin number A0 has a digital pin number above 14, A0 and 14 are not equivalent, and 14 will instead be taken as a reference to A14. Whether that is valid or not for a particular board will depend on how many analog pins exist on that board.

NOTE - on the Arduino DUE, A0 is defined as 54, so 14 will not be A0, and is not a valid analog port.

I had assumed that earlier, but I did not have a proper reference. Now that I have one. Thank you for taking time to clarify the issue.