Introduction: UCL - Embedded - RMC/Autonomous Linetracking Car

In this school project I made a car that can be remote controlled and set in autonomous mode where it’s able to follow a black line. The joystick sends data via Bluetooth to the car, the controls consist of two potentiometers which control the speed and direction, two switches for mode selection and start/stop. On the joystick there is a display that gives a few information. In autonomous mode it uses three IR-sensors to track the line. In both manual and autonomous mode there’s an ultra-sonic sensor that prevents the car from driving into stuff.

Step 1: Video / Pictures

The steering in manual mode is very clunky, my original idea was to use one xy-joystick, but the output values were too random, that’s the reason why I’m using two potentiometers instead. A better alternative is to use two xy-joysticks and then only use one axis on both.

Step 2: Components List

In this project I’ve used Arduino mega’s instead of uno’s for convenience sake. With the mega’s I was able to use the serial monitor, and upload programs while the Bluetooth/serial communication was running. The arduino uno used in this project is only used to read the output from the ultrasonic sensor, this should be possible to do with an interrupt pin, a smart library or better code, but I wasn’t able to figure it out. To reduce the amount of components used you could also create an APP and replace the joystick.

2x Arduino
mega

1x Arduino uno

2x HC-05 bluetooth modul

2x breadboard

2x dc motor

1x l298n motor driver

1x Car chassis

2x wheels

1x Servo motor

3x IR obstacle sensor

1x ultrasonic sensor

1x LCD

2x potentiometer

2x slide switch

2x push button switch

Battery (7,2 V RC car battery preferable)

Wires

Resistances

- 2x 2k Ohm

- 2x 1k Ohm

Cable ties

Insulating tape

Step 3: Wiring Diagrams

Before wiring everything up, start with configuring the Bluetooth modules, this is described later in the guide.

When finished wiring everything up you must calibrate the IR sensors, you do that by adjusting the onboard potentiometer.

Step 4: Bluetooth Communication Setup

To configure the Bluetooth master/slave, you must upload an empty sketch to the Arduino and connect the Bluetooth module almost like in the sketch, but Rx to Rx, Tx to Tx and 5v on the EN pin on the Bluetooth module. NB you can’t upload the program if Rx and Tx is connected. When powering the Bluetooth module hold the switch above EN pin and the LED will start flashing every 2 seconds. Now open the serial monitor and chose “Both NL & CR” in the dropdown menu. Type in “AT”, if you receive OK you have connection. The first module we configure is the Slave Arduino, the commands we are going to use is “AT+UART?” to check the baud rate, in this project I’ve used 38400, if the baud rate is different type “AT+UART=38400,0,0”. Next command is “AT+ROLE?” which should be 0 for slave. Then “AT+ADDR?” to check the address of the module. Write the address down and change the semicolons to commas.

Change the Bluetooth module to the master module, power it up with the EN switch pressed like earlier. Change the role to 1, for master, check the baud rate, change if necessary. Use “AT+CMODE=0” for automatic connection to a partner. “AT+BIND= address of the slave” fx “AT+BIND=98d3,31,3058b0”.

Step 5: CAD Drawings

1. Ultra sonic sensor bracket

2. IR sensor bracket

3. Potentiometer bracket

I’ve 3D-printed three small brackets, one for the ultra-sonic sensor, this need a few adjustments, a holder for the potentiometers, and for the IR-sensors. The IR-sensors needs to be raised about 2 cm to work properly.

These drawings are not optimal for this project so I would recommend making your own.

Step 6: Flow Diagrams

Step 7: CODE - Car

<p>// Car arduino<br>// BY MB
////////////////////////////////////////////////////////////////////
//************************Libraries*******************************\\
////////////////////////////////////////////////////////////////////</p><p>#include <easytransfer.h>
#include <servo.h></servo.h></easytransfer.h></p><p>////////////////////////////////////////////////////////////////////
//**********************Communication*****************************\\
///////////////////////////////////////////////////////////////////</p><p>/*********Easy transfer*********\\</p><p>EasyTransfer ET; // receive joystick
EasyTransfer ET1; // send joystick
EasyTransfer ET2; // rec Ultra Sonic</p><p>struct RECEIVE_DATA_STRUCTURE {
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t joystick_rx;
  int16_t joystick_ry;
  boolean joystick_switch; //pullup "always high" low on press
  unsigned int komTest = 0;
  boolean startSwitch;</p><p>};</p><p>//give a name to the group of data
