Jose Romaní
Published © GPL3+

Three robotic bat cars in unison

An instructor says the drills voice commands and two or more sportswomen follow. It also plays music recorded in a SD card through a speaker

ExpertShowcase (no instructions)427
Three robotic bat cars in unison

Things used in this project

Hardware components

smart bat car robot
×3
DSD TECH HM-10 Bluetooth 4.0 BLE
×4
Mini MP3 Player DFPlayer Master Module
×1
Flash memory SD card 32G
×1
Speaker 3W
×1
Amazon Web Services ProtoShield
×1
USB to serial TTL cable
×1

Software apps and online services

MIT App Inventor
MIT App Inventor
Arduino IDE
Arduino IDE
Audacity
For editing sound
facebook
to download free music (see creator tools)

Hand tools and fabrication machines

screwdriver
the one which comes with the Smart Robot Cars

Story

Read more

Schematics

mp3sketch_x3jQRuwF25.fzz

Code

Instructor-sportswomen robots

Arduino
/* Title: INSTRUCTOR-SPORTSWOMAN (MONITOR-DEPORTISTA FEMENINA)
 * Voice, songs, movements advertised. MP3 player + SD
 * Valid for a series of BAT CAR robots connected by bluetooth. Change only the MACs
 * Configuere also where you find  the simbol ◄
 * Includes anofficial Real Madrid's melody (of basketball)
 * Spirals and circles
 * Reprogrammed and improved by engineer Jose Romaní. Vigo, Septiembre 2019.
 * Based on a BAT CAR robot manufactured by a detached chinese company.
 * Special buzzer melody for final stop and other modes
 * This code does not permit remote control by buttons through infrared
 */

//============================================================================
//  Comprehensive Experiment
//=============================================================================
//#include "./IRremote.h"
//==========================================
#include <SoftwareSerial.h> //first slave (peripheral) HC-06 or HM-10(BLE) of each robot
const int RX = 13; //excepcionally changed the usual order and number of pins
const int TX = 12;
SoftwareSerial Monitor(RX, TX); //"Monitor" in Spanish. "Instructor" in English
//==============================================
//for connect a robot to the following. Slave modules HM-10
String MAC_sportswoman = "606405CFC91F"; //◄ modify if necessary
//first slave (second robot) MAC "606405CFC91F", second slave (third robot): "90E2028DCE49" ) 
//Change depending on the slave (peripheral) module

unsigned int Connected = 3; //◄ = 1  Modify if necessary
//Put Connected = 3 in case of last robot of the group (not connected to another robot)
//===========================================================
//MP3
bool speaker = false; //◄ true, "speaker = false;" if the robot does not have a MP3 player
#include <DFRobotDFPlayerMini.h> //if there is not a MP3 player , is not necessary this line
SoftwareSerial serialMP3(SDA, SCL); //if there is not a MP3 player, is not necessary this line
DFRobotDFPlayerMini playerMP3; //if there is not a MP3 player, is not necessary this line
int music = 1; //for playing the first song
unsigned int volume = 30;  //0-30
//===========================================================
#define run_car        '1'
#define back_car       '2'
#define left_car       '3'
#define right_car      '4'
#define stop_car       '0'
#define back_left_car  '5'
#define back_right_car '6' 
#define circles        '7' //for potencimetre

//==============================
//Car running status enumeration
//==============================
enum {
  enSTOP = 0,
  enRUN,
  enBACK,
  enLEFT,
  enRIGHT,
  enTLEFT,
  enTRIGHT,
  enBACK_LEFT,
  enBACK_RIGHT,
  enCIRCLES //for potenciometre
} enCarState;

//==============================
//Speed control
//==============================
int control = 175;//PWM control speed

//==============================
//Set motor port
//==============================
int Left_motor_back = 9; 
int Left_motor_go = 5; 
int Right_motor_go = 6; 
int Right_motor_back = 10; 
int Right_motor_en = 8; 
int Left_motor_en = 7; 

