Proboscide99:
I checked the formulas on both bobuino pinout against 328P but didn't find the reason.Is it a known problem?
Example: analogRead(4) does not work. analogRead(A4) does work.
I'm not sure what environment you are using as there seems to be several mighty cores floating around.
But for Jacks mighty core 1.6.3 I don't believe that analogRead(A4) on bobuino would work either not unless someone went and broke the analog code in yet another bad way to "fix" it for bobuino which will break all the other 1284 boards.
The problem goes back to the Arduino IDE core code and it goes back more than 4 years.
It cannot be solved by any fix in the variant file and it affects all variants other than "standard".
So all the other boards like SleepingBeauty, Bobuino, and avr_developers have analog pin mapping issues as well as any newly created variants.
Here is the reason.
The high level summary:
The code n wiring_analog.c in the function analogRead()
hard codes the analog pin to digital pin mapping as well as the analog pin number to analog channel number mapping.
This is an absolute no no!
It completely bypasses the pin mapping information in pins_arduino.h so there are guaranteed to be pin mapping problems.
This is a problem for nearly all the AVR boards, not just the 1284 based board.
It only shows up on the 1284 based boards because there is more then one pin mapping for the 1284 boards.
The code in analogRead() should be using the analogPinToChannel() macro to convert the pin value passed into analogRead() to the needed analog channel. Instead it has hardcoded the mapping in the code and it only works for the "standard" variant. (The older code from the mighy core use to use the macro correctly rather than hard code the mapping)
This needs to be fixed! and the solutions is very simple.
Use the macro in the pins_arduino.h file rather than hard code the pin mapping.
The define analogPinToChannel() was created for this very purpose.
Details:
It is a bit of wreck since the code and the documentation are very sloppy about what the "pin" parameter means.
The code in wiring_analog.c in the function analogRead() interprets the "pin" argument in multiple ways - as it can mean different things.
It can be a an analog pin/channel number or it can be a digital pin number that is assigned to an analog channel.
There is some confusion as to what the "analog pin #" argument really means.
For example if a value of say 0 is passed to analogRead() does that mean analog pin #0 or does it mean analog channel #0?
The two are not necessarily the same.
The Arduino documentation here:
sloppily uses the term "channel" in some places and "number of the analog input pin" in others.
When the mapping from analog pin # to analog channel # is one to one, it doesn't matter.
But there is no restriction to do so.
And the comments in the actual analogRead() code there are comments that say:
// allow for channel or pin numbers
which seems to imply that the argument is an actual channel number and not an analog pin #.
In fact the analogRead() code in the IDE AVR core treats the argument as an analog channel number and not an analog pin# whenever the value is a small number.
There was a somewhat heated discussion over this between me and jack over this a few years back when the mighty core was actually still shipping/including its own core code vs using the AVR core that comes with the IDE.
If you look at all the the other AVR based boards, and I mean ALL, from 328, 32u4 leonardo, they all map the analog pin # directly to the analog channels. EXCEPT..... bobuino which inverts them.
so on bobuino analog pin #0 is analog channel #7
To allow the variant to control not only the analog pin to analog channel mapping but to control the digital pin to analog pin mapping, there must be some way for the variant file to indicate this.
My suggestion (which one out) was to create a new macro analogPinToChannel() macro to do this mapping.
And... The somewhat controversial part was to assume that the argument passed into analogRead() was either a analog pin number or a digital pin number assigned to that analog pin number and not ever an analog channel number.
This is right thing to do since all boards other than bobuino, the analog pin # and the analog channel number are the same. If you make the agument a analog pin # rather than an analog channel # things get simpler and it can be mapped as needed - all while still being backward compatible with all existing code and documentation.
By using the analog pin mapping macro analogPinToChannel() it ensures that you can pass in:
- naked analog pin numbers
- A0 to A7 symbols
- the appropriate digital pin number that is the same as the analog pin.
an through the analogPinToChannel() macro, the proper analog channel will always be selected since the variant file is control of the mapping vs having it hard coded in the analogRead() code.
So as of right now, all the 1284 variant files have an analogPinToChannel() macro in them and have for quite some time.
The problem is the analogRead() code doesn't use it.
The code in analogRead() right now is totally broken for the 1284 cores.
bobuino is the worst affected as there is no way to ever get the channel you want unless someone has gone in and created a hacked version that hard coded it for bobuino - which not the proper way to fix this.
With the other 1284 variants, since they map the analog pins one to one to the analog channels, they can use naked analog pin numbers and it will work.
However, the symbols A0 to A7 are used it will only work correctly on the "standard" core.
But it depends on which version of the mighty core you are using as some of them have bad hacks in them trying to fix the mapping issues-
As soon as the code in analogRead() is corrected to use the analogPinToChannel() macro rather than hard code the mapping, EVERYTHING will work correctly and as desired no matter what which pin # is passed in. (naked analog pin#, A0-A7, appropriate digital pin)
i.e. the analogRead() code needs to go back to using the analogPinToChannel() like it did in jacks 1.6.3 core.
It is a very simple fix.
The bad/broken code looks like this:
This is from the IDE AVR core:
#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
or this goofy hack from here:
https://github.com/MCUdude/MightyCore/blob/master/avr/cores/MightyCore/wiring_analog.c
That still hard codes things.
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) \
|| defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) \
|| defined(__AVR_ATmega324__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324PA__) \
|| defined(__AVR_ATmega32__) || defined(__AVR_ATmega32A__) || defined(__AVR_ATmega164__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega164PA__) || defined(__AVR_ATmega16__) \
|| defined(__AVR_ATmega16A__) || defined(__AVR_ATmega8535__)
#if defined(BOBUINO_PINOUT)
if (pin >= 14) pin = 7 - (pin-14);
#elif defined(STANDARD_PINOUT)
if (pin >= 24) pin -= 24;
#endif
And the fixed/correct code should look like more like this:
(not exactly but it uses the macro in the variant file to do the mapping vs hard coding it)
This code goes back at least 4 years back to when the mighty core was shipping its own AVR core.
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
pin = analogPinToChannel(pin);
I guess somebody needs to create a pull request to the Arduino.cc IDE wiring_analog.c to fix it in the IDE code.
--- bill