Different ADC behavior between RedBoard Artemis and RedBoard Artemis ATP

I am getting some strange behavior differences between an Artemis Redboard and an ATP.

I have a program that when run on an ATP behaves as expected. I do an analogRead on a pin and get a reasonable value (reading on pins A0 and A1).

When I recompile the program for an Artemis RedBoard (changing the board type prior to the compile), I always read zero for A0 and A1. I have verified using a VOM that the voltage is not zero. I have tried this on several Artemis Redboards.

Interestingly if I run a very simple sketch that just sets up a serial port and then reads/writes A)/A1 values, it works fine on an Artemis Redboard.

So something I am doing in my more complex program is breaking the AtoD functionality on the RedBoard but not the ATP.

Hoping y’all might have some clues of where to look for that I might be screwing up the AtoD ports?

So I’ve tracked it down and it is weird…

If you initialize an int with ‘A0’ and print it, it says 29.

But if you use that int as a parameter to analogRead, it returns zero.

So if you run the code:

int inputPin = A0;

Serial.printf(“A0 = %d: %d %d\n”, inputPin, analogRead(inputPin), analogRead(A0));

You get this for output:

17:42:41.971 → A0 = 29: 0 542

Please explain!!!

It is complex because of all the mapping. I’ll try to keep it simple.

There are PinNames (like A0) and padNumbers.

The pinName is just a variable with an assigned value, 29 in this case. But it could be any value. For the Artemis in PinNames.h (part of Mbed-os/targets…) A0 = D16; in the same file above D16 is defined as 29. So both variables A0 and D16 are assigned the value 29.

A padNumber is the connection point, the GPIO pin, on the Artemis processor.

There is a conversion table between pinName and padNumber for each variant called ‘variantPinStates’. Each variant can have a different connection schema / wiring between breakout pins (like A0) on which you connect your sensor and hardware GPIO pin the processor. The program should not care. This conversion table is defined in the variants folder of the library for each variant. The table has multiple entries that are used for different functions. The first entry is the pinName, the second entry is the padNumber.

When you perform an analogRead(A0), it will search in the PinName entry of the table. In the Artemis variant there is an entry with D16 (so actually 29 in this case). So we have match and we find padNumber entry the number 16. So A0 pinName is connected to GPIO pin 16 of the processor.

When you perform an analogRead(29), it will search in the padNumber entry of the conversion table. There is NO padNumber 29 defined in that table and hence there lookup fails and analogRead returns ‘zero’.

Always use the PinName as it is portable between different boards.

I hope this was clear enough.

I am wanting to have an array of ADC ports so I can access the ‘ith’ ADC port in the array.

If I can’t initialize an integer array elements like this:

int adc[3] = {A0, A1, A2};

What can I do?

Will not work. Due to the wonders of C++ you can have functions with the same name but with different parameters. in this case, you have

1. analogRead(PinName pinName) 
       and 
2. analogRead(pin_size_t pinNumber)

pin_size_t is a typedef of uint8_t.

C++ will decide which function to use based on the provided parameter; A0, A1 etc will use the first, int, unit8_t will use the second.

Not sure what you want to do but you can try with a define, something like :

// if your board is an Artemis Redboard keep the define, in case of ATP comment out
#define ARTEMIS 1

#ifdef ARTEMIS
#define First_ADC   A0
#define  Scnd_ADC  A1
#else                  // it is an ATP
#define First_ADC   A29
#define  Scnd_ADC  A11
#endif

// then use that like
analogRead(First_ADC);

Does there exist a predefined preprocessor constant that is included in the processor variant code that indicates which processor variant is being compiled for?

That way I could do what you suggest with the ‘First_ADC’/‘Second_ADC’ without having to change my code when the processor variant changes.

the different boards are defined the boards.txt file in the library as the ‘build.board’ variable. here an example you could use.

#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS)
#define board "APOLLO3_SFE_ARTEMIS"

#elif defined(ARDUINO_APOLLO3_SFE_ARTEMIS_DK)
#define board "APOLLO3_SFE_ARTEMIS_DK"

#elif defined(ARDUINO_APOLLO3_SFE_ARTEMIS_ATP)
#define board "APOLLO3_SFE_ARTEMIS_ATP"

#elif defined(ARDUINO_APOLLO3_SFE_ARTEMIS_NANOK)
#define board "APOLLO3_SFE_ARTEMIS_NANO"
#endif

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.print("\nWelcome to board check. Your board is : ");
  Serial.println(board);

}

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

}