S22: Firebolt

From Embedded Systems Learning Academy
Revision as of 00:00, 28 May 2022 by 243 user1 (talk | contribs) (Software Design)

Jump to: navigation, search
The RC Car

Abstract

Firebolt is battery powered autonomous RC car. The car uses four microcontrollers for communication between the nodes- driver node, motor node, bridge & sensor node, and geological node over the CAN bus. It is interfaced to the mobile application which sends GPS coordinates for the destination location to the driver node and reaches the destination by avoiding any obstacles that comes in the path. For obstacle detection and avoidance it uses Ultrasonic Sensor and makes the decision of steering and maintaining speed after performing calculations based on the bridge and sensor node's data.

Objectives & Introduction

Objectives

The objective of this project is to get hands on experience of application of embedded systems in autonomous vehicles, have understanding of CAN bus communication, CAN database files, TDD and other related tools such as PCAN dongle and Busmaster.

Software side

  • The car communicates with an Android application
  • Receive coordinates from gps to drive itself to the destination while avoiding obstacles
  • Display useful information on the LCD
  • Take care of elevation and make correct speed decisions
  • DBC file for all the nodes

Hardware side

  • Design PCB for four controllers and other necessary components
  • Choose good options for mounting the ultrasonic sensors on the car
  • Make a good GUI Android application for interfacing with the microcontroller

Introduction

Four Nodes of the RC Car are:

  1. Driver Node
  2. GEO Node
  3. Sensors and Bridge Node
  4. Motor Node
  5. Mobile Application

Team Members & Responsibilities

  • Team FireBolt
  • Team FireBolt

Priyanka Rai LinkedIn'

  • Geo Controller
  • GPS and Compass Interfacing
  • Motor Controller
  • Integration Testing
  • Wiki Page Update

Ritu Patil LinkedIn'

  • Motor Controller
  • RPM Sensor
  • Integration Testing
  • Wiki Page Update

Ritika Beniwal LinkedIn'

  • Driver Node
  • LCD interfacing
  • Motor Controller
  • Integration Testing
  • Wiki Page Update

Utsav Savaliya LinkedIn'

  • Sensor Controller
  • Integration Testing
  • Wiki Page Update

Dhanush Babu LinkedIn'

  • Bluetooth module interfacing
  • Motor Controller
  • Android App
  • Integration Testing

Schedule

Week# Start Date Target Date Task Completion Date Status
Week 1
  • 03/06
  • 03/08
  • 03/12
  • 03/10
  • 03/10
  • 03/12
  • Study and discuss previous project reports
  • Brainstorm on the requirements for the project
  • Identify and order/purchase the required components
  • 03/10
  • 03/10
  • 03/12
  • Completed
  • Completed
  • Completed
Week 2
  • 03/13
  • 03/13
  • 03/14
  • 03/14
  • 03/18
  • 03/18
  • Distribute initial roles among the team members
  • Study the datasheets and manual of acquired components
  • Create and setup Gitlab Repository
  • 03/14
  • 03/18
  • 03/18
  • Completed
  • Completed
  • Completed
Week 3
  • 03/20
  • 03/22
  • 03/20
  • 03/25
  • 03/26
  • 03/24
  • Write basic driver for ultrasonic sensor
  • Analyze and decide the hardware placement of the RC Car
  • Create SENSOR and DRIVER nodes to transmit and receive data
  • 03/26
  • 03/23
  • 03/25
  • Completed
  • Completed
  • Completed
Week 4
  • 03/27
  • 03/27
  • 03/27
  • 04/04
  • 04/01
  • 03/28
  • Create the GEO node to get coordinates and cardinal directions from GPS and Compass
  • Create the MOTOR node to drive the RC Car
  • Design DBC file and create CAN signals for every node
  • 04/02
  • 04/04
  • 04/01
  • Completed
  • Completed
  • Completed
Week 5
  • 04/02
  • 04/02
  • 04/02
  • 04/02
  • 04/08
  • 04/08
  • 04/08
  • 04/08
  • Finalize the DBC file
  • Design obstacle avoidance and steering logic on the DRIVER node
  • Design motor driving logic on the MOTOR node with the encoder
  • Start and design the Bluetooth app xml for destination.
  • 04/09
  • 04/09
  • 04/09
  • 04/09
  • Completed
  • Completed
  • Completed
  • Completed