//==============================
//Bluetooth protocol related
//==============================
int incomingByte = 0;       // Store Received Data(byte)
String inputString = "";         // Store Received Data(String)
boolean newLineReceived = false; // Previous data end flag
boolean startBit  = false;  // Protocol start flag
String returntemp = ""; // Store return data

/*Set BUZZER port*/
int BUZZER = 3;
int buzzerState = HIGH; // set the BUZZER (mute)
                        // Generally, you should use "unsigned long" for variables that hold time
                        // The value will quickly become too large for an int to store
unsigned long previousMillis = 0;   // (me)will store last time back buzzer was updated
                                    // constants won't change:
const long intervalBack = 50;  // interval at which back buzzer sounds (milliseconds)
const long intervalOff = 200;  // interval buzzer is off (milliseconds)
boolean atras = false;   // indicates the robot has gone towards back
#include "Buzzer.h" //include buzzer sounds
Buzzer buzzer(BUZZER); //buzzer object


/*Set LED port*/
int LED = 11;  // Show Bluetooth Remote Control(light on)

/*Ultrasonic Sensor*/
int Echo = A1;  // Set Echo port
int Trig = A0;  // Set Trig port
int Distance = 0;

/*Line Walking*/
const int SensorRight = A3;   	// Set Right Line Walking Infrared sensor port
const int SensorLeft = A2;     	// Set Left Line Walking Infrared sensor port
int SL;    // State of Left Line Walking Infrared sensor
int SR;    // State of Right Line Walking Infrared sensor

//State
int g_carstate = enSTOP; //  1:front 2:back 3:left 4:right 0:stop // State of vehicle running state
int g_modeSelect = 0;  // 0:remote control mode(default); 1:line walking mode ; 2: obstacle avoidance mode; 3: tracking
int g_AllState = 0;  // 0:Busy, 1:Mode selection 

/*Format string initialization*/ //Valora si borrar estas dos funiciones
int serial_putc( char c, struct __file * )
{
  Serial.write( c );
  return c;
}

void printf_begin(void)
{
  fdevopen( &serial_putc, 0 );
}

//----------------------------------------------------------------
//prepares for a connection and once the second module is on, connects automatically
void connect2Modules() //HM-10s
{
while (Connected == 1) //Wait till answare is ok. 
  {
    Monitor.print("AT");
    delay(100); //change delay according to response speed
    if (Monitor.available())
    {
      String resp1 = Monitor.readString();
      if (resp1.equals("OK"))
        Connected = 2;
    }
  }
while (Connected == 2)
  {
    Monitor.print("AT+CON" + MAC_sportswoman); //Connect HM-10 central to HM-10 peripheral MAC
    delay(100); //Wait for the response
    if (Monitor.available())
    {
      String resp2 = Monitor.readString(); //Read response
      if (resp2.equals("OK+CONNA"))
        Connected = 3; 
    }
  } 
}
//-----------------------------------------------------------------

