Hi
I'm trying to use the Adafruit16CServiceDriver. I'm sure it's broken,but thats OK. I can spend some time to make it worky. I have downloaded the library for the driver and used MRLComm and the commented code from Adafruit16CServoDriver to make an arduino sketch that I think will work for my first experiments. But when I read the examples, and I try the code it looks like the implementation of attach differs from what I expected. Nomally I would do something like this to attach a servo.
comPort = "COM4"
Arduino = runtime.createAndStart("Arduino","Arduino")
thumb = runtime.createAndStart("Thumb","Servo")
thumb.attach("Arduino",2)
So the servo attaches to the Arduino ( servocontroller )
But in the example for Adafruit16CServoDriver things are reversed. If I understand things correct the Adafruit16CServoDriver will act like a servocontroller and be a layer between the servo and the Arduino.
So I do like this:
adaFruitRight = Runtime.createAndStart("adaFruitRight","Adafruit16CServoDriver")
adaFruitRight.connect("COM4")
thumb = runtime.createAndStart("Thumb","Servo")
But the next line from the example confuses me:
adaFruitRight.attach(thumb,3)
I would expect the servo to attach to the controller, not the controller to attach the servo, like this:
thumb.attach(adaFruitRight,3)
I have tried both alternatives, but in both cases I get an error, servo not attached when I try to move the servo:
thumb.moveTo(0)
I can dig into debugging and reworking the Adafruit16CServoDriver, but I need to know what syntax to use.
1. adaFruitRight.attach(thumb,3)
2. thumb.attach(adaFruitRight,3)
Should alternative 1 or 2 work ?
references:
Servo: http://myrobotlab.org/service/Servo
Adafruit16CServoDriver: http://myrobotlab.org/service/Adafruit16CServoDriver
Reworking Adafruit16CServoDriver
After looking at how Servo is implemented and the servocontroler interface is defined it's now obvoius that alternative 2 is the one to go for, and alternative 1 will be abandoned.
So I will continue to implement the missing parts and also try to add some more stuff to be able to use multiple Adafruit16CServoDriver on the same Arduino using different I2C addresses.
Hi Mats, You've hit on
Yes, more confusing
Hi Grog
So for each service I create, some other service, that was already there should attach to my new service.
That sounds strange to me.
I would prefer to create a new service and then for that service attach to one of the already existing services.
Otherwise it will be necessary to create different attach methods, one for each service that the parent can attach to. So for example an Arduino can have several different devices, like motors, servos, and so on. You can see how that scheme works in the Arduino service. motorAttach, servoAttach, sensorAttach and so on. Many different methods for attach.
If you do it the other way around a service can attach to any parent service that implements the interface that has been defined. Like the Servo can attach to the Arduino service or the Adafruit16CServoDriver or any other service that implements the ServoController. It will still only be one attach method that attaches to the service that the Servo wants to communicate thru.
So I'm thinking in a parent - child, where the child attaches to a single parent.
I understand that you have been thinking about this problem before. I found some comments in Adafruit16CServoDriver.java
Disregard my previous
Disregard my previous post.
It's very true:
In software - the important thing is "how much" Service A knows about Service B.
The most preferred model would be where neither know of each other - and if necessary, only through interfaces.
To be pragmatic, in early development interfaces are cumbersome .. so I usually let things evolve into interfaces (once method creation, deletion, and renaming have slowed down)
An attach(String name) method is required if the expectation is for the method to "attach" thing on different processes.. In this case, that certainly won't happen, since the Servo, Arduino & AdaFruit will all be on one computer...
How are you currently accessing your methods Mats ? I did not see anything added to the Arduino service.. But I'm excited to see your Wire I2C methods ...
However, part of the MRLComm.c is completely generated. I did this when maintenance became a hassle, and I don't want to maintain non-generated bindings.. but we can work that out.
I've noticed with I2C - the lowlevel methods are very similar to serial, of course, but every device needs its own "driver" ...
I'm of the firm belief that the "driver" logic of a particular device should be implemented in the Service which represents it....
Would like to hear more about your implementation....
I2C
Hi Grog.
I didn't make any changes to the Arduino service. I only use the methods in it to send the commands to the Arduino board. All the logic is in Adafruit16CServoDriver and in MLRComm.c. I have marked all changes in MRLComm.c with Start Adafruit16CServoDriver ... and End Adafruit16CServoDriver ... so that it's easy to find the changes. No changes really, just additions. I use the wire.h include for I2C commands, and added a section at the end that contains the I2C commands used to communicate with Adafruit16CServoDriver.
I first tried to use the Adafruit16CServoDriver library but the way it supported I2C addressing was not easy to implement in MRLComm.c so I cut and pasted the parts that I needed from the library and changed it so that I pass the I2C address with each command. The default is x040 but it can be set with the setI2CAddress method in Adafruit16CServoDriver.
If you want to help me get it to a good state, then I need help with 2 things.
1. I changed version in MRLComm to 28 but didn't find where to change it in MRL
2. The serial monitor doesn't show the command that i send. It shows null as the command. I found a mapping, but couldn't figure out how to change it, since it seems to be autogenerated from the Arduino service.
Please look at the changes. Any comments, good or bad are appreciated, since my goal is to understand MRL and to be able to contribute more. And the best way to learn is to try to implement something, and then have someone more experienced to do a code review.
I agree on your point that each device driver should have the logic for the device and that the I2C driver in the Arduino should be generic so that any I2C device can use it. Since I have two other I2C devices that I want to use, I will try to make it more generic and some of the code that now is in MRLComm.c should be moved to Adafruit16CServoDriver.
/Mats
Hi Mats ! Of course, I'm
Hi Mats !
Of course, I'm excited you're interested, and I think adding I2C would be great.
Lets start :)
are function prototypes - in older C compilers - the method signature needs to be defined, so the it can be used in other methods and defined later. I've uncommented it and checked it back in. Perhaps it does not error for you because you are using a "smarter" pre-processor or newer version of the avr c compiler
I thinks its great you took
I thinks its great you took what you needed out of Wire vs trying to use the AF library.
Its definately preferrable to use "native" libraries which come with Arduino vs dependencies which might not be there ... although at this point perhaps the necessary AF library is now part of Aruduino ?
With my original implementation I used the AF library and was unhappy with the implemenation
Very excited ! Does this work ?
Can you show us a AF servo controller in action ! Video ! :)
AF library
The Adafruit_PWMServoDriver library is not part of the Arduino default install. That's why I used copy / paste from it. The I2C library ( wire ) has been part if the default Ardino install for a long time, so I used it.
I found that there is a RasPi service that can be used to access the Raspberry PI GPIO, including the I2C interface. But I haven't tested it. I'm thinking that with a well defined I2C interface we could connect things together in many different ways.
Servo <ServoControl=> Arduino
Servo <ServoControl=> Adafruit16CServodriver <I2CControl=> Arduino
Servo <ServoControl=> Adafruit16CServodriver <I2CControl=> RasPI
"Any I2CDevice" <I2CControl=> Ardino
"Any I2CDevice" <I2CControl=> Raspi
Servo, Ardino, Adafruit16CServodriver, RasPI and "Any I2CDevice" are services.
ServoControl and I2CControl are interfaces.
The ServoControl interface is already defined. I'm trying to define what methods should be in the I2CControl interface. But I need to study the I2C protocol a little more.
Pi4J latest version
Things are moving forward with the i2c library. I installed the latest pi4j library ( 1.1-SNAPSHOT ) locally on my PI and made a test program to see if I could write a Java program to use it. And it works. I can move the servos uing this https://learn.adafruit.com/adafruit-16-channel-servo-driver-with-raspbe… connected to the GPOI / i2c pins on th PI. WOOHOO !
So the next step is to make the latest version of the pi4j library available to MRL, so that I can continue developing the RasPi service to use it. The plan is to move device specific things away from MRLComm and RasPI and have all the device logic in the device drivers. Arduino+MRLcomm and RasPi should have the same set of methods that only implements low level i2c read and writes. The drivers should know what i2c methods to use.
But I'm not sure how to make the new pi4j library available to MLR the right way.
I created a folder 1.1-SNAPSHOT in my local repo in parallell to 0.0.5 version in C:\MRL2\repo\com.pi4j.pi4j and copied all the content from the pi4j library to that location, but restructring it to the same structre as 0.0.5 has.
I also created a ivy.xml file, that I think is ok, but I'm not 100% sure.
So what next steps do I need to take ? I guess that I need to make git aware of the new libraries and push it to the repo. And Eclipse needs to know that I want to use 1.1-SNAPSHOT, not 0.0.5. And change the services that use pi4j to have the right dependency. How do I do this? Anything else that I need to do ?
After looking at how Servo is
After looking at how Servo is implemented and the servocontroler interface is defined it's now obvoius that alternative 2 is the one to go for, and alternative 1 will be abandoned. So you should continue to implement the missing parts and also try to add some more stuff to be able to use multiple Adafruit16CServoDriver on the same Arduino using different I2C addresses.
IC programming
I2CMux service
I added a I2CMux service so now things can be connected like this:
"Any I2CDevice" <I2CControl=> Ardino
"Any I2CDevice" <I2CControl=> Raspi
But also
"AnyI2CDevice" <I2CControl=> I2CMux <I2CControl=> RasPi
"AnyI2CDevice" <I2CControl=> I2CMux <I2CControl=> Arduino
I2CMux, Ardino, , RasPI and "Any I2CDevice" are services.
ServoControl and I2CControl are interfaces.
So now its possible to use multiple i2c devices even if they have conflicting addresses.
I2CMux is a service that uses this device:
https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-bre…
/Mats