Week 6
  • 04/09
  • 04/09
  • 04/09
  • 04/09
  • 04/09
  • 04/15
  • 04/15
  • 04/15
  • 04/15
  • 04/15
  • Integrate GPS module with compass to get the current location.
  • Write UART interface for Bluetooth integration on sensor node.
  • Get raw sensor data from the ultrasonic sensor.
  • Integrate GEO node to DRIVER node for navigation. Check whether the DRIVER node is receiving the coordinates.
  • Backend development for android app. Should be able to scan BT devices and connect.
  • 04/15
  • 04/15
  • 04/15
  • 04/15
  • 04/15
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
Week 7
  • 04/16
  • 04/16
  • 04/16
  • 04/16
  • 04/16
  • 04/16
  • 04/23
  • 04/23
  • 04/23
  • 04/23
  • 04/23
  • 04/23
  • Communicate to the GEO node over Bluetooth via Android app
  • Complete Driver obstacle logic
  • Design driving decision logic based on the navigation data
  • Lay out basic PCB Board design for mounting the ECUs
  • Filtering ultrasonic sensor data and sending processed data to Driver
  • RPM Sensor logic and testing.
  • 04/26
  • 04/26
  • 04/26
  • 04/26
  • 04/26
  • 04/26
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
Week 8
  • 04/25
  • 04/25
  • 04/25
  • 04/25
  • 04/25
  • 04/25
  • 04/30
  • 04/30
  • 04/30
  • 04/30
  • 04/30
  • 04/30
  • Design a dashboard on the LCD to display the values
  • Driver logic for sensor data and geo data on busmaster.
  • Add functionality for pinning location on maps and extracting latitude and longitude
  • Improve obstacle avoidance logic
  • Break and ramp logic for the motor.
  • Collective Test 1: Drive the car to a hardcoded GPS destination
  • 04/29
  • 04/27
  • 04/30
  • 04/30
  • 04/30
  • 05/06
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
Week 9
  • 05/01
  • 05/01
  • 05/01
  • 05/01
  • 05/01
  • 05/07
  • 05/07
  • 05/07
  • 05/07
  • 05/07
  • Design individual architecture diagrams and algorithms for documentation
  • Make any necessary improvements based on previous test results
  • Complete the final version of the Android app
  • Get the PCB printed
  • Collective Test 2: Test the car driving with navigation data from the Android app
  • 05/10
  • 05/07
  • 05/01
  • 05/07
  • 05/11
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
Week 10
  • 05/09
  • 05/09
  • 05/09
  • 05/09
  • 05/14
  • 05/14
  • 05/14
  • 05/14
  • Replace the circuits with their corresponding PCBs and assemble
  • Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1
  • Refactor the code modules with necessary improvements
  • Collective Test 3: Test car on various terrains and slopes
  • 05/20
  • 05/20
  • 05/20
  • 05/20
  • Completed
  • Completed
  • Completed
  • Completed
Week 11
  • 05/16
  • 05/16
  • 05/16
  • 05/16
  • 05/21
  • 05/21
  • 05/21
  • 05/21
  • Revise and improve the wiki report to cover all the aspects of design and implementation
  • Fix all the errors and make improvements
  • Final testing of all the modules and car
  • Collective Test 4: Have the final version of the project tested with all the functionalities
  • 05/22
  • 05/22
  • 05/22
  • 05/22
  • Completed
  • Completed
  • Completed
  • Completed
Week 12
  • 05/25
  • 05/25
  • 05/27
  • 05/27
  • Demo
  • Final Wiki Page Update with addition of all the problems faced during the development
  • 05/25
  • 05/26
  • Completed
  • Completed


Parts List & Cost

Item# Part Desciption Vendor Qty Price($)
1 RC Car Traxxas [1] 1 280
2 CAN Transceivers MCP2551-I/P Comimark [2] 5 8.99
3 Ultrasonic Sensors Max Botix[3] 4 24.95
4 GPS Breakout Board Adafruit[4] 1 29.95
5 GPS Antenna Adafruit[5] 1 19.95
6 RPSMA female to mhf4 Superbat[6] 1 7.99
7 HC05 bluetooth RF Transceiver HiLetgo[7] 1 15.99
8 Triple-axis Accelerometer Adafruit[8] 1 14.95
9 Traxxas RPM Sensor Traxxas[9] 1 13.76
10 Traxxas Battery and Charger Traxxas[10] 1 62.95
11 Voltage Regulator Valefod[11] 6 10.99
12 Headlights Hobbypark[12] 1 7.96


Printed Circuit Board

Initially we started our testing with mounting all our hardware on the breadboard (yes, it was messy and unstable!).

  • Initial_Hardware


PCB Schematic

  • Schematic
  • Final_Board


PCB Board

  • Top_Side
  • Bottom_Side

Challenges

  • Since there are four controllers and a significant number of components (gps, sensors, can transceivers, volt regulator etc.) it was difficult for us to keep our hardware stable because every time we go for field testing some will get disconnected and we were kind of stuck up in the hardware setup.
  • We decided to get the PCB printed but there were some issues and resolving them and getting a new PCB would take time.

Solution

  • Finally we decided to use the prototype board for mounting all the components and stabilizing our hardware.
  • Protoype_Board

CAN Communication