void setup()
{ 
  //set a slave bluetooth module (managed by the app, or by another master for 2º,3º,etc robot) on this serial port
  Serial.begin(115200);  // Set Bluetooth baud rate. Must match the one of the module
  //HC-06 or HM-10. They have to be set up to 115200 baud rate

  analogReference(DEFAULT); //to 5 volts. To use as 5V output. This is not a normal use
  
  //Initialize MP3
  if (speaker) serialMP3.begin(9600); //inicializes softwareserial with the MP3 player
  if (speaker) playerMP3.begin(serialMP3); //inicialices the object player
  if (speaker) playerMP3.volume(volume); //0 to 30
  if (speaker) playerMP3.loopFolder(music); //first song 
  music++;
  
  //Initialize motor drive for output mode
  pinMode(Left_motor_go, OUTPUT);
  pinMode(Left_motor_back, OUTPUT); 
  pinMode(Right_motor_go, OUTPUT); 
  pinMode(Right_motor_back, OUTPUT); 
  pinMode(Right_motor_en, OUTPUT); 
  pinMode(Left_motor_en, OUTPUT); 

  pinMode(BUZZER, OUTPUT);// Set buzzer as output
  digitalWrite(BUZZER, buzzerState);   // set buzzer mute
  buzzer.init(); //initialize buzzer sounds
  
  pinMode(LED, OUTPUT);// Set led as output
  digitalWrite(LED, HIGH); //On led


  pinMode(Echo, INPUT);    // Set Ultrasonic echo port as input
  pinMode(Trig, OUTPUT);   // Set Ultrasonic trig port as input

  pinMode(SensorRight, INPUT); // Set Right Line Walking Infrared sensor as input
  pinMode(SensorLeft, INPUT); // Set left Line Walking Infrared sensor as input
  
  Monitor.begin(115200); // HC-05 master
 
  connect2Modules();
  
  digitalWrite(Left_motor_en, HIGH); // set left motor enable
  digitalWrite(Right_motor_en, HIGH); // set right motor enable

  //Initialize state
  g_carstate = enSTOP; // stop 
  g_modeSelect = 0;    // remote mode

  
  //Initializes the pseudo-random number generator for a delay
  randomSeed(3);//needs an unsigned long int, 3 for example

  printf_begin();
  
  if (speaker) playerMP3.advertise(1); //"monitor" wellcome
  
}

//robot follows a curve in an spiral shape
/*NOVELTY!*/
void spiral(){
  int rightWheel = 200;
  analogWrite(Right_motor_go, rightWheel); //I already do not use digitialWrite HIGH
  for (int leftWheel = 50; leftWheel <= 150; leftWheel += 5)
    {
      analogWrite(Left_motor_go, leftWheel);
      delay(250);
    }
}


void Distance_test()   // Measuring front distance
{
  digitalWrite(Trig, LOW);   // set trig port low level for 2μs
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);  // set trig port high level for 10μs(at least 10μs)
  delayMicroseconds(10);
  digitalWrite(Trig, LOW);    // set trig port low level
  float Fdistance = pulseIn(Echo, HIGH);  // Read echo port high level time(unit:μs)
  Fdistance = Fdistance / 58;    // Distance(m) =(time(s) * 344(m/s)) / 2     /****** The speed of sound is 344m/s.*******/
                                 //  ==> 2*Distance(cm) = time(μs) * 0.0344(cm/μs)
                                 // ==> Distance(cm) = time(μs) * 0.0172 = time(μs) / 58
  Distance = Fdistance;
}

void forward()     // go ahead 
{
  // right motor go ahead
  digitalWrite(Right_motor_back, LOW);
  analogWrite(Right_motor_go, control); //PWM--Pulse Width Modulation(0~255) control speed. It can be adjusted to control speed.

  // left motor go ahead
  digitalWrite(Left_motor_back, LOW);
  analogWrite(Left_motor_go, control); //PWM--Pulse Width Modulation(0~255) control speed. It can be adjusted to control speed.

}

void brake()         //stop
{
  if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}//stops the buzzer
  
  digitalWrite(Left_motor_back, LOW);
  digitalWrite(Left_motor_go, LOW);
  digitalWrite(Right_motor_go, LOW);
  digitalWrite(Right_motor_back, LOW);
}

void left()         //turn left
{
  if (buzzerState == LOW)
  digitalWrite(BUZZER, HIGH);//Avoids buzzer couplings after going backwards
  
  // right motor go ahead
  digitalWrite(Right_motor_back, LOW);
  analogWrite(Right_motor_go, control);//control speed

  digitalWrite(Left_motor_go, LOW);  // left motor stop
  digitalWrite(Left_motor_back, LOW);
}

//I add a rotation towars back from left side
/*NOVELTY!*/
void backLeft()
{
digitalWrite(Right_motor_go, LOW);
digitalWrite(Right_motor_back, LOW);

//digitalWrite(Left_motor_go, LOW);
digitalWrite(Left_motor_back, HIGH);
analogWrite(Left_motor_back, control);

/*NOVELTY!*/
backBeep();   //we make the buzzer sound on back rotation
}

