Update On Universal i2c Support

Today I connected an ADXL345 Accelerometer to a BeagleBone Black and another to a Raspberry Pi.

Using a single application running on my Linux PC, I was able to simultaneously receive data updates from both devices.  The Linux PC sends out one universal Xideco i2c command and both devices respond. One message to control multiple devices!!!

In turn, each board forms a universal reply message and publishes the message.  The Linux application subscribes to these messages and parses them on arrival. Reply messages are consistent no matter what type of board is reporting.

Currently the data reported by each board consists of:

  • Board number ID
  • X, Y and Z Axis Raw data
  • X, Y, and Z Axis data expressed in g's
  • X, Y, and Z Axis data expressed as normalized acceleration values.
  • Pitch and Roll

Some of the features supported by the ADXL345 application:

  • Broadcast i2c requests simultaneously to all ADXL345 devices.
    • Each board replies with its own reply message
  • Send i2c requests addressed to a single board.
    •  Only  devices of interest respond, all others stay quiescent.
  • Data requests can be single shot for polling the i2c device.
  • Data requests can be set to report continuosly
    • Continuous reporting can be paused and restarted at any time.
Lots more to test , but this is a very good beginning.  If all goes well, I hope to publish this code within the next couple of weeks.

If you are using pymata-iot and are now seeing these exceptions:

/usr/bin/python3.5 /home/afy/PycharmProjects/pymata_aio/pymata_aio/
Traceback (most recent call last):
  File "/home/afy/PycharmProjects/pymata_aio/pymata_aio/", line 27, in
    from autobahn.asyncio.websocket import WebSocketServerProtocol, \
  File "/usr/local/lib/python3.5/dist-packages/autobahn/asyncio/", line 38, in
    from autobahn.asyncio.wamp import ApplicationSession
  File "/usr/local/lib/python3.5/dist-packages/autobahn/asyncio/", line 32, in
    from autobahn.wamp import protocol
  File "/usr/local/lib/python3.5/dist-packages/autobahn/wamp/", line 42, in
    from autobahn.wamp.keyring import EncryptedPayload
  File "/usr/local/lib/python3.5/dist-packages/autobahn/wamp/", line 64, in
    from pytrie import StringTrie
ImportError: No module named 'pytrie'

Process finished with exit code 1
You will need to manually install pytrie with:
pip install pytrie.

I submitted an issue with Autobahn and hopefully they will fix the issue and install pytrie automatically from a pip install.

PyMata Version 2.12 and pymata-aio Version 2.11 Released

These releases assure that all data sent to Firmata is in 7 bit bytes. There was a  potential for data to be sent as an 8 bit value and these releases assure only 7 bits are transmitted.

Universal i2c Support Took A Major Step Forward Today!

"Write Once, Run Everywhere"

16 February 2016

Using a single application that uses a JSON description of  ADXL345 Accelerometer operations, I successfully communicated with an Arduino, Raspberry Pi and BeagleBone Black to initialize and retrieve the raw X, Y and Z data from the device. 

Each board is able to accept a Xideco set of i2c commands and each board has the capability to translate and execute those commands using its own native i2c library.

What this means is, that on an ongoing basis, new i2c devices will be able to be supported by describing their operations in a single file, and all the boards will be able to support the device without any code changes to the board level (bridge level) code.

Over the next few weeks, I will be further testing and cleaning up the code, and will publish the code as soon as I am satisfied that it is stable. 

Stay tuned!

A New Xideco Router Design

Updates Are In The i2c Branch of Github

14 February 2016

I modified the Xideco router to use the ZeroMQ Forwarder Device. Not only did this simplify the software, but it made it more consistent. All modules connect their publishers and subscribers in the same manner.

Originally I had intended to have two Forwarders, but this actually limited the flexibility of the system. So now, the router consists of a single Forwarder and believe it or not, having a single Forwarder adds system flexibility. Since there is no longer a sense of data flowing explicitly from one type of module or another, any module can subscribe to the topic published by another module. This means that data no longer has to flow to the application for interpretation. This is going to make implementing the i2c features much simpler.

The code is not fully tested, but preliminary tests have not revealed any issues.

Xideco Is Moving Forward

What I Am Working On Now

I am currently working on two Xideco features, one to improve xirt, the Xideco router, and the other is to provide i2c support in a universal and unconstrained manner.

Xideco Router Improvements

The current router implementation is somewhat "brittle". Each time a new message topic is introduced into the network, the router needs to modified to accommodate the new message.

I am looking to change the current implementation so that the router becomes a totally stable component that will need no modification as new components and message topics are added or removed. It will transparently forward all published messages without regard to message topic. The ZeroMQ Forwarder Device provides that functionality. A Forwarder is a ZeroMQ networking pattern that subscribes to all messages, and transparently publishes them with original topics intact.

The new Xideco Router will consist of 2 Forwarders so that messages can flow and be routed in 2 independent directions, one in the upstream direction towards a user application from the hardware devices, and the other in the downstream direction, towards the hardware actuators.

Universal i2c Support