We used controller area network to communicate data between four nodes. All nodes are connected to each other through a physically conventional two wire bus CANH and CANL. The wires are a twisted pair with 120 Ω termination resistors at each end of the bus. 1s and 0s are transmitted as CAN High(0V difference) and Can Low(2v difference). A CAN frame has the following contents:

  • Data Length Code (4bits)
  • Remote Transmission Request.
  • ID extend bit.
  • Message ID (11 bit or 29 bit)
  • Data bytes( depends on DLC)
  • CRC


Arbitration: No two nodes will transmit at the same time because of arbitration. A lower Message-ID has a Higher priority on the CAN bus since 0 is the dominant bit.

Bit Stuffing: CAN bus stuffs extra bits when a long chain of multiple 1's or 0's occur to improve CAN integrity.

Project Can Bus Diagram


DBC File

The DBC file is a simple text file that consists of information for decoding raw CAN bus data to physical values or in human readable form.


Sr. No Message ID Message function Receivers
Driver command
1 300 Speed and steering direction for the motor Motor
2 100 Driver Heartbeat Motor, Sensor, Geo
Sensor And Bridge Controller
3 200 Sensor sonars from front, back, left ,right sensor Driver
Motor Controller
4 600 motor speed, motor direction Driver
Geo Controller
8 400 Bearing, Heading and Distance Driver
Debug messages
6 700 Driver Debug BRIDGE_SENSOR,MOTOR,GEO
7 750 Geo Debug BRIDGE_SENSOR,MOTOR,DRIVER
VERSION ""
NS_ :
    BA_
    BA_DEF_
    BA_DEF_DEF_
    BA_DEF_DEF_REL_
    BA_DEF_REL_
    BA_DEF_SGTYPE_
    BA_REL_
    BA_SGTYPE_
    BO_TX_BU_
    BU_BO_REL_
    BU_EV_REL_
    BU_SG_REL_
    CAT_
    CAT_DEF_
    CM_
    ENVVAR_DATA_
    EV_DATA_
    FILTER
    NS_DESC_
    SGTYPE_
    SGTYPE_VAL_
    SG_MUL_VAL_
    SIGTYPE_VALTYPE_
    SIG_GROUP_
    SIG_TYPE_REF_
    SIG_VALTYPE_
    VAL_
    VAL_TABLE_
BS_:

BU_: DRIVER MOTOR BRIDGE_SENSOR GEO DEBUG

BO_ 100 DRIVER_HEARTBEAT: 1 DRIVER
  SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" BRIDGE_SENSOR,MOTOR,GEO

BO_ 101 DRIVE_STATUS: 1 BRIDGE_SENSOR
  SG_ DRIVE_START_STOP : 0|8@1+ (1,0) [0|0] "" DRIVER

BO_ 200 SENSOR_SONARS: 5 BRIDGE_SENSOR
 SG_ SENSOR_SONARS_left : 0|10@1+ (1,0) [0|0] "cm" DRIVER
 SG_ SENSOR_SONARS_right : 10|10@1+ (1,0) [0|0] "cm" DRIVER
 SG_ SENSOR_SONARS_middle : 20|10@1+ (1,0) [0|0] "cm" DRIVER
 SG_ SENSOR_SONARS_rear : 30|10@1+ (1,0) [0|0] "cm" DRIVER

BO_ 250 DESTINATION_LOCATION: 8 BRIDGE_SENSOR
 SG_ DEST_LATITUDE : 0|28@1+ (0.000001,-90.000000) [-90|90] "degrees" GEO
 SG_ DEST_LONGITUDE : 28|28@1+ (0.000001,-180.000000) [-180|180] "degrees" GEO

BO_ 300 DRIVER_TO_MOTOR: 2 DRIVER
SG_ DRIVER_TO_MOTOR_speed : 0|8@1+ (0.1,-10) [-10|10] "kmph" MOTOR, BRIDGE_SENSOR
 SG_ DRIVER_TO_MOTOR_direction : 8|8@1+ (1,-45) [-45|45] "degrees" MOTOR, BRIDGE_SENSOR

BO_ 400 GEO_CONTROLLER_COMPASS: 8 GEO
  SG_ HEADING : 0|12@1+ (0.1,0) [0|359.9] "degrees" DRIVER, BRIDGE_SENSOR
  SG_ BEARING : 12|12@1+ (0.1,0) [0|359.9] "degrees" DRIVER,BRIDGE_SENSOR
  SG_ DISTANCE_TO_DESTINATION: 24|32@1+ (0.01,0) [0|359.9] "meters" DRIVER,BRIDGE_SENSOR

BO_ 600 MOTOR_SPEED: 2 MOTOR
SG_ MOTOR_SPEED_info : 0|8@1+ (0.1,-10) [-10|10] "kmph" DRIVER, BRIDGE_SENSOR


