MrYsLab / pymata-aio

This is the second generation PyMata client.
https://github.com/MrYsLab/pymata-aio/wiki
GNU Affero General Public License v3.0
155 stars 51 forks source link

Wrong calculation of first analog pin #103

Closed michsens closed 4 years ago

michsens commented 4 years ago

Hello everybody,

I had an issue with the reading of analog pins. After inserting some debug outputs to the firmata I found some weird pin numbers for the analog pins. Eventually the major problem was the first analog pin number. Going through the pymata3 code I found following line:

        self.first_analog_pin = len(self.digital_pins) - len(self.analog_pins)

According to the auto-discovery there are 50 digital pins and 10 analog ones. And there they were - my problems. This equation calculated the first analog pin to be 40. In real it was number 16.

How about changing the above line to:

        analogMapTask = asyncio.ensure_future(self.get_analog_map())
        analogMapReport = asyncio.get_event_loop().run_until_complete(analogMapTask)
        self.first_analog_pin = analogMapReport.index(0)

Then, the correct first analog pin is found independently from the variant itself.

Maybe there is a better solution. For me, it works fine now.

To be honest, I designed my own pcb with an STM32F373R8T6. Means, I also wrote myself the necessary board definitions for Arduino.

Regards

Robert.

MrYsLab commented 4 years ago

@michsens I am not sure how you defined your custom board in boards.h, but it sounds like it is not specified correctly. For example, the Uno describes its analog pins this way, while the Mega 2650 is described this way. The python code uses boards.h as a map for many of the reports it generates. Since I have had no issues with this exception (issue #91), which is a bug in Firmata, I am not likely to make any changes to the Python code, and the amount of testing required across all Arduino boards would simply be a huge effort. Therefore, I am closing this issue, but please feel free to comment here, and I will see your comment even though this issue is closed. It can always be reopened if needs be.

Which profile in boards.h did you pick for your custom board? If there is no profile that matches your hardware, you will need to create your own.

michsens commented 4 years ago

Well I made some more investigations on that problem and found, that each variant.h is defined in following logic: The first analog pin is set to one of the last pins. The number of digital pins is then calculated according to this first pin number plus the number of analog pins even if the controller does not have that number of pins. Changing the whole variant.h also solve this issue, but somehow it feels a bit odd. Is there a specific reason to do it this way?

To answer your question: The profile which is used is the "ARDUINO_ARCH_STM32".

MrYsLab commented 4 years ago

If you are using the FirmataPlus sketch, it is using an older version of Firmata that does not contain the stm 32 boards in boards.h. The FirmataExpress sketch, used in conjunction with pymata-express is based on a new version of Firmata and does contain the stm 32 board descriptions.

If you created your own Firmata sketch and are using the latest boards.h, it should have worked correctly.

I may not have been clear in my previous statements. The pymata client code is totally independent of any knowledge of the hardware it is connected to. To determine the number of analog and digital pins, it uses Firmata reporting, specifically the get_analog_map report. Once the report is returned, it is parsed to find the total number of analog and digital pins reported by Firmata. Using digital pin numbering, the first analog pin number is calculated here.

I hope this explains how things work in a clearer fashion.

michsens commented 4 years ago

Thanks for your explanation.

The line with the calculation is exactly the line I pointed out in the first post. And for that I wanted to give an idea how to find the first analog pin number in an alternative way. My idea just is to point out this pin by finding the index of pin "0" in the analog map.

The beginning of my confusion after all was the "variant.h" not your code in the first place. my analog map look like that:

[127, 127, 127, 127, ... , 127, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 127, 127, 127, ... , 127, 127]

The number of digital pins was 50, the number of analog pins 10. According to the analog map the first analog pin was 16, according to the calculation 40 (50 - 10). Do you see my problem? If the analog pins are located in the middle of the map than you get such confusion. It was not clear to me, that this would not work.

michsens commented 4 years ago

By the way, it seems this variant.h is specific to stm32duino. I also found that the newest version handles this in a slidly different way but by the same logic. You can find one example here: variant.h. variant.cpp

MrYsLab commented 4 years ago

I understand what you are saying, and it is a legitimate proposal, however, Arduino Firmata does not expose any of the underlying Arduino tool-chain code used for compiling Arduino sketches. Firmata clients implement the Firmata protocol and have no knowledge of the information in the tool-chain. You could propose a change to Arduino Firmata to expose that data as part of the protocol.

michsens commented 4 years ago

You are completely right. I am not complaining. It is just this little point: Finding the first analog input from the analog map instead of the calculation with the number of digital and analog pins. pymata3 itself has the tools already included. However, thanks for your time. It was an interresting conversation.