The code for this is going to look very similar to PROJ05 - it uses a similar structure to handle IR remote button presses, but with the servo instead of USB HID. We are also going to introduce three new concepts that you might've seen in previous CIRCs - random()
, min()
and max()
.
First, let's import both IRLib and Servo:
#include <IRLibAll.h> #include <Servo.h>
Then, we are going to include all of the remote-specific code. This is going to include #define's for remote values, the receiver pin assignment, the decoder object, and the ir protocol used.
/* Adafruit Mini Remote */ #define MY_PROTOCOL NEC #define RIGHT_ARROW 0xfd50af #define LEFT_ARROW 0xfd10ef #define SELECT_BUTTON 0xfd906f #define BUTTON_0 0xfd30cf #define BUTTON_1 0xfd08f7 #define BUTTON_2 0xfd8877 #define BUTTON_3 0xfd48b7 #define BUTTON_4 0xfd28d7 #define BUTTON_5 0xfda857 #define BUTTON_6 0xfd6897 #define BUTTON_7 0xfd18e7 #define BUTTON_8 0xfd9867 #define BUTTON_9 0xfd58a7 // pin number for the receiver IRrecv myReceiver(2); IRdecode myDecoder; // handles nec repeat codes uint32_t Previous;
Next, we are going to create a servo object myServo, a variable to store the servo position and a variable to hold the angle (in degrees) of the servo.
/* Servo */ // create a servo object Servo myServo; // stores the servo position int16_t pos; // angle (degrees) to move the servo left/right int16_t Speed;
(Optional) If you're using a laser and are able to control it from the metro (see: assembly), we are going to connect the power to pin 11. We are also going to make a boolean, laserToggle
, to turn the laser on and off. laserToggle
holds one of two values - true or false. Depending on the button pressed and the current state, we can easily toggle the laser.
/* Laser */ // connect laser PWR to a pin 11 const int laserPin = 11; // toggle the laser bool laserToggle = false;
Our setup() code needs to set the laser pin as an output, attach a servo to pin 9, set the initial pos
to 90, the initial pos
to 90 and the initial Speed
to 5. Then, we are going to write pos
to the servo and start the IR receiver.
void setup() { // randomizes a seed for random() calls randomSeed(analogRead(0)); // set the laser pin as an output pinMode(laserPin, OUTPUT); // attach servo to pin 9 myServo.attach(9); // set initial position pos = 90; // set initial speed Speed = 5; // write initial pos to servo at startup myServo.write(pos); // Start the IR receiver myReceiver.enableIRIn(); }
As previously mentioned, this code is similar to PROJ05:
The loop()
is quite complicated, but we'll break it down to make it easier. We are going to first detect if the receiver gets an input from the remote with myReceiver.getResults()
. Then, we are going to decode it with a call to myDecoder.decode()
.
Next, we want to check if the protocol is the same as what's used by the Mini Remote, NEC, by checking if(myDecoder.protocolNum==MY_PROTOCOL)
. Finally, we are going to detect the repeat codes, and set the current value to the previous decoded value if(myDecoder.value==0xFFFFFFFF {myDecoder.value=Previous;}
void loop() { if (myReceiver.getResults()) { myDecoder.decode(); if(myDecoder.protocolNum==MY_PROTOCOL) { if(myDecoder.value==0xFFFFFFFF) myDecoder.value=Previous; switch(myDecoder.value) {
This time, though, we are going to set the position of the servo before writing to it. Hobby servos are incredibly particular with how far they can rotate, and can break if you rotate them too far. Let's prevent this with the min() function. This function will set the position of the servo to pos+Speed, but it'll keep the value underneath or at 180 degrees so that it won't go past that point.
case LEFT_ARROW: // move servo pos=min(180,pos+Speed); break;
Similarly if we want to constrain the right side, we set pos
to max(0, pos-Speed).
Max is the opposite of min, it constrains the lower-ends of the value.
case RIGHT_ARROW: pos=max(0,pos-Speed); break;
One of the cool things Arduino lets you do is generate a random number. We can generate a random number between 0 and 180 if we call random(0, 180)
. Let's set one of the buttons to set the pos to call to random.
case BUTTON_0: pos=random(0,180); break;
After the case statements, you'll want to:
1. Write to the servo,
2. Handle the NEC repeat code: Previous=myDecoder.value;
3. Re-enable the IR Receiver
myServo.write(pos); Previous=myDecoder.value; myReceiver.enableIRIn();
The full code is below
/* Metro Explorers Guide PROJ06 - IR Laser Pet Toy by Brent Rubell and Asher Lieber for Adafruit Industries. Support Open Source, buy Adafruit! Note: this sketch requires IRLIB2.x */ #include <IRLibAll.h> #include <Servo.h> /* Adafruit Mini Remote */ #define MY_PROTOCOL NEC #define RIGHT_ARROW 0xfd50af #define LEFT_ARROW 0xfd10ef #define SELECT_BUTTON 0xfd906f #define BUTTON_0 0xfd30cf #define BUTTON_1 0xfd08f7 #define BUTTON_2 0xfd8877 #define BUTTON_3 0xfd48b7 #define BUTTON_4 0xfd28d7 #define BUTTON_5 0xfda857 #define BUTTON_6 0xfd6897 #define BUTTON_7 0xfd18e7 #define BUTTON_8 0xfd9867 #define BUTTON_9 0xfd58a7 // pin number for the receiver IRrecv myReceiver(2); IRdecode myDecoder; // handles nec repeat codes uint32_t Previous; /* Servo */ // create a servo object Servo myServo; // stores the servo position int16_t pos; // angle (degrees) to move the servo left/right int16_t Speed; void setup() { // randomizes a seed for random() calls randomSeed(analogRead(0)); // set the laser pin as an output //pinMode(laserPin, OUTPUT); // attach servo to pin 9 myServo.attach(9); // set initial position pos = 90; // set initial speed Speed = 5; // write initial pos to servo at startup myServo.write(pos); // Start the IR receiver myReceiver.enableIRIn(); } void loop() { if (myReceiver.getResults()) { myDecoder.decode(); if (myDecoder.protocolNum == MY_PROTOCOL) { if (myDecoder.value == 0xFFFFFFFF) myDecoder.value = Previous; switch (myDecoder.value) { case LEFT_ARROW: // move servo pos = min(180, pos + Speed); break; case RIGHT_ARROW: pos=max(0,pos-Speed); break; case BUTTON_0: pos=random(0,180); break; } // tell servo 'move to variable pos' myServo.write(pos); Previous=myDecoder.value; } myReceiver.enableIRIn(); } }
Make sure your servo is attached to Digital Pin 9 on your Metro or Metro Express. Also make sure you have the servo library included in your sketch (at the top of your sketch, you should see #include
).
The code for this project only works with the Adafruit Mini Remote. If you want to use another remote, please check this guide for more information.
Text editor powered by tinymce.