BO_ 700 DRIVER_DEBUG: 2 DEBUG
  SG_ car_driving_status: 0|8@1+ (1,0) [0|0] "" DEBUG
  SG_ car_steering_status: 8|8@1+ (1,0) [0|0] "" DEBUG

BO_ 750 GEO_CONTROLLER_DEBUG_MESG: 10 DEBUG
 SG_ CURR_LATITUDE : 0|28@1+ (0.000001,-90.000000) [-90|90] "degrees" DEBUG
 SG_ CURR_LONGITUDE : 28|28@1+ (0.000001,-180.000000) [-180|180] "degrees" DEBUG
 SG_ RAW_HEADING : 56|12@1+ (0.1,0) [0|359.9] "degrees" DEBUG

CM_ BU_ DRIVER "The driver controller driving the car";
CM_ BU_ MOTOR "The motor controller of the car";
CM_ BU_ SENSOR "The sensor controller of the car";
CM_ BO_ 100 "Sync message used to synchronize the controllers";
CM_ BU_ GEO "To provide raw GPS and compass heading";
CM_ SG_ 100 DRIVER_HEARTBEAT_cmd "Heartbeat command from the driver";

VAL_ 700 car_steering_status 2 "RIGHT" 1 "LEFT" 0 "STRAIGHT";
VAL_ 700 car_driving_status 2 "BACKWARD" 1 "FORWARD" 0 "STOPPED";

Sensor and Bluetooth ECU

Sensor Controller Diagram

The obstacle detection sensors used here are Ultrasonic sensors. The HRLV-MaxSonar-EZ1 sensors from MaxBotix are used here. In these sensors there is membrane which needs to be triggered in order to generate and send ultrasonic objects every few seconds. When ultrasonic waves collide and come back and strikes with this membrane a pulse is generated which is used for sensing.

Hardware Design

Pin connections between board and sensor:

Sensor Controller Diagram



Software Design

The sensor node has to receive values from all the sensors and send the distance values on the CAN bus for the driver to run the obstacle avoidance logic.

1. Receive sensor values:

Four sensors are used here. Three in the front and one at the rear side. We need four ADC channels to address the receiving from all sensors. In order to use four pins on the SJ2 board we need to set the pins to analog mode. In the adc.h file and adc.c file there are only three channels initialized, so one needs to add ADC channel 3 in these files. On how to use these sensors, the datasheet of helped a lot. It addresses every aspect of how to use this particular sensor and the solution to most of the problem that can arise. All the sensor raw values are digitally converted in the range of 0 to 1024( 10 bit ADC). These value is in inches as mentioned in the datasheet. So, one needs to convert it into centimeter by applying some formula. The formula can be different based on the configuration used to setup the ADC channel even if same sensor is used.

Technical Challenges

The main challenge while using ultrasonic sensor with this particular project is of crosstalk. While detecting objects in the front all the front sensors waves are interfering with each other giving false values in the left or right sensor while the object is in the front only. The datasheet addresses this issues and what to do when multiple sensors are used in a system. It says that trigger each sensor are different time period in order to avoid crosstalk. So we triggered the front and rear at one particular time and left and right at one particular time. One sequence is triggered at psrticular 10Hz and other sequence is triggered at another 10Hz. There is a division of callbacks counts in 100Hz and a lock mechanism is used in order to used different 20Hz period out of 100Hz.

For frequency noise measurements like when the values suddenly change or vary between certain range sometimes, a filter is implemented. The most common filter for this type of use is median filter where a series of values are stored in a array and median is taken of all the values stored in that array.




Motor ECU

The Motor ECU acts as an encoder for the DC motor (used for propulsion) and Servo motor (used for turning the axle and changing direction of the car). The car is a two wheel drive with DC motor connected to the rear wheels and the servo motor is connected to the front wheels. The DC motor is controlled by Electronic Speed Control. The ECU supplies PWM signal to the ESC and the ESC powers the DC motor. The Servo motor is powered by the car battery as well and gets its PWM signal from the ECU. The RPM sensor sends its output to motor ECU by which the actual speed of the wheels is calculated.

Hardware Design

Hardware Schematic Diagram

ESC & DC Motor

The DC motor is controlled by ESC using PWM signals provided by the motor controller for forward and reverse movements. We used the 9v NiMH battery to power up the ESC. The DC motor is powered by the ESC which has a dc-to-dc converter which converts 9v to 6v. The output from the ESC is used to power the Servo motor. ESC has an ease set button which is used for calibration and setting different modes for the car.

The car can be operated in the following 3 modes:
Sport mode(100% Forward, 100% Brakes, 100% Reverse)
Racing mode(100% Forward, 100% Brakes, No Reverse)
Training mode(50% Forward, 100% Brakes, 50% Reverse)

