p.bot -- A paper robot
Definition
What is the minimal definition of a robot? How about: a computer-controlled system that can (i) sense something (ii) communicate and (iii) produce some physical action. This very broad definition is also pretty much what electromechanical prototypes in ME310 are about. Therefore, your "paper bike" challenge to kick off ME310b is the Paper Robot: p.bot
The specific challenge to kick off ME310b is to create an “Universal Agent” p.bot that can send and receive messages with others of its kind using a standard protocol. The basic requirements are:
1. Use "sensors" (of any kind, including switches) to detect an input state that is imparted to the p.bot by a naive human user.
2. Communicate with others of its kind in a predefined standard format and protocol. In this activity, you will be using a software serial library, which simulates UART communication on standard digital pins.
3. Interpret received messages and do something physical to reflect the received messages as output that naive users can recognize and enjoy.
Constraints and Logistics
Stanford teams will be provided with a basic kit consisting of an Arduino equivalent (Really Bare Bones Board - RBBB, Modern Devices) microprocessor prototyping board and some accoutrements. The kit supports simple code development on Windows, Macintosh and Linux and has provisions for communicating, for controlling RC servo motors, lights, relays, etc., and for monitoring analog and digital input lines connected to switches, potentiometers, etc.
The p.bot systems need to be able to send and receive messages in a standard format, using the
NewSoftwareSerial? library.
Communication and Connections
We will implement the software serial functions in order to pass information between the paper robots according to a standard protocol for the whole class. Everyone will use the same pins for receiving and transmitting data (digital pin 3 and 4) at a baud rate of 9600. Each robot will have an RJ-11 jack (for 4-wire telephone cables) attached.
You may wonder, Why not use the onboard RX and TX pins for communication? The answer: the RBBB, and most of the Arduino boards (Uno, Duemillanove, Fio, Mini, etc.) have one dedicated UART connection. This means, if you want to connect an FDTI USB cable between your board and the computer for debugging, you will not be able to use the onboard RX and TX pins for transmitting and receiving data between two robots while sending data to the computer at the exact same time. The Arduino Mega 2560 on the other hand, has 4 UART ports, so multiple serial connections are possible without the use of the software serial library. However, due to cost and size restrictions, we are using the smaller, RBBB board.
In the end, your robot will have two ports that will be visible (the RJ-11) jack and a mini-USB:
- figure1_pbotconnections.png:
The mini-USB is used for debugging your robot and for programming the microprocessor. It will be connected by a USB A-mini cable to your computer. A RJ-11 crossover cable (typical for PC applications) will connect your robot to other robots. (With this setup, you are able to connect to one robot at a time.)
The RJ-11 jack has four wires, each of a different color, which you will connect to your RBBB on the robot. The wiring convention for this project is as follows:
- figure2_connection.png:
Each emotion is identified by a character (this is the easiest way to implement a switch case case statements to implement each output.)
'a' - happy
'b' - sad
'c' - excited
'd' - angry
An example program which uses the RJ-11 jack and
NewSoftSerial? library to communicate between two RBBB boards (
PushButton? - LED) can be found in the tutorials.
Input/Output
Based on an input sensor, or combination of inputs, your p.bot will communication an emotional state: happy, sad, angry, or excited. Sensors can be analog: touch sensors, pressure sensors, potentiometers, bend sensors, photoresistors, etc. or digital: switches, push buttons, photo detectors, etc. You will decide which input sensor and outputs (LEDs, servos, motors, etc.) you want to user for your robot. See the Parts List for suggested retailers.
The tutorials section contains examples of using LEDs as indicators, push-buttons and resistive force sensors as inputs, and the Servo library for controlling servo motors.
Note: To drive larger loads (DC motors, fans, etc.) which draw more than 20mA, a current regulating circuit must be used to avoid burning the pin or worse yet, the whole processor. The example p.bot includes the use of a MOSFET to drive a DC motor. There are also many Arduino compatible motor shields available to easily drive motors and switches directions. If you have experience with mechatronics, it may be easier to build your own H-bridge for the job.
Example p.bot
Here is an example robot which sends one of four possible emotions, based on the state of four input sensors, as well as responds to received emotions. This sample has one input per emotional state; yours will probably be more exciting and include a combination of states, for example, to make the robot "happy". Also, you may choose to keep "turning ON" components of your robots even when a new emotion is discovered. In this example, only one output is displayed at a time.
The input and outputs are summarized in the following table:
EMOTION INPUT (to send this emotion) Sensor Input OUTPUT (when this emotion received)
Happy Squeeze left hand. Force sensing resistor. Heart lights up.
Sad Squeeze right hand. Force sensing resistor. Wave right arm (servo).
Excited Bend forward head/neck. Flex sensor. Dances - turns in circle (dc motor).
Angry Press nose. Push-Button yes light up.
Default No wave, eyes off, heart off, not dancing.
The robot has a default button, that when pressed, will turn everything OFF, and bring it back to its "normal" state. Also, we have a "mirror" board, which includes the default switch. The mirror code is to give you an example of using the
NewSoftwareSerial? library to communicate with your robot. Right now, the mirror reads the input sent by the p.bot and sends it back. For example, when you press the robot's nose, it's eyes light up red with anger.
Materials:
* Two RBBB boards
* Two bread boards
* A FDTI USU BUB and A to mini cable (programs the boards and powers one)
* 9V adapter (or a 4 AA battery holder) with 2.1mm barrel (powers the other board)
* Two RJ-11 jacks and one 4-wire crossover cable
* 9V battery (powers DC motor)
* Alligator clips, jumper wire of assorted sizes
* Resistors: three 330, six 10K, one 3.3K
* Four LEDs
* Three push-buttons
* One MOSFET (
IRLZ34N? ) voltage regulator
* One DC motor (Jameco, 155821)
* One servo motor (Hi-Tec 322HD)
* One flex sensor
* Two force sensing resistors
Getting Started
1.) Download the Arduino IDE. Go to
http://www.arduino.cc/en/Main/Softwareand follow the installation instructions for your operating system. In Windows, there will be a folder (e.g. arduino-0021) saved in the hard disk (C:\) with an executable file which runs the sketch environment. In My Documents, the sketches (code which you program onto the microprocessor) will be saved within a folder called "Arduino". In most Linux distributions, an Arduino folder will be saved in your home directory, and the default location for saving code may point to the same folder (within a file called "sketchbook").
2.) Download the
NewSoftSerial? Library. Go to
http://arduiniana.org/libraries/newsoftserial/ and download the library files (most importantly there is one *.h and one *.cpp file) into a folder you need to create in "C:\arduino-0021\libraries\NewSoftSerial".
3.) Assemble your RBBB. See the end of the instructions document for soldering tips. Assemble the USB-BUB. Most likely, you will want to use Configuration 1.
4.) Start with some basic tutorials and learn how to write simple code in Arduino. Then, acquire some parts (LEDs, resistors, servo motors) and do some advanced tutorials. Come back to this page and try to follow some parts of the example p.bot.
There are two sketches, one is loaded on the mirror RBBB, which is also connected to a reset switch to bring the robot to a default setting, and the other is loaded on the P.bot itself. The P.bot also contains a reset switch.
Each Arduino sketch has an initialization section, a setup function, and a main loop. More examples can be found in the Tutorials section. The entire mirror and example p.bot code are saved as .pde documents in the .zip file in the Attachments section of this page. The important lines to note and circuits to build are described below.
Robot Code (ExamplePBot? _NSS)
The libraries that need to be included are the
NewSoftSerial? and the Servo library. The servo library is given in the Arduino distribution (so the sketch IDE already knows where to find the library files.)
NewSoftSerial? must be downloaded and saved in the proper directory (see the Getting Started section.) To access and use the library functions, the first lines of the code are:
#include <NewSoftSerial.h>
#include <Servo.h>
The initial #define statements are used to refer to the pin numbers associated with the different elements:
// I/O specifies input or output.
#define rxPin 3 // P.Bot receive pin.
#define txPin 4 // P.Bot transmit pin.
#define squeezeL A1 // Force sensing resistor on left hand. (Happy/I)
#define squeezeR A2 // Force sensing resistor on right hand. (Sad/I)
#define bobHead A3 // Bend resistor on neck. (Excited/I)
#define NOSE 5 // Push-button. (Angry/I)
#define HEART 8 // Large red LED. (Happy/O)
#define waveArm 9 // PWM, servo for waving left arm. (Sad/O)
#define bodyTwist 10 // DC motor, dances robot in circles. (Excited/O)
#define EYES 11 // Two eye LEDs in series. (Angry/O)
#define reset 12 // Set the robot back to normal.
All switches in this example are wired as such (the push-buttons used are "normally open"):
- switchcircuit.png:
All LEDs in the example are wired as such (where the negative cathode connects to ground):
- LEDcircuit.png:
Arduinos intrinsically can be used to drive servo motors using the PWM pins, and no extra circuitry. In the Duemilanove equivalent RBBB, servos can be connected to any of the following digital pins: 3, 5, 6, 9, 10, and 11. The black and red wires go into the common ground and 5V supply, and the yellow (or sometimes white) signal wire will connect to the digital pin of choice (in this example, it is connected to pin 9.)
The analog bend and force sensors are connected as such:
- forcesensorcircuit.png:
Driving the DC motor takes more thought. In order to drive loads that take more than 20mA, a voltage regulating
needs to be used with the motor. Alternatively, motor shields and integrated H-bridges can be bought. This is especially usefully if you want to drive multiple motors in a compact circuit. In this example circuit, the motor can only be driven in one direction, and only ON/OFF states can be controlled. (The motor shield from ladyada.net has a set of functions that can be used to change speed and direction.) The circuit used in this example is:
* dcmotorcircuit.png:
Before the void setup()function, the software serial communication and servo objects need to be initialized:
// set up a new serial port
NewSoftSerial? mySerial(rxPin, txPin);
Servo myservo; // create servo object to control a servo
Also, any additional useful variables are declared:
int pos = 0; // variable to store the servo position
// for reset button
int val = 0; //stores state of input pin
Inside the setup function, all the used pins are set as output or input pins. For example, all code will include:
// define pin modes for tx, rx:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
Another important part of the setup() function
Also, the most important communication initialization is done here. Between all p.bots, use a 9600 baud rate connection. Your debugging baud rate can be set as you choose, but make sure the Serial Monitor is connected with the same baud rate.
// initialize serial communication:
mySerial.begin(9600); //NewSoftSerial
Serial.begin(9600); //To Serial Monitor.
The main loop starts by seeing if the reset button is pressed, if so it sends a character which is not a, b, c, or d. This way, the default conditions are applied.
// If reset pin pressed, send the robot to its default position.
val = digitalRead(reset);
if (val == HIGH) {
mySerial.print(char('e')); //set state to default.
Serial.print('Default state.'); //for debugging in Serial Monitor.
Serial.println();
}
Next, activation of each sensor is checked. See the full code for all examples. The flex sensor is checked, then the "excited" character is sent based on a condition:
if (analogRead(bobHead)/4 < 50){
//neck nodded, excited
mySerial.print('c');
}
Determining the best output to work with for analog sensors may take some playing around with. The value is divided by four in this case, so that the output is an integer between 0 and 255. The condition "< 50" was based on the outputs with the given pull-down resistor (10K).
Finally, we wait to receive characters, and act accordingly. The if mySerial.available() function tells us whether or not we have established communication and characters are being sent.
// Received states. Do something in response.
if (mySerial.available()) {
Each possible p.bot output is controlled in the switch statement.
switch((char)mySerial.read()){
case 'a':
Serial.println("I'm so happy."); // To see on Serial Monitor.
digitalWrite(HEART, HIGH);
myservo.write(0);
break;
case 'b':
Serial.println("I'm so sad."); // To see on Serial Monitor.
// wave arm up and down - goodbye! ;(
myservo.attach(waveArm);
for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
myservo.detach();
break;
...
The default states are contained at the end of the switch statement.
default:
// turns everything off or back to normal.
digitalWrite(HEART, LOW);
digitalWrite(EYES, LOW);
digitalWrite(bodyTwist, LOW);
Serial.println("Normal.");
}
}
Mirror Code (
MirrorPBot? )
This board also has a reset switch connected to it. However, there are no additional sensors or actuators. This board simply reads what the example p.bot sends and sends the same message back to it.
First, the communication and pinmode setup is similar to the example p.bot:
#include <NewSoftSerial.h>
#define BUTTON 2 // connect default push-button to digital pin 2
#define rxPin 3 // everyone uses the same software serial pins
#define txPin 4
// set up a new serial port
NewSoftSerial? mySerial(rxPin, txPin);
int val = 0; // stores state of input pin
void setup()
{
pinMode(BUTTON, INPUT); // digital sensor is an input
// define pin modes for tx, rx:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
// start serial port at 9600 bps:
mySerial.begin(9600); // baud rate for software serial connection
Serial.begin(9600); // to Serial Monitor (for debugging)
}
Again, if the reset button is pressed, send the p.bot to its default state.
void loop()
{
val = digitalRead(BUTTON);
//check if the default button was pressed
if (val == HIGH) {
mySerial.print(char('e')); //set state to default
Serial.print('Default state.'); //for debugging
Serial.println();
}
Check if the soft serial communication is established. Then, read the incoming character and send the same character back.
// Receive states, and send them back.
if (mySerial.available()) {
char inByte = (char)mySerial.read();
Serial.println(inByte); // for debugging
mySerial.print(inByte);
}
}
Final Deliverable
You are expected to deliver (in your corporate teams) a p.bot that:
1.) Communicates with another p.bot in the protocol described (9600 baud rate, implementing software serial on pins 3 and 4, sending characters "a, b, c, d" and a default condition).
2.) Responds to four different states (happy, sad, angry, excited.)
3.) It is assumed that you will use the provided RBBB kit and RJ-11 4 wire connections. See the Parts List for other suggested components (which can be found in nearby vendors).