The RoboSlam robot is built in three stages. Each stage involves some circuit construction and programming to add a new feature to the robot.
Preparation
Step 0.1: Switch to Firefox
If you’re reading this in Internet Explorer, please switch to Firefox now. Copying and pasting the example programs from Internet Explorer does not work correctly.
Step 0.2: Download roboslam.zip
To use the example programs provided below to control your robot, you need a text editor called Notepad++ and a C compiler called mspgcc. We have created a zip file called "roboslam.zip" which contains both, together with some other useful tools. If you haven’t already downloaded this zip file, you should do so now:
Extract the contents of the zip file to "C:\RoboSlam\".
Stage 1: Blinking LED
In this stage, we build a very simple breadboard circuit and then copy a short example program onto the microcontroller to blink an LED on and off.
Step 1.1: Introducing the breadboard
This is the breadboard. We use it to build electronic circuits quickly without any soldering. Each of the two main sections in the centre of the breadboard consists of many short rows of five connected holes. To connect two wires or components together, just plug them into the same short row. For example, wires plugged into holes a3 and e3 will become electrically connected because they are both in the same short row.
The long red and blue lines on each side of the breadboard indicate that each of these long rows of holes is connected continuously along the full length of the board. We call these long rows “rails” and they are normally used to supply voltage to different parts of the circuit. The red rail is used for the positive supply voltage (6V in this circuit). The blue rail is normally used for the negative supply voltage (0V).
Step 1.2: Connect the battery pack
If there are batteries in your battery pack, remove at least one of them and don’t put it back until the circuit is ready to be powered up.
Connect the battery pack to the breadboard as shown below.
Step 1.3: Place the MSP430 microcontroller on the breadboard
The “brain” of the robot is the MSP430 microcontroller. A microcontroller is an entire computer on a single chip. It contains a microprocessor, RAM memory, flash memory (like in a USB memory stick) and other useful features.
Place the MSP430G2553 microcontroller in the position shown. Make sure that the end of the chip with the semi-circular indentation is in row 4.
Step 1.4: Connect a “pull-up” resistor to the reset pin
To prevent the microcontroller from accidentally resetting while the robot is running, a 22kΩ resistor (colour code: red, red, orange, gold) must be placed in the position shown below (between d4 and g8). It doesn’t matter which way around it is inserted.
Step 1.5: Connect the voltage supply to the microcontroller
To supply voltage to the MSP430 microcontroller,
- Connect a diode between the red rail on the left and hole a2. The diode is a small black cylidrical component with a silver band at one end and two metal legs. The end with the silver band must be connected to hole a2.
- Connect a green LED between hole b2 and hole b4. The LED is ever so slightly flattened on one side of its plastic body. This side is the cathode (minus leg) and must be connected to hole b4.
- Connect a black wire between the left-hand blue rail (0V) and hole 4g.
Step 1.6: Add a capacitor to stabilise the microcontroller supply voltage
- Connect a capacitor between the left-hand blue rail and hole a4. The capacitor is the small cylindrical component with two parallel legs sticking out the bottom. Note that the minus leg of the capacitor, which is marked by a long black stripe running down the body of the capacitor, must be connected to the blue rail (0V).
Step 1.7: Add an indicator LED
- Connect a green LED between holes c5 and d1. The slight flattening on one side of the LED should be on the side that is connected to hole d1.
- Connect the 270Ω resistor (colour code: red, violet, brown, gold) between the blue rail (0V) and hole b1.
Step 1.8: Connect the LaunchPad to the microcontroller
The LaunchPad is the red circuit board shown below. It is used to transfer the programs you write from the PC to the microcontroller. Connect it to the breadboard using the black, yellow and green wires as shown below.
Step 1.9: Program the microcontroller to blink the LED
It’s time to compile the first program for your microcontroller.
- Create a folder called "C:\RoboSlam\blink\".
- Copy and paste the C code below into Notepad++ and save it as the filename "main.c" in the "blink" folder.
- Copy and paste the file "build_for_g2553.bat" from the "RoboSlam" folder into the "blink" folder.
- Ask one of the workshop facilitators to check your circuit before inserting the batteries!
- Insert the batteries into your battery holder so that the microcontroller is receiving power.
- Double click the file “build_for_g2553.bat” to compile the blinking LED example and copy it onto the microcontroller, where it should start running immediately, causing the LED to blink on and off!
// // RoboSlam Example: Blinking LED // Code is for MSP430G2553 // Last updated 26-9-2014 // #include <msp430.h> // main function int main( void ) { // stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; // configure digital inputs and outputs P1OUT = 0b00000000; // set P1.0-7 low P1DIR = 0b00000001; // set P1.0 as an output // repeat the following steps indefinitely while(1) { // LED on for 1 second P1OUT = 0b00000001; __delay_cycles(1000000); // LED off for 1 second P1OUT = 0b00000000; __delay_cycles(1000000); } return 0; }
Stage 2: Motor control
Step 2.1: Add the SN754410NE driver chip
- Remove at least one battery from the battery holder to power down the robot.
- Add the SN754410NE driver chip to the breadboard as shown below. The end of the chip with the semi-circuitar indentation must be in row 21.
Step 2.2: Connect the voltage supply to the driver chip
Add the supply voltage connections shown below:
- A red wire between the left-hand red rail (6V) and hole a28.
- A black wire between the left-hand blue rail (0V) and hole a25.
- A red wire between holes d28 and g21.
Step 2.3: Add a capacitor to the supply rails to reduce motor interference
Add a 220uF capacitor between the left-hand red (6V) and blue (0V) rails as shown below. Note that the negative leg of the capacitor, which is marked by the long black stripe down the side of its cylindrical body, must be connected to the blue rail (0V).
Step 2.4: Connect the microcontroller to the driver chip
Add the connections shown below. These allow the microcontroller to send signals to the driver chip to control the motors:
- A purple wire between holes 11d and 27d.
- A purple wire between holes 12d and 22d.
- A blue wire between holes 13d and 21d.
- A blue wire between holes 11g and 28g.
- A purple wire between holes 12g and 27g.
- A purple wire between holes 13g and 22g.
Step 2.5: Connect the motors to the driver chip
- Connect the left motor to holes 23h and 26h
- Connect the right motor to holes 23b and 26b
Step 2.6: Program the microcontroller to control the motors
- Create another new folder called "C:\RoboSlam\zigzag\".
- Copy and paste the code below into a new file in Notepad++ and save it as filename "main.c" in the "zigzag" folder.
- Copy and paste the file "build_for_g2553.bat" from the "RoboSlam" folder into the "zigzag" folder.
- Ask one of the workshop facilitators to check your circuit before inserting the batteries!
- Insert the batteries into your battery holder so that the microcontroller is receiving power.
- Double click the file “build_for_g2553.bat” to compile the zigzag example program and copy it onto the microcontroller, where it should immediately start running, causing the motors to move.
- Disconnect the robot from the LaunchPad and it should drive along the floor in a zigzag pattern.
// // RoboSlam Example: Driving ZigZag // Code is for MSP430G2553 // Last updated 26-9-2014 // #include <msp430.h> // function prototypes void setup(); void set_motors(int left_speed, int right_speed); // main function int main( void ) { // call setup function to configure microcontroller setup(); // repeat the following steps indefinitely while(1) { // forward for 1 second set_motors(100, 100); __delay_cycles(1000000); // turn left for 0.5 seconds set_motors(-100, 100); __delay_cycles(500000); // forward for 1 second set_motors(100, 100); __delay_cycles(1000000); // turn right for 0.5 seconds set_motors(100, -100); __delay_cycles(500000); } return 0; } // // This function configures the microcontroller. It disables the // watchdog timer, configures digital i/o, sets up Timer_A0 for // measuring the duration of the rangefinder echo pulse, sets up // Timer_A1 for motor PWM, and enables the internal pull up // resistor on digital input P1.6. // void setup() { // stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; // configure digital inputs and outputs P1OUT = 0b00000000; // set P1.0-7 low P1DIR = 0b10000001; // set P1.0, P1.7 as outputs P2OUT = 0b00000000; // set P2.0-7 low P2SEL = 0b00100100; // set pin 10 as TA1.1, pin 13 as TA1.2 P2DIR = 0b00111111; // set P2.0-5 as outputs // configure Timer_A1 for motor PWM (for speed control) TA1CTL = TASSEL_2 + ID_0 + MC_1; // Timer_A1: SMCLK clock, input divider=1, "up" mode TA1CCR0 = 1000; // set Timer_A1 period to 1ms for 1kHz PWM TA1CCR1 = 1000; // 100% duty cycle initially TA1CCR2 = 1000; // 100% duty cycle initially TA1CCTL1 = OUTMOD_7; // select "Reset/Set" output mode TA1CCTL2 = OUTMOD_7; // select "Reset/Set" output mode } // // This function sets the speed and direction of both motors. The // first argument controls the left motor. The second argument // controls the right motor. Each argument can be any integer between // -100 and +100, where -100 is full speed reverse. +100 is full speed // forwards. // void set_motors(int left_speed, int right_speed) { // work out P2OUT value for requested directions int p2out_value = 0; if (left_speed > 0) p2out_value += 0b00000001; if (left_speed < 0) p2out_value += 0b00000010; if (right_speed > 0) p2out_value += 0b00001000; if (right_speed < 0) p2out_value += 0b00010000; // clamp motor speed to allowed range if (left_speed > 100) left_speed = 100; if (left_speed < -100) left_speed = -100; if (right_speed > 100) right_speed = 100; if (right_speed < -100) right_speed = -100; // set motor directions and speeds P2OUT = p2out_value; TA1CCR1 = 10 * left_speed; TA1CCR2 = 10 * right_speed; }
Stage 3: Rangefinder
Step 3.1: Add the rangefinder and connect it to the microcontroller
The rangefinder is an ultrasonic distance sensor.
- Add the rangefinder to the breadboard in the position shown (holes 14j, 15j, 16j and 17j).
- Connect a red wire from the left-hand red rail (6V) to hole 17h.
- Connect a black wire from the left-hand blue rail (0V) to hole 14h.
- Connect a diode between holes 15i and 10h. The end of the diode marked with a silver band must be connected to hole 15i.
- Connect a blue wire between holes 9h and 16i.
Step 3.4: Program the microcontroller to navigate using the rangefinder
// // RoboSlam Example: Rangefinder navigation // Code is for MSP430G2553 // Last updated 26-9-2014 // #include <msp430.h> // function prototypes void setup(); void set_motors(int left_speed, int right_speed); int get_distance(); // main function int main( void ) { // call setup function to configure microcontroller setup(); // implement robot behaviour while(1) { __delay_cycles(50000); // is distance greater than 500mm? if (get_distance() > 500) { // yes, so turn around looking for enemy set_motors(50,-50); } else { // no, so enemy is straight ahead set_motors(100,100); } } return 0; } // // This function configures the microcontroller. It disables the // watchdog timer, configures digital i/o, sets up Timer_A0 for // measuring the duration of the rangefinder echo pulse, sets up // Timer_A1 for motor PWM, and enables the internal pull up // resistor on digital input P1.6. // void setup() { // stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; // configure digital inputs and outputs P1OUT = 0b00000000; // set P1.0-7 low P1DIR = 0b10000001; // set P1.0, P1.7 as outputs P2OUT = 0b00000000; // set P2.0-7 low P2SEL = 0b00100100; // set pin 10 as TA1.1, pin 13 as TA1.2 P2DIR = 0b00111111; // set P2.0-5 as outputs // configure Timer_A1 for motor PWM TA1CTL = TASSEL_2 + ID_0 + MC_1; // Timer_A1: SMCLK clock, input divider=1, "up" mode TA1CCR0 = 1000; // set Timer_A1 period to 1ms for 1kHz PWM TA1CCR1 = 1000; // 100% duty cycle initially TA1CCR2 = 1000; // 100% duty cycle initially TA1CCTL1 = OUTMOD_7; // select "Reset/Set" output mode TA1CCTL2 = OUTMOD_7; // select "Reset/Set" output mode // configure Timer_A0 for measuring rangefinder echo pulse // select SMCLK clock, input divider=1, "continuous" mode TA0CTL = TASSEL_2 + ID_0 + MC_2; // enable pull up resistor on P1.6 for rangefinder echo P1OUT |= BIT6; P1REN |= BIT6; } // // This function sets the speed and direction of both motors. The // first argument controls the left motor. The second argument // controls the right motor. Each argument can be any integer between // -100 and +100, where -100 is full speed reverse. +100 is full speed // forwards. // void set_motors(int left_speed, int right_speed) { // work out P2OUT value for requested directions int p2out_value = 0; if (left_speed > 0) p2out_value += 0b00000001; if (left_speed < 0) p2out_value += 0b00000010; if (right_speed > 0) p2out_value += 0b00001000; if (right_speed < 0) p2out_value += 0b00010000; // clamp motor speed to allowed range if (left_speed > 100) left_speed = 100; if (left_speed < -100) left_speed = -100; if (right_speed > 100) right_speed = 100; if (right_speed < -100) right_speed = -100; // set motor directions and speeds P2OUT = p2out_value; TA1CCR1 = 10 * left_speed; TA1CCR2 = 10 * right_speed; } // // This function measures the distance in mm to the nearest object // using the rangefinder. // int get_distance() { // send trigger pulse P1OUT |= BIT7; __delay_cycles(20); P1OUT &= ~BIT7; // measure echo pulse duration TA0CTL |= TACLR; // reset timer while ((P1IN & BIT6) == 0 && TA0R < 12000); // wait for start of echo pulse TA0CTL |= TACLR; // reset timer while ((P1IN & BIT6) > 0 && TA0R < 12000); // wait for end of echo pulse return (TA0R / 6); // return the distance in mm }