I have a partial success running 18 channels of servo from the 128. The timing pulses are good and It holds steady with no chatter whatsover. I did originally look at the SSC code as advised but it really is a phenomenal piece of work. I understand the principles of it but the low level machine code is quite complex and beyond my understanding. As I said, I can see what it achieves but how is another matter. Still it did give me some inspiration for my own.
I have run into what appears to be a common problem and one that is probably only resolved at machine level. That of background processing commands to update and change the positions.
All processing has to be done between the last pulse going low and the end of the duty cycle, i.e. between 2.5mS (maximum pulse width for any servo) and 20mS which is when it all has to start again.
Comms is easy enough, just buffer it and deal with it at the 2.5mS point but if there is anything to do, i.e. move one or more servo’s it can get a bit busy and sometimes over-run. If that happens the servo’s can get unpredictable and either go to sleep or jump to positions not expected.
I’m beginning to run short of ideas so I’ll probably set it aside for a while and have a think but it may simply be because I don’t know the tmega well enough.
The SSC code is very much geared towards the Atmega8 and will not directly compile for the 128 though removing references to the bootloader sequences allows it to do so. Because it hasnt got all the links in place, its hard to tell if it actually runs. There is one other fundamental difference which is that the SSC outputs to Registers on the board. Mine uses ports A, B and part of port C.
If there is anyone who knows about the SSC code and would be willing to assist with a port to the 128 it would be appreciated. I was considering contacting the original author but I hate cold-calling and it does seem a bit cheeky.
PaulP, I’m coming in a bit late to the discussion but I might be able to shed some light on your problems.
The SSC32 uses the registers just to multiplex its output. The ATMega8 just doesn’t have enough pins to drive 32 servos directly. So it uses 4x 8bit shift registers to come up with the 32 outputs. As a result of this design choice, it also has to phase the pulses into 4 sets of 2.5ms.
I assume you are not using register and driving the servos pulses directly from your output pins. If that’s the case, you don’t need to break the pulses up into 4 banks as the SSC32 does. If you make that change alone, you’ll end up with 17ms to do all your other processing.
Another key to getting jitter free timing is to use interrupt based timers, not busy counters. I believe you can also prioritize the interrupts on the mega128 such that your serial ISR could be lower than your timer ISR. If you end up with the serial ISR higher priority than your timer, or if the timer is a busy wait style rather than an interrupt, than your servo pulses can be longer than desired by as much time as it takes to process the incoming serial comms.
If you don’t get interrupt prioritization (I simply don’t remember) than you’ll want to buffer the incoming comms on ISR and return from the interrupt immediately, thus minimizing the potential delay to the sensitive pulse timings. Once your 2.5ms block is up, parse your buffer.
I’d strongly recommend that this chip be responsible only for receiving commands and issuing pulses. Put the actual control logic elsewhere. When your worrying about gaits and what not, you don’t want to have to be concerned with upsetting the pulse timings.
OK, reading back through your last post more carefully, it seems you’re already doing a lot of what I was suggesting…
If your timers are counter based and your doing the comms buffering in the serial ISR, make sure that that handler returns as quickly as possible. Those interrupts will happen whenever data arrives (in the middle of your counting) and will disrupt the timing by as much time as it takes you to buffer/return.
If you can’t parse the commands in the 17ms then you need to optimize your parsing code or use a faster crystal.
What about porting your gait generator to a 2nd 128? Just like the Atom. Then it could talk to an SSC-32.
Also, there are plans I believe to move the SSC-32 over to a 168 already by Lynxmotion, so that more can be added to it. I personally have been able to compile the SSC-32 code, and have been studying it. After the news of the 168, I ordered some so that I could port the existing SSC-32 code over to the 168 to give me a little room to add code. I’d be interested in assisting you in this pursuit. I’ve also implemented SPI and used 74HC595MTC (and 74HC597) chips in both PIC and Atmel ARM7 designs, and feel I know a little about their use in the Mega8 design as well.
I’d like very much to hear more about your gait implementation, as this is a direction I’d like to go, especially after reading all the research on implementing hardware Neurons. Did I hear right that something is in the public domain? Would you be willing to share the gait portion of what you’re running your robot with?
The register bit I’d managed to work out from the circuit diagram and I’d surmised that it was somehow grouping the pulses.
Thats correct, essentialy using 3 ports which allows up to 24 servos directly controlled.
This bit I’ve done as you described. Timer 2 is running on an Interrupt and doing the servo control. The USART interrupt adds to a buffer and is dealt with in idle time. This part works well without interfering with the servo’s
Unfortunately this is my main reason for porting the servo control. The SSC has limited ability to control peripheral equipment at present. One of the requirements of terrain adaption is to be able to tell when a foot comes in contact with the ground, the other requires the use of a gyro to adjust body attitude to the ground.
The SSC does have inputs both analog and digital but over the same 4 pins. They could be multiplexed quite easily but the analog modes would require a period of settling for correct reading and I believe the digital modes are already debounced. The overheads of these delays and the comms overhead combined means that responding to a foot touching the floor would be almost impossible in a quick and clean manner. Also, for terrain adaption I would need to be able to retrieve the the positions at which the legs had stopped to process the data and recalculate the next set of leg movements.
As I mentioned, I am using interrupts running on a 14.745 crystal. I could move to 16Mhz but then I lose the 115200 baud rate. The step to 16 may not give me enough.
My main aim was to acheive a single chip solution, essentially something as accurate and well behaved as the SSC combined with something as versatile as the Atom on one chip.
I did consider using the 168 but as it has less output pins than the 128 it wouldn’t accomodate the number of servos without external hardware.
Another option was the 256 which has more memory.
The little I’ve managed to do on the gait generation is all based around the document available from matt on micromagicsystems. Apart from the token management and delays described in the document I’ve done nothing more. It explains how the delay in passing tokens can turn the standard tripod gait into a wave gait. The one thing that it does need though is the foot contact sensors which is what has stopped my .NET version in favour of a single chip solution.
To be blunt, I think the Atmega128 has the ability to achieve what I want it to. It would make a good single chip implementation of the SSC with the addition of at least 8 analog and 8 digital inputs.
It possibly even has the ability to do a lot more in the background such as gait generation and command handling.
With the limited amount of time, 17mS at best, to do all this, the main reason why this will not work is going to be my coding ability. I have little knowledge of C as a language and even less of the specialist manner in which it is implemented for the AVR range.
I believe even more now that I need to find a faster processor based system that will make up for my shortcomings.
As Andy quite rightly says. It may be better to keep the logic and servos seperate. My work on the KHR showed that that way can be done but I may have to forego certain frills.
I agree that you can probably do everything you want with the single chip solution. I’ll reiterate though that it’s simply not worth the headache that will almost definitely come along with it.
From what you’ve described that you are trying to do, I’d say use the SSC32 slaved to your ATMega. Do all your analog I/O directly in the Mega (no need to mess with the SSC32s a/d inputs) and stream your output to the SSC32, let it worry about the pulses.
I don’t mean to discourage you from building a custom servo controller if it’s just for the exercise of doing it (I did the same, though only 6 channels per chip over I2C) but if you take my other advice of keeping the servo controller separate from the logic, then rebuilding the SSC32 seems excessive. Perhaps I’m missing something.
If your concern is about how quickly you can stream new positions to the SSC32, I’m pretty sure that over 115K and even in the rather verbose command syntax of the SSC32 you can get 32 new positions in there every 20ms. Given that, I don’t see how you’d be giving up frills?
Andy you are right in more ways than one, it is a headache and the results probably won’t justify the effort. SEQ runs all the servos over the serial link extremely effectively. Its all “do-able” and I’ve implemented them in some degree or other.
One requirement is all that is driving me at present and that is the absence of a STOP command for the servo.
To achieve a good terrain adaption I need to implement a “LOWER” function which essentially lowers the leg until it hits the floor.
I can issue a command that will lower the leg properly, more likely a sequence of shorter moves, but I have no way of stopping movement if contact is made part way through a movement.
say for example the leg starts at 1000 and I send it to 2000. If at 1600 it touchs the floor it will continue to 2000 before stopping thus trying to lift the whole body on one leg.
The only possible solution I could try is to set the leg moving and when the contact is detected, query the 3 servos involved, get the results and send those values as the position. Its not tidy but it might work. Again the only issue would be speed and delays.
Solving this one problem tidily would allow me to put aside the servo control aspect and move on. Admitedly, I have had an immense amount of fun and gratification from achieving what I have so far.
Assuming my prior assertion about how quickly you can update all the positions over 115K is correct, then you have no reason to use the speed capped move feature of the SSC32.
That routine simply adds to the current position the speed value until it reaches the desired position. If you can do full bot updates every 20ms, bring that logic to a higher level so that you never ask the SSC32 to do anything in the future beyond the next 20ms. Then you never have to ask it to stop
In CNC we have Gcodes that do a “move until sense”. They are used to “digitize” a surface (Renishaw). I think that’s similar to what you’re talking about.
If the SSC-32 were to receive a “sense” input from a foot sensor and cause an interrupt, then the leg number could be used to “kill” the three axis moves for that leg (or joint?). the servo(s) would terminate their programmed move, and the position of the stopped servo(s) would be reported back to the host via the back channel (RS-232). This WOULD be through the SSC-32 rather then sensors going directly to the host.
If the SSC-32 were limited to the 24 servos required, maybe it would have more time for other things. Just a thought. Hafta call it an SSC-24 (w/sensors).
If I understand what you are alluding to, sending a sequence of shorter move commands instead of one large one was something I tried. It has the unfortunate effect of causing jerky movements which most times lead to oscillation and chattering in the servos…
You’ve interpreted my suggestion correctly. I think it’s worth pursuing this route for a couple reasons.
Moving your foot vertically in 3D requires non-linear speeds across the individual joints. This is the immediate limitation of using the built in sequences, but I think as you go you’ll find a lot more. I assume you’re intending to do real-time IK in the main controller. If you have it generating new joint angles every 20ms you don’t have to worry about trying to fit a non-linear peg into a linear hole.
Secondly, interpreting the sensor data from ground contact is unlikely to be as cut and dry as you’re hoping. Depending on what type of sensor you employ (I’ve tried many and found no good solutions yet) you’re probably going to end up with some sort of analog value for force. The simplest interpretation of this might be a threshold value which says “Contact = Value>Threshold”. You’re likely to want to have different thresholds for each sensor to calibrate them due to slight mechanical differences. You might want to have the threshold work against a moving average. Maybe go so far as to apply Kalman filtering or some such. My point here is that this problem can easily become complex enough that you’ll want to handle higher level than inside the SSC32 or a black box servo controller if you scratch build it.
I’m fairly certain you can work out the jerky motion. What the SSC32 is doing internally is nothing special. It has no data that you don’t externally. It’s just a question of getting high enough bandwidth between your IK engine and the SSC32 and I’m pretty sure I worked it out once before that the 115K and the protocol will just make it under 20ms for a full 32 servos. And as long as your using a hardware UART from your master, then there’s extremely little overhead beyond keeping a table of joint angles. Every 20ms you render that into a buffer and let the hardware UART do the rest.
If you use Open Servos, you can still control the servos using PWM as from an SSC-32, AND you can read position and status information back from it using i2c. You can detect stall conditions using the current sensing feature, like when a foot contacts the ground. This is something you might want to consider as your applications seems to be pretty much tailor made for the features of the Open Servos.
ahhh… I no longer have to be the only OpenServo evangelist
While OpenServos will probably provide much better current sense data than I managed with my early hacks, these are still very difficult data to use effectively. The internal PIDs in any servo work via pulsing power to the motor by an amount related to the error in position. If the load happens to get a bit ahead of the desired movement, the servo will pulse backwards to slow the movement. Uneven loading of a servo thwarts any simple methods of interpreting the data even during slow movements. This is likely better in the OpenServos because the PID bandwidth is high enough that it will likely yield a much smoother graph than a 20ms analog but it’s still very difficult data.
I had some very limited success doing ground detection via current sensing by training a neural net on the current sense data that came back from the movement of a leg while unloaded. So essentially it would flail its legs around and the net was trained to predict the loading that each joint would see based on the commanded movements with no obstacles. In this video it’s comparing these predictions against moving averages of the actual data, thresholded to determine contact. During the recording of this video is about as good as I ever had it working, which to be honest, was rather ham-fisted at best. That’s not to say that others can’t beat it or shouldn’t try, just that attempting to use servo loading as a means of ground detection is a non-trivial task, perhaps even harder than finding an effective means of directly sensing ground contact