| View previous topic :: View next topic |
| Author |
Message |
ROCHE
Joined: 06 May 2007 Posts: 4 Location: FRANCE
|
Posted: Sun May 06, 2007 4:38 pm Post subject: broadcast/synchronization |
|
|
Hello everybody,
I have in project to build a hexapod with 18 servos and I would like to use Openservo with a command I2C to start all the servos at the same time. But this feature is not yet implemented.
Mike said to me " the standard I2C bus speed should allow you to send position updates to all servos in well under a millisecond". OK, the standard I2C bus and the OpenServo are certainly very fast. This delay of 1 ms give an error de 0.63 mm for the movement, it’s not very important. But the main processor (CuBloc 280, programmed in basic) risk to set too much time to send all the orders. It is for these reasons that the idea of a global command on the 0x00 I2C address would be the solution ideal.
Would other persons be interested in this new feature ? The persons who build a hexapode, can they indicate to me what is their solution ?
Thanks to all
Bertrand (France) |
|
| Back to top |
|
 |
guru
Joined: 03 Jan 2006 Posts: 128 Location: St Pete Beach, FL
|
Posted: Sun May 06, 2007 4:53 pm Post subject: |
|
|
I remember I did this in my original version 1 of my superservo. However, that was a bit banged i2c implementation and it had its own problems. If I remember, when did version 2 and used the PICs i2c hardware peripheral, it only allowed a single address to answer on and didnt include a 0x00 global address....if I remember correctly. There may be a similar restriction on the i2c implementation of the Atmel in openservo.
C |
|
| Back to top |
|
 |
ginge Site Admin
Joined: 14 Jan 2006 Posts: 1028 Location: Manchester, UK
|
Posted: Sun May 06, 2007 5:38 pm Post subject: |
|
|
Hi,
You can set the AVR TWI module to listen to a device address and the general call address 0x00 simultaneously.
A simple patch could be made that enables the general call addressing, but how this would be handled in the scope of setting the position is open to discussion.
My recommendation would be to create a new 16 bit register that stores the new position and waits for the general call before initialising the move.
This is something I am willing to look into if time permits.
Barry _________________ http://www.headfuzz.co.uk/
http://www.robotfuzz.co.uk/ |
|
| Back to top |
|
 |
guru
Joined: 03 Jan 2006 Posts: 128 Location: St Pete Beach, FL
|
Posted: Sun May 06, 2007 8:02 pm Post subject: |
|
|
Can you detect a zero length read from the general call address?
That way a only a single byte is sent on the i2c to sync the command.
C |
|
| Back to top |
|
 |