void spin_left()   //Left rotation
{
  //digitalWrite(Right_motor_go, HIGH);	// right motor go ahead
  digitalWrite(Right_motor_back, LOW);
  analogWrite(Right_motor_go, 180);

  digitalWrite(Left_motor_go, LOW);  // left motor back off
  //digitalWrite(Left_motor_back, HIGH);
  analogWrite(Left_motor_back, 180); //has to be enough speed to rotate
}

void right()       //turn right
{
  if (buzzerState == LOW)
  digitalWrite(BUZZER, HIGH);//Avoids buzzer couplings after going backwards
  
  digitalWrite(Right_motor_go, LOW);  // right motor stop
  digitalWrite(Right_motor_back, LOW);

  //digitalWrite(Left_motor_go, HIGH); // left motor go ahead
  digitalWrite(Left_motor_back, LOW);
  analogWrite(Left_motor_go, control); //PWM--Pulse Width Modulation(0~255) control speed
}

//I add a rotation backwards from the right
/*NOVELTY!*/
void backRight()
{
//digitalWrite(Right_motor_go, LOW);
digitalWrite(Right_motor_back, HIGH);
analogWrite(Right_motor_back, control);

digitalWrite(Left_motor_go, LOW);
digitalWrite(Left_motor_back, LOW);

backBeep(); //we make the buzzer sound on back rotation
}

void spin_right()        //Right rotation
{
  
  digitalWrite(Right_motor_go, LOW);  // right motor back off
  analogWrite(Right_motor_back, 180); // has to be enough speed to rotate

  digitalWrite(Left_motor_back, LOW);
  analogWrite(Left_motor_go, 180); // has to be enough espeed to rotate
}

/*NOVELTY!*/
void circle ()
{
  int slow;
  // right motor back off
  digitalWrite(Right_motor_back, LOW);
  analogWrite(Right_motor_go, control); // PWM--Pulse Width Modulation(0~255) control speed

  // left motor go ahead
  digitalWrite(Left_motor_back, LOW);
  slow = (int)(control * 2 / 3);//without decimals
  analogWrite(Left_motor_go, slow); // PWM--Pulse Width Modulation(0~255) control speed   
  //speed of left wheel is two thirds of right wheel
}


//beep with interruptible delay 
/*NOVELTY!*/
void backBeep()
{ //empieza la bocina a sonar a intervalos:
  unsigned long currentMillis = millis();
  
  if (atras == false){
        buzzerState = LOW;
        previousMillis = currentMillis; //la cuenta de intervalo comienza
        atras = true;
  }
  
  if ((currentMillis - previousMillis >= intervalBack) && (buzzerState == LOW)){ 
   
    // if the interval sounding has past 
    previousMillis = currentMillis;
    buzzerState = HIGH; //switch off
  }
  
  if (currentMillis - previousMillis >= intervalOff){
    //if interval off (a multiple of intervalBack) has past, switch on buzzer
    buzzerState = LOW; //switch on buffer
    previousMillis = currentMillis;
  }
  
  digitalWrite(BUZZER, buzzerState); //it presents the state buzzer has to have
}


void back()          //back off 
{
  digitalWrite(Right_motor_go, LOW); //right motor back off
  //digitalWrite(Right_motor_back, HIGH);
  analogWrite(Right_motor_back, control); // PWM--Pulse Width Modulation(0~255) control speed

  digitalWrite(Left_motor_go, LOW); //left motor back off
  //digitalWrite(Left_motor_back, HIGH);
  analogWrite(Left_motor_back, control); // PWM--Pulse Width Modulation(0~255) control speed
  backBeep(); //makes buzzer sound
}