RECEIVE_DATA_STRUCTURE mydata_receive;</p><p>struct SEND_DATA_STRUCTURE {
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t mode;
  int16_t startStop;
  int16_t ultraVal;</p><p>};</p><p>//give a name to the group of data
SEND_DATA_STRUCTURE mydata_send;</p><p>struct RECEIVE_ULTRA_STRUCTURE {
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t distance;</p><p>};</p><p>//give a name to the group of data
RECEIVE_ULTRA_STRUCTURE ultra_receive;</p><p>////////////////////////////////////////////////////////////////////
//***************************Variables****************************\\
////////////////////////////////////////////////////////////////////</p><p>Servo distServo; // Servo for ultrasonic sensor</p><p>unsigned long previousMillis = 0; // Send / receive delay
const long interval = 20;</p><p>unsigned long serialPreviousMillis = 0; // PC serial monitor delay
const long serialInterval = 200;</p><p>int motorRightSpeed; // Analog output for motors
int motorLeftSpeed;</p><p>int menuMode = 0; // Menu 1 = RMC, Menu 0 = autonomous
int startStop = 0;
unsigned long switchPreviousMillis = 0;
const long switchInterval = 500; // delay between switch reading</p><p>unsigned long servoPreviousMillis = 0;
const long servoInterval = 10; // Interval between servo decr/incr
int i = 0; // Servo speed PWM value
int servoLoopFlag = 0; //Servo speed up/down flag
int servoMax = 180;
int servoMin = 80;</p><p>/*long duration; // Ultra sonic sensor travel time
  int distance;  // calculated distance
  int trigState = LOW; //state of trigPin
  int ultraInterval = 1; // interval in milliseconds at which trigPin turns on
  int ultraPreviousMillis = 0;
*/
int filterUltra;</p><p>////////////////////////////////////////////////////////////////////
//*************************IO PIN LIST****************************\\
////////////////////////////////////////////////////////////////////</p><p>const int motorLeftPinBackward = 2;
const int motorLeftPinForward = 3;
const int motorRightPinBackward = 4;
const int motorRightPinForward = 5;
const int servoPinDistanceSensor = 6;
const int rightIRSensor = 7;
const int leftIRSensor = 8;
const int motorRightSpeedPin = 9; // Analog output
const int motorLeftSpeedPin = 10; // Analog output
//const int distTrigPin = 11;
//const int distEchoPin = 12;
const int midIRSensor = 13;</p><p>void setup() {</p><p>  Serial.begin(9600); // PC Serial monitor
  Serial1.begin(38400); // Bluetooth com port
  Serial2.begin(9600); // Ultra sonic com port</p><p>  ET.begin(details(mydata_receive), &Serial1);
  ET1.begin(details(mydata_send), &Serial1);
  ET2.begin(details(ultra_receive), &Serial2);</p><p>  pinMode(motorRightPinForward, OUTPUT);
  pinMode(motorRightPinBackward, OUTPUT);
  pinMode(motorLeftPinForward, OUTPUT);
  pinMode(motorLeftPinBackward, OUTPUT);
  distServo.attach(servoPinDistanceSensor);
  pinMode(rightIRSensor, INPUT);
  pinMode(leftIRSensor, INPUT);
  pinMode(motorRightSpeedPin, OUTPUT);
  pinMode(motorLeftSpeedPin, OUTPUT);
  // pinMode(distTrigPin, OUTPUT);
  // pinMode(distEchoPin, INPUT);
  pinMode(midIRSensor, INPUT);
  //pinMode(ultraOverLimit, INPUT);
}</p><p>void loop() {</p><p>  //////////////////////////////////////////////////////////////////////////
  //************************** SEND/RECEIVE DATA  **************************
  //////////////////////////////////////////////////////////////////////////</p><p>  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (ET.receiveData()) {</p><p>    }</p><p>    if (ET2.receiveData()) {</p><p>    }
    mydata_send.mode = menuMode;
    mydata_send.startStop = startStop;
    mydata_send.ultraVal = filterUltra;
    //filterUltra = 20;
    ET1.sendData();
  }</p><p>  filterUltra = filter(ultra_receive.distance, filterUltra);</p><p>  ////////////////////////////////////////////////////////////////////
  //************************** MENU MODE *****************************
  ////////////////////////////////////////////////////////////////////</p><p>  unsigned long switchCurrentMillis = millis();</p><p>  if (mydata_receive.joystick_switch == LOW && menuMode == 0) //FLIP FLOP
  {</p><p>    if (switchCurrentMillis - switchPreviousMillis >= switchInterval) {
      switchPreviousMillis = switchCurrentMillis;
      menuMode = 1;
      startStop = 0;
      //Serial.println(menuMode);
    }
  }
  if (mydata_receive.joystick_switch == LOW && menuMode == 1)
  {</p><p>    if (switchCurrentMillis - switchPreviousMillis >= switchInterval) {
      switchPreviousMillis = switchCurrentMillis;
      menuMode = 0;
      startStop = 0;
      //Serial.println(menuMode);
    }</p><p>  }</p><p>  if (mydata_receive.startSwitch == LOW && startStop == 0)
  {</p><p>    if (switchCurrentMillis - switchPreviousMillis >= switchInterval) {
      switchPreviousMillis = switchCurrentMillis;
      startStop = 1;
      //Serial.println(startStop);
    }
  }
  if (mydata_receive.startSwitch == LOW && startStop == 1)
  {</p><p>    if (switchCurrentMillis - switchPreviousMillis >= switchInterval) {
      switchPreviousMillis = switchCurrentMillis;
      startStop = 0;</p><p>      //Serial.println(startStop);
    }</p><p>  }
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //***********************************************************MOTOR CONTROL***********************************************************\\
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////</p><p>  if ( startStop == 1) {</p><p>    if (menuMode == 1) { // REMOTE CONTROL</p><p>      if (mydata_receive.joystick_rx >= 520 && filterUltra > 10) // ************************** Forward **************************
      {</p><p>        motorForward();</p><p>        if (mydata_receive.joystick_ry >= 520) // Motor speed forward right
        {</p><p>          motorLeftSpeed = map(mydata_receive.joystick_rx, 520, 1023, 0, 255); // Forward 0-255  LEFT MOTOR SPEED
          motorRightSpeed = motorLeftSpeed - map(mydata_receive.joystick_ry, 520, 1023, 0, motorLeftSpeed); // Forward 0-255  RIGHT MOTOR SPEED</p><p>        }</p><p>        else if (mydata_receive.joystick_ry <= 480) // Motor speed forward left
        {</p><p>          motorRightSpeed = map(mydata_receive.joystick_rx, 520, 1023, 0, 255); // Forward 0-255  RIGHT MOTOR SPEED
          motorLeftSpeed = motorRightSpeed - map(mydata_receive.joystick_ry, 480, 0, 0, motorRightSpeed); // Forward 0-255  LEFT MOTOR SPEED</p><p>        }
        else // Motor speed straight forward
        {
          motorRightSpeed = map(mydata_receive.joystick_rx, 520, 1023, 0, 255);
          motorLeftSpeed = motorRightSpeed;</p><p>        }
      }</p><p>      else if (mydata_receive.joystick_rx <= 480) // ************************** Backwards **************************</p><p>      {</p><p>        motorBackward();</p><p>        if (mydata_receive.joystick_ry >= 520) // Motor speed backward right
        {</p><p>          motorLeftSpeed = map(mydata_receive.joystick_rx, 480, 0, 0, 255); // Backward 0-255  LEFT MOTOR SPEED
          motorRightSpeed = motorLeftSpeed - map(mydata_receive.joystick_ry, 520, 1023, 0, motorLeftSpeed); // Backward 0-255  RIGHT MOTOR SPEED</p><p>        }</p><p>        else if (mydata_receive.joystick_ry <= 480) // Motor speed backward left
        {</p><p>          motorRightSpeed = map(mydata_receive.joystick_rx, 480, 0, 0, 255); // Backward 0-255  LEFT MOTOR SPEED
          motorLeftSpeed = motorRightSpeed - map(mydata_receive.joystick_ry, 480, 0, 0, motorRightSpeed); // Backward 0-255  RIGHT MOTOR SPEED</p><p>        }
        else // Motor speed straight backward
        {
          motorRightSpeed = map(mydata_receive.joystick_rx, 480, 0, 0, 255);
          motorLeftSpeed = motorRightSpeed;
        }
      }</p><p>      else if ( (mydata_receive.joystick_rx > 480 && mydata_receive.joystick_rx < 520) || filterUltra <= 10 )      //************************** BRAKE **************************</p><p>      {</p><p>        motorBrake();</p><p>      }</p><p>    }</p><p>    if (menuMode == 0) { // Autonomous</p><p>int maxRight = 150;
int maxLeft = 150;
int minRight = 0;
int minLeft = 0;
int 
      if (digitalRead(midIRSensor) == 1 && filterUltra > 10) { // go forward until right or left sensor is hit
        motorForward();
        motorRightSpeed = maxRight;
        motorLeftSpeed = maxLeft;
      }</p><p>      if (digitalRead(rightIRSensor) == 1 && filterUltra > 10) { // turn left until middle sensor is activated
        motorForward();
        motorRightSpeed = minRight;
        motorLeftSpeed = maxLeft;
      }</p><p>      if (digitalRead(leftIRSensor) == 1  && filterUltra > 10) { // turn right until middle sensor is activated
        motorForward();</p><p>        motorRightSpeed = maxRight;
        motorLeftSpeed = minLeft;
      }</p><p>      if (filterUltra <= 10) {</p><p>        motorBrake();</p><p>      }</p><p>    }
  }</p><p>  else {
    motorBrake();
  }</p><p>  analogWrite(motorRightSpeedPin, motorRightSpeed);
  analogWrite(motorLeftSpeedPin, motorLeftSpeed);</p><p>  ////////////////////////////////////////////////////////////////////////////////////////////
  //************************** Servo control for ultra sonic sensor **************************
  ////////////////////////////////////////////////////////////////////////////////////////////</p><p>  unsigned long servoCurrentMillis = millis();</p><p>  if ( startStop == 1) {</p><p>    if ((servoCurrentMillis - servoPreviousMillis >= servoInterval) && i < servoMax && servoLoopFlag == 0) {
      servoPreviousMillis = servoCurrentMillis;</p><p>      i++;
      if (i == servoMax) {</p><p>        servoLoopFlag = 1 ;</p><p>      }
    }</p><p>    if ((servoCurrentMillis - servoPreviousMillis >= servoInterval) && i > servoMin && servoLoopFlag == 1) {
      servoPreviousMillis = servoCurrentMillis;</p><p>      i--;</p><p>      if (i == servoMin) {</p><p>        servoLoopFlag = 0 ;</p><p>      }</p><p>    }
  }</p><p>  distServo.write(i); // Analog write servo motor</p><p>  ////////////////////////////////////////////////////////////////////
  //************************** TROUBLESHOOT **************************
  ////////////////////////////////////////////////////////////////////</p><p>  unsigned long serialCurrentMillis = millis();
  if (serialCurrentMillis - serialPreviousMillis >= serialInterval) {
    serialPreviousMillis = serialCurrentMillis;</p><p>    // Serial.println(mydata_receive.komTest);
    // Serial.println(menuMode);
    //  Serial.println(mydata_receive.joystick_switch);
    //Serial.println(ultra_receive.distance);
    //Serial.println(startStop);
    //  /*</p><p>    //  */
    //************************** MOTOR CONTROL **************************
    /*
        Serial.print("\t");
        Serial.print("mydata_receive.joystick_rx  ");
        Serial.print("\t");
        Serial.print(mydata_receive.joystick_rx);
        Serial.print("\t");
        Serial.print("mydata_receive.joystick_ry  ");
        Serial.print("\t");
        Serial.print(mydata_receive.joystick_ry);
        Serial.print("\t");
        Serial.print("MotorHFrem  ");
        Serial.print("\t");
        Serial.print(bitRead(PORTD, motorRightPinForward));
        Serial.print("\t");
        Serial.print("MotorLFREM ");
        Serial.print("\t");
        Serial.print(bitRead(PORTD, motorLeftPinForward));
        Serial.print("\t");
        Serial.print("MotorHTILBAGE  ");
        Serial.print("\t");
        Serial.print(bitRead(PORTD, motorRightPinBackward));
        Serial.print("\t");
        Serial.print("MotorLTILBAGE ");
        Serial.print("\t");
        Serial.print(bitRead(PORTD, motorLeftPinBackward));
        Serial.print("\t");
        Serial.print("MotorL_HASTIGHED ");
        Serial.print("\t");
        Serial.print(motorLeftSpeed);
        Serial.print("\t");
        Serial.print("MotorH_HASTIGHED ");
        Serial.print("\t");
        Serial.println(motorRightSpeed);
        Serial.print("\t");
    */</p><p>    //Serial.println(bitRead(PORTD, 12));</p><p>    //Serial.println(mydata_receive.joystick_rx);
    Serial.print("Højre");
    Serial.print(digitalRead(7));
    Serial.print("\t");
    Serial.print("Midt");
    Serial.print(digitalRead(13));
    Serial.print("\t");
    Serial.print("Venstre");
    Serial.println(digitalRead(8));</p><p>  }</p><p>  /*
     joystick_rx_scaled = map(mydata_receive.joystick_rx, 0, 1023, 0, 255);
     joystick_ry_scaled = map(mydata_receive.joystick_ry, 0, 1023, 0, 255);</p><p>     distServo.write(0);</p><p>     mydata_send.test = mydata_send.test + 1;
  */</p><p>}</p><p>////////////////////////////////////////////////////////////////////
//***********************Functions********************************\\
////////////////////////////////////////////////////////////////////</p><p>void motorForward() {
  digitalWrite(motorRightPinForward, HIGH);
  digitalWrite(motorRightPinBackward, LOW);
  digitalWrite(motorLeftPinForward, HIGH);
  digitalWrite(motorLeftPinBackward, LOW);</p><p>}</p><p>void motorBackward() {
  digitalWrite(motorRightPinForward, LOW);
  digitalWrite(motorRightPinBackward, HIGH);
  digitalWrite(motorLeftPinForward, LOW);
  digitalWrite(motorLeftPinBackward, HIGH);
}</p><p>void motorBrake() {
  digitalWrite(motorRightPinForward, LOW);
  digitalWrite(motorRightPinBackward, LOW);
  digitalWrite(motorLeftPinForward, LOW);
  digitalWrite(motorLeftPinBackward, LOW);
  motorRightSpeed = 0;
  motorLeftSpeed = 0;</p><p>}</p><p>double filter(double lengthOrig, double currentValue) { //Filter from https://github.com/XRobots/openDog/blob/master/Part8/Dog008/Dog008.ino
  double filter = 5;
  double lengthFiltered =  (lengthOrig + (currentValue * filter)) / (filter + 1);
  return lengthFiltered;
}</p>