As we desire to run the car at full throttle, Sport mode is being used. The frequency of the PWM signal fed to the servo motor is 100Hz. Based on the duty cycle set by the user, the car will go forward, reverse, or neutral.
PWM 10 to 14.9 for reverse.
PWM 15 for neutral.
PWM 15.1 to 20 for the forward.

Wires on ESC Description Wire Color
PWM(P2.1) Takes PWM input from SJ2-Board WHITE
VDD(6V) Power Output RED
GND Ground BLACK



Traxxas ESC
Traxxas Brushless DC Motor

Servo Motor

We are using Traxxas 2075 for this project which came with the car and it is responsible for steering the car. It takes the 6V power directly from ESC. The servo motor is controlled directly from the SJ2 micro-controller board. The PWM signal is supplied at a frequency of 100 Hz. Based on the duty cycle of the signal sent to the servo, the direction of servo motor can be changed:

PWM 10 to 14.9 for turning left.
PWM 15 for straight.
PWM 15.1 to 20 for turning right.

Wires on ESC Description Wire Color
PWM(P2.0) Takes PWM input from SJ2-Board WHITE
VDD(6V) Power Input RED
GND Ground BLACK
Traxass Servo Motor(2075)

RPM Sensor

The RPM sensor is used as an input to maintain a constant speed of the vehicle. The sensor we are using is Traxxas RPM sensor which using hall effect to detect the movement of the DC motor.
Mounting the sensor:
There are two parts to the RPM sensor - one is the trigger magnet and the other is the sensor. The sensor mounts on the inside of the gear cover, the trigger magnet mounts on the DC motor shaft. The gear cover and motor shaft need to be removed using the toolkit provided along with the RC car. The mounting process can be found on youtube.
How the sensor works:
The trigger magnet attaches to the spur gear. The sensor uses the DC voltage of the motor to trigger a pulse on the sensor for every rotation of the spur gear. These pulses are sent as hardware interrupt to the SJ2 board. The number of pulses are counted for every half second and that is converted into RPM and KMPH. The RPM sensor has 3 wires, the white wire is the output wire that provides the pulses to the SJ2 Board, and the other wires are Supply(3.3V) and GND.

Wires on ESC Description Wire Color
GPIO(P0.6) Provides pulses to Motor SJ2-Board WHITE
VDD(3.3V) Power Input RED
GND Ground BLACK


Traxxas RPM Sensor
Trigger Magnet

Software Design

At startup the motor is initialized by giving a neutral PWM signal for 3s and the interrupt for the rpm sensor input is setup as well.

The motor receives angle for steering and speed in a single CAN message from the driver ECU. After receiving the command the speed value is converted into corresponding value of PWM by increasing or decreasing neutral PWM value in steps of 0.01. The physical value of the motor speed is compared to the speed received from the driver and it is reduced or increased to match with the desired speed. For reverse a PWM of 14.5 is given to smoothly reverse the car.

The direction of the car is set according to the value of ENUM received from the driver ECU. For navigation the car takes soft turns and when and obstacle is detected it takes hard turns to avoid collisions.


Speed Control Flowchart

Technical Challenges

  • ESC calibration: The ESC controlling the DC motor goes out of calibration again and again. We had to connect it to the receiver of the RC car and re-calibrate it again. Finally I added a neutral signal in for the first 3 seconds in the initialization sequence of the motor so that the ESC can be calibrated every time the controller is reset or powered on.
  • Changing PWM: PWM value of the motor will change sometimes and depends on the weight of the car and also a faster speed might not give enough time for the sensor to detect an obstacle. Hence keeping a slow and steady speed and relying on the RPM sensor is necessary to ensure the car keeps moving and doesn't stop on any inclines.
  • Receiving steer commands at higher frequency helped in reducing the response time in obstacle avoidance.




Geographical And Bridge Controller

Hardware Design