/*NOVELTY!*/
/*Real Madrid's party melody*/
void madrid() 
{
  //2 spaced sounds
  digitalWrite(BUZZER, LOW);
  delay(75);
  digitalWrite(BUZZER, HIGH);
  delay(400);
  
  
  digitalWrite(BUZZER, LOW);
  delay(75);
  digitalWrite(BUZZER, HIGH);
  delay(400);

  //3 sounds
  digitalWrite(BUZZER, LOW);
  delay(50);
  digitalWrite(BUZZER, HIGH);
  delay(200);
  

  digitalWrite(BUZZER, LOW);
  delay(50);
  digitalWrite(BUZZER, HIGH);
  delay(200);
  
  digitalWrite(BUZZER, LOW);
  delay(75);
  digitalWrite(BUZZER, HIGH);
  delay(400); 
  
  //another 4 sounds
  digitalWrite(BUZZER, LOW);
  delay(50);
  digitalWrite(BUZZER, HIGH);
  delay(200);

  digitalWrite(BUZZER, LOW);
  delay(50);
  digitalWrite(BUZZER, HIGH);
  delay(200);
  
  digitalWrite(BUZZER, LOW);
  delay(50);
  digitalWrite(BUZZER, HIGH);
  delay(200); 

  digitalWrite(BUZZER, LOW);
  delay(75);
  digitalWrite(BUZZER, HIGH);
  delay(400); 

  //2 sounds
  digitalWrite(BUZZER, LOW);
  delay(50);
  digitalWrite(BUZZER, HIGH);
  delay(200);
  
  digitalWrite(BUZZER, LOW);
  delay(75);
  digitalWrite(BUZZER, HIGH);
  delay(200); 
}


//buzzer sounds for 1s to wait mode selection
void BeepOnOffMode()
{
  buzzer.playRttl(PROGRAM_FINISHED_RTTL);
  digitalWrite(BUZZER_PIN, HIGH);  //mute
}

