Hello everyone! I am new to this forum and to Arduino in general(I've done PIC for years though) and wanted to share a project I have been working on. It is a protocol that lets a master discover devices, ask them about their capabilities, read and write data, and perform remote function calls. Devices have a fixed 128 bit UUID so no more dip switches or buying vendor ids.
My original intent was to create a modern hobbyist oriented lighting control protocol but it got way outta hand fast
The protocol supports discovery,error reporting,units of measure, arrays,nested arrays,enumerations,nested arrays of enumerations, FIFO queues(messagewise or itemwise) and a whole bunch of other stuff.
The key idea is that devices document themselves. In the below code example the computer had no idea that the device was supposed to have a parameter named AnalogWrite, it asked the device for its parameter list, then asked for details about each parameter.
I have only tested over USB with the leonardo so far, and the code is early pre alpha and needs a ton of work, but I do have a somewhat stable working prototype. I intend to test with RS485 soon.
I have made a simple sketch called SpookyCastle with Firmata-like features using the protocol, and a python library which is well documented.
The sketch used compiles to around 9k of code for the Leonardo.
Here is a code example:
Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
>>> manager = NetworkManager('com6') #using serial port com6
>>> manager.EnumerateSlaves() #Search the "bus"( not rs486 at the moment)
>>> manager.slaves #after 15s per device or so it populates the list
{'Z3RoczR2bG9nZmVk': <Gazebo Slave SpookyCastle for Arduino I/O board with ID Z3RoczR2bG9nZmVk>}
>>> s = manager.slaves['Z3RoczR2bG9nZmVk']
>>> s.params #lets take a look at the parameters the slave exposes
{'AnalogWrite': <Parameter Object AnalogWrite of type void with interpretation void>, 'DigitalWrite': <Parameter Object DigitalWrite of type void with interpretation void>, 'AnalogRead': <Parameter Object AnalogRead of type uint16 with interpretation Volts*204.8>, 'TheRaven': <Parameter Object TheRaven of type UTF-8[0:80] with interpretation GrimUngainlyGhastlyGauntAndOminousBirdOfYore>, 'DigitalRead': <Parameter Object DigitalRead of type uint8 with interpretation boolean>, 'PinMode': <Parameter Object PinMode of type void with interpretation void>}
>>> analogWrite = s.params['AnalogWrite']
>>>analogWrite.pinfo()
Readable parameter of type void to be interpreted as void
This parameter plays role none in group none of type none
The following arguments are required when reading from this parameter(in first to last order):
GazeboReadArgument(name='pin', type='uint8', interpretation='number')
GazeboReadArgument(name='value', type='uint8', interpretation='duty*255')
Reads are idempotent(two succesive reads will produce the same data absent external changes).
The slave provides the following description of ths parameter:Use ~460Hz PWM to write an analog value to a pin.
>>> analogWrite(3,127)
True
>>> #It returned true because the slave sent an ACK
>>> digitalRead = s.params['DigitalRead']
>>> digitalRead.read(1)
0
>>> #Parameters are callable objects, not functions. calling the param() directly
>>> #is an alias for param.read()
>>> #in Gazebo, function calls are read operations with arguments. Gazebo parameters also may support write operations, which are what the sound like.
>>> digitalRead.read(1)
1
>>> #After connecting voltage to Arduino input 1, we see that we read a 1 from it.
>>> digitalWrite = s.params['DigitalWrite']
>>> digitalWrite(2,'high')
True
>>> #Gazebo supports enumeration types
>>> digitalWrite(2,0)
True
>>> #Which are compatible with simple numbers
>>>master.close() #Otherwise pyserial sits around hogging the port till you restart or close from task manager
All the code is available here:
Keep in mind the core protocol is not backwards compatible till version 1.0