PArduino - An Arduino-based 2WD Robot
I'm pleased to show you PArduino, my first Arduino-based Robot!
It's a 2 wheel drive robot, remotly controlled (Bluetooth) by smartphone: you can use your touchscreen or your voice! And it also support an autopilot mode!
Here is the list of its components (maybe, and I say maybe, one day I'll draw a Fritzing sketch of it!):
- 1 Arduino Uno R3
- 1 plexiglass chassis
- 2 small DC motors with gearboxes and rubber wheels
- 2 buck-boost adjustable voltage regulators Pololu S7V8A
- 1 H-bridge motor drive L293DNE
- 1 Bluetooth module HC-05
- 1 ultrasound sensor HC-SR04
- 1 big yellow LED
- 1 4AA battery holder
- 1 220 ohm resistor
- 2 100 uF capacitors
- 1 piezo buzz
- 1 small breadboard
- 1 smaller breadboard
- many jumpers and cables
- some other less important things to assemble everything
Here it is the "PArduino Remote Control", the Android app I created to control the robot! It's made with the MIT App Inventor online development environment:
Here you can find the Arduino code: take it "as is", it works, and I know it could work better and be more easy-to-read...Some code is made by me, some code is taken from the web and revisited to my project, so I hope no one will take offence about its publication here: in case, let me know!
#include <SoftwareSerial.h> // nota:le icone app sono caribbean blue www.iconsdb.com SoftwareSerial Pasquale(7, 8); // RX, TX int motor1Pin1 = 4; int motor1Pin2 = 2; int motor2Pin1 = 6; int motor2Pin2 = 5; int pinluce = 13; //int pinclacson=3; int pintrig = 9; int pinecho = 10; int distmin=25; int direzione=1; unsigned long tlastsceltadir; unsigned long tlastdir; long durata; long distanza; int comando; int forzastop=0; int statoluce=0; int statoauto=0; //RTTTL #define OCTAVE_OFFSET 0 #define TONE_PIN 3 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 int notes[] = { 0, NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5, NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6, NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7 }; //char *song = "The Simpsons:d=4,o=5,b=160:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6"; //char *song = "Indiana:d=4,o=5,b=250:e,8p,8f,8g,8p,1c6,8p.,d,8p,8e,1f,p.,g,8p,8a,8b,8p,1f6,p,a,8p,8b,2c6,2d6,2e6,e,8p,8f,8g,8p,1c6,p,d6,8p,8e6,1f.6,g,8p,8g,e.6,8p,d6,8p,8g,e.6,8p,d6,8p,8g,f.6,8p,e6,8p,8d6,2c6"; char *song1 = "IndianaLITE:d=4,o=5,b=250:e,8p,8f,8g,8p,1c6,8p.,d,8p,8e,1f"; //char *song = "Entertainer:d=4,o=5,b=140:8d,8d#,8e,c6,8e,c6,8e,2c.6,8c6,8d6,8d#6,8e6,8c6,8d6,e6,8b,d6,2c6,p,8d,8d#,8e,c6,8e,c6,8e,2c.6,8p,8a,8g,8f#,8a,8c6,e6,8d6,8c6,8a,2d6"; //char *song = "Looney:d=4,o=5,b=140:32p,c6,8f6,8e6,8d6,8c6,a.,8c6,8f6,8e6,8d6,8d#6,e.6,8e6,8e6,8c6,8d6,8c6,8e6,8c6,8d6,8a,8c6,8g,8a#,8a,8f"; //char *song = "Bond:d=4,o=5,b=80:32p,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d#6,16d#6,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d6,16c#6,16c#7,c.7,16g#6,16f#6,g#.6"; //char *song = "StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6"; //char *song = "GoodBad:d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#"; //char *song = "TopGun:d=4,o=4,b=31:32p,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,16f,d#,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,g#"; //char *song = "Flinstones:d=4,o=5,b=40:32p,16f6,16a#,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,d6,16f6,16a#.,16a#6,32g6,16f6,16a#.,32f6,32f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,a#,16a6,16d.6,16a#6,32a6,32a6,32g6,32f#6,32a6,8g6,16g6,16c.6,32a6,32a6,32g6,32g6,32f6,32e6,32g6,8f6,16f6,16a#.,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#6,16c7,8a#.6"; //char *song = "MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,4d#,8d#."; //char *song = "MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d"; //char *song = "KnightRider:d=4,o=5,b=125:16e,16p,16f,16e,16e,16p,16e,16e,16f,16e,16e,16e,16d#,16e,16e,16e,16e,16p,16f,16e,16e,16p,16f,16e,16f,16e,16e,16e,16d#,16e,16e,16e,16d,16p,16e,16d,16d,16p,16e,16d,16e,16d,16d,16d,16c,16d,16d,16d,16d,16p,16e,16d,16d,16p,16e,16d,16e,16d,16d,16d,16c,16d,16d,16d"; char *song2 = "PoliceP:d=4,o=6,b=140:8e,8c,8e,8c"; char *song = "Metallica:d=4,o=6,b=150:16e,16e,p,8p,8d,8c#,2c,16e5,16e5,16e,16e5,16e5,16e,16e5,16e5,8d,8c#,c,16e5,16e5,16e,16e5,16e5,16e,16e5,16e5,8d,8c#,8c,8b5,16e5,16e5,16e,16e5,16e5,16f,16e5,16e5,16f#,16e5,16e5,16f#,16e5,16e5,8f"; #define isdigit(n) (n >= '0' && n <= '9') //fine RTTTL void setup() { pinMode(pinluce,OUTPUT); digitalWrite(pinluce,LOW); pinMode(motor1Pin1, OUTPUT); pinMode(motor1Pin2, OUTPUT); pinMode(motor2Pin1, OUTPUT); pinMode(motor2Pin2, OUTPUT); pinMode(pintrig, OUTPUT); pinMode(pinecho, INPUT); digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); Pasquale.begin(9600); } void loop() { if(Pasquale.available()){ comando = Pasquale.read(); } if (comando == '0') { if(statoauto==0){ play_rtttl(song1); } statoauto=1; automatico(); } else if (comando == '1') { statoauto=0; avanti(); } else if (comando == '2') { statoauto=0; sinistra(); } else if (comando == '3' || forzastop==1) { statoauto=0; fermo(); } else if (comando == '4') { statoauto=0; destra(); } else if (comando == '5') { statoauto=0; indietro(); } else if (comando == '6') { statoauto=0; luce(); } else if (comando == '7') { statoauto=0; clacson(); } else if (comando == '8') { statoauto=0; avantistop(); } else if (comando == '9') { statoauto=0; indietrostop(); } else if (comando == ':') { statoauto=0; destrastop(); } else if (comando == ';') { statoauto=0; sinistrastop(); } delay(100); } void avanti(){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); } void avantistop(){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); delay(1000); comando=3; forzastop=1; } void indietro(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); digitalWrite(motor2Pin1, HIGH); digitalWrite(motor2Pin2, LOW); } void indietrostop(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); digitalWrite(motor2Pin1, HIGH); digitalWrite(motor2Pin2, LOW); delay(1000); comando=3; forzastop=1; } void destra(){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); } void destrastop(){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); delay(350); comando=3; forzastop=1; } void destraauto(int t){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); delay(t); fermo(); } void sinistra(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); } void sinistrastop(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); delay(350); comando=3; forzastop=1; } void sinistraauto(int t){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); delay(t); fermo(); } void fermo(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); forzastop=0; } void luce(){ if (statoluce == 0){ digitalWrite(pinluce,HIGH); comando=3; forzastop=1; statoluce=1; } else{ digitalWrite(pinluce,LOW); comando=3; forzastop=1; statoluce=0; } } void clacson(){ fermo(); play_rtttl(song); comando=3; forzastop=1; } void automatico(){ //vuoto = analogRead(A0); //if(vuoto>900){ // indietro(); // delay(1000); // fermo(); // delay(1); //} //else{ digitalWrite(pintrig, LOW); delayMicroseconds(2); digitalWrite(pintrig, HIGH); delayMicroseconds(10); digitalWrite(pintrig, LOW); durata = pulseIn(pinecho, HIGH); distanza = durata/58.2; //cm if(millis()-tlastsceltadir > 10000){ direzione=random(1,100); tlastsceltadir=millis(); } if (distanza >= distmin){ if (millis()-tlastdir > 10000){ fermo(); indietro(); delay(500); fermo(); if(direzione>50){ destraauto(200); } else{ sinistraauto(200); } fermo(); avanti(); tlastdir=millis(); } else{ avanti(); } } else { tlastdir=millis(); fermo(); play_rtttl(song2); delay(100); indietro(); delay(500); if(direzione>50){ fermo(); destraauto(350); } else{ fermo(); sinistraauto(350); } } delay(50); //} } void play_rtttl(char *p) { // Absolutely no error checking in here byte default_dur = 4; byte default_oct = 6; int bpm = 63; int num; long wholenote; long duration; byte note; byte scale; // format: d=N,o=N,b=NNN: // find the start (skip name, etc) while(*p != ':') p++; // ignore name p++; // skip ':' // get default duration if(*p == 'd') { p++; p++; // skip "d=" num = 0; while(isdigit(*p)) { num = (num * 10) + (*p++ - '0'); } if(num > 0) default_dur = num; p++; // skip comma } // get default octave if(*p == 'o') { p++; p++; // skip "o=" num = *p++ - '0'; if(num >= 3 && num <=7) default_oct = num; p++; // skip comma } // get BPM if(*p == 'b') { p++; p++; // skip "b=" num = 0; while(isdigit(*p)) { num = (num * 10) + (*p++ - '0'); } bpm = num; p++; // skip colon } // BPM usually expresses the number of quarter notes per minute wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) // now begin note loop while(*p) { // first, get note duration, if available num = 0; while(isdigit(*p)) { num = (num * 10) + (*p++ - '0'); } if(num) duration = wholenote / num; else duration = wholenote / default_dur; // we will need to check if we are a dotted note after // now get the note note = 0; switch(*p) { case 'c': note = 1; break; case 'd': note = 3; break; case 'e': note = 5; break; case 'f': note = 6; break; case 'g': note = 8; break; case 'a': note = 10; break; case 'b': note = 12; break; case 'p': default: note = 0; } p++; // now, get optional '#' sharp if(*p == '#') { note++; p++; } // now, get optional '.' dotted note if(*p == '.') { duration += duration/2; p++; } // now, get scale if(isdigit(*p)) { scale = *p - '0'; p++; } else { scale = default_oct; } scale += OCTAVE_OFFSET; if(*p == ',') p++; // skip comma for next note (or we may be at the end) // now play the note if(note) { tone(TONE_PIN, notes[(scale - 4) * 12 + note]); digitalWrite(pinluce,HIGH); delay(duration*0.75); digitalWrite(pinluce,LOW); delay(duration*0.25); noTone(TONE_PIN); } else { delay(duration); } } }
And finally, see it in action! In the first video, you can see how speech recognition works. In the second video, you can see a demo of the autopilot mode. Finally, in the third video an experimental attempt to make PArduino become a tiny rover! Enjoy!
Here you can find the source files: