Programming

Intro




01110010 01101111 01100010 01101111 01110100

Time to program our robot! You can probably freestyle your way through the code, as it is simply a few servos and LEDs. However, in case you wanted your Buddy 4000 to be really similar to ours, here is an example sketch.



Download example sketch

There are two external libraries that the example code uses. Be sure to download these into your /libraries folder, and reboot the Arduino IDE.

Libraries
Streaming
HSBColor

Here is an example configuration of the robot for the pins.

- Servos: 8, 9, 10
- LEDs: 6, 5, 3

LET'S GET CODING!

Serial Monitor Mode


If you upload the example code to your Buddy 4000, open up the Serial Monitor on 9600 baud. From here, you will be able to send characters to make the robot move.

Here are the characters and their action:

Character Action
r/g/b
o
a
t/y/u
x/c/v
j/k/l
e

All of the serial reading is done in the readSerialMon() function.

Easing


The servos & LEDs are able to move smoothly thanks to an easing function - float easeInOutCubic(float t, float b, float c, float d). This easing function is from Robert Penner, who has tons of documentation online about easing. Be sure to check it out, and maybe see what other easing functions you can use.

One thing that is definitely good to know is what on earth the t, b, c, d variables mean! Here is a list:

Variable Description
float t
float b
float c
float d


In order to organize all of the variables for the easing for all of the Servos and LEDs, there are structs. Here is a description of the variables inside the structs:

Variable Description
float time
float startCol/Pos
float endCol/Pos
float change
float duration
float interval
float newCol
boolean activeNow
long lastUpdate


From observation, the total time it takes to complete an ease is duration*interval. However, sometimes we have noticed results taking a bit longer (*10?)... your results may vary as well.

Now to see how we use easing in action, check out the Routines section below.

Routines


Routines are pre-programmed 'dances'. If not currently dancing, robot will perform an idle behaviour eg: changing LED colours.

In each routine are keys (or 'dance moves'). In here is what moves the servos to different places, or changes the LEDs.

It is best to use non-breaking actions, unless there is something that needs to be changed and completed in that key.

Below is an example of the arm alternating routine. Notice how ignoreMoves is set to false, this means that when iterating through the keys, it will always check to make sure none of the servos are moving before going on to the next key.


void armAltRoutine() {
  
  int numKeys = 1;
  int del = 50; // 50 nice pace
  
  ignoreMoves = false;
  ignoreLights = true;
  
  switch(keyStep) {
          case 0: {
            
            float poss[] = {headLeft, leftDown, rightUp};
            float times[] = {del, 10};
            servoUpdate(poss, times);
            
            float vals[] = {128, 0, 255};
            float ledtimez[] = {20, 10};
            ledUpdate(vals, ledtimez);
            
          }
          break;
          case 1: {
            
            float poss[] = {headRight, leftUp, rightDown};
            float times[] = {del, 10};
            servoUpdate(poss, times);
            
            float vals[] = {128, 0, 255};
            float ledtimez[] = {20, 10};
            ledUpdate(vals, ledtimez);
            
          }
          break;
        }
        
        keyStep++;
        if(keyStep > numKeys) keyStep = 0;
  
}


Inside of loop() is where the 'switching' (as I call it) happens for doing the various routines. Each routine has a specific number, and when the current routine is that number ... well, then it will do that routine (duh!).

If the robot isn't in routine mode, then it will just do the idle behaviour, which is fading the hue of the LEDs.

	  
if(routineMode) {
    
    switch(currentRoutine) {
      case 0:
          if(ignoreLights && ignoreMoves) {
            armAltRoutine();
          } else if(ignoreLights && !ignoreMoves) {
            if(!isMoving) armAltRoutine();
          } else if(!ignoreLights && ignoreMoves) {
            if(!isLighting) armAltRoutine();
          } else if(!ignoreLights && !ignoreMoves) {
            if(!isMoving && !isLighting) armAltRoutine();
          }
      break;
    }
    
  } else {
    idleBehaviour();
  }


Just in case you're curious, here is the idle behaviour. It uses the HSBColor library to change its hue!

	  
void idleBehaviour() {
 
   if(millis()-lastTick >= 100) {
      
      int rgbz[3];
      H2R_HSBtoRGB(hueCount, 25, 100, rgbz);
      
      float vals[] = { (float)rgbz[0], (float)rgbz[1], (float)rgbz[2] };
      float ledtimez[] = {5, 10};
      ledUpdate(vals, ledtimez);
      
      hueCount+=10; // 5 is cool, 10 is cool, 15 is fast
      if(hueCount > 360) hueCount = 0;
      
      lastTick = millis();
    }
  
}


You can explore the rest of the code in the example sketch, it is all quite similar to the above descriptions.

Next


Now that we're done with programming, that's it! We're done! Feel free to proceed to check out the Open Source Hardware files for Buddy 4000.

OSHW

...or back to the main page:

Back