Getting started with BART by a 12 year old evil genius

On my 12th birthday my Dad got me a B.R.A.T, it took about 1 week to build and fix all my mistakes.When I finally finish all the mechinics I started programming using the Aduino programming it to turn a light on then off (you may think this is easy but i’ve never programmed before)then got harder and harder till I got to morse code.When I finished morse code I decided to program the B.R.A.T to make it kick a ball ,can ,air and a Wall (it can kick anything).This code has been cleand and should be easy to understand (this is for anyone who wants to start program using servos).

I posted this because I looked EVERWHERE to learn how to use servos and I think this will help anyone that is in the same postion as I was in.

Feel free to improve this program.

can anyone point me in the right direction to make the movement smooth and jerky!

Thanks
Rory
Brat_kick_the_ball_v2.zip (755 Bytes)

Hi and welcome!

Thanks for sharing your work.

I don’t have time right now, but I will try to give some suggestions later today or tomorrow on how you can make leg motions work more smoothly. It has to do with breaking your movements down into smaller chunks.

Again welcome aboard!
Kurt

Hi again,

I did a little hacking on your code (nice job) as I have a brat with the Botborduino on it…

As I mentioned, one way to get smoother motions is to split the moves up into smaller chunks instead of moving lets say 30 degrees as fast as the servo can move. I did a quick version that I think does that with only one servo at a time, that is in the archive I included here. I only did a real quick test of the code so still could be issues.

There are many improvements that could be made here, like to move all of the joints of the leg at the same time. Also converting the degrees (servo.write(x)) to microseconds would also make it smoother.

Let me know if what I did does not make any sense…

Also FYI - I have a version of the Servo Library that I call ServoEx that does all of this for you. That is you can tell one servo to move to a new position in X time and it takes care of the dirty work…

Kurt
Brat_kick_the_ball_v2-121010a.zip (1.15 KB)

Thanks this is much smoother then before but the last part stand up is too fast and is jerky.So i’ve been studing your program to make that bit smoother and i don’t get what a “enum” is and whatthe code does.

void ServoTimedMove(int iServo, int NewPosition, int Time) {
  // can not do a timed move for ones we don't know their current position
  if ((Time != 0) && (aiLastPositions[iServo] != -1)) {
    int Delta = NewPosition - aiLastPositions[iServo];
    int CycleTime = 20;
    int CntOfCycles = Time / 20;  // 20ms is natural recycle time for servos
    int DeltaPerCycle = Delta/CntOfCycles;
    if (DeltaPerCycle  == 0) {
      // Not enough change to do it so...
      DeltaPerCycle = (Delta > 0)?1 : -1;  // assume a change per cycle.
      CntOfCycles = abs(Delta);
      CycleTime = Time/CntOfCycles;
    }
    int iPos = aiLastPositions[iServo];
    while (CntOfCycles--) {
      iPos += DeltaPerCycle;
      aServos[iServo].write(iPos);
      delay(CycleTime);
    }
  }
  aServos[iServo].write(NewPosition);
  aiLastPositions[iServo] = NewPosition;
}

I know this is a big chunk of what you did but I would like to Know what is does!

THANKS so much!!!
Rory

First the easy part: enum…
The enum is a quick way to do defines, where basically the next element in the list is equal to the previous one plus 1…
so: enum {SERVO_RH=0, SERVO_RK, SERVO_RA, SERVO_LH, SERVO_LK, SERVO_LA};
is like:

#define SERVO_RH 0 #define SERVO_RK 1 ... #define SERVO_LA 5
The next difference in my version is I converted your individual defined servos to be an array of servos.

Servo aServos[6];

Now to the harder stuff…

Most Servos require a pulse about 50 times per second. The command servo.write (or servo.writeMicroseconds), sets the width of each of these pulses. There is lots of details about the pulse requirements up on the net such as: viewtopic.php?f=31&t=3172

So for example if in your code you wish for a servo to move from 90 degrees to 120 degrees in a half second (500ms), if you did something like:

MyServo.write(90); delay(500); MyServo.write(120);
That after waiting for a half second the servo would jump to 120 as fast as the servo could get there, which makes it very jerky. So instead suppose you did something like:

MyServo.write(90); delay(20); MyServo.write(91); delay(20); MyServo.write(92); delay(20); ... MyServo.write(120);
The servo would only move small increments at a time and as such would be far less jerky.

That is what the code you mentioned does.

The first part verifies that the time that you wish to make the move in is not 0 (IE mediated), and it has moved previously as on the first move, the system has no way of knowing where the servos are).

So in my case above, suppose we are doing the example I mentioned above and aiLastPositions[iServo] is 90 and we passed in120 for the NewPosition and Time=500

The variable Delta would be set to 120-90 or 30
CntOfCycles would be set to 500/20 or 25
DeltaPerCycle would be 30/25 = 1 (Integer math, note in the code I mentioned there are things we can improve here).
So we can skip some of the code as DeltaPerCycle does not equal 0.
iPos starts off with the value 90
We then loop (while (cntofCycyles–) {
Sorry I should probably not used some of C’s short hand ways of saying things. It might be easier to understand if I said something like:
while(CntOfCycles!= 0) {
CntOfCycles= CntOfCycles-1;

the variable iPos is incremented by DeltaPerCycle. Again might be easier to understand if I wrote it like:
iPos = iPos + DeltaPerCycle;
We then write out each of these values and then delay by our cycle time in this case the default 20ms

Hope that helps
Kurt

I’m working on my BRAT and I want to slow it down so I put you program in and I didn’t understand the end part of this line.
ServoTimedMove(SERVO_RA, 100, 1000);
this part “,1000);”

can you tell me what it does?

Thanks
Rory

The 1000 parameter is telling the function, I want this move to complete in 1000 milliseconds(ms) or 1 second. I tried to explain this in my previous 2 posts… But again the idea is that you wish to move to servo location 100 (degrees) from where it is now and do it in 1000ms.

In the code we wish to update our position every 20ms or 50 times per second… So if the current position when you called this function was lets say 50 degrees, the code would loop 50 times (10000/20). The first time through and since we are moving 50 units during this time and by chance that turns out to be one degree difference per our 20ms time unit. So the first time we call servo.write, we call it with 50, the next time we call it with 51, next time 52, after our last call we should be calling it with 100 which is where we wanted to go. But as each of our moves were very small, the servo will move much smoother, than simply calling it after 1 second at 100…

Kurt