ROCHE
Joined: 06 May 2007 Posts: 4 Location: FRANCE
|
Posted: Sun May 06, 2007 9:14 pm Post subject: broadcast/synchronization |
|
|
Hi
(I thank you for having made an effort to understand my bad English
I think that it would be preferable to keep the current registers for the location (SEEK_HI / LO, SEEK_NEXT_HI / LO, SEEK_SPEED_HI / LO and SEEK_TIME_HI / LO) and only of to add a new register (SYNCHRO) to enable or disable the function of start of the movement by the call of the address 0x00.
For example, the main CPU set SYNCHRO = Yes, then send the data of position to all the servos. Then it sends the command of address 0x00.
OpenServo starts the movement (according to the registers of location) and set SYNCHRO = No.
It is a little simplified but for Mike it will be a little more complicated
Bertrand |
|
| Back to top |
|
 |
ROCHE
Joined: 06 May 2007 Posts: 4 Location: FRANCE
|
Posted: Sun May 06, 2007 9:31 pm Post subject: broadcast/synchronization |
|
|
I have forgotten :
Mike had written in the forum (May 15, 2006)
"The ATmega I2C hardware supports receiving broadcasts on the 0x00 I2C address. Creating a synchronized move mechanism will have to be investigated further".
Bertrand |
|
| Back to top |
|
 |
ginge Site Admin
Joined: 14 Jan 2006 Posts: 1028 Location: Manchester, UK
|
Posted: Sun May 06, 2007 10:29 pm Post subject: |
|
|
Bertrand, your English is very good!
| Quote: | | I think that it would be preferable to keep the current registers for the location ...snip |
This could work. a single 8 bit register could be reserved for setting this flag. It could also be reused for future use if it is carefully considered.
using one bit to flag the syncro mode and reserving the rest for future use would yield this layout.
| Code: |
00000001
0x01 SYNCRO_MODE
0x02 RESERVED
0x04 RESERVED
0x08 RESERVED
etc.
|
| guru wrote: | Can you detect a zero length read from the general call address?
That way a only a single byte is sent on the i2c to sync the command.
|
I am not sure what you mean by this. I have used the general call function before by using a single byte write to 0x00 i.e
Start | addr | R/W | 0x01 | Stop
I guess you mean doing something like
Start | addr | R | Stop
I would have to look over the AVR TWI module implementation to see if that is possible. Let me know if I misunderstood.
Barry _________________ http://www.headfuzz.co.uk/
http://www.robotfuzz.co.uk/ |
|
| Back to top |
|
 |
ROCHE
Joined: 06 May 2007 Posts: 4 Location: FRANCE
|
Posted: Mon May 07, 2007 6:19 am Post subject: broadcast/synchronization |
|
|
Thank you Barry, it is nice.
OK for the register of flags.
For the general call, we find precision in page 16 of the documentation I2C-Bus specifications of Philips semi conductors : 39340011.pdf
Bertrand |
|
| Back to top |
|
 |
guru
Joined: 03 Jan 2006 Posts: 128 Location: St Pete Beach, FL
|
Posted: Mon May 07, 2007 12:34 pm Post subject: |
|
|
Yes, exactly. A zero length call to 0x00 would start the movement. Save a byte.
| ginge wrote: | I am not sure what you mean by this. I have used the general call function before by using a single byte write to 0x00 i.e
Start | addr | R/W | 0x01 | Stop
I guess you mean doing something like
Start | addr | R | Stop
Barry |
|
|
| Back to top |
|
 |
ginge Site Admin
Joined: 14 Jan 2006 Posts: 1028 Location: Manchester, UK
|
Posted: Mon May 07, 2007 4:10 pm Post subject: |
|
|
Colin,
According to the Mega168 datasheet and also the I2C spec no bytes is an unsupported configuration. I thought I would try it out anyway, and it didn't work out. I guess one byte of data is not too bad.
Anyway, I have created a patch and tested with a couple of servos. My implementation is a little shaky as I was unsure how Mike would like to proceed with this feature. Looking at twi.h we have run out of r/w addresses, so I have created this function as a command.
| Code: |
#define TWI_CMD_GCALL_ENABLE 0x95 // Enable General Call
#define TWI_CMD_GCALL_DISABLE 0x96 // Disable General Call
#define TWI_CMD_GCALL_START_WAIT 0x97 // Wait for the start command before moving
#define TWI_CMD_GCALL_START_MOVE 0x98 // Start the General call syncro move
|
The servo does nothing if the GCALL (SYNCRO) mode is enabled, and TWI_CMD_GCALL_START_WAIT is enabled. to trigger a move send the command TWI_CMD_GCALL_START_MOVE
The beauty if doing it with a command is that you can send any I2C data/command over the general call address and it is treated by the servo as if it were being called exclusively. "So why is this good?" you might ask. Well... you can disable PWM to all servos at the same time, kind of like an emergency stop feature. You could also write all of the servos with the same position/velocity and it will be executed simultaneously. Basically anything you could send to one servo, you can send to all servos at the same time.
I will submit this to Mike for review.
Barry _________________ http://www.headfuzz.co.uk/
http://www.robotfuzz.co.uk/ |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Tue May 08, 2007 4:36 am Post subject: |
|
|
I ducked out for a few days to take care of some family obligations and this topic has sure taken off. Let me start off with a few observations to try and find the essence of the functionality that we are trying to achieve. We can then examine Barry's implementation in more detail and consider some other ways we might achieve the desired functionality.
First, I would like to start off with the observation that standard RC servos receive a pulse train that has a rate of about 40 to 50 Hz. This means that there is about a 20 millisecond separation between the pulses that command an RC servo and on average it will take about 10 milliseconds for the servo to respond to a new position. The OpenServo, based on I2C communication is a bit of a different beast where a new position command can be delivered at an arbitrary time rather than part of a steady pulse train. With the OpenServo, currently the servo ADC readings that govern motion control are taken at a 100Hz rate or every 10 milliseconds. This means on average, it will take the OpenServo 5 milliseconds to respond to a new position value passed to it.
The point I'm trying to make is that it is probably pointless to attempt to control OpenServos (or RC servos as well) with a granularity of time finer than 10 to 20 milliseconds without significant redesign of the motion control algorithms. Furthermore, all servos are essentially operating asynchronous from each other. Even if all servos receive a sync byte how fast the servos will respond to the sync byte is governed by when the next ADC reading is taken and response will vary to under a 1 millisecond up to 10 milliseconds across the servo chain.
Finally, given typical I2C bus speeds of 100KHz to 200KHz (some have tested the OpenServo bus speed faster) the time it takes to update the position of even a large group of servos should be on the order of 10 milliseconds or less (My assumption here is that the controller can work at an I2C bus speed of 100kHz or more).
With all this in mind, I guess I'll go back and ask what is the essential functionality we are attempting to implement? Is it to control a group of servos at a millisecond-level timing resolution or to have some type of storage mechanism where the next pending position can be stored and triggered at a minimal timing resolution of about 10 milliseconds at best? If the former, such efforts to control the timing of the servos at such a resolution will be futile for the reasons explained above. If the later, I guess I question the need for such functionality when the I2C bus gives us the speed needed to update the position values of all servos within the maximum timing resolution of the servo motion control.
Continued... |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Tue May 08, 2007 5:01 am Post subject: |
|
|
Basically, I am raising the questions above in an attempt to play "devil's advocate" and avoid adding unnecessary complexity to the OpenServo. As I look to the work I'm doing on the Lynxmotion and Version 3.x OpenServo firmware I'm wondering if we have already made the OpenServo too complex which I is why I may seem somewhat sensitive to this feature.
I really do feel that the future of the OpenServo lays in the curve based motion control where the position of the servo is controlled at the maximum resolution of 10ms using a mathematically defined curve over a specific span of time -- typically measured in dozens to thousands of milliseconds in duration. Therefore, I would tend to look to find a general solution for synchronizing the motion of servos within the context of curved based motion control. I strongly feel that if you are attempting to coordinate the motions of a large group of servos by passing new position values to all servos every 10 to 20 milliseconds or so you are going down the wrong path (I speak to this from experience).
Rather than add complexity by adding the buffering and triggering of a pending servo position, I would propose that we instead look to leverage the existing buffering mechanism already built into the OpenServo motion control algorithms. My thoughts about this are as follows:
The existing curve motion buffers can already buffer up to seven curve segments that can describe a very complex movement for the servo over a significant span of time (see Barry's video in the thread on curve motion). All that's needed to implement synchronization is the ability to buffer motions without the servo executing them and then implement the global trigger that would tell all servos to execute their buffered motions.
From my perspective, such a feature leverages an already powerful feature of the OpenServo and is much more flexible than buffering just a single position that the other proposals would offer. At the simplest level it would offer just moving to the next position, but also easily be able to offer a lot more.
Thoughts?
-Mike |
|
| Back to top |
|
 |
ginge Site Admin
Joined: 14 Jan 2006 Posts: 1028 Location: Manchester, UK
|
Posted: Tue May 08, 2007 8:46 am Post subject: |
|
|
Hi Mike,
| Quote: | | what is the essential functionality we are attempting to implement? Is it to control a group of servos at a millisecond-level timing resolution or to have some type of storage mechanism where the next pending position can be stored and triggered at a minimal timing resolution of about 10 milliseconds at best? |
From my understanding, the latter.
Can we work though a thought experiment before I go off and try and justify why this might be useful...
I have 100 servos connected to the bus, each one controlling a ligament in a chain.
It takes me 10ms to write a single packet to each servo in this chain (including start stop address and whatnot), meaning a total of 1000ms (1s) to write stop to all of the servos in sequence. In one second, the average servo can move 170 degrees, of just about enough to cause some very serious damage. ( I am speaking from experience this time )
I agree that sending new positions every 10-20ms is just wrong. it doesn't work and ends up flooding the bus. Curves are not ideal in all circumstances either:-
eg. On my cheapola (tm) host controller it takes me 10ms to calculate each curve segment, of which there are 2 for each movement of the hex leg. Each curve requires 6x8bits of data, which are going to take an addition 20ms to send over the I2C bus (remember cheapola host controller) add on the the OpenServo timing delay and we have ~50ms in total for each sweep of the leg. We have to write these values out for each leg, so 16x50ms = 800ms. We are nearing the 1s mark again. I know I have fudged these values a little, but remember this is all hypothetical.
Although you may not see the merit in sending a single broadcast packet to say go/stop, there are people (myself included) who would use this feature. An emergency stop on my robot is very important, as it can easily rip through the table, any cabling, and itself.
BTW, I am not sure I agree with you on having too many features. Curve support does not fit for all situations. The calculation overhead, and the (perceived) complexity of the feature is enough to put people off.
The only feature I don't use at the moment is the PWM input support. While very cool, it is pretty pointless when being controlled via I2C.
Personally I think it is important to keep things as simple as possible. Asking use curves for every type of movement is not a simple ask. It is hard enough for the average robot enthusiast to get into OpenServo as it is. It has a steep learning curve.
I will make the patch available for anyone who might want this feature. Alternatively, you can tear the patch apart and use the general call support in any way you wish. Either way, we are looking at a few dozen lines of code max.
Barry _________________ http://www.headfuzz.co.uk/
http://www.robotfuzz.co.uk/ |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Tue May 08, 2007 5:18 pm Post subject: |
|
|
Barry, point taken. I responded late at night and I'll look over your proposed implementation. I do want to better understand myself the nature of I2C broadcasts as well. One way or the other we'll get it into CVS soon.
-Mike |
|
| Back to top |
|
 |
linuxguy
Joined: 16 Oct 2006 Posts: 120 Location: Beaverton, OR
|
Posted: Wed May 09, 2007 1:13 am Post subject: |
|
|
| ginge wrote: | Hey Barry!
The only feature I don't use at the moment is the PWM input support. While very cool, it is pretty pointless when being controlled via I2C. |
There are instances when controlling servos via PWM and reading back status info via i2c is desirable, such as controlling servos using an SSC-32 servo controller (PWM) and reading status info by i2c. One might want to take advantage of the SSC-32's group and timed moved functions, for instance, and use i2c to get better status info (current sensing for stall detection, position, etc).
| ginge wrote: | | Personally I think it is important to keep things as simple as possible. Asking use curves for every type of movement is not a simple ask. It is hard enough for the average robot enthusiast to get into OpenServo as it is. It has a steep learning curve. |
My current interest in Open Servos is to either control them via PWN and read status via i2c OR to control everything via i2c by sending simple position and status commands.
The general call facility is also interesting to me for use in synchronizing servo movements via i2c without using an SSC-32.
Oh yes, and encoder support is of interest to me also, but it doesn't have to be within the Open Servo if decent resolution can't be maintained reliably.
I suspect that a lot of users who would use Open Servos would be primarily interested in this small feature set. It's simple, not a lot to learn, and would do the trick for most servo control.
8-Dale _________________ No, Mr. Jobs, the BiPod is a ROBOT. It does not play music OR interface with iTunes.
The Dynaplex Network - Robotics, Open Source, Linux, and Technology Forums |
|
| Back to top |
|
 |
|