/*Bluetooth receive*/
/*with improvements*/
void Bluetooth(void)
{
  if (newLineReceived)
  {
    
    //Determine if mode selection or not
    if (inputString[1] == 'M' && inputString[2] == 'O' && inputString[3] == 'D' && inputString[4] == 'E')
    {
      if (inputString[6] == '0') //stop
      {
        Monitor.print("$MODE 0#"); //send instruction to slave module
        g_carstate = enSTOP;
        g_modeSelect = 4; //4: no mode. It is necessary to select another mode
        g_AllState = 0; //0:Busy, 1:Mode selection
        if(speaker) playerMP3.pause(); //off MP3 player mini
        BeepOnOffMode();
        restartMusic();   
      }
      else
      {
        switch (inputString[5])//the fifth bit in the string (0:remote control mode(default); 1:line walking mode)
        {
          case '0': Monitor.print("$MODE0#");
                    g_modeSelect = 0; control = 175; break;              
          case '1': Monitor.print("$MODE1#");
                    g_modeSelect = 1; control = 100; break;
        }
        g_AllState = 0;
        BeepOnOffMode();
      }
    }
    else
      {
        if (g_modeSelect == 0)
          { 
            unsigned long pastTime; pastTime = 0; //initial time
            pastTime = millis();  
            switch (inputString[1]) //Direction
            {
              case run_car:   // stops the buzzer in case it has stayed on
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}
                              g_carstate = enRUN;
                              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
                              if (speaker) playerMP3.start(); //avoids ramdom breaks
                              if(speaker) playerMP3.advertise(2); //play "Adelante"
                              Monitor.print("$1#"); //to send the order to the following robot  
                              break; 
                              
              case back_car:  // stops the buzzer in case it has stayed on
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;} 
                              g_carstate = enBACK;
                              // stops the buzzer in case it has stayed on 
                              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
                              if (speaker) playerMP3.start(); //avoids ramdom breaks
                              if(speaker) playerMP3.advertise(3); //play "Atrás"
                              Monitor.print("$2#"); //to send the order to the following robot  
                              break; 
              case left_car:  Monitor.print("$3#");
                              // stops the buzzer in case it has stayed on
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}
                              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
                              if (speaker) playerMP3.start(); //avoids ramdom breaks
                              if(speaker) playerMP3.advertise(14);
                              while ((millis()- pastTime) < 850) //waits 850ms with interruptible delay
                              {
                                int x; x = x+0;
                              }
                              //delay(850); 
                              g_carstate = enLEFT;  break;
              case right_car: Monitor.print("$4#");
                              // stops the buzzer in case it has stayed on 
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}
                              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
                              if (speaker) playerMP3.start(); //avoids ramdom breaks
                              if(speaker) playerMP3.advertise(15);
                              while ((millis()- pastTime) < 850) //waits 850ms with interruptible delay
                              {
                                int x; x = x+0;
                              } 
                              //delay(850); 
                              g_carstate = enRIGHT; break;
              case stop_car:  Monitor.print("$0#");
                              // stops the buzzer in case it has stayed on
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}
                              g_carstate = enSTOP; break; 
              case back_left_car: Monitor.print("$5#"); 
                              // stops the buzzer in case it has stayed on
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}
                              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
                              if (speaker) playerMP3.start(); //avoids ramdom breaks
                              if(speaker) playerMP3.advertise(13); 
                              while ((millis()- pastTime) < 1400) //waits 1400ms with interruptible delay
                              {
                                int x; x = x+0;
                              }
                              //delay(1400); 
                              g_carstate = enBACK_LEFT; break;
              case back_right_car: Monitor.print("$6#");
                              // stops the buzzer in case it has stayed on
                              if (atras == true) {digitalWrite(BUZZER, HIGH); atras = false;}
                              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps 
                              if (speaker) playerMP3.start(); //avoids ramdom breaks
                              if(speaker) playerMP3.advertise(12);
                              while ((millis()- pastTime) < 1400) //waits 1400ms with interruptible delay
                              {
                                int x; x = x+0;
                              }
                              1; 
                              //delay(1400); 
                              g_carstate = enBACK_RIGHT; break;
              case circles:   Monitor.print("$7#");
                              g_carstate = enCIRCLES; break;
            }
            if (inputString[3] == '1') //Left rotation and madrid melody
            { 
              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
              if (speaker) playerMP3.start(); //avoids ramdom breaks
              if(speaker) playerMP3.advertise(5); //play "Giro a la izquierda" (Spanish) 
              Monitor.print("$--1#"); //send the instruction to slave robot
              spin_left();
              madrid();
              brake();
            }
            else if (inputString[3] == '2') //Right rotation and madrid melody
            {
              if (speaker) playerMP3.stopAdvertise(); //avoids overlaps
              if (speaker) playerMP3.start(); //avoids ramdom breaks
              if(speaker) playerMP3.advertise(6);  //play "Giro a la derecha" (Spanish)
              Monitor.print("$--2#"); //send instruction to slave module
              spin_right();
              madrid();
              brake();
            }
            else if (inputString[3] == '3') //Circle
            {
              Monitor.print("$--3#"); //send instruction to slave module
              if(speaker) playerMP3.advertise(10);
              circle();
              delay(2000);
              brake();
            }
            else if (inputString[3] == '4')
            {
              Monitor.print("$--4#"); //send instruction to slave module  
              if (speaker) playerMP3.advertise(11); //advertise "spiral" 0011.mp3 in folder ADVERT              
              delay(950);
              spiral();
              brake();
            }
          }
        if (inputString[5] == '1') //next song/stop
        {
          if (speaker) playNextSong(); //next song/stop. The function does not belongs to the library
        }
        if (inputString[5] == '2')
        {
          Monitor.print("$_ _ 2#"); //send instruction to slave module
          if(speaker) playerMP3.advertise(4); //"Hala Madrid" reproduction (Spanish)
          madrid();
        }
        if (inputString[7] == '1') //speed up
          {
            Monitor.print("$_ _ _ 1#"); //send instruction to slave module
            control += 20; //or 50
            if (control > 255)
            {
              control = 255;
            }
          }
        if (inputString[9] == '1') //speed reduction
          {
            Monitor.print("$_ _ _ _ 1#"); //send instruction to slave module
            control -= 20; //or 50
            if (control < 50)
            {
              control = 100;
            }
          }
        if (inputString[1] == 'D' && speaker)
        playerMP3.volumeDown();
        if (inputString[1] == 'U' && speaker)
        playerMP3.volumeUp();
        if (inputString[8] == 'P') //button hands begging emoticon
          { //We can add more functions to the button like stopping for example
            Monitor.print("$- - - -P#"); //send message to other robots
            if(speaker) playerMP3.advertise(16); //"Perdón, no era así el ejercicio. Me equivoqué" (advertise in Spanish)
          }
      }
   inputString = "";   // clear the string
   newLineReceived = false;
  }
}