Step 8: CODE - Joystick

<p>// Joystick arduino<br>// BY MB</p><p>//*********Libraries*********\\</p><p>#include 
#include 
#include 
#include 
#include </p><p>//*********Communication*********\\
//*********Easy transfer*********\\</p><p>EasyTransfer ET; //send
EasyTransfer ET1; //receive</p><p>struct SEND_DATA_STRUCTURE {
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t joystick_rx;
  int16_t joystick_ry;
  boolean joystick_switch;
  unsigned int komTest = 0;
  boolean startSwitch;
};</p><p>//give a name to the group of data
SEND_DATA_STRUCTURE mydata_send;</p><p>struct RECEIVE_DATA_STRUCTURE {
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t mode;
  int16_t startStop;
  int16_t ultraVal;</p><p>};</p><p>//give a name to the group of data
RECEIVE_DATA_STRUCTURE mydata_receive;</p><p>//*********Display*********\\</p><p>#define OLED_MOSI   22
#define OLED_CLK   23
#define OLED_DC    24
#define OLED_CS    25
#define OLED_RESET 26
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);</p><p>//*********Variables*********\\</p><p>unsigned long previousMillis = 0;
const long interval = 20;</p><p>int filterRX;
int filterRY;</p><p>//*********IO LIST*********\\</p><p>const int joystickPinRx = 0; // Analog 0
const int joystickPinRy = 1; // Analog 1
const int joystickPinSwitch = 2; // Digital 2
const int startSwitchPin = 3;</p><p>void setup() {
  Serial.begin(9600); // PC Serial monitor
  Serial1.begin(38400); // Bluetooth com port</p><p>  ET.begin(details(mydata_send), &Serial1);
  ET1.begin(details(mydata_receive), &Serial1);</p><p>  pinMode(joystickPinSwitch, INPUT_PULLUP);
  pinMode(startSwitchPin, INPUT_PULLUP);</p><p>  display.begin(SSD1306_SWITCHCAPVCC);
  display.display();
  delay(1000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);</p><p>}</p><p>void loop() {</p><p>  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;</p><p>    if (ET1.receiveData()) {</p><p>    }</p><p>    mydata_send.joystick_rx = analogRead(joystickPinRx);
    mydata_send.joystick_ry = analogRead(joystickPinRy);
    mydata_send.joystick_switch = digitalRead(joystickPinSwitch);
    mydata_send.startSwitch = digitalRead(startSwitchPin);
    
    mydata_send.komTest = mydata_send.komTest + 1;
    
    filterRX = filter(analogRead(joystickPinRx), filterRX);
    filterRY = filter(analogRead(joystickPinRy), filterRY);</p><p>    //Serial.println(mydata_receive.ultraVal);</p><p>    ET.sendData();
  }
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Start: ");
  display.print(mydata_receive.startStop);
  display.print("  ");
  display.print("Mode: ");
  display.print(mydata_receive.mode);
  display.print("\n");
  display.print("Hastighed: ");
  display.print(filterRX);
  display.print("\n");
  display.print("Retning: ");
  display.print(filterRY);
  display.print("\n");
  display.print("UltraVal: ");
  display.print(mydata_receive.ultraVal);
  display.print("\n");
  display.display();</p><p>  //Serial.println(mydata_receive.test);
  //Serial.println(digitalRead(2));
  //Serial.println(digitalRead(3));</p><p>}</p><p>double filter(double lengthOrig, double currentValue) { //Filter from https://github.com/XRobots/openDog/blob/master/Part8/Dog008/Dog008.ino
  double filter = 5;
  double lengthFiltered =  (lengthOrig + (currentValue * filter)) / (filter + 1);
  return lengthFiltered;
}</p>

