Go Down

Topic: Servos Patterns and Serial Comms - suggestions please (Read 784 times) previous topic - next topic

AdLab

Hey Guys,

I've written a simple RS232 protocol that uses an Mega to communicate several integer values to multiple Unos. It works fine, robust and quick. To make sure I don't miss important data changes (for whatever reason, e.g. noise) I send the data packets continuously.

The Unos are going to continually move 2-4 servos each, going through preset motion patterns. When data from the mega changes the servos will either switch into a different motion pattern, or modify the variables in the existing one (e.g. the servos maybe sweeping between two angles, the new message might change these angles). The changes need to be instant and smooth on receipt of the new message.

At the moment I'm not sure what the best way to approach this is. I don't want glitchy servo motion from slow position updates as a result of checking serial messages, and I don't really want to implement a state machine where message checking is done infrequently and important packets may be missed.

I'd love to hear your suggestions of a nice way to get these two functions to work together as seamlessly as possible. I've tried searching the forum but most question of this nature relate to quite simple digital functions, I'm worried that using serial and the servo library might complicate things. Also, many people use a serial packet to move a servo, which is quite easy as you just update the position when the message arrives. I need the servo to be going through its motions all the time.

Many Thanks,

Ad

Korman

Are you using the usual hobby R/C-Servos? If so, the Servo library will take care of the Servo management for you and setting an new position will be as fast as possible (which means at the next refresh for this servo) and as fast as the servo can handle. From your program's perspective, the setting is instant and you can busily wait for the next serial message.

On the other hand, I might have totally misunderstood your problem.

Korman

AdLab

Hi Korman,

Thanks for your reply but I'm not sure if I described my problem clearly.

Each of the 4 servos connected to one of the unos will be continuously moving autonomously (going through some pattern), while at the same time I'll be recieving and checking the serial packets, which arrive every 10-100ms I think (I don't have the code with me right now).

So my program will have to set 4 new servo positions at every time step while also listening for messages on the serial port. If a message arrives while I'm in the middle of sending the sevo commands, I'll miss it. This is the problem.

What I need is a way to make sure that I don't miss messages while maintaining nice servo messages. It's almost like both of these things need to be on their own loop. If this was a computer program I would use multi-threading.

I wonder if there is a solution using Interrupts? I've use these for managing digital outputs but not checking the serial port?

Korman

Ah, ok.

In this case, have a set of dance patterns and check before each step has arrived. In case of a message, set the dance pattern pointer to the start of the new pattern. After this, take the next step in the pattern. Your loop could look something like this:

Code: [Select]

void loop() {
    static unsigned long laststeptime = 0L;

    // Read serial if soemthing came in
    while (Serial.available () > 0) {
         incomingbuffer[nextfree++] = Serial.read();
         // Check here if you have a full message yet
         if (message is complete) {
              patternpointer = ... set  new dance pattern ...
             
              nextfree = 0; // Reset input buffer;
         }

    // Check if you can take the next dance step
    unsigned long curtime = millis();
    if (curtime - laststeptime > patternpointer->delay) {
        // We have waited long enough, take next step
        myservo.write (patternpointer->position);
        if (... have we reached the last step in the pattern? ...) {
               // Reset patternpointer to the start to loop current pattern
               patternpointer = startofpattern;
        }
        else {
              // Increment pattern pointer to next step
              patternpointer++;
       }
       // Reset timer for this step
       laststeptime = curtime;
   }
}


The pseudo-code assumes you have a fixed collection of pattern which are structures with a delay and position. How you organise that depends on what you really need, this is more to illustrate how you do this in one loop.

Korman

wildbill

Serial read data is buffered - IIRC, it's 128 bytes, so you have some time to play with before you start dropping messages

AdLab

Hi Korman, so you'd suggest doing the whole thing inside the same loop, but splitting the steps of the motion up? That seems to make sense, especially due to the buffer, which wildbill mentioned. I'll give it a shot and let you know how it goes...

Go Up