Calibrating - Overview


In order for RoboBrrd to not destroy itself using its own servos, we need to set the minimum and maximum positions for the left wing, right wing, and beak. The reason why is because if either of the wings go up or down too far, then the servo is 'fighting' against its own geometry. The servo is trying to move the wing, when there is no where else for it to move. The same goes for the beak servo, it can only open and close to a certain position.

We developed an simple application for you to use to calibrate the servos called RoboBrrd Dashboard.



With the RoboBrrd Dashboard, you can use sliders to adjust the servo positions. You can also set the various position values, and test them out with the action buttons. There is also buttons for the eyes to turn them on and off (with the option of independent control), and a bar graph display of the photocells.

It runs on Mac, Linux, and Windows. Download the latest version here!

*Note: If you have not plugged in your servos yet, see Extras Step #1.

Calibrating - Code


In order for your RoboBrrd to work with the RoboBrrd Dashboard software, we have to add some code to run on the Brain Board. It will be best if you create a new sketch, and paste your original RoboBrrd code into it.

Remember the basic program structure of RoboBrrd (from Programming - Intro)? Here is the structure again, with indications of where we will be adding the code.

// 1. includes

// -- (A) we will be adding some variables here -- //

// 2. variable declarations

// -- (B) and adding some more variables here -- //

void setup() {

	// 3. initializing everything

}

void loop() {

	// 4. doing robobrrd actions!
	
	// -- (C) replacing the contents of loop() -- //

}

// 5. various helper functions



(A) Here are the extra variables that we need


#define DEBUG false
int ticks = 0;
long lastSend = 0;


(B) Here are more variables that we need


// -- lalalala -- //
boolean reading = false;
boolean completed = false;
int msgIndex = 0;
const int msgLen = 12;
char msg[msgLen];

char cmd[2];
char val[4];
int valLen = 0;
double valResult = 0;

// areas //
// !BK:180~
char allCmds[12][2] = { {'B', 'K'},
                        {'L', 'W'},
                        {'R', 'W'},
                        {'A', 'X'},
                        {'R', '1'},
                        {'G', '1'},
                        {'B', '1'},
                        {'R', '2'},
                        {'G', '2'},
                        {'B', '2'},                   
                        {'L', 'D'},
                        {'R', 'D'} };

int cmdCount = 12;
int cmdRow = 99;
                   
// actions //
static int bkOpenSerial = 0;
static int bkClosedSerial = 1;

static int lwingUpSerial = 2;
static int lwingDownSerial = 3;
static int lwingHomeSerial = 4;

static int rwingUpSerial = 5;
static int rwingDownSerial = 6;
static int rwingHomeSerial = 7;