At the board level, Xideco takes advantage of existing GPIO APIs. For Arduino, pymata-aio is being used, for Raspberry Pi, pigpio is being used and for the BeagleBone Black the adafruit bbio library is being used. If you look at the  three i2c library APIs, each is markedly different, but in essence results in the same low level i2c functionality.

The goal of Universal i2c Support is to have the control and operation of an i2c device described in a single universal file.  What this results in, is having one set of commands describing the device operation across all of the boards in a consistent manner, and when any changes or additions to functionality occur,  all modifications are limited to that one file. When a control message is received by a board translator it simply executes the i2c request by translating the message into board level i2c API calls, without having to have knowledge of the logic behind the request. All "intelligence" remains as close to the application as possible, and execution of that intelligence occurs as close to the target board as possible.

To understand what I am striving for,  let's look at a proposed implementation supporting the ADXL345 accelerometer.

Xideco will be using a JSON formatted file to describe the control and maintenance of i2c devices. The reason for JSON is that Xideco uses MessagePack to serialize its messages and MessagePack formatting is very JSON-like.

The JSON descriptions reside in the Xideco i2c Library, and TinyDB will be used to build the library file. In the future, a Tkinter GUI will be provided so that adding new i2c devices will be simplified.

Let's look at a sample JSON descriptor file supporting two i2c devices, the ADXL345 and the TMP102 temperature device. We will be concentrating on the ADXL345 for the sake of this discussion.

   "adxl345": {
      "device_address": 83,
      "commands": {
         "init": [{
            "cmd": "write_byte",
            "register": 45,
            "value": 0         }, {
            "cmd": "write_byte",
            "register": 45,
            "value": 8         }, {
            "cmd": "write_byte",
            "register": 49,
            "value": 0         }, {
            "cmd": "write_byte",
            "register": 49,
            "value": 3         }],
         "read": [{
            "cmd": "read_block",
            "register": 50,
            "num_bytes": 6         }]
   "tmp102": {
      "device_address": 72,
      "commands": {
         "read": [{
            "cmd": "read_block",
            "register": 50,
            "num_bytes": 2         }]

The full operational description for a given device begins with its name.

Below that is the default i2c address of the device. The user will be able to modify that address value if necessary as part of an API call and will not have to modify the library to change the address.

Next comes the commands that are supported for the device. In the case of the ADXL345, there are 2 commands, "init" and "read".

Below the command is a list of Xideco primitives that describe the i2c instructions used to accomplish the command. A command could be as simple as writing a single byte to a device register, or a list of primitives that must be performed in sequence to accomplish the command.

So for example, to "init" the ADLX345, a sequence of 4 primitives are necessary to be executed in order to initialize the device for operation:
  • Writing a value of 0 to  register 45.
  • Writing a value of 8 to register 45
  • Writing a value of 0 to register 49
  • Writing a value of 3 to register 49
Dereferencing the JSON description will result in the following Python dictionaries:
{'value': 0, 'cmd': 'write_byte', 'register': 45}
{'value': 8, 'cmd': 'write_byte', 'register': 45}
{'value': 0, 'cmd': 'write_byte', 'register': 49}
{'value': 3, 'cmd': 'write_byte', 'register': 49}
The device address will also be dereferenced separately  and added to the MessagePack message published messages.

The i2c translators will translate these Xideco primitive message into  specific native board i2c API calls. When data is returned from an i2c device, the translator will translate the data into a Xideco primitive i2c reply message.

Here are the board specific translations for the Xideco primitive "write_byte":

  • pymata-aio
    • i2c_write_request
  • pigpio
    • i2c_write_byte_data
  • bbio
    • write8

i2c For BeagleBone Black

The BBB has posed some unforeseen challenges. The adafuuit BBIO library does not support Python 3 for i2c (it does support Python 3 for GPIO).  As a result, the i2c Translator for the BBB must run in its own process to support Python 2. This is not a problem for Xideco, and will demonstrate that applications of differing languages (in this case Python 2 and Python 3) can and will interact seamlessly. I considered using other languages to support BBB i2c, but i could not find one that actually worked "out of the box", so I decided to stay with the adafruit library.

Want to Keep Up With The Progress?

If you want to keep with the changes, I have created a new Github branch for the i2c and Forwarder changes. Currently there are is not much to see, but you can follow any progress by visiting the branch from time to time. Whenever there is a significant milestone met, I will announce it on this blog.

As always, any comments, questions, or suggestions are always welcome.

pymata-aio 2.1


This release addresses issues not fixed with release 2.09

To install:              pip install pymata-aio
To upgrade:           pip install pymata-aio --upgrade

Note: Linux users may need to use sudo for the pip install

pymata-aio 2.9 


This release addresses issues with HC-SR04 support.

To install:              pip install pymata-aio
To upgrade:           pip install pymata-aio --upgrade

Note: Linux users may need to use sudo for the pip install.

Xideco 0.3.0 Released

This release implements a BeagleBone Black Bridge in addition to the Arduino and Raspberry Pi bridges of release 0.2.0

#BeagleBoneBlack  #arduino #raspberrypi #python3