Introduction: Give a New Life to Your RC Toy Car

Time to take out your remote control toy car and give it a new life with Annikken Andee.

Build the RC car of your dreams by controlling the car with your mobile phone, Annikken Andee lets you customise the UI on the Arduino IDE. Add more buttons to add function to your car, like sensors and buzzers. Ready set go! Start Making!


Materials Needed:

- 1 DRV8833 Dual DC Motor Driver
- 1 Arduino Uno
- 1 Annikken Andee U
- 1 Bread board 1 remote car include two DC motor, 4 LED Lights
- 1 Buzzer
- 2 Ultrasonic
- 1 Proto Shield Board
- Bluetack/Tape
- Styroform
- 5 x AA battery and 12V battery

Tool Needed:
- Arduino IDE
- Screw driver
- One soldering kit
- Annikken Andee resources (online at http://resources.annikken.com )

Step 1: Connecting Everything Together

DRIVER - ANDEE

GND - GND

BIN1 - PIN 10

BIN2 - PIN 9

AIN2 - PIN 6

AIN1 - PIN 5

DRIVER - DC MOTORS(M1 AND M2)

BOUT1 - M1 DC MOTOR
BOUT2 - M1 DC MOTOR

AOUT2 - M2 DC MOTOR

AOUT1 - M2 DC MOTOR

DRIVER - POWER SUPPLY
GND - SUPPLYGND
VIN - VOLTAGE

Front motor

  • BIN1 9
  • BIN2 10

Back motor

  • AIN1 5
  • AIN2 6

LEDs

  • Front LED 7
  • Back LED

Front Ultrasonic

  • Trigger - A0
  • Echo - A1

Back Ultrasonic

  • Trigger - A2
  • Echo - A3

Buzzer

  • PIN 3

Do not connect to PIN 8, 11, 12, 13 as Annikken Andee is using those PINS

Step 2: Connecting the Motor Drive

This is how we are going to connect the Motor driver to the desired assigned pins and to the remote controlled car.

Step 3: Soldering the Motor Driver Onto the Board

This is the overview of how the board looks like after soldering the motor driver onto the board with the PINs connected. As you can see, there are red wires connected from the motor driver to the assigned pins and there are two black wires which is connected to the resistor which is also connected onto the ground. They are for the LEDs light where all your black wires of the RC LED were suppose to connect to and there are also two red wires which are connected to PIN 7 which are also for the LED. In this example there are only two black and two red wires when there are suppose to be 4 red and black wires for 4 LEDs but because the the back LEDs of the RC car that was used in this example is faulty. Not to worry the codes are still made available in the source code and for the wiring it's the same as before but the red wires should be wired to the desired PIN you want unless you want to light up all four LEDs with just one PIN.

Step 4: Breadboard Connection

This is the breadboard connection that was used, starting from the left hand side is the white cable which is to the 5V on your proto board and the black cable to the ground. For the other cables, they are for the utlrasonic sensor as they require the 5V connection and also the ground connection.

Step 5: Ultrasonic Sensor

Previously we connected the VCC and the GND of both ultrasonic sensor to the breadboard. Now we are going to connect their trigger and echo onto the Proto board. The image above is the overview of the ultrasonic sensor triggers and echo pin connection on my proto board.

Step 6:

Now to complete the wiring for the entire RC car we need to include the buzzer connection at PIN 3 (orange cable) and to the ground(blue cable).

Step 7:

After finishing up the wiring we are left with the reassembling everything back to together. So here is the overview of the entire car after bluetacking the wires and the ultrasonic while taping the styroform to the front and back of the RC car to prevent damages inflicted to the ultrasonic in cases where the car is unable to stop in time and launches for an impact.

Step 8: Going Through the Source Code, Part 1: Declarations

/*

* ======================================================

* Pins declaration

* ======================================================

*/

// Front motor PIN

#define BIN1 9 // Left

#define BIN2 10 // Right

// Back motor PIN

#define AIN1 5 // Down/Backward

#define AIN2 6 // Up/Forward

// LEDs PIN

#define LedFront 7 // LED Front

#define LedBack A3 // LED Back

//ultrasonic PIN

#define trigger A2

#define echo A3

#define fronttrigger A0

#define frontecho A1

//buzzer PIN

#define buzzer 4

/*

* ======================================================

* Variables Declaration

* ======================================================

*/

//Variables to check current state of the car

bool isMovingBack = false;

bool isMovingForward = false;

bool isRight = false;

bool isLeft = false;

//ultrasonic variables to calculate the distance

int duration, distance, front, back;

bool constant = false;

bool justStart = false;

//this is similar to a state change in term of the speed

int gear = 0;

//these two variables are used as a counter to

//determine or estimate the duration of the speed

//that the car is moving on

int speedCounter = 0; // gear 2 - 255

int speedCounter2 = 0; // gear 1 - 120 or below

//this is a global variable used to keep track of the current car's speed

int power = 0;

//this variable are used to load updating of UI once

bool loadOnce = true;

Step 9: Going Through the Source Code, Part 2 : Void Setup()

void setup() {

// put your setup code here, to run once:

// Initialize driver control pins

// DC Motor

pinMode(AIN1, OUTPUT);

pinMode(AIN2, OUTPUT);

pinMode(BIN1, OUTPUT);

pinMode(BIN2, OUTPUT);

// LED Lights

pinMode(LedFront, OUTPUT);

pinMode(LedBack, OUTPUT);

// Ultrasonic

pinMode(trigger, OUTPUT);

pinMode(echo, INPUT);

pinMode(fronttrigger, OUTPUT);

pinMode(frontecho, INPUT);

// Buzzer

pinMode(buzzer, OUTPUT);

// start with drivers off, motors coasting

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(BIN2, LOW);

// Initialize UI once checker

loadOnce = true;

// Andee

Andee.begin();

Andee.clear();

setInitialData();

// For debugging purposes: allows printing message to console during testing

Serial.begin(9600);

}

Step 10: Going Through the Source Code, Part 3 : Void SetInitialData()

void setInitialData()

{

// controls UI declaration

up.setId(0); // UI Id

up.setType(BUTTON_IN); // type of UI

up.setLocation(2,0, ONE_THIRD); // location/position of the UI

up.setTitle("Up"); // UI title text

up.requireAck(false); // require no acknowledge for multiple tapping

left.setId(1);

left.setType(BUTTON_IN);

left.setLocation(3,1, ONE_THIRD);

left.setTitle("Left");

left.requireAck(false);

down.setId(2);

down.setType(BUTTON_IN);

down.setLocation(3,0, ONE_THIRD);

down.setTitle("Down");

down.requireAck(false);

right.setId(3);

right.setType(BUTTON_IN);

right.setLocation(3,2, ONE_THIRD);

right.setTitle("Right");

right.requireAck(false);

//speed control

topSpeed.setId(6);

topSpeed.setType(BUTTON_IN);

topSpeed.setLocation(0,1, ONE_THIRD);

topSpeed.setTitle("Increase/Decrease speed");

topSpeed.requireAck(false);

//honk

honk.setId(5);

honk.setType(BUTTON_IN);

honk.setLocation(0,0, ONE_THIRD);

honk.setTitle("Honk");

honk.requireAck(false);

//4 LED lights toggle buttons

frontLight.setId(7);

frontLight.setType(BUTTON_IN);

frontLight.setLocation(0, 2, ONE_THIRD);

frontLight.setTitle("Lights");

//backlights - the location might need to be changed in term of the size

//if it's included in, you might want to change from ONE_THIRD to ONE_QUART

//same for the rest of the buttons that are in the same row

//this is commented because the RC's backlight used in this example is faulty

/*

backLight.setId(10);

backLight.setType(BUTTON_IN);

backLight.setLocation(0, 3, ONE_THIRD);

backLight.setTitle("Lights");

*/

//halt/stop

kill.setId(8);

kill.setType(BUTTON_IN);

kill.setLocation(2, 2, TWO_THIRD);

kill.setTitle("Stop");

kill.requireAck(false);

//debug purposes can be removed after testing is done

/*

displayText.setId(9);

displayText.setType(DATA_OUT);

displayText.setLocation(1, 0, FULL);

displayText.setTitle("debug");

displayText.setData("");

*/

}

Step 11: Going Through the Source Code, Part 4

/*

* ======================================================

* Sound functions

* ======================================================

*/

//double purposes to get the distance for both front and back ultrasonic

void sense(int trig, int ech)

{

//ensure that the ultrasonic works

digitalWrite(trig, LOW);

delayMicroseconds(2);

digitalWrite(trig, HIGH);

delayMicroseconds(10);

digitalWrite(trig, LOW);

duration = pulseIn(ech, HIGH);

distance = duration/58;

}

void beep()

{

//Beep when reversing

//Beep when car reaches a certain distance between

//the back of the car and the object behind it

//check reversing

//Serial.println("Back");

sense(trigger, echo);

back = distance;

Serial.print("Back: ");

Serial.print(back);

Serial.println("cm");

if(constant == true)

{

if(back <= 120 && back >= 0) // distance <= 15cm and >= 0

{

//Serial.println("too close");

tone(buzzer, 956);

Halt();

}

else if(back <= 150 && back > 120) // distance <= 35cm and > 15cm

{

//Serial.println("close");

/*

//Reduce speed

tone(buzzer, 1915);

delay(100);

noTone(buzzer);

delay(20);

power = 100;

if(isMovingBack == true)

{

if(isRight == true)

{

controlRightB(power);

}

else if(isLeft == true)

{

controlLeftB(power);

}

else

{

controlDown(power);

}

}

gear = 1;

*/

}

else

{

tone(buzzer, 1915);

delay(200);

noTone(buzzer);

delay(20);

}

}

else

{

if(back <= 100 && back >= 0) // distance <= 15cm and >= 0

{

//Serial.println("too close");

tone(buzzer, 956);

Halt();

}

else if(back <= 150 && back > 100) // distance <= 35cm and > 15cm

{

//Serial.println("close");

/*

//Reduce speed

tone(buzzer, 1915);

delay(100);

noTone(buzzer);

delay(20);

power = 100;

if(isMovingBack == true) //car is moving backward

{

if(isRight == true) //still turning right

{

controlRightB(power);

}

else if(isLeft == true) //still turning left

{

controlLeftB(power);

}

else //continuing moving back without turning

{

controlDown(power);

}

}

gear = 1; //speed that is currently at

*/

}

else //no object within the distance of 150cm

{

tone(buzzer, 1915);

delay(200);

noTone(buzzer);

delay(20);

}

}

}

void frontbeep()

{

//Beep when car reaches a certain distance between

//the front of the car and the object infront of it

//check

//Serial.println("Front");

sense(fronttrigger, frontecho);

front = distance;

Serial.print("Front: ");

Serial.print(distance);

Serial.println("cm");

//running at a constant speed of 255

if(constant == true)

{

if(front <= 120 && front > 0)

{

//Serial.println("too close");

Halt();

}

else if(front <= 150 && front > 120)

{

/*

//Reduce speed

power = 100;

if(isMovingForward == true) // if car is moving forward

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

gear = 1;

*/

}

else

{

noTone(buzzer);

}

}

else // running at a speed 120 or lower

{

if(front <= 100 && front > 0)

{

//Serial.println("too close");

Halt();

}

else if(front <= 150 && front > 100)

{

/*

//Reduce speed

power = 100;

if(isMovingForward == true)

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

gear = 1;

*/

}

else

{

noTone(buzzer);

}

}

}

void honkBeep()

{

if(honk.isPressed())

{

tone(buzzer, 1915);

delay(200);

}

}

Step 12: Going Through the Source Code, Part 5 : Honk and Lights

/*
* ======================================================

* Honk functions : works similar to pressing of button example

* just that it is used to trigger the buzzer

* ======================================================

*/

void honkBeep()

{

if(honk.isPressed())

{

tone(buzzer, 1915);

delay(200);

}

}

/*

* ======================================================

* Light functions : similar to the honk function or how you normally

* code for turning on and off for an LED light

* ======================================================

*/

void light()

{

// Light up front lights

if(frontLight.isPressed())

{

frontLight.ack();

if (frontLightState == 0)

{

digitalWrite(LedFront, HIGH);

frontLightState = 1;

}

else

{

digitalWrite(LedFront, LOW);

frontLightState = 0;

}

}

/*

// Not implemented as the RC car that was used has a fault with

// the back lights but the code is similar to the front lights

// Light up back lights

if(backLight.isPressed())

{

backLight.ack();

if (backLightState == 0)

{

digitalWrite(LedBack, HIGH);

backLightState = 1;

}

else

{

digitalWrite(LedBack, LOW);

backLightState = 0;

}

}

*/

}

Step 13: Going Through the Source Code, Part 6 : Basic Control for RC Movement and Loading UI

/*

* ======================================================

* Movement functions

* ======================================================

*/

/*

* 5 condition:

* - Move Forward: controlUp();

* - Turn Right: controlRight();

* - Turn Left: controlLeft();

* - Turn Right Backward: controlRightB();

* - Turn Left Backward: controlLeftB();

* - Move Backward: controlDown();

* - Complete stop: Halt();

* AIN1 - for moving backward

* AIN2 - for moving forward

* BIN1 - for turning wheel to left

* BIN2 - for turning wheel to right

*/

void Halt()

{

//Serial.println("Halt");

if(constant == true) // if car is moving at a constant speed

{

if(isMovingForward == true) // moving at a high speed forward

{

Serial.print("650");

//pulling back the car against the current speed it's running at in order to allow the car to stop

//by using a certain amount of effort against the opposite direction

digitalWrite(AIN2, LOW); // stop wheel from moving forward

digitalWrite(AIN1, HIGH); // start wheel from moving back

delay(750);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

constant = false;

justStart = true;

}

else if(isMovingBack == true) // moving at a high speed backward

{

Serial.print("650");

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, HIGH);

delay(750);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

constant = false;

justStart = true;

}

}

else

{

if(justStart == false) // car started moving for awhile

{

if(isMovingForward == true) // moving at a high speed forward

{

Serial.print("300");

digitalWrite(AIN2, LOW);

digitalWrite(AIN1, HIGH);

delay(350);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

else if(isMovingBack == true) // moving at a high speed backward

{

Serial.print("300");

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, HIGH);

delay(350);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

}

else // if car just starting moving

{

if(isMovingForward == true) // moving at a high speed forward

{

Serial.print("100");

digitalWrite(AIN2, LOW);

digitalWrite(AIN1, HIGH);

delay(200);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

else if(isMovingBack == true) // moving at a high speed backward

{

Serial.print("100");

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, HIGH);

delay(200);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

}

}

//debugging purposes, can be removed after testing

/*

displayText.setData(distance);

displayText.setUnit("cm");

displayText.update();

*/

}

// control

void controlUp(int p) // overwrite turning controls if up is pressed

{

//Serial.println("up");

analogWrite(AIN2, p);

digitalWrite(AIN1, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(BIN2, LOW);

isMovingForward = true;

isMovingBack = false;

isRight = false;

isLeft = false;

}

void controlDown(int p) // overwrite turning controls if down is pressed

{

//Serial.println("down");

analogWrite(AIN1, p);

digitalWrite(AIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(BIN2, LOW);

isMovingBack = true;

isMovingForward = false;

isRight = false;

isLeft = false;

}

void controlLeft(int p)

{

//Serial.println("left turn");

if(isLeft == false) // left turn while moving forward

{

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

else

{

// continue but different speed

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

}

void controlLeftB(int p)

{

//Serial.println("left turn back");

if(isLeft == false) // left turn while moving backward

{

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

else

{

// continue but different speed

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

}

void controlRight(int p)

{

//Serial.println("right turn");

if(isRight == false) // right turn while moving forward

{

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

else

{

// continue but different speed

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

}

void controlRightB(int p)

{

//Serial.println("right turn back");

if(isRight == false) // right turn after while moving backward

{

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

else

{

// continue but different speed

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

}

// loading of UI
void UI()

{

//update once

frontLight.update();

//controls

up.update();

left.update();

down.update();

right.update();

kill.update();

//speed

topSpeed.update();

honk.update();

//debugging purposes

//displayText.update();

loadOnce = false; // UI loaded once

}

Step 14: Going Through the Source Code, Part 7 : Void Loop()

void loop() {
// put your main code here, to run repeatedly:

// only occur when speed is changed

//Serial.println("Low speed");

if(topSpeed.isPressed())

{

Serial.println("Top speed");

if(gear == 1)

{

Serial.println("g2");

power = 255;

if(isMovingForward == true) // check if car is moving forward

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

else if(isMovingBack == true) // check if car is moving backward

{

if(isRight == true)

{

controlRightB(power); // still turning right

}

else if(isLeft == true)

{

controlLeftB(power); // still turning left

}

else

{

controlDown(power); // still moving backward

}

}

gear = 2;

}

else if(gear == 2)

{

Serial.println("g2");

power = 120;

if(isMovingForward == true) // check if moving forward

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

else if(isMovingBack == true) // check if moving backward

{

if(isRight == true)

{

controlRightB(power); // still turning right

}

else if(isLeft == true)

{

controlLeftB(power); // still turning left

}

else

{

controlDown(power); // still moving backward

}

}

gear = 1;

}

}

if(power == 0)

{

//Serial.println("Power more than 0");

if(up.isPressed())

{

power = 120;

gear = 1;

controlUp(power); // move forward

}

if(down.isPressed())

{

power = 120;

gear = 1;

controlDown(power); // move back

}

if(left.isPressed())

{

if(isMovingBack == true)

{

controlLeftB(power); // turn left backward

}

else if(isMovingForward == true)

{

controlLeft(power); // turn left

}

}

if(right.isPressed())

{

if(isMovingBack == true)

{

controlRightB(power); // turn right backward

}

else if(isMovingForward == true)

{

controlRight(power); // turn right

}

}

if(kill.isPressed())

{

Halt(); // stop

}

}

else

{

//Serial.println("Power more than 0");

if(up.isPressed())

{

controlUp(power); // move forward

}

if(down.isPressed())

{

controlDown(power); // move back

}

if(left.isPressed())

{

if(isMovingBack == true)

{

controlLeftB(power); // turn left backward

}

else if(isMovingForward == true)

{

controlLeft(power); // turn left

}

}

if(right.isPressed())

{

if(isMovingBack == true)

{

controlRightB(power); // turn right backward

}

else if(isMovingForward == true)

{

controlRight(power); // turn right

}

}

if(kill.isPressed())

{

Halt(); // stop

}

}

light(); // check lights and light up

if(isMovingBack == true) // check if moving back

beep(); // ultrasonic to beep, reduce speed and halt

else if(isMovingForward == true) // check if moving forward

frontbeep(); // ultrasonic to beep, reduce speed and halt

else

noTone(buzzer);

if(loadOnce == true) // update UI once

{

UI(); // update UI, loadOnce = false

}

honkBeep(); //honk

// rough estimation of the power used

// to hit a certain constant speed

if(power == 255)

{

if(speedCounter >= 4)

{

// assuming that the car is now at a state of constant speed

// after running at a power of 255 for maybe a rough estimated

// duration of 0.5

constant = true;

speedCounter2 == 0;

}

speedCounter++;

}

else

{

if(speedCounter2 >= 0 && speedCounter2 <= 5)

{

// the opposite effect of the above code

constant = false;

justStart = true;

}

else if(speedCounter2 > 10)

{

constant = false;

speedCounter == 0;

justStart = false;

}

speedCounter2++;

}

delay(100);

}

Step 15: Complete Source Code

// Define each component of the desired pin numbers that you want to assign to.
// noted: 8, 11, 12, 13 are being used by Anikken Andee hence the pins available are

// 0 - 7, 9, 10, A0 - A5

/*

* Pins declaration

*/

// Front motor PIN

#define BIN1 9 // Left

#define BIN2 10 // Right

// Back motor PIN

#define AIN1 5 // Down/Backward

#define AIN2 6 // Up/Forward

// LEDs PIN

#define LedFront 7 // LED Front

#define LedBack A3 // LED Back

//ultrasonic PIN

#define trigger A2

#define echo A3

#define fronttrigger A0

#define frontecho A1

//buzzer PIN

#define buzzer 4

/*

* Variables Declaration

*/

//Variables to check current state of the car

bool isMovingBack = false;

bool isMovingForward = false;

bool isRight = false;

bool isLeft = false;

//ultrasonic variables to calculate the distance

int duration, distance, front, back;

bool constant = false;

bool justStart = false;

int speedCounter = 0; // gear 2 - 255

int speedCounter2 = 0; // gear 1 - 120 or below

//this is a global variable used to keep track of the current car's speed

int power = 0;

//this variable are used to load updating of UI once

bool loadOnce = true;

//this is similar to a state change in term of the speed

int gear = 0;

// Things you need to work with Arduino and Andee

#include

#include

//4 LED lights toggle buttons

//Front Lights

AndeeHelper frontLight;

int frontLightState = 0;

//Back Lights

//AndeeHelper backLight;

//int backLightState = 0;

//controls of car's movement

AndeeHelper up;

AndeeHelper down;

AndeeHelper left;

AndeeHelper right;

AndeeHelper kill;

//control of car's speed

AndeeHelper topSpeed;

//Debugging purposes to display debugging text

//AndeeHelper displayText;

//honk

AndeeHelper honk;

void setup() {

// put your setup code here, to run once:

// Initialize driver control pins

// DC Motor

pinMode(AIN1, OUTPUT);

pinMode(AIN2, OUTPUT);

pinMode(BIN1, OUTPUT);

pinMode(BIN2, OUTPUT);

// LED Lights

pinMode(LedFront, OUTPUT);

pinMode(LedBack, OUTPUT);

// Ultrasonic

pinMode(trigger, OUTPUT);

pinMode(echo, INPUT);

pinMode(fronttrigger, OUTPUT);

pinMode(frontecho, INPUT);

// Buzzer

pinMode(buzzer, OUTPUT);

// start with drivers off, motors coasting

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(BIN2, LOW);

// Initialize UI once count

loadOnce = true;

// Andee

Andee.begin();

Andee.clear();

setInitialData();

// For debugging purposes: allows printing message to console during testing

Serial.begin(9600);

}

/*

* ======================================================

* Initialise/Declare UI

* ======================================================

*/

void setInitialData()

{

// controls UI declaration

up.setId(0); // UI Id

up.setType(BUTTON_IN); // type of UI

up.setLocation(2,0, ONE_THIRD); // location/position of the UI

up.setTitle("Up"); // UI title text

up.requireAck(false); // require no acknowledge

left.setId(1);

left.setType(BUTTON_IN);

left.setLocation(3,1, ONE_THIRD);

left.setTitle("Left");

left.requireAck(false);

down.setId(2);

down.setType(BUTTON_IN);

down.setLocation(3,0, ONE_THIRD);

down.setTitle("Down");

down.requireAck(false);

right.setId(3);

right.setType(BUTTON_IN);

right.setLocation(3,2, ONE_THIRD);

right.setTitle("Right");

right.requireAck(false);

//speed control

topSpeed.setId(6);

topSpeed.setType(BUTTON_IN);

topSpeed.setLocation(0,1, ONE_THIRD);

topSpeed.setTitle("Increase/Decrease speed");

topSpeed.requireAck(false);

//honk

honk.setId(5);

honk.setType(BUTTON_IN);

honk.setLocation(0,0, ONE_THIRD);

honk.setTitle("Honk");

honk.requireAck(false);

//4 LED lights toggle buttons

frontLight.setId(7);

frontLight.setType(BUTTON_IN);

frontLight.setLocation(0, 2, ONE_THIRD);

frontLight.setTitle("Lights");

//backlights - the location might need to be changed

/*

backLight.setId(10);

backLight.setType(BUTTON_IN);

backLight.setLocation(0, 3, ONE_THIRD);

backLight.setTitle("Lights");

*/

//halt/stop

kill.setId(8);

kill.setType(BUTTON_IN);

kill.setLocation(2, 2, TWO_THIRD);

kill.setTitle("Stop");

kill.requireAck(false);

//debug purposes can be removed after testing is done

/*

displayText.setId(9);

displayText.setType(DATA_OUT);

displayText.setLocation(1, 0, FULL);

displayText.setTitle("debug");

displayText.setData("");

*/

}

/*

* ======================================================

* Sound functions

* ======================================================

*/

void sense(int trig, int ech)

{

//ensure that the ultrasonic works

digitalWrite(trig, LOW);

delayMicroseconds(2);

digitalWrite(trig, HIGH);

delayMicroseconds(10);

digitalWrite(trig, LOW);

duration = pulseIn(ech, HIGH);

distance = duration/58;

}

void beep()

{

//Beep when reversing

//Beep when car reaches a certain distance between

//the back of the car and the object behind it

//check reversing

//Serial.println("Back");

sense(trigger, echo);

back = distance;

Serial.print("Back: ");

Serial.print(back);

Serial.println("cm");

if(constant == true)

{

if(back <= 120 && back >= 0) // distance <= 15cm and >= 0

{

//Serial.println("too close");

tone(buzzer, 956);

Halt();

}

else if(back <= 150 && back > 120) // distance <= 35cm and > 15cm

{

//Serial.println("close");

/*

//Reduce speed

tone(buzzer, 1915);

delay(100);

noTone(buzzer);

delay(20);

power = 100;

if(isMovingBack == true)

{

if(isRight == true)

{

controlRightB(power);

}

else if(isLeft == true)

{

controlLeftB(power);

}

else

{

controlDown(power);

}

}

gear = 1;

*/

}

else

{

tone(buzzer, 1915);

delay(200);

noTone(buzzer);

delay(20);

}

}

else

{

if(back <= 100 && back >= 0) // distance <= 15cm and >= 0

{

//Serial.println("too close");

tone(buzzer, 956);

Halt();

}

else if(back <= 150 && back > 100) // distance <= 35cm and > 15cm

{

//Serial.println("close");

/*

//Reduce speed

tone(buzzer, 1915);

delay(100);

noTone(buzzer);

delay(20);

power = 100;

if(isMovingBack == true)

{

if(isRight == true)

{

controlRightB(power);

}

else if(isLeft == true)

{

controlLeftB(power);

}

else

{

controlDown(power);

}

}

gear = 1;

*/

}

else

{

tone(buzzer, 1915);

delay(200);

noTone(buzzer);

delay(20);

}

}

}

void frontbeep()

{

//Beep when car reaches a certain distance between

//the front of the car and the object infront of it

//check

//Serial.println("Front");

sense(fronttrigger, frontecho);

front = distance;

Serial.print("Front: ");

Serial.print(distance);

Serial.println("cm");

//running at a constant speed of 255

if(constant == true)

{

if(front <= 120 && front > 0)

{

//Serial.println("too close");

Halt();

}

else if(front <= 150 && front > 120)

{

/*

//Reduce speed

power = 100;

if(isMovingForward == true)

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

gear = 1;

*/

}

else

{

noTone(buzzer);

}

}

else // running at a speed 120 or lower

{

if(front <= 100 && front > 0)

{

//Serial.println("too close");

Halt();

}

else if(front <= 150 && front > 100)

{

/*

//Reduce speed

power = 100;

if(isMovingForward == true)

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

gear = 1;

*/

}

else

{

noTone(buzzer);

}

}

}

/*

* ======================================================

* Honk functions

* ======================================================

*/

void honkBeep()

{

if(honk.isPressed())

{

tone(buzzer, 1915);

delay(200);

}

}

/*

* ======================================================

* Light functions

* ======================================================

*/

void light()

{

// Light up front lights

if(frontLight.isPressed())

{

frontLight.ack();

if (frontLightState == 0)

{

digitalWrite(LedFront, HIGH);

frontLightState = 1;

}

else

{

digitalWrite(LedFront, LOW);

frontLightState = 0;

}

}

/*

// Not implemented as the RC car that was used has a fault with

// the back lights but the code is similar to the front lights

// Light up back lights

if(backLight.isPressed())

{

backLight.ack();

if (backLightState == 0)

{

digitalWrite(LedBack, HIGH);

backLightState = 1;

}

else

{

digitalWrite(LedBack, LOW);

backLightState = 0;

}

}

*/

}

/*

* ======================================================

* Movement functions

* ======================================================

*/

/*

* 5 condition:

* - Move Forward: controlUp();

* - Turn Right: controlRight();

* - Turn Left: controlLeft();

* - Turn Right Backward: controlRightB();

* - Turn Left Backward: controlLeftB();

* - Move Backward: controlDown();

* - Complete stop: Halt()

*/

void Halt()

{

//Serial.println("Halt");

if(constant == true)

{

if(isMovingForward == true) // moving at a high speed forward

{

Serial.print("650");

digitalWrite(AIN2, LOW);

digitalWrite(AIN1, HIGH);

delay(750);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

constant = false;

justStart = true;

}

else if(isMovingBack == true) // moving at a high speed backward

{

Serial.print("650");

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, HIGH);

delay(750);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

constant = false;

justStart = true;

}

}

else

{

if(justStart == false) // started awhile

{

if(isMovingForward == true) // moving at a high speed forward

{

Serial.print("300");

digitalWrite(AIN2, LOW);

digitalWrite(AIN1, HIGH);

delay(350);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

else if(isMovingBack == true) // moving at a high speed backward

{

Serial.print("300");

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, HIGH);

delay(350);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

}

else // if just starting

{

if(isMovingForward == true) // moving at a high speed forward

{

Serial.print("100");

digitalWrite(AIN2, LOW);

digitalWrite(AIN1, HIGH);

delay(200);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

else if(isMovingBack == true) // moving at a high speed backward

{

Serial.print("100");

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, HIGH);

delay(200);

digitalWrite(BIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(AIN1, LOW);

digitalWrite(AIN2, LOW);

isMovingForward = false;

isMovingBack = false;

isRight = false;

isLeft = false;

power = 0;

gear = 0;

speedCounter = 0;

speedCounter2 = 0;

justStart = true;

}

}

}

//debugging purposes, can be removed after testing

/*

displayText.setData(distance);

displayText.setUnit("cm");

displayText.update();

*/

}

// control

void controlUp(int p) // overwrite turning controls if up is pressed

{

//Serial.println("up");

analogWrite(AIN2, p);

digitalWrite(AIN1, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(BIN2, LOW);

isMovingForward = true;

isMovingBack = false;

isRight = false;

isLeft = false;

}

void controlDown(int p) // overwrite turning controls if down is pressed

{

//Serial.println("down");

analogWrite(AIN1, p);

digitalWrite(AIN2, LOW);

digitalWrite(BIN1, LOW);

digitalWrite(BIN2, LOW);

isMovingBack = true;

isMovingForward = false;

isRight = false;

isLeft = false;

}

void controlLeft(int p)

{

//Serial.println("left turn");

if(isLeft == false) // left turn while moving forward

{

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

else

{

// continue but different speed

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

}

void controlLeftB(int p)

{

//Serial.println("left turn back");

if(isLeft == false) // left turn while moving backward

{

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

else

{

// continue but different speed

digitalWrite(BIN1, HIGH);

digitalWrite(BIN2, LOW);

isLeft = true;

isRight = false;

}

}

void controlRight(int p)

{

//Serial.println("right turn");

if(isRight == false) // right turn while moving forward

{

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

else

{

// continue but different speed

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

}

void controlRightB(int p)

{

//Serial.println("right turn back");

if(isRight == false) // right turn after while moving backward

{

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

else

{

// continue but different speed

digitalWrite(BIN2, HIGH);

digitalWrite(BIN1, LOW);

isRight = true;

isLeft = false;

}

}

// loading of UI

void UI()

{

//update once

frontLight.update();

//controls

up.update();

left.update();

down.update();

right.update();

kill.update();

//speed

topSpeed.update();

honk.update();

//debugging purposes

//displayText.update();

loadOnce = false; // UI loaded once

}

void loop() {

// put your main code here, to run repeatedly:

// only occur when speed is changed

//Serial.println("Low speed");

if(topSpeed.isPressed())

{

Serial.println("Top speed");

if(gear == 1)

{

Serial.println("g2");

power = 255;

if(isMovingForward == true) // check if car is moving forward

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

else if(isMovingBack == true) // check if car is moving backward

{

if(isRight == true)

{

controlRightB(power); // still turning right

}

else if(isLeft == true)

{

controlLeftB(power); // still turning left

}

else

{

controlDown(power); // still moving backward

}

}

gear = 2;

}

else if(gear == 2)

{

Serial.println("g2");

power = 120;

if(isMovingForward == true) // check if moving forward

{

if(isRight == true)

{

controlRight(power); // still turning right

}

else if(isLeft == true)

{

controlLeft(power); // still turning left

}

else

{

controlUp(power); // still moving forward

}

}

else if(isMovingBack == true) // check if moving backward

{

if(isRight == true)

{

controlRightB(power); // still turning right

}

else if(isLeft == true)

{

controlLeftB(power); // still turning left

}

else

{

controlDown(power); // still moving backward

}

}

gear = 1;

}

}

if(power == 0)

{

//Serial.println("Power more than 0");

if(up.isPressed())

{

power = 120;

gear = 1;

controlUp(power); // move forward

}

if(down.isPressed())

{

power = 120;

gear = 1;

controlDown(power); // move back

}

if(left.isPressed())

{

if(isMovingBack == true)

{

controlLeftB(power); // turn left backward

}

else if(isMovingForward == true)

{

controlLeft(power); // turn left

}

}

if(right.isPressed())

{

if(isMovingBack == true)

{

controlRightB(power); // turn right backward

}

else if(isMovingForward == true)

{

controlRight(power); // turn right

}

}

if(kill.isPressed())

{

Halt(); // stop

}

}

else

{

//Serial.println("Power more than 0");

if(up.isPressed())

{

controlUp(power); // move forward

}

if(down.isPressed())

{

controlDown(power); // move back

}

if(left.isPressed())

{

if(isMovingBack == true)

{

controlLeftB(power); // turn left backward

}

else if(isMovingForward == true)

{

controlLeft(power); // turn left

}

}

if(right.isPressed())

{

if(isMovingBack == true)

{

controlRightB(power); // turn right backward

}

else if(isMovingForward == true)

{

controlRight(power); // turn right

}

}

if(kill.isPressed())

{

Halt(); // stop

}

}

light(); // check lights and light up

if(isMovingBack == true) // check if moving back

beep(); // ultrasonic to beep, reduce speed and halt

else if(isMovingForward == true) // check if moving forward

frontbeep(); // ultrasonic to beep, reduce speed and halt

else

noTone(buzzer);

if(loadOnce == true) // update UI once

{

UI(); // update UI, loadOnce = false

}

honkBeep(); //honk

// rough estimation of the power used

// to hit a certain constant speed

if(power == 255)

{

if(speedCounter >= 4)

{

// assuming that the car is now at a state of constant speed

// after running at a power of 255 for maybe a rough estimated

// duration of 0.5

constant = true;

speedCounter2 == 0;

}

speedCounter++;

}

else

{

if(speedCounter2 >= 0 && speedCounter2 <= 5)

{

// the opposite effect of the above code

constant = false;

justStart = true;

}

else if(speedCounter2 > 10)

{

constant = false;

speedCounter == 0;

justStart = false;

}

speedCounter2++;

}

delay(100);

}