(C) Remove the previous contents of loop(), and add this block of code:




  // -- LISTEN -- //
  char m;
  if(Serial.available() > 0) {
    while(Serial.available() > 0) {
    
      m = Serial.read();
      
      if(m == '!') {
        reading = true;
      }
      
      if(reading) {
        if(msgIndex < msgLen) msg[msgIndex++] = m; 
      }
      
      if(m == '~') {
        reading = false;
        completed = true;
      }
      
    }
  }
  
  if(completed) {
   if(DEBUG) Serial << "good job" << endl; 
   
   for(int i=0; i<msgIndex; i++) {
     if(DEBUG) Serial << msg[i];
   }
   if(DEBUG) Serial << "\n";
   
   if(msg[0] == '!') {
     cmd[0] = msg[1];
     cmd[1] = msg[2];
   }
   
   if(msg[3] == ':') {
     for(int i=4; i<(msgIndex-1); i++) {
       val[i-4] = msg[i];
     }
     valLen = msgIndex-5;
   }
   
   boolean good = false;
   if(msg[(msgIndex-1)] == '~') {
     good = true;
   }
   
   if(good) {
     if(DEBUG) Serial << "good!" << endl;
     
     boolean match = false;
       for(int j=0; j<cmdCount; j++) {
         if(cmd[0] == allCmds[j][0]) {
           if(cmd[1] == allCmds[j][1]) {
             if(DEBUG) Serial << "match!" << j << endl;
             match = true;
             cmdRow = j;
           }
         }
       }
       
       if(match) {
           
           for(int i=0; i<valLen; i++) {
             if(DEBUG) Serial << val[i] << " ";
           }
           if(DEBUG) Serial << endl;
           
           for(int i=0; i<valLen; i++) {
               valResult += (val[(valLen-1)-i] - '0')*pow(10, i);
               if(DEBUG) Serial << i << ": " << val[(valLen-1)-i] << " " << (val[(valLen-1)-i] - '0') << " " << pow(10, i) << "=" << (val[(valLen-1)-i] - '0')*pow(10, i) << endl;
           }
           
           /*  
           if(valLen > 3) {
             valResult += (val[0] - '0')*1000;
             valResult += (val[1] - '0')*100;
             valResult += (val[2] - '0')*10;
             valResult += (val[3] - '0')*1;
           } else if(valLen > 2) {
             valResult += (val[0] - '0')*100;
             valResult += (val[1] - '0')*10;
             valResult += (val[2] - '0')*1;
           } else if(valLen > 1) {
             valResult += (val[1] - '0')*10;
             valResult += (val[2] - '0')*1;
           } else {
             valResult += (val[0] - '0')*1;
           }
           */
           
           if(DEBUG) Serial << "Result: " << (int)valResult << endl;
           
           // do something with result
           
           switch(cmdRow) {
             case 0: // beak
             beak.write((int)valResult);
             break;
             case 1: // left wing
             lwing.write((int)valResult);
             break;
             case 2: // right wing
             rwing.write((int)valResult);
             break;
             case 3: // action
             break;
             case 4: {// red1
             
             if((int)valResult == 1) {
                digitalWrite(r, HIGH);
              } else {
                digitalWrite(r, LOW);
              }
             
             break;
             }
             case 5: {// green1
             
             if((int)valResult == 1) {
                digitalWrite(g, HIGH);
              } else {
                digitalWrite(g, LOW);
              }
             
             break;
             }
             case 6: {// blue1
             
             if((int)valResult == 1) {
                digitalWrite(b, HIGH);
              } else {
                digitalWrite(b, LOW);
              }
             
             break;
             }
             case 7: {// red2
             
             if((int)valResult == 1) {
                digitalWrite(r, HIGH);
              } else {
                digitalWrite(r, LOW);
              }
             
             break;
             }
             case 8: {// green2
             
             if((int)valResult == 1) {
                digitalWrite(g, HIGH);
              } else {
                digitalWrite(g, LOW);
              }
             
             break;
             }
             case 9: {// blue2
             
             if((int)valResult == 1) {
                digitalWrite(b, HIGH);
              } else {
                digitalWrite(b, LOW);
              }
             
             break;
             }
           }
           
           
           // at the end, clean!
           valResult = 0;
           valLen = 0;

       }
     
   }
   
   msgIndex = 0;
   completed = false;
   
  }
  
  
  // -- SENSORS -- //
  if(millis()-lastSend >= 20) {
  
  if(ticks%2 == 0) {
    Serial << "!" << "LD" << ":" << analogRead(A0) << "~" << endl;
  } else {
    Serial << "!" << "RD" << ":" << analogRead(A1) << "~" << endl;
  }
  
  lastSend = millis();
  
  }
  
  ticks++;
  
  


Once you have added this to your code, it's time to upload it to the Brain Board. (If you don't remember how to do this, please revisit Programming - Step 5) Make sure you don't turn on the serial monitor- it will interfere with the RoboBrrd Dashboard and won't be able to work.

Calibrating - Calibrate


Now it is time to connect to your RoboBrrd and start calibrating the servos! If the RoboBrrd Dashboard software is not running yet, start running it. Using the RoboBrrd Dashboard is straight-forward, and below you will find an explanation of how to calibrate the servos.

  • The first action we have to do is connect the Brain Board. At the top, there is the serial port drop down and connect button. Select the same serial port that you use to upload code to, then press connect.

  • Start with moving the sliders in the 'Servos' section. You should notice the servos starting to move. For the beak, move the slider to where the beak is completely open, and shut. You can also carefully listen to the servo to hear when it begins to make more noise for when it is pushing against something that is not moving.

  • Look to the left side of the slider to see a number corresponding to the servo position. Type that number into the corresponding box in the 'Positions' section, and press enter to set it. Repeat this process for the other servos and boxes as well.

  • Note: For the 'home' position, that is when the wings are in between their upper and lower positions, parallel with the table and perpendicular to the side edge of RoboBrrd.

  • In the 'Actions' section, there are quick buttons that you can press to test out the positions. These are handy to try it out and see if the values are what they should be.


When you have the values all set, it is time to add them to the Brain Board code. If you remember from Programming - Step 1, this is the block of code where we add the values. You can edit this directly in the Arduino IDE and replace the given numbers with the calibrated values from RoboBrrd Dashboard.

// -- SERVO VALUES -- //
// determine the min and max values of
// your servos, and write them here
const int r_upper = 0;
const int r_lower = 180;

const int l_upper = 180;
const int l_lower = 0;

const int b_open = 90;
const int b_closed = 0;

int r_middle = 90;
int l_middle = 90;


Remember to save your code! That's all there is to the calibration, it's done :)

Congrats!


You are done calibrating the servos for RoboBrrd! Next up, let's start to make our RoboBrrd do something- this will be all programming, we will add some more helper functions and also two behaviours! Let's hop to it!

Behaviours

"I just finished calibrating RoboBrrd's servos! Whirrr whirrr"
RoboBrrd Kit Building I just finished calibrating RoboBrrd's servos! Whirrr whirrr #RoboBrrd