// 1. includes
// 2. variable declarations
void setup() {
// 3. initializing everything
}
void loop() {
// 4. doing robobrrd actions!
}
// 5. various helper functions
#include <Servo.h>
#include <Streaming.h>
// -- SERVOS -- //
// label your servo pin numbers here
const int rpin = 8;
const int lpin = 9;
const int bpin = 10;
Servo rwing, lwing, beak;
Here is where the servo pin numbers are being set. Remember the wires that we soldered going from the headers to the pins on the back of the Brain Board? This is that. If you plug in the beak servo to the header on the left, then it will be the 11th pin.// -- 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;
These are values that will tell the servos what their minimum and maximum values are. This is useful so that RoboBrrd does not hurt itself by trying to raise its wing too high, or open its beak too much. When we will calibrate the servos, we will be figuring out the precise values for these.// -- LED PINS -- //
const int led = 13;
// the rgb pins of your servos
const int r = 3;
const int g = 5;
const int b = 6;
const int leds[] = {r, g, b};
These are the pins that the RGB LEDs are connected to, as well as the pin 13 LED. We also create an array called 'leds' for the RGB LEDs, which will have the pin numbers inside of that array. We are giving the basic example here of putting both the left and right side of LEDs on the same pins. Also notice, these pins have PWM, so we can fade the eyes. Later on, if you want to control both sides of the eyes, you can go back and customize the definitions to do that.// -- MISC -- //
const int spkr = 7;
const int ldrL = A0;
const int ldrR = A1;
const int tmp = A2;
Here is just some extra stuff that we need, like the speaker, photocells, and the TMP36. The reason why the ldrs and tmp have an 'A' before their pin number is to signify that it is on the Analog Input.
// -- LET'S GO! :) -- //
void setup() {
// -- serial
Serial.begin(9600);
Serial << "Hello from RoboBrrd! SQUAWK! CHIRP! Beginning initialization... beep beep" << endl;
Here we start off the initialization by starting up our Serial connection. The 9600 is the baud rate. It's not very fast, but the speed does not matter at this stage anyway. We will also print out a hello to the serial console! In this case the << characters are overloaded, and the Streaming library handles the call to Serial.print() (you may have seen it this way in other tutorials online). This overloading way comes in handy with lots of variables, as we will see below! // -- servos
rwing.attach(rpin);
lwing.attach(lpin);
beak.attach(bpin);
rwing.write(r_middle);
lwing.write(l_middle);
beak.write(b_closed);
Now we attach the servo pins to our Servo objects. This is a function provided to us from the Servo library. Next, we set their initial 'home' positions by telling the servo to write the middle position. // -- leds
pinMode(led, OUTPUT);
blinkLed(led, 5, 100);
for(int i=0; i<3; i++) {
pinMode(leds[i], OUTPUT);
analogWrite(leds[i], 128);
}
Now we will set our LEDs to output, and also test fire them! For the first LED, we use a helper function called 'blinkLed' to blink it, which we will be defining below. The RGB LEDs are handled inside of the for loop. Inside of the for loop, we set the LED to output, and turn it on the medium brightness. // -- misc
pinMode(spkr, OUTPUT);
for(int i=0; i<5; i++) {
playTone(260, 70);
playTone(280, 70);
playTone(300, 70);
delay(100);
}
pinMode(ldrL, INPUT);
pinMode(ldrR, INPUT);
pinMode(tmp, INPUT);
Serial << "LDR L: " << analogRead(ldrL) << " ";
Serial << "LDR R: " << analogRead(ldrR) << " ";
Serial << "TMP36: " << analogRead(tmp) << endl;
// -- go!
Serial << "Finished initializing! Beep bloop boop whirrrr" << endl;
}
Time to add in the misc stuff now! First up is the speaker, we will define it as an output, then do a test melody. The way the melody works is that it plays three tones in sequence, five times -- because it is in a for loop. The tones are generated thanks to another helper function called playTone. We will be touching on this helper function in a later step.void loop() {
// -- right wing -- //
Serial << "--rwing--" << endl;
blinkLed(led, 1, 500);
for(int i=r_lower; i>r_upper; i--) {
rwing.write(i);
delay(5);
}
delay(500);
for(int i=r_upper; i<r_lower; i++) {
rwing.write(i);
delay(5);
}
For this part, we are testing the right wing. The first for loop moves the servo from the lower position to the upper position. For each step, it pauses 5ms. This makes the movement slow. When it is at the upper position, it waits 1/2 of a second, then returns to the lower position. // -- left wing -- //
Serial << "--lwing--" << endl;
blinkLed(led, 2, 500);
for(int i=l_lower; i<l_upper; i--) {
lwing.write(i);
delay(5);
}
delay(500);
for(int i=l_upper; i>l_lower; i++) {
lwing.write(i);
delay(5);
}
This is the same as the block of code above, except it is for the left wing. // -- beak -- //
Serial << "--beak--" << endl;
blinkLed(led, 3, 500);
for(int i=b_closed; i<b_open; i++) {
beak.write(i);
delay(5);
}
delay(500);
for(int i=b_open; i>b_closed; i--) {
beak.write(i);
delay(5);
}
Again, the same as the previous two blocks of code, but it is for the beak. // -- heartbeat -- //
Serial << "--heartbeat--" << endl;
blinkLed(led, 5, 100);
// -- eyes -- //
blinkLed(led, 4, 500);
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
digitalWrite(leds[j], LOW);
}
digitalWrite(leds[i], HIGH);
delay(500);
}
for(int i=0; i<255; i++) {
for(int j=0; j<3; j++) {
analogWrite(leds[j], i);
}
delay(10);
}
The first part is a little 'heartbeat' of a blink for the LED on pin 13. // -- sensors -- //
Serial << "--sensors--" << endl;
blinkLed(led, 5, 500);
for(int i=0; i<20; i++) {
Serial << "LDR L: " << analogRead(ldrL) << " ";
Serial << "LDR R: " << analogRead(ldrR) << " ";
Serial << "TMP36: " << analogRead(tmp) << endl;
delay(50);
}
}
Here is the code for the sensors. Much like the code we used at the end of setup(), except here it is inside of a for loop so that it prints out 20 readings, 50ms apart.// -- BLINK -- //
void blinkLed(int pin, int rep, int del) {
for(int i=0; i<rep; i++) {
digitalWrite(pin, HIGH);
delay(del);
digitalWrite(pin, LOW);
delay(del);
}
}
This is a handy function to blink the LED without crowding up our code. It takes a pin, how many times it should repeat the blink, and how long to delay after each blink (in ms). The way the code works is that it sets the pin to HIGH, waits the given delay, sets the pin to LOW, and waits the given delay again. This is repeated for the given number of times using the for loop.// -- SPEAKER -- //
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(spkr, HIGH);
delayMicroseconds(tone);
digitalWrite(spkr, LOW);
delayMicroseconds(tone);
}
}
Here is how we can pulse the speaker to make a sound. We pass it a tone and how long the tone should be (in ms). Check out the for loop: it starts at 0, goes until how long the tone should be times 1000, and increments itself by tone*2. Inside of the for loop, we again set a pin high and low while pausing, though this time in microseconds.