//Car running control
void CarControl()
{
  switch (g_carstate)
  {
    case enSTOP: brake(); break; 
    case enRUN: forward(); break;
    case enLEFT: left(); break;
    case enRIGHT: right(); break;
    case enBACK_LEFT: backLeft(); break; //I added
    case enBACK_RIGHT: backRight(); break; //I added
    case enCIRCLES: circle(); break; //for potentiometre
    case enBACK: back(); break;
    case enTLEFT: spin_left(); break;
    case enTRIGHT: spin_right(); break;
    default: brake(); break;
  }  
}


//line walking mode. Maybe it only works at low speed
void track()
{
  /**************************************************************************************
  Infrared signal back means white undersurface ,returns low level and led lights up.
  Infrared signal gone means black undersurface ,returns high level and led lights off. 
  **************************************************************************************/
  SR = digitalRead(SensorRight);//Right Line Walking Infrared sensor against white undersurface,then LED[L2] light illuminates and while against black undersurface,LED[L2] goes off
  SL = digitalRead(SensorLeft);//Left Line Walking Infrared sensor against white undersurface,then LED[L3] light illuminates and while against black undersurface,LED[L3] goes off

  if (SL == LOW && SR == LOW) // Black lines were not detected at the same time
    {g_carstate = enRUN;   // go ahead
    //if (speaker) playerMP3.advertise(2);
    }
  else if (SL == LOW & SR == HIGH)// Left sensor against white undersurface and right against black undersurface , the car left off track and need to adjust to the right.
    {g_carstate = enRIGHT;
    //if(speaker) playerMP3.advertise(15);
    }
  else if (SR == LOW & SL ==  HIGH) // Rihgt sensor against white undersurface and left against black undersurface , the car right off track and need to adjust to the left.
    {g_carstate = enLEFT;
    //if(speaker) playerMP3.advertise(14);
    }
  else // Black lines were detected at the same time , the car stop.
    {g_carstate = enSTOP; 
    //if(speaker) playerMP3.advertise(1);
    }
    
}
  

/*main loop*/
void loop()
{
  Bluetooth();
  // Switch different mode
  if (g_AllState == 0 && g_modeSelect == 1)
    track();
  CarControl();
}

//Serial read data
void serialEvent() //only checks the serial port each time the loop is finished
{
  while (Serial.available())
  {
    incomingByte = Serial.read();   //One byte by one byte reads 
    if (incomingByte == '$')  // '$' means the start of packet.$#
    {
      startBit = true;
    }
    if (startBit == true)
    {
      inputString += (char) incomingByte;     // The received data constitutes a completed packet.
    }
    if (incomingByte == '#')    // '#' means the end of packet
    {
      newLineReceived = true;
      startBit = false;
    }
  }
}

//--------------------------------------------------------------
//MP3 new function
//to play following song, or at the end, to stop
void playNextSong()
{
  if(music == 0)
  {
    if(speaker) playerMP3.pause(); //stop music
    music++;
  }
  else
  {
    if(speaker) playerMP3.loopFolder(music); //next song
    music++;
    if(music == 4)
    music = 0;
  }
}

//begin again with the first song after final stop (scissors icon button of the app)
void restartMusic()
{
  if (speaker)
  {
  music = 1;
  playerMP3.loopFolder(music);
  music++;
  }
}

Credits

Jose Romaní

Jose Romaní

8 projects • 4 followers
Industrial Technical Engineer in Electronics and Automation
Thanks to Yahboom.

Comments