MrYsLab / pymata4

A High Performance Python Client For Arduino Firmata
GNU Affero General Public License v3.0
76 stars 30 forks source link

Example fails with Atmega32U4 #4

Closed majuss closed 4 years ago

majuss commented 4 years ago

Hi ther,

I'am using a custom Board with an Atmega32U4. I uploaded FirmataExpress via the Arduino IDE and ran the example inside the README.

pymata4:  Version 1.02

Copyright (c) 2020 Alan Yorinks All Rights Reserved.

Opening all potential serial ports...
    /dev/ttyACM0

Waiting 4 seconds(arduino_wait) for Arduino devices to reset...

Searching for an Arduino configured with an arduino_instance = 1
Arduino compatible device found and connected to /dev/ttyACM0

Retrieving Arduino Firmware ID...
Arduino Firmware ID: 2.5 FirmataExpress.ino

Retrieving analog map...
Traceback (most recent call last):
  File "example.py", line 60, in <module>
    board = pymata4.Pymata4()
  File "/home/pi/venv/lib/python3.7/site-packages/pymata4/pymata4.py", line 255, in __init__
    raise RuntimeError(f'*** Analog map retrieval timed out. ***'
RuntimeError: *** Analog map retrieval timed out. ***
Do you have Arduino connectivity and do you have the correct Firmata sketch uploaded to the board?

However this happened only once and now I get:

pymata4:  Version 1.02

Copyright (c) 2020 Alan Yorinks All Rights Reserved.

Opening all potential serial ports...
    /dev/ttyACM0

Waiting 4 seconds(arduino_wait) for Arduino devices to reset...

Searching for an Arduino configured with an arduino_instance = 1
Arduino compatible device found and connected to /dev/ttyACM0

Retrieving Arduino Firmware ID...
Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/home/pi/venv/lib/python3.7/site-packages/pymata4/pymata4.py", line 1706, in _serial_receiver
    self.the_deque.append(ord(c))
TypeError: ord() expected a character, but string of length 0 found

Traceback (most recent call last):
  File "example.py", line 60, in <module>
    board = pymata4.Pymata4()
  File "/home/pi/venv/lib/python3.7/site-packages/pymata4/pymata4.py", line 232, in __init__
    raise RuntimeError(f'Firmata Sketch Firmware Version Not Found')
RuntimeError: Firmata Sketch Firmware Version Not Found

My custom board is basically a Pro Micro with an USB-C Port, but it works totally fine with my own sketches and PlatformIO.

majuss commented 4 years ago

I found the culprit. I'am trying to integrate the board into home assistant, but it always fails. Home assistant is blocking the serial port eventhough the setup was not successfull. So after disconnecting and connecting the board, everything works. Now I need to dig into home assistant and see what is wrong there...

majuss commented 4 years ago

Do you have something like an upgrade guide to make code that ran on PyMata 2.20 compatible to pymata4? Home assistant still utilizes your old pymata: https://github.com/home-assistant/core/blob/f1d3c0d19b4065a1f6ec80ecdc080380f728196c/homeassistant/components/arduino/manifest.json

MrYsLab commented 4 years ago

Thanks for chasing this down and providing the updates. The PyMata and pymata4 APIs are significantly different and unfortunately, I don't have a mapping document between the 2 libraries.

It appears that PyMata is only used in home-assistant/core. Would you know if that is true and if all the PyMata calls are limited to core-dev/homeassistant/components/arduino/init.py ? If things are limited to that one file, I may be able to provide a conversion or assist you in doing the conversion. I do not use home-assistant, and therefore would not be able to adequately test, so you would probably have to provide all the testing.

majuss commented 4 years ago

Hey, thank you for the quick answer. Yes this is totally right, all calls are in __init__.py. The calls are for example:

.disconnect()
PyMata(self._port, verbose=False)
.set_pin_mode()
.get_analog_response_table()
.digital_write()
.digital_read()
.get_firmata_version()
.reset()
.close()
.capability_query()

So I found out for example that .get_firmata_version() got .get_firmware_version() but I think the return type is different... So if you could get me a mapping table for these calls and what changed, it would be really helpful. Then I do the Home Assistant integration, since pull requests are a pain there :D

MrYsLab commented 4 years ago

I am looking at this now and hope to get back to you within a day or two.

MrYsLab commented 4 years ago

Do you have an email I can send the information to? If you do not wish to post your email here, you can send me an email to the address listed on this page and I will reply to it.

I am compiling the information and it may be lengthy, so I would like to send you the information via email.

Also, are you able to read LibreOffice formatted files?

majuss commented 4 years ago

Sure LibreOffice is fine, but markdown would be cooler :) Email is: ich@majuss.de

MrYsLab commented 4 years ago

This may not be necessary since I think I can summarise things below.

To port to pymata4 is probably going to take a fairly large rewrite of the home-assistant code. I am not sure if there is a great benefit in actually doing so other than having the capability of using FirmataExpress.

Here are the differences:

One thing that may not be obvious is the way modes are set. In PyMata, the generic set_pin_mode method is used. Here a pin is being set as a digital input

            self._board.set_pin_mode(pin, self._board.INPUT, self._board.DIGITAL)

In pymata4, you no longer need to remember the values for all these parameters. There are direct calls to set the mode. Here is the equivalent in pymata4:

set_pin_mode_digital_input(pin, callback=the_callback)

Also, pymata4 has the notion of a callback built into the mode setting for input pins. PyMata had callbacks, but establishing them was very cumbersome.

Another thing. PyMata had the ability to turn off my banner information when starting the library. the pymata4 library no longer provides this capability.

Because the pymata4 philosophy is to use callbacks and not polling for input data, you can no longer retrieve the response tables, but need to poll each individual pin. This supports getting the data in "real-time" and not having to constantly poll.

The Capability Report results are the same for both pymata4 and PyMata.

get_firmata_version() was renamed to get_protocol_version in pymata4. PyMata returns a list containing the major and minor numbers, and pymata4 returns a string with a dot between the 2 numbers. [2,5] vs 2.5

Let me know if you have any questions or if I left anything out.