Step 9: Code - Ultra-sonic Slave

<p>#include <br>EasyTransfer ET2; // send Ultra Sonic</p><p>struct SEND_ULTRA_STRUCTURE {
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t distance;</p><p>};</p><p>//give a name to the group of data
SEND_ULTRA_STRUCTURE ultra_send;</p><p>int duration;</p><p>const int distTrigPin = 2;
const int distEchoPin = 3;</p><p>void setup() {
  Serial.begin(9600);
  ET2.begin(details(ultra_send), &Serial);</p><p>  pinMode(distTrigPin, OUTPUT);
  pinMode(distEchoPin, INPUT);
 </p><p>}</p><p>void loop() 
{</p><p>    
  //////////////////////////////////////////////////////////////////////////
  //**************************     SEND DATA      **************************
  //////////////////////////////////////////////////////////////////////////
  </p><p>ET2.sendData();</p><p>  //////////////////////////////////////////////////////////////////////////
  //**************************    ULTRA SONIC     **************************
  //////////////////////////////////////////////////////////////////////////</p><p> 
  digitalWrite(distTrigPin, LOW); //code from  https://howtomechatronics.com/tutorials/arduino/ultrasonic-sensor-hc-sr04/
  delayMicroseconds(2);
  digitalWrite(distTrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(distTrigPin, LOW);
  duration = pulseIn(distEchoPin, HIGH); // Reads the distEchoPing, returns the sound wave travel time in microseconds
  ultra_send.distance = duration * 0.034 / 2; // Calculating the distance, (0.034 the speed of sound in air, /2, distance back and forth)
  
}</p>

Step 10: Improvements

- Better noise filtration

- Better CAD-drawings

- More 3D printed stuff

- Better steering

- Better use of functions in the code

- More permanent solutions

- APP-support

Step 11: Conclusion/reflection

In this project I’ve become better at programming Arduino, and learned about serial communication, how to set up Bluetooth communication, making CAD drawing and 3D print them. I’ve managed to create an autonomous car that can follow a line, but there is room for a lot of improvements. Overall it was a fun project and I’m satisfied with the result.