The Geographical controller does the processing for compass data and GPS data. After processing the data for heading ,bearing and distance to destination , the controller sends these data over can bus to the Driver node. The GPS module is interfaced with SJ2 board using UART. SJ2 board gets the data (NMEA string) for GPS coordinates processing. The controller sends the command to GPS module to filter the string and only send GPGGA string. The Compass module is interfaced over I2C to find the heading for car navigation. The CAN transceiver uses port 0 (can1) of the SJ2 board.

  • Geo Node Schematic.jpg
  • 3 Axis Magnetometer (eCompass)
  • GPS Module

  • Table :Geographical Node Pinout
    SJTwo Board GPS/Compass Module Description
    P0.15 (TX3) RX Adafruit GPS Breakout
    P0.16 (RX3) TX Adafruit GPS Breakout
    P0.10 (SDA) SDA Adafruit Magnetometer
    P0.11 (SCL) SCL Adafruit Magnetometer
    P0.1 CAN transceiver (Tx) CAN transmit
    P0.0 CAN transceiver (Rx) CAN receive
    Vcc 3.3V Vcc Vcc
    GND GND Ground


    Software Design

    The GEO controller consisted of 4 main parts which are: 1. GPS Module 2. Compass 3.Waypoints Algorithm 4. Geo Logic

    Overview

    The geographical node calls periodically the following code modules:

    • gps.c
    • compass.c
    • checkpoint.c
    • geological.c
    • can_bus_message_handler.c

    These modules, calculate compass heading degree, bearing, parse GPS coordinates, calculate the checkpoints the RC car has to go through when navigating to a destination, send distance to destination to driver node, and handle messages received on the CAN bus.

    • The period_callbacks__initialize() function calls the following functions:
      • can_bus_initializer__init(): initializes the CAN bus to handle MIA and messages.
      • geological__init(): initializes the GPS, compass, and checkpoint algorithm.
    • The period_callbacks__1Hz() function calls the following function:
      • can_bus_initializer__handle_bus_off()
    • The period_callbacks__10Hz() function calls the following functions:
      • can_bus_message_handler__manage_mia_10Hz() to manage MIA signals.
      • can_bus_meesage_handler__handle_all_incoming_messages_10Hz() to handle messages on the CAN bus (e.g. destination coordinates from Bridge sensor node).

    GPS

    Initialization

    In the initialization process of the GPS, the line buffer module is configured to parse the GPS messages, the GPIOs P4.28(Tx) and P4.29(Rx) are configured, UART interrupt queues enabled, and the UART is configured at a baudrate of 9600.

    Configuration

    In the gps__run_once_10Hz() the GPS is initially configured once to disable all NMEA messages except GNGGA which is message chosen to parse the coordinates and GPS lock.

    Parsing NMEA GNGGA messages

    The GPS module constantly transmits NMEA GNGGA messages over UART to the SJTwo MCU. These messages which come in the form of a string are stored character by character in the line buffer until a new line character which indicates the end of string. The stored string is then extracted from the line buffer and the checksum is verified to ensure that the message is not corrupted. The extracted line is then tokenized to parse the latitude, latitude direction, longitude, longitude direction, and fix quality. South and West directions are also properly handled to make the latitude and longitude negative values.

    GPS lock

    The GPS lock is a function in the gps.c module that has the job to set a bool flag and blink an LED when the fix quality is either 1 or 2 in the GNGGA message. When the fix quality is one of those values it means the GPS has acquired a good connection to the satellites and the data received is valid. The LED blinking functionality was used for debugging purposes indicating the GPS has a lock. Whereas the bool flag was used as a condition to calculate the bearing and checkpoints only when the GPS had a lock meaning that the current coordinates were valid.

    Compass

    Initialization

    The compass initialization configures the HMC5883L magnetometer registers over I2C bus to default settings using a gain of 1090 and single mode.

    Heading degree computation

    The compass heading degree is computed by using the tilt compensation algorithm and the pitch and roll values calculated from the SJTwo accelerometer. The tilt compensation algorithm ensures that the values of the compass heading are precise within an error of 1 to 2 degrees when the compass is tilted in all directions. Shown below are the formulas used to compute the heading degree referenced from this link.

    Pitch and Roll:

    pitch = asin(-accelerometer_x_axis) 
    roll = asin(accelerometer_y_axis / cos(pitch)

    Tilt compensated magnetic sensor values for x and y:

    Mx_c = (Mx - offset_x_axis) * cos(pitch) + Mz * sin(pitch)
    My_c = (Mx - offset_x_axis) * sin(roll) * sin(pitch) + (My - offset_y) * cos(roll) - Mz * sin(roll) cos(pitch)
    • where:
      • Mx_c = Magnetometer x-axis tilt compensated
      • My_c = Magnetometer y-axis tilt compensated
      • Mx = Magnetometer x-axis value
      • My = Magnetometer y-axis value
      • Mz = Magnetometer z-axis value

    The offset values for x and y are calculated during calibration to reduce soft-iron and hard-iron distortions. Soft-iron distortions are generally caused by nearby metals such nickel and iron in which distorts the existing magnetic field of the compass depending in which direction the field acts. Hard-iron distortions are produced by objects that generate a magnetic field such as the motor of the RC car causing a permanent bias in the compass sensor if not corrected.

    To calculate the scale factors for x and y to reduce soft-iron distortions the following equations were used:

    a = (max_y - min_y) / (max_x - min_x) 
    b = (max_x - min_x) / (max_y - min_y)
    x_scale = a > 1.0 ? a : 1.0;
    y_scale = b > 1.0 ? b : 1.0;

    To calculate the offset for x and y to reduce hard-iron distortions the following equations were used:

    offset_x = ((max_x + min_x) / 2.0) * x_scale
    offset_y = ((max_y + min_y) / 2.0) * y_scale

    Heading angle

    heading = azimuth = atan2(magnetometer_x_axis / magnetomer_y_axis) - π + 0.23
    

    To the heading is also added the declination angle which is based on location and in our case it is 0.23. This heading is calculated in radians since atan2 returns a value between -π and +π. Therefore, before converting the heading into degrees the value needs to be normalized to put it in the range from 0 to 360 degrees.

    Geological.c module

    Initialization

    The geological.c module initializes the gps and compass with the configurations explained before.

    Run once at 10Hz

    Every 10Hz the geological_run_once() function periodically calls the gps module, gets the parsed coordinates, gets the compass heading degree, sets the current and destination coordinates, sends the calculated bearing degree over CAN to the driver node, and runs the checkpoint algorithm.

    Bearing Angle computation

    The bearing which is the angle towards our desired destination is computed using the formulas below referenced at this link.

    X = cos θb * sin ∆L
    Y = cos θa * sin θb – sin θa * cos θb * cos ∆L
    
    β = atan2(X,Y)
    
    • where:
      • θa = current latitude
      • θb = destination latitude
      • ∆L = destination longitude - current longitude
      • β = heading degree in radians

    The bearing is also calculated in radians since atan2 returns a value between -π and +π. Therefore, before converting the heading into degrees the value needs to be normalized to put it in the range from 0 to 360 degrees. The calculated bearing is then sent to the driver node which use the compass heading degree and the bearing to align the car toward the target destination.

    Checkpoints Algorithm

    The checkpoint algorithm depicted below uses a simple algorithm in which chooses the next point to navigate to if the checkpoint is the closest to the car while at the same time the closest to the destination. For the testing of our car navigation system, we choose the top floor of the north garage at San Jose State University as it provides a great open space and best signal for the GPS. In the figure shown below, five checkpoints were chosen in which the car can navigate to depending on where the destination is set to. Having fewer points rather then having too many reduces the amount of checkpoints the car has to move to and allows to reach the destination quicker while at the same time avoid areas such as the ramp in which the car should not go to.

    Figure #. Checkpoints Algorithm Figure #. Checkpoints North Garage


    To calculate the geographical distance between the two points the haversine formula was used which is called periodically from the checkpoint.c module. Below is the formula used:

    a = sin²(ΔlatDifference/2) + cos(lat1) * cos(lt2) * sin²(ΔlonDifference/2)
    c = 2 * atan2(sqrt(a), sqrt(1−a))
    d = R * c 
    
    • where:
      • ΔlatDifference = latitude 2 - latitude 1 (difference of latitude)
      • ΔlonDifference = longitude 2 - longitude 1 (difference of longitude)
      • R = 6371000.0 meters = radius of earth
      • d = distance computed between two points
      • a and c are intermediate steps

    Technical Challenges


    Driver Node

    Driver Node is the master controller. It receives input from sensor and bridge node, processes it to make right decision for controlling the speed and steering direction of the car and then commands the motor node to drive accordingly. This node is also interfaced to the LCD, which acts as dashboard of the car and displays information such as car speed and distance to destination on the screen.

    Hardware

    LCD is interfaced with the SJ2 board and it communicates over UART. P4.28 and P4.29 which is UART3 on board is used. Headlights and Tailights are also connected to the driver node using four GPIOs.

  • Sjtwo-board
  • LCD Display
  • Software Architecture Driver Logic

    • Basic_Logic
    • Obstacle Avoidance Logic
    • Reverse Functionality


    Obstacle Avoidance Logic

    if (obstacle_on_all_front_sides()) {
              stop_the_car();
              reverse_car_and_steer();
            } else if (obstacle_on_left() && obstacle_in_right() && (!obstacle_on_front())) {
              drive_forward();
            } else if (obstacle_on_left() && (!obstacle_in_right())) {
              obstacle_on_right = false;
              get_steering_range(obstacle_on_right); // right steer
            } else if (obstacle_in_right() && (!obstacle_on_left())) {
              obstacle_on_right = true;
              get_steering_range(obstacle_on_right); // left steer
            } else if (obstacle_on_front() && (!obstacle_on_left() && !obstacle_in_right())) {
              stop_the_car();
              reverse_car_and_steer();
              obstacle_on_right =
                  (internal_sensor_data.SENSOR_SONARS_right < internal_sensor_data.SENSOR_SONARS_left) ? true : false;
              get_steering_range(obstacle_on_right);
    
            } else if (obstacle_on_rear() && (!obstacle_on_all_front_sides())) {
              obstacle_on_right =
                  (internal_sensor_data.SENSOR_SONARS_right < internal_sensor_data.SENSOR_SONARS_left) ? true : false;
              get_steering_range(obstacle_on_right);
              debug_values.car_driving_status = FORWARD;
              debug_values.car_steering_status = STRAIGHT;
            } else {
              stop_the_car();
    
              debug_values.car_driving_status = STOPPED;
              debug_values.car_steering_status = STRAIGHT;
            }
    


    Steer Left and Right

      if (obstactle_on_right == true) {
        //steer left
        motor_signal.DRIVER_TO_MOTOR_direction = (motor_signal.DRIVER_TO_MOTOR_direction <= 40)
                                                     ? motor_signal.DRIVER_TO_MOTOR_direction + offset_to_angle
                                                     : max_angle_threshold;
        motor_signal.DRIVER_TO_MOTOR_speed = slow_speed;
        update_lights(10, headlight_left);
    
      } else {
        //steer right
        motor_signal.DRIVER_TO_MOTOR_direction = (motor_signal.DRIVER_TO_MOTOR_direction >= -40)
                                                     ? motor_signal.DRIVER_TO_MOTOR_direction - offset_to_angle
                                                     : -max_angle_threshold;
    
        motor_signal.DRIVER_TO_MOTOR_speed = slow_speed;
        update_lights(10, headlight_right);
      }
    

    Reverse and Steer

      if (!obstacle_on_rear()) {
        motor_signal.DRIVER_TO_MOTOR_direction = 0;
        motor_signal.DRIVER_TO_MOTOR_speed = reverse_speed;
        update_lights(10, taillight_left);
        update_lights(10, taillight_right);
      } else {
        stop_the_car();
      }
    

    Navigation to Destination

    Driver receives raw heading and bearing from the Geo node and in order to calculate the turning direction, it first computes the difference between heading and bearing. Then based on which quadrant the difference lies and where the destination lies, take navigation decisions to steer left, right or straight.

    if (heading_difference >= 350 && heading_difference <= 10) {
        gps_navigation_direction = straight;
        heading_difference = fabs(heading_difference);
    
        debug_values.car_driving_status = FORWARD;
        debug_values.car_steering_status = STRAIGHT;
      } else if (heading_difference > 180) {
        gps_navigation_direction = left;
        heading_difference = 360 - heading_difference;
    
        debug_values.car_driving_status = FORWARD;
        debug_values.car_steering_status = LEFT;
    
      } else if (heading_difference < 0 && heading_difference > -180) {
        gps_navigation_direction = left;
        heading_difference = fabs(heading_difference);
    
        debug_values.car_driving_status = FORWARD;
        debug_values.car_steering_status = LEFT;
      }
    
      else if (heading_difference < -180) {
        gps_navigation_direction = right;
        heading_difference = fabs(heading_difference + 360);
    
        debug_values.car_driving_status = FORWARD;
        debug_values.car_steering_status = RIGHT;
      } else if (heading_difference > 0 && heading_difference <= 180) {
        gps_navigation_direction = right;
    
        debug_values.car_driving_status = FORWARD;
        debug_values.car_steering_status = RIGHT;
      }
    

    Technical Challenges

    • Driver receives data from sensor and geo node, so mainly the issue was sometimes not getting data accurate data from sensors or receiving late. This has made the obstacle avoidance quite slow. Make sure the sensor is transmitting data fast enough and driver is also receiving fast.
    • Driver Node has the least hardware interfacing compared to other nodes, so there were not many challenges on hardware front. If the LCD communicates over UART, remember to connect the gnd of both lcd and board otherwise the data printed on LCD could be gibberish.
    • High speed of car can also cause to problem for sensors, we noticed that they cannot accurately detect obstacles on high speed.
    • Compass calibration was also issue sometimes, if not properly calibrated the car will have trouble navigating to gps location.


    Mobile Application

    Through the app we first scan for available devices and connect to the Bluetooth present on the RC car. After the connection is successful the destination is pinned on the map and by clicking on the "Send Destination to Car" button the car is notified of the destination. After this we can control the start and stop of the car with the two buttons present on the application.

    User Interface


  • App User Interface

  • Software Design

    The app was developed using MIT App inventor

  • MIT App Inventor
  • Backend development

  • Bluetooth

    Technical Challenges





    Conclusion

    Project Video

    Project Source Code

    https://gitlab.com/ritupatil1/firebolt/-/tree/master

    Advise for Future Students

    • Get started early and make your hardware stable as early as possible so that you have enough time for extensive testing of the software. Because without on field testing corner cases and potential problems in the code can't be determined.
    • We took references from previous projects and ran into problems due to lack of information. Ensure that you fully understand both software and hardware you are taking reference from before implementing on the car.
    • First of all make your motor run smoothly only then you will be able to do on field testing. So even if you have to use initial week to get the motor part ready. Buy new hardware for that to---- to be continued*(Ritika)

    Acknowledgement

    References

    http://socialledge.com/sjsu/index.php/Industrial_Application_using_CAN_Bus