Session 2: Programming Dave Pelowitz pelowitz@pelowitz.com Tim Hamlin tim.hamlin@gmail.com Overview Roughly three months of 3 to 5 hours per week for all this material. Help people get the programming environment installed and working on their system, Load a simple program and run it (“blink” from the examples provided), with some discussion of the code (line by line), Discussion on what the arduino is, including input and output capability, Some discussion on what the C programming language is, Write/load/run the simple edge trigger software enabling the minisumobot to run around on a competition field without going off the edge, Discuss what inputs/outputs are available for other sensors (opponent, rear sensor, side sensors, etc.), Overview next class/meeting. Programming Environment www.arduino.cc/download UI to convert C to machine High level vs Machine Interpreted vs Compiled Elements of the UI Menu Icons Edit window Set Board and Port Uno Plug in USB to Uno and Computer Port (dependent on system) Programming Environment (cont) ICONS Verify -- Checks your code for errors. Upload -- Compiles your code and uploads it to the Arduino I/O board. See uploading below for details. New -- Creates a new sketch. Open -- Presents a menu of all the sketches in your sketchbook. Clicking one will open it within the current window. Save -- Saves your sketch. Serial Monitor -- Opens the serial monitor. Simple Program Load blink into UI (file / examples / basics / blink) Compile and Upload into your arduino Simple Program (cont.) Verify led is flashing Modify to print “on” and “off” Serial.begin(9600) in setup(); Serial.println(“on”); after line with HIGH and Serial.println(“off”); after line with LOW Leave off one of the “;” Compile without loading into Arduino Fix the error Compile and load into Arduino Open “Serial Monitor” Watch for “on” and “off” messages The Arduino 8 bit Micro-controller Arduino can sense the environment by receiving input from a variety of sensors and can affect its surroundings by controlling lights, motors, and other actuators. The microcontroller on the board is programmed using the Arduino programming language (based on Wiring) and the Arduino development environment (based on Processing). Arduino projects can be stand-alone or they can communicate with software running on a computer (e.g. Flash, Processing, MaxMSP). ATmega328P, 32K bytes FLASH, 1K bytes EEPROM, 2K bytes RAM. Sketches (programs) and Shields (physical add-on/plug-ins) The Arduino Uno http://arduino.cc/en/Main/ ArduinoBoardUno Input and Outputs Digital: 0-13 Analog: A0-A5 (10b gnd-5v) Special Uses 0,1: Serial Communications 2,3: External Interrupts 3,5,6,9,10,11: PWM A4,A5: I2C 10,11,12,13: SPI 13: LED Used by Mini-SumoBot 3: buzzer 7: right motor direction 8: left motor direction 9: right motor PWM 10: left motor PWM 12: user push button A1: optional battery level 4,5,11,A0,A2,A3: Reflectance(edge sensor) Arduino Shields Ethernet, WIFI, Motor, WIFI, Touch Screen, GPS… www.arduino.cc, www.adafruit.com, www.pololu.com, www.sparkfun.com, … C Programming Language “The C Programming Language”, Brian W. Kernighan, Dennis M. Ritchie General Purpose programming language Algebraic language: a=b+c, sqrt((a*a) + (b*b)), c=(5/9)(F-32) Comments: /* this is a comment */ and //this is a comment http://arduino.cc/en/Reference/HomePage Variables Symbolic Constants (manifest constants): #define LOWER 0 #define UPPER 300 #define STEP 20 Arrays What is a variable—a reference to a memory location (little endian). Type: void, boolean, char, unsigned char, byte, int, unsigned int, word, long unsigned long, short, float, double, string, String, array, Scope: local, function, global, block {} Form: case sensitive a != A, must start with a letter, no white space, no “special” characters. ALL variables must be declared! int a[100] char[16] Reference by value or by reference/de-reference myInt &myInt *myInt C Programming Language (cont) Expression: grammer Unary operators: * & - ! ~ prefix++ prefix-- postfix++ postfix--, (type name)exp, sizeof exp, sizeof(type-name) Monadic and Dyadic Binary operators: * / % + - << >> < > <= >= == != & ^ | && || Conditional: expressionA ? expressionB : expressionC Assignment: = += -= *= /= %= >>= <<= &= ^= |= Statements Form: “expression;” {} Assignment: int myInt = 0; myInt += 3; myInt = myInt + 3; Precedence and Associativity (order of evaluation) 3*a/b C Programming Language (cont) Precedence and Associativity (order of evaluation) 3*a/b What if a is near max int? Consider 3*(a/b) Operator Associativity () [] -> . Left to right ! ~ ++ -- - (type) * & sizeof Right to left */% Left to right +- Left to right << >> Left to right == != Left to right & Left to right ^ Left to right | Left to right && Left to right || Left to right ?: Left to right = += -= etc. Right to left , Left to right C Programming Language (cont) Statements (cont) if (expression) statement; if (myInt == 5) Serial.print(“myInt equals 5”); if (expression) statement else statement if (myInt != 5) Serial.println(“myInt is not equal to five”); else Serial.println(“myInt is equal to five”); while (expression) statement while (j < 10) {Serial.println(j); ++j;} do statement while (expression); do j++; while (j < 10); do { Serial.println(j); ++j; } while (j < 10); do Serial.println(j++); while (j < 10); for (expressionAopt; expressionBopt; expressionCopt) statement; For (j=10,k=100; j>=0; j--){k++;Serial.print(j);Serial.print(“:”);Serial.println(k}; C Programming Language (cont) Statements (cont) switch (expression) statement and case constant-expression: switch (i+k+k) { case 0: Serial.println(“is zero”); break; case 1: case 2: Serial.println(“is either one or two”);break; default: Serial.println(“no idea other than is not 0, 1, or 2”); } continue; jumps to the end of while, do, or for loops goto identifier; identifier: (warning: leads to spaghetti code) return; or return expression; C Programming Language (cont) Functions In classic c there will be a main() void setup() void loop() To create a function… ret.type functionName(optional list of type var name ) int printMessage(int iRepeat, char* myMessage) { if (iRepeat < 1) return -1; for (int i=0; i<iRepeat; i++) Println(myMessage) return 0; } To call the function… printMessage(10, “this is my message”); C Programming Language (cont) Common errors… “if (a=b)...” instead of “if (a==b)…”. “a=b” or “myFunction(b)” without setting b to a value. myFunction(a) instead of (myFunction(&a) when the function needs to change the value stored at a. Infinite loop—there are lots of forms. for (unsigned int uI=0; uI==-1; uI++){…} or for(;;) or while(true){} or … Scope errors: e.g. variable with same name in and out of a block: int i = 5; { int i = 6; println(i);} println(i); Missing { or } or both char szString[16]; then trying to put 16 chars into it and then using it as a string. All “strings” terminate with zero byte. Where char szString[n] trying to index from 1 instead of 0 C Programming Language (cont) Good Practices… Comments “header” Inline Indentation Not needed for C but helps prevent errors and understand code Consistency {} placement of open (see next slide) Variable Names Hungarian notation (there are many other styles too) Scope_TypeName: g_uiTimeToComplete global unsigned int m_fTimeToComplete class member float szTimeToComplete local array of character Arduino Blink Example Revisited /* Blink Turns on an LED on for one second, then off for one second, repeatedly. This example code is in the public domain. */ // Pin 13 has an LED connected on most Arduino boards. // give it a name: int led = 13; // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } ZumoBot BorderDetect Software Load the Pololu Zumo Shield libraries https://github.com/pololu/zumo-shield or http://www.pelowitz.com/zumo-shield-master.zip Download the archive from one of the sites above, decompress it, and move each library folder (Pushbutton, QTRSensors, ZumoBuzzer, ZumoExamples, ZumoMotors, and ZumoReflectanceSensorArray) into the “libraries” subdirectory inside your Arduino sketchbook directory. You can view your sketchbook location by selecting File→Preferences in the Arduino environment; if there is not already a “libraries” folder in that location, you should create it yourself. After installing the library, restart the Arduino environment so it can find the Zumo Shield libraries and their examples. ZumoBot BorderDetect Software void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); } #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); } void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } ZumoBot BorderDetect Software #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 } void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } ZumoBot BorderDetect Software #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } } void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } ZumoBot BorderDetect Software void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); } #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); } void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } ZumoBot BorderDetect Software void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); } if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } ZumoBot BorderDetect Software else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } #include <ZumoBuzzer.h> #include <ZumoMotors.h> #include <Pushbutton.h> #include <QTRSensors.h> #include <ZumoReflectanceSensorArray.h> #define LED 13 // this might need to be tuned for different lighting conditions, surfaces, etc. #define QTR_THRESHOLD 1500 // microseconds // these might need to be tuned for different motor types #define REVERSE_SPEED 200 // 0 is stopped, 400 is full speed #define TURN_SPEED 200 #define FORWARD_SPEED 200 #define REVERSE_DURATION 200 // ms #define TURN_DURATION 400 // ms ZumoBuzzer buzzer; ZumoMotors motors; Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12 #define NUM_SENSORS 6 unsigned int sensor_values[NUM_SENSORS]; ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN); void waitForButtonAndCountDown() { digitalWrite(LED, HIGH); button.waitForButton(); digitalWrite(LED, LOW); // play audible countdown for (int i = 0; i < 3; i++) { delay(1000); buzzer.playNote(NOTE_G(3), 200, 15); } delay(1000); buzzer.playNote(NOTE_G(4), 500, 15); delay(1000); } void setup() { // uncomment if necessary to correct motor directions //motors.flipLeftMotor(true); //motors.flipRightMotor(true); pinMode(LED, HIGH); waitForButtonAndCountDown(); } void loop() { if (button.isPressed()) { // if button is pressed, stop and wait for another press to go again motors.setSpeeds(0, 0); button.waitForRelease(); waitForButtonAndCountDown(); } sensors.read(sensor_values); if (sensor_values[0] < QTR_THRESHOLD) { // if leftmost sensor detects line, reverse and turn to the right motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(TURN_SPEED, -TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else if (sensor_values[5] < QTR_THRESHOLD) { // if rightmost sensor detects line, reverse and turn to the left motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED); delay(200); motors.setSpeeds(-TURN_SPEED, TURN_SPEED); delay(300); motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } else { // otherwise, go straight motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED); } } Next Session Mechanically adding sensors and other stuff Side Rear Modifying the program for the new sensors Available arduino inputs Where in the code Optimizing the code Float vs Int, * vs /, use of arrays[], use of delay() Implementing priorities by how you organize the code Using the runtime clock instead of delay() function New strategies for a winning bot. The sky’s the limit within 500 grams and 10 x 10 cm.