Go Down

Topic: Analog Pin Reporting in Latest IDE (Read 2012 times) previous topic - next topic

Deve

I am pretty new so maybe this is a non-issue for some reason, but personally I hope it's an oversight that can be looked into...

When using the Analog ports on the Uno or Mega, in global variables we use:

analogPin1 = A0;

The IDE understands A0 and all is well. The problem is, when using that variable to report that same information back to the user....

Serial.println (analogPin1);

the Uno reports back pin 14 and the Mega reports back pin 54. This is a bad thing when sorting out multiple Analog pins and telling the user which pin they are using. Especially on the Mega.

How are others handling this issue, is there a workaround, and is this something that will be fixed in the future? Thank You!


pert

Ideally there would be a standard digitalPinToAnalogChannel macro in the variant file for each board but there is not (there is the opposite, analogInputToDigitalPin).

However, you can pass the analog channel to analogRead(). For example this:
Code: [Select]
analogRead(0)
is the same as this:
Code: [Select]
analogRead(A0)
So you can change your code to this:
Code: [Select]
analogPin1 = 0;
...
Serial.print("A");
Serial.println(analogPin1);

Deve

But that wouldn't work for all 15 mega Analog pins and all 5 Uno pins since anything after 0 or 1 would be considered Digital pins right?

So was that done to conserve memory? There is no workaround? Seems like a worthwhile project. :)

I have tried this with mixed results...

Code: [Select]

void reconcileAnalog() {
if (analogPin1 == 54 || analogPin1 == 14){
    Serial.print ("A0");       
  }
  else if (analogPin1 == 55 || analogPin1 == 15){
    Serial.print ("A1");
  }
  else if (analogPin1 == 56 || analogPin1 == 16){
    Serial.print ("A2");
  }
  else if (analogPin1 == 57 || analogPin1 == 17){
    Serial.print ("A3");
  }
  else if (analogPin1 == 58 || analogPin1 == 18){
    Serial.print ("A4");
  }
  else if (analogPin1 == 59 || analogPin1 == 19){
    Serial.print ("A5");
  }
  else if (analogPin1 == 60) {
    Serial.print ("A6");
  }
  else if (analogPin1 == 61) {
    Serial.print ("A7");
  }
  else if (analogPin1 == 62) {
    Serial.print ("A8");
  }
  else if (analogPin1 == 63) {
    Serial.print ("A9");
  }
  else if (analogPin1 == 64) {
    Serial.print ("A10");
  }
  else if (analogPin1 == 65) {
    Serial.print ("A11");
  }
  else if (analogPin1 == 66) {
    Serial.print ("A12");
  }
  else if (analogPin1 == 67) {
    Serial.print ("A13");
  }
  else if (analogPin1 == 68) {
    Serial.print ("A14");
  }
  else if (analogPin1 == 69) {
    Serial.print ("A15");
  } 
}

CrossRoads

analogPin0 = A0;
to
analogPin5 = A5; // for '328P chips (with A6, A7 on surface mount chips)
and up to
analogPin15 = A15; // for the 2560




"all 15 mega Analog pins and all 5 Uno pins"
16 Mega and 6 Uno

Why would one use A6 (or A8) & above on a '328P chip know the selection does not exist?

Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

pert

But that wouldn't work for all 15 mega Analog pins and all 5 Uno pins since anything after 0 or 1 would be considered Digital pins right?
Wrong, give it a try.

So was that done to conserve memory?
No, macros don't use any memory if they're not used. It's just that pretty much nobody else except you ever needed this. That said, the macro does exist in the ESP32 hardware package:
https://github.com/espressif/arduino-esp32/blob/80a7d6084bc0297d371198cbf4d0eab0b98ddd0c/cores/esp32/esp32-hal-gpio.h#L73
and there's some relevant discussion here:
https://github.com/SpenceKonde/ATTinyCore/issues/161

Deve

I made that so I didn't have to remake it depending on if its a Mega or an Uno. Yeah, 0-5 is 6. Good point. Doesn't change that it would be AWFUL nice not to have to make this huge code addition for such a trivial problem. But if that's the way it is, I will get over it. With just two analog devices out of the available 16 on the mega, I am already at:

Code: [Select]

void reconcileAnalogPin1() {
/*  This is how to get around the fact that the Analog Pins do not report back the
 *  proper numbers. A0 is not what comes back when you choose for example,
 *  analogpin1 = A0; On the Uno, A0 = Pin 14. On the Mega 2560, A0 = Pin 54. Since
 *  the Mega has 15 Analog pins and the Uno has 5, lets resolve that issue here: */
  if (analogPin1 == 54 || analogPin1 == 14){
    Serial.print ("A0");        
  }
  else if (analogPin1 == 55 || analogPin1 == 15){
    Serial.print ("A1");
  }
  else if (analogPin1 == 56 || analogPin1 == 16){
    Serial.print ("A2");
  }
  else if (analogPin1 == 57 || analogPin1 == 17){
    Serial.print ("A3");
  }
  else if (analogPin1 == 58 || analogPin1 == 18){
    Serial.print ("A4");
  }
  else if (analogPin1 == 59 || analogPin1 == 19){
    Serial.print ("A5");
  }
  else if (analogPin1 == 60) {
    Serial.print ("A6");
  }
  else if (analogPin1 == 61) {
    Serial.print ("A7");
  }
  else if (analogPin1 == 62) {
    Serial.print ("A8");
  }
  else if (analogPin1 == 63) {
    Serial.print ("A9");
  }
  else if (analogPin1 == 64) {
    Serial.print ("A10");
  }
  else if (analogPin1 == 65) {
    Serial.print ("A11");
  }
  else if (analogPin1 == 66) {
    Serial.print ("A12");
  }
  else if (analogPin1 == 67) {
    Serial.print ("A13");
  }
  else if (analogPin1 == 68) {
    Serial.print ("A14");
  }
  else if (analogPin1 == 69) {
    Serial.print ("A15");
  }  
}
void reconcileAnalogPin2() {
  if (analogPin2 == 54 || analogPin2 == 14){
    Serial.print ("A0");        
  }
  else if (analogPin2 == 55 || analogPin2 == 15){
    Serial.print ("A1");
  }
  else if (analogPin2 == 56 || analogPin2 == 16){
    Serial.print ("A2");
  }
  else if (analogPin2 == 57 || analogPin2 == 17){
    Serial.print ("A3");
  }
  else if (analogPin2 == 58 || analogPin2 == 18){
    Serial.print ("A4");
  }
  else if (analogPin2 == 59 || analogPin2 == 19){
    Serial.print ("A5");
  }
  else if (analogPin2 == 60) {
    Serial.print ("A6");
  }
  else if (analogPin2 == 61) {
    Serial.print ("A7");
  }
  else if (analogPin2 == 62) {
    Serial.print ("A8");
  }
  else if (analogPin2 == 63) {
    Serial.print ("A9");
  }
  else if (analogPin2 == 64) {
    Serial.print ("A10");
  }
  else if (analogPin2 == 65) {
    Serial.print ("A11");
  }
  else if (analogPin2 == 66) {
    Serial.print ("A12");
  }
  else if (analogPin2 == 67) {
    Serial.print ("A13");
  }
  else if (analogPin2 == 68) {
    Serial.print ("A14");
  }
  else if (analogPin2 == 69) {
    Serial.print ("A15");
  }
}


unless anyone knows of shorter code. I am new to all this, so it's VERY possible my code could be shortened. I just don't know how.


pert

unless anyone knows of shorter code.
I already gave it to you:
Code: [Select]
analogPin1 = 0;
...
Serial.print("A");
Serial.println(analogPin1);

Why are you so resistant to using that solution?

Deve

Pert, if that means that digital pins 1-5 (or 1-15) are doing double duty, I can't conceive how that wouldn't be the case if that works, I would much rather do it the hard way since I may very well be using:

int commPin1 = 1;
int commPin2 = 2;

at the same time I am using the analog pins for something else. Maybe I am not understanding what you are saying?

You chose the PAN Servo connected to Digital Pin 18.
This is controlled with the Potentiometer at Pin A0.

You chose the TILT Servo connected to Digital Pin 19.
This is controlled with the Potentiometer at: Pin A1.

Just a simple reporting back to the user what calibration pins they chose so there is no doubt they got the wiring correct. Seems basic to me, but I haven't been here long so haven't suffered through all the history.

Thanks guys! VERY much appreciate it. I still think there is an opportunity here.

pert

They aren't doing double duty, it's actually the analog channel rather than the pin number. analogRead() is written so that it can take either the pin number (e.g. A0) or the analog channel (e.g. 0). See the source code:
https://github.com/arduino/ArduinoCore-avr/blob/3f63f2975e7183c3254b6794bfcc8f19ca0301c9/cores/arduino/wiring_analog.c#L47-L55
Code: [Select]
#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

Now it would be better not to have this hardcoded into the function and instead for the variants to define their own standard macros, which would be the more valid reason for adding the functionality you're looking for.

bperrybap

It can be done if you use a define rather than a integer to hold the value of your analog pin.
To do it, you must play some games with stringification to be able to print A0 instead of what A0 is.
I do this quite a bit in my openGLCD diagnostic tool to report how pins are mapped.

Here is a small example sketch to show how it is done:
Code: [Select]
#define analogpin1 A0

#define xstr(s) str(s)
#define str(...) #__VA_ARGS__

void setup(void )
{
 Serial.begin(9600);
 Serial.println(str(analogpin1));  // name of define
 Serial.println(xstr(analogpin1)); // unexpanded value of define
 Serial.println(analogpin1);       // fully expanded value
 
}

void loop(void) {}


If you need to be able to print the analog channel number from a digital pin number, that can be done as well but it requires using either a lookup table or a ternary that is specific to the variant.
This can be done (I also do some of this in openGLCD) but it is PAINFUL as the IDE doesn't provide all the information you need and it gets really complicated to look around at what you have in the variant file to figure out the mappings. It can be done but it is painful if you want it work across all cores and variants within each core.

--- bill

Deve

Thanks for that. I have a short wish list of things I wish could be incorporated into the IDE. That is one of them. The other is, I wish all rem statements could be greyed out. So, if you do:

// I dont care how old you think I am because I use the word REM.

and

/* Just having fun */

LOOK the same. Greying out makes it easier on the eyes to see the valid code as opposed to the 'comments'. The latter example IS already greyed out. The former doesn't differentiate.

Those two things would be on my wish list for sure. Thanks everyone!

pert

The former doesn't differentiate.
Actually it does, it's just a darker shade of grey, almost indistinguishable from the standard black text. You can customize this to your liking by editing the editor.comment1.style property in lib/theme/theme.txt in your Arduino IDE installation folder. If you want it the same as the C style comment coloration just copy the value editor.comment2.style is set to.

Deve


Go Up