Difference between revisions of "S22: Firebolt"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Team Members & Responsibilities)
(Team Members & Responsibilities)
 
(593 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== FireBolt ==
+
[[File:Firebolt2.jpeg|500px|thumb|right| The RC Car]]
  
 
== Abstract ==
 
== Abstract ==
The Firebolt project is a path finding and obstacle avoiding RC car.It can interface with an Android application to get new coordinates to travel to, and will do so all while avoiding obstacles visible by ultrasonic sensors.
+
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 & Introduction ==
==== Objectives ====
+
=== Objectives ===
* RC car can communicate with an Android application to:
+
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.
** Receive new coordinates to travel to
 
** Send diagnostic information to the application
 
** Emergency stop and start driving
 
* RC car can travel to received coordinates in an efficient path while avoiding obstacles
 
* RC car can maintain speed when driving on sloped ground
 
* Design printed circuit board (PCB) to neatly connect all SJ2 boards
 
* Design and 3D print sensor mounts for the ultrasonic sensors
 
* Design a simple and intuitive user interface for the Android application
 
* Design a DBC file
 
  
==== Introduction ====
+
====Software side ====
The Firebolt RC car uses 4 SJ2 boards as nodes on the CAN bus
+
* The car communicates with an Android application
# Driver and LCD
+
* Receive coordinates from gps to drive itself to the destination while avoiding obstacles
# GEO and path finding
+
* Display useful information on the LCD
# Sensors and bridge app
+
* Take care of elevation and make correct speed decisions
# Motor
+
* DBC file for all the nodes
  
=== Team Members & Responsibilities ===
+
====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
  
[[File:Priyanka Rai]]
+
<div><ul>
*
+
<li style="display: inline-block;">[[File:High_Level_Implementation2.png|600px|thumb|Center|High Level Hardware]] </li>
** Motor Controller
+
</ul></div>
** Geographical Controller
 
  
 +
==== Introduction ====
 +
The controllers for the project are divided in 5 parts. Each controller has different tasks and communicate with each other over CAN bus.
 +
# Driver Node
 +
# GEO Node
 +
# Sensors and Bridge Node
 +
# Motor Node
 +
# Mobile Application
  
[[File:jbeardphoto.jpg|200px|middle]]
+
=== Team Members & Responsibilities ===
*'''''[https://www.linkedin.com/in/jonathan-beard-155840205/ Jonathan Beard]''''' '''''[https://gitlab.com/jbeard79 Gitlab]'''''
+
<div><ul>
** Android Application Developer
+
<li style="display: inline-block;">[[File:Team_Photo_2.jpg|600px|thumb|Right|Team FireBolt]] </li>
** Communication Bridge Controller
+
<li style="display: inline-block;">[[File:Team_Photo_Final.jpeg|500px|thumb|Left|Team FireBolt]]</li>
 +
</ul></div>
 +
<font color="black"> '''Priyanka Rai  [https://www.linkedin.com/in/priyanka-rai-009ba975/ LinkedIn]''''''
 +
* Geo Controller
 +
* GPS and Compass Interfacing
 +
* Integration Testing
 +
* Wiki Page Update
  
[[File:AmeerAli.jpg|200px|middle]]
+
<font color="black"> '''Ritu Patil    [https://www.linkedin.com/in/ritu-patil/ LinkedIn]''''''
*'''''[https://www.linkedin.com/in/ameer-ali-13703b127/ Ameer Ali]''''' '''''[https://gitlab.com/Ameer12 Gitlab]'''''
+
* Motor Controller
** Master Controller
+
*  RPM Sensor
 +
*  Integration Testing
 +
* Wiki Page Update
  
[[File:Jonathan tran self pic.jpeg|200px|middle]]
+
<font color="black"> '''Ritika Beniwal  [https://www.linkedin.com/in/ritikabeniwal03/  LinkedIn]''''''
*Jonathan Tran '''''[https://gitlab.com/jtran1028 Gitlab]'''''
+
* Driver Node
** Sensors Controller
+
*  LCD interfacing
 +
*  Integration Testing
 +
* Wiki Page Update
  
[[File:Download.jpeg|200px|middle]]
+
<font color="black"> '''Utsav Savaliya  [https://www.linkedin.com/in/utsav-savaliya-7383ab15b/ LinkedIn]''''''
*Shreevats Gadhikar '''''[https://gitlab.com/Shreevats Gitlab]''''
+
* Sensor Controller
** Motor Controller
+
* Integration Testing
** Hardware Integration
+
* Wiki Page Update
** PCB Designing
+
* Bluetooth integration with Sensor
  
*Amritpal Sidhu
+
<font color="black"> '''Dhanush Babu  [https://www.linkedin.com/in/dhanushsbabu/ LinkedIn]''''''
** Motor Controller
+
* Bluetooth module interfacing
 +
* Motor Controller
 +
*  Android App
 +
*  Integration Testing
  
 
== Schedule ==
 
== Schedule ==
 
{| class="wikitable"
 
|-
 
|+ Legend
 
|-
 
! Description !! Color
 
|-
 
| Administrative || Black
 
|-
 
| Sensor || <span style="color:cyan">Cyan</span>
 
|-
 
| Bluetooth & App || <span style="color:blue">Blue</span>
 
|-
 
| GEO || <span style="color:red">Red</span>
 
|-
 
| Motor || <span style="color:magenta">Magenta</span>
 
|-
 
| Main || <span style="color:orange">Orange</span>
 
|}
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 79: Line 73:
 
! scope="col"| Week#
 
! scope="col"| Week#
 
! scope="col"| Start Date
 
! scope="col"| Start Date
! scope="col"| End Date  
+
! scope="col"| Target Date
 
! scope="col"| Task
 
! scope="col"| Task
 +
! scope=:col"| Completion Date
 
! scope="col"| Status
 
! scope="col"| Status
 
|-
 
|-
! scope="row"| 1
+
! scope="row"| Week 1  
|  
+
|
  <div style="text-align:center">02/15/2021</div>
+
* 03/06
 +
* 03/08
 +
* 03/12
 +
|
 +
* 03/10
 +
* 03/10
 +
* 03/12
 
|
 
|
  <div style="text-align:center">02/21/2021</div>
+
* Study and discuss previous project reports
 +
* Brainstorm on the requirements for the project
 +
* Identify and order/purchase the required components
 
|
 
|
* Read previous projects to understand what is expected and have some meaningful knowledge by first meeting. Assign roles.
+
* 03/10
 +
* 03/10
 +
* 03/12
 
|  
 
|  
* <span style="color:green">Completed</span>
+
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 2
+
! scope="row"| Week 2
|  
+
|
  <div style="text-align:center">02/22/2021</div>
+
* 03/13
|  
+
* 03/13
  <div style="text-align:center">02/28/2021</div>
+
* 03/14
 +
|
 +
* 03/14
 +
* 03/18
 +
* 03/18
 
|
 
|
*Acquire parts: Canbus modules, GPS module, Ultrasonic module, Bluetooth module, Car frame, and LCD display
+
* Distribute initial roles among the team members
*Conduct meeting: Discuss GitLab layout and expectation of each assigned role
+
* Study the datasheets and manual of acquired components
 +
* Create and setup Gitlab Repository
 
|
 
|
* <span style="color:green">Completed</span>
+
* 03/14
* <span style="color:green">Completed</span>
+
* 03/18
 +
* 03/18
 +
|
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 3
+
! scope="row"| Week 3
 
|
 
|
  <div style="text-align:center">03/01/2021</div>
+
* 03/20
 +
* 03/22
 +
* 03/20
 
|
 
|
  <div style="text-align:center">03/07/2021</div>
+
* 03/25
 +
* 03/26
 +
* 03/24
 
|
 
|
*Purchased RC car and batteries.
+
* Write basic driver for ultrasonic sensor
*<span style="color:cyan">Research and finalize which ultrasonic sensor the project will use.</span>
+
* Analyze and decide the hardware placement of the RC Car
*<span style="color:blue">Purchased Bluetooth connector</span>
+
* Create SENSOR and DRIVER nodes to transmit and receive data
*<span style="color:red">Research math needed to determine distance between navigation points. Decide on distance algorithm</span>
 
*<span style="color:red">Research multiple navigation point algorithm(Djikstra's) to determine shortest path.</span>
 
*<span style="color:magenta">Create branch for motor controller driver.  Create draft template API for motor controller.</span>
 
*<span style="color:orange">Using previous projects, determine what works needs to be completed for main board. Bring findings to weekly meeting</span>
 
 
|
 
|
* <span style="color:green">Completed</span>
+
* 03/26
* <span style="color:green">Completed</span>
+
* 03/23
* <span style="color:green">Completed</span>
+
* 03/25
* <span style="color:green">Completed</span>
+
|
* <span style="color:green">Completed</span>
+
*<font color = "green"> Completed
* <span style="color:green">Completed</span>
+
*<font color = "green"> Completed
* <span style="color:green">Completed</span>
+
*<font color = "green"> Completed
 
 
 
|-
 
|-
! scope="row"| 4
+
! scope="row"| Week 4
 
|
 
|
  <div style="text-align:center">03/08/2021</div>
+
* 03/27
 +
* 03/27
 +
* 03/27
 
|
 
|
  <div style="text-align:center">03/14/2021</div>
+
* 04/04
 +
* 04/01
 +
* 03/28
 
|
 
|
*<span style="color:blue">Research connection with Bluetooth from board to application. Decide between bluetooth connection or wifi connection by this day</span>
+
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass
*<span style="color:red">Work on implementation of multiple navigation point algorithm to determine shortest path </span>
+
* Create the MOTOR node to drive the RC Car
*<span style="color:magenta">Plan motor controller API and create basic software flow of API</span>
+
* Design DBC file and create CAN signals for every node
 
|
 
|
* <span style="color:green">Completed</span>
+
* 04/02
* <span style="color:green">Completed</span>
+
* 04/04
* <span style="color:green">Completed</span>
+
* 04/01
 +
|
 +
*<font color = "Green"> Completed
 +
*<font color = "Green"> Completed
 +
*<font color = "Green"> Completed
 
|-
 
|-
! scope="row"| 5
+
! scope="row"| Week 5
 
|
 
|
  <div style="text-align:center">03/15/2021</div>
+
* 04/02
 +
* 04/02
 +
* 04/02
 +
* 04/02
 
|
 
|
  <div style="text-align:center">03/21/2021</div>
+
* 04/08
 +
* 04/08
 +
* 04/08
 +
* 04/08
 
|
 
|
*<span style="color:black">Begin laying out hardware requirements for PCB on excel document. Include voltage and pinout requirements in excel document</span>
+
* Finalize the DBC file
*<span style="color:blue">Finish research on application building with android studio. Install android studio and necessary dependencies</span>
+
* Design obstacle avoidance and steering logic on the DRIVER node
*<span style="color:blue">Implement a simple application with a button and text</span>
+
* Design motor driving logic on the MOTOR node with the encoder
*<span style="color:magenta">Start researching on Wheel encoder according to the requirement</span>
+
* Start and design the Bluetooth app xml for destination.  
*<span style="color:red">Unit Test Direction Distance Calculation Module. Manual calculation of data should match module output</span>
+
 
*<span style="color:red">Begin coding and digesting adafruit Compass data. Print Compass data.</span>
 
 
|
 
|
* <span style="color:green">Completed</span>
+
* 04/09
* <span style="color:green">Completed</span>
+
* 04/09
* <span style="color:green">Completed</span>
+
* 04/09
* <span style="color:green">Completed</span>
+
* 04/09
* <span style="color:green">Completed</span>
+
|
* <span style="color:green">Completed</span>
+
*<font color = "green"> Completed
 +
*<font color = "green"> Completed
 +
*<font color = "green"> Completed
 +
*<font color = "green"> Completed
 
|-
 
|-
! scope="row"| 6
+
! scope="row"| Week 6
 
|
 
|
  <div style="text-align:center">03/22/2021</div>
+
* 04/09
 +
* 04/09
 +
* 04/09
 +
* 04/09
 +
* 04/09
 
|
 
|
  <div style="text-align:center">03/28/2021</div>
+
* 04/15
 +
* 04/15
 +
* 04/15
 +
* 04/15
 +
* 04/15
 
|
 
|
*<span style="color:cyan">Acquire sensor and interface sensors to SJ2 Board and receive raw data</span>
+
* Integrate GPS module with compass to get the current location.
*<span style="color:blue">Implement basic communication between board and app</span>
+
* Write UART interface for Bluetooth integration on sensor node.
*<span style="color:red">Update Wiki with proper software diagrams for GPS and Compass data flow</span>
+
* Get raw sensor data from the ultrasonic sensor.
*<span style="color:orange">Begin Mapping out pins used on all board</span>
+
* Integrate GEO node to DRIVER node for navigation. Check whether the DRIVER node is receiving the coordinates.
*<span style="color:orange">Complete a block diagram and a control scheme</span>
+
* Backend development for android app. Should be able to scan BT devices and connect.
<ol>
 
<li style="color:orange">Top Level Driver Logic diagram</li>
 
<li style="color:orange">Periodic Callback Functions Diagram</li>
 
</ol>
 
*<span style="color:orange">Create a basic Obstacle avoidance algorithm for Driver</span>
 
*<span style="color:magenta">Probe RC car to determine expected behavior of signals and install RPM sensor</span>
 
*<span style="color:magenta">Write motor controller modules and tests</span>
 
 
|
 
|
* <span style="color:green">Completed</span>
+
* 04/15
* <span style="color:green">Completed</span>
+
* 04/15
* <span style="color:green">Completed</span>
+
* 04/15
* <span style="color:green">Completed</span>
+
* 04/15
* <span style="color:green">Completed</span>
+
* 04/15
* <span style="color:green">Completed</span>
+
|
* <span style="color:green">Completed</span>
+
*<font color = "green">Completed
* <span style="color:green">Completed</span>
+
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 7
+
! scope="row"| Week 7
|  
+
|
  <div style="text-align:center">03/29/2021</div>
+
* 04/16
 +
* 04/16
 +
* 04/16
 +
* 04/16
 +
* 04/16
 +
* 04/16
 
|
 
|
  <div style="text-align:center">04/04/2021</div>
+
* 04/23
 +
* 04/23
 +
* 04/23
 +
* 04/23
 +
* 04/23
 +
* 04/23
 
|
 
|
*<span style="color:black">Discuss and construct DBC file</span>
+
* Communicate to the GEO node over Bluetooth via Android app
*<span style="color:cyan">Create sensor API to parse raw data and convert into inches</span>
+
* Complete Driver obstacle logic
*<span style="color:blue">Integrate google map features into app</span>
+
* Design driving decision logic based on the navigation data
*<span style="color:magenta">Integration testing of motor controller logic</span>
+
* Lay out basic PCB Board design for mounting the ECUs
*<span style="color:orange">Create a Checkpoint Navigation algorithm for Driver</span>
+
* Filtering ultrasonic sensor data and sending processed data to Driver
 +
* RPM Sensor logic and testing.
 
|
 
|
* <span style="color:green">Completed</span>
+
* 04/26
* <span style="color:green">Completed</span>
+
* 04/26
* <span style="color:green">Completed</span>
+
* 04/26
* <span style="color:green">Completed</span>
+
* 04/26
* <span style="color:green">Completed</span>
+
* 04/26
 +
* 04/26
 +
|
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 8
+
! scope="row"| Week 8
|  
+
|
  <div style="text-align:center">04/05/2021</div>
+
* 04/25
 +
* 04/25
 +
* 04/25
 +
* 04/25
 +
* 04/25
 +
* 04/25
 
|
 
|
  <div style="text-align:center">04/11/2021</div>
+
* 04/30
 +
* 04/30
 +
* 04/30
 +
* 04/30
 +
* 04/30
 +
* 04/30
 
|
 
|
*<span style="color:black">Finish implementation of canbus between controllers and begin real world testing</span>
+
* Design a dashboard on the LCD to display the values
*<span style="color:cyan">3D print sensor mounts, sensor guards, and draft sensor offset timing to deter sensor cross talk</span>
+
* Driver logic for sensor data and geo data on busmaster.
*<span style="color:magenta">Finish integrating wheel encoder and display speed on SJTwo Telemetry</span>
+
* Add functionality for pinning location on maps and extracting latitude and longitude
*<span style="color:orange">Establish Communication between the LCD display and Master Board over I2C</span>
+
* Improve obstacle avoidance logic
 +
* Break and ramp logic for the motor.
 +
* '''Collective Test 1''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color>
 
|
 
|
* <span style="color:green">Completed</span>
+
* 04/29
* <span style="color:green">Completed</span>
+
* 04/27
* <span style="color:green">Completed</span>
+
* 04/30
* <span style="color:green">Completed</span>
+
* 04/30
 +
* 04/30
 +
* 05/06
 +
|
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 9
+
! scope="row"| Week 9
|
 
  <div style="text-align:center">04/12/2021</div>
 
 
|
 
|
  <div style="text-align:center">04/18/2021</div>
+
* 05/01
 +
* 05/01
 +
* 05/01
 +
* 05/01
 +
* 05/01
 
|
 
|
*<span style="color:black">Integrate Driver, Geo, Bridge sensor, and Motor nodes. Successful communication between all boards.</span>
+
* 05/07
*<span style="color:blue">Implement Kill button on app for emergency stop</span>
+
* 05/07
*<span style="color:cyan">Analyze noise in sensor values and design a filter to mitigate the noise</span>
+
* 05/07
*<span style="color:magenta">Complete "Self Test" for motor test(DC motor moves forward and backwards and servo moves right - left)</span>
+
* 05/07
*<span style="color:magenta">Start working on PID control algorithm. Design bare skeleton for workflow</span>
+
* 05/07
*<span style="color:orange">Create an algorithm to account for speed when the car is on an incline</span>
 
 
|
 
|
* <span style="color:green">Completed</span>
+
* Design individual architecture diagrams and algorithms for documentation
* <span style="color:green">Completed</span>
+
* Make any necessary improvements based on previous test results
* <span style="color:green">Completed</span>
+
* Complete the final version of the Android app
* <span style="color:green">Completed</span>
+
* Get the PCB printed
* <span style="color:green">Completed</span>
+
* '''Collective Test 2''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color>
* <span style="color:green">Completed</span>
 
  
 +
|
 +
* 05/10
 +
* 05/07
 +
* 05/01
 +
* 05/07
 +
* 05/11
 +
|
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "Green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 10
+
! scope="row"| Week 10
|
 
  <div style="text-align:center">04/19/2021</div>
 
 
|
 
|
  <div style="text-align:center">05/25/2021</div>
+
* 05/09
 +
* 05/09
 +
* 05/09
 +
* 05/09
 
|
 
|
*<span style="color:black">Begin to analysis real world tests from previous weeks implementation and perform fixes for issues faced</span>
+
* 05/14
*<span style="color:black">Ensure Canbus nodes are communicating correctly by verifying PCON data. Verify that timing for data is correct</span>
+
* 05/14
*<span style="color:black">Added CAN debug messages</span>
+
* 05/14
*<span style="color:black">Start working on the PCB, order the PCB and also purchase the required components </span>
+
* 05/14
*<span style="color:cyan">Integration testing with obstacle avoidance.</span>
 
<ol>
 
<li style="color:cyan">Analyze possible blind spots and make adjustments to sensor placements. </li>
 
<li style="color:cyan">Analyze sensor response time and data while rc car is moving and make adjustments if needed.</li>
 
</ol>
 
*<span style="color:orange">Display relevant Motor and Checkpoint Information to the LCD.</span>
 
*<span style="color:magenta">Tuned and tested PID on RC Car (More refinement needed)</span>
 
|
 
* <span style="color:green">Completed</span>
 
* <span style="color:green">Completed</span>
 
*<span style="color:green">Completed</span>
 
*<span style="color:green">Completed</span>
 
*<span style="color:green">Completed</span>
 
*<span style="color:green">Completed</span>
 
*<span style="color:green">Completed</span>
 
* <span style="color:green">Completed</span>
 
*<span style="color:green">Completed</span>
 
|-
 
! scope="row"| 11
 
|
 
  <div style="text-align:center">04/26/2021</div>
 
 
|
 
|
  <div style="text-align:center">05/02/2021</div>
+
* 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:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color>
 
|
 
|
*<span style="color:black">Perform more real world tests and isolate bugs. Update issues for bugs find during real world test</span>
+
* 05/20
*<span style="color:black">Perform final bug fixes, as listed under issues, for all Canbus nodes. </span>
+
* 05/20
*<span style="color:black">Integrate all the parts on the PCB. </span>
+
* 05/20
 +
* 05/20
 
|
 
|
* <span style="color:green">Completed</span>
+
*<font color = "green">Completed
* <span style="color:green">Completed</span>
+
*<font color = "green">Completed
* <span style="color:Green">Completed</span>
+
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 12
+
! scope="row"| Week 11
|
 
  <div style="text-align:center">05/03/2021</div>
 
 
|
 
|
  <div style="text-align:center">05/09/2021</div>
+
* 05/16
 +
* 05/16
 +
* 05/16
 +
* 05/16
 
|
 
|
*<span style="color:black">Update Wiki Report to reflect all changes and include final testing video</span>
+
* 05/21
*<span style="color:black">Perform final code changes and commit to master branch</span>
+
* 05/21
*<span style="color:black">Received manufactured PCB, installed, and integration tested</span>
+
* 05/21
*<span style="color:magenta">Refactored motor controller code and wrote much needed unit tests</span>
+
* 05/21
*<span style="color:magenta">Finished tuning PID and tested RC Car driving on slope</span>
 
 
|
 
|
* <span style="color:green">Completed</span>
+
* Revise and improve the wiki report to cover all the aspects of design and implementation
* <span style="color:green">Completed</span>
+
* Fix all the errors and make improvements
* <span style="color:green">Completed</span>
+
* Final testing of all the modules and car
* <span style="color:green">Completed</span>
+
* '''Collective Test 4:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color>
* <span style="color:green">Completed</span>
 
|-
 
! scope="row"| 13
 
|
 
  <div style="text-align:center">05/10/2021</div>
 
 
|
 
|
  <div style="text-align:center">05/16/2021</div>
+
* 05/22
 +
* 05/22
 +
* 05/22
 +
* 05/22
 
|
 
|
*<span style="color:black">Update Wiki schedule and begin draft for individual controller documentation</span>
+
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
|-
 +
! scope="row"| Week 12
 
|
 
|
* <span style="color:green">Completed</span>
+
* 05/25
|-
+
* 05/25
! scope="row"| 14
 
|
 
  <div style="text-align:center">05/17/2021</div>
 
 
|
 
|
  <div style="text-align:center">05/23/2021</div>
+
* 05/27
 +
* 05/27
 
|
 
|
*<span style="color:black">Update Wiki individual controller and general documentation</span>
+
* Demo
*<span style="color:orange">Last minute bug fixes/refining</span>
+
* Final Wiki Page Update with addition of all the problems faced during the development
*<span style="color:orange">Waypoint algorithm integration and test</span>
 
*<span style="color:magenta">Last minute bug fixes/refining & code cleanup</span>
 
 
|
 
|
* <span style="color:green">Completed</span>
+
* 05/25
* <span style="color:green">Completed</span>
+
* 05/26
* <span style="color:green">Completed</span>
 
* <span style="color:green">Completed</span>
 
* <span style="color:green">Completed</span>
 
|-
 
! scope="row"| 15
 
 
|  
 
|  
  <div style="text-align:center">05/24/2021</div>
+
*<font color = "green"> Completed
|
+
*<font color = "green"> Completed
  <div style="text-align:center">05/30/2021</div>
 
|
 
*<span style="color:black">Demo Project</span>
 
*<span style="color:black">Finalize Wiki Documentation</span>
 
|
 
* <span style="color:green">Completed</span>
 
* <span style="color:green">Completed</span>
 
|-
 
 
|}
 
|}
  
Line 353: Line 412:
 
|-
 
|-
 
! scope="col"| Item#
 
! scope="col"| Item#
! scope="col"| Part Description
+
! scope="col"| Part Desciption
 
! scope="col"| Vendor
 
! scope="col"| Vendor
 
! scope="col"| Qty
 
! scope="col"| Qty
! scope="col"| Cost
+
! scope="col"| Price($)
 
|-
 
|-
 
! scope="row"| 1
 
! scope="row"| 1
| Traxxas 1/10 Scale RC Short Truck
+
| RC Car
| Traxxas [https://traxxas.com/products/models/electric/58034-1slash]
+
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]
 
| 1
 
| 1
| $239.99 + Tax
+
|280
 
|-
 
|-
 
! scope="row"| 2
 
! scope="row"| 2
| RPM Sensor & Mount
+
| CAN Transceivers MCP2551-I/P
| Traxxas [https://traxxas.com/sites/default/files/Rustler-Bandit-Stampede-Slash%20RPM%20Sensor%20Installation.pdf]
+
| Comimark [https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/ref=sr_1_4?crid=L6PXVWD9BFTN&dchild=1&keywords=can+transceiver&qid=1621786818&sprefix=can+trans%2Caps%2C566&sr=8-4]
| 1
+
| 5
| $19.00 + Tax
+
| 8.99
 
|-
 
|-
 
! scope="row"| 3
 
! scope="row"| 3
| 2S 7.4V 5000mAh LiPo Battery Pack
+
| Ultrasonic Sensors
| Amazon [https://www.amazon.com/gp/product/B00WOAWHUK]
+
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]
| 2
+
| 4
| $40.69 + Tax
+
| 24.95
 
|-
 
|-
 
! scope="row"| 4
 
! scope="row"| 4
| Bluetooth Adapter
+
| GPS Breakout Board
| Amazon [https://www.amazon.com/DSD-TECH-HC-05-Pass-through-Communication/dp/B01G9KSAF6]
+
| Adafruit[https://www.adafruit.com/product/746]
 
| 1
 
| 1
| $8.99 + Tax
+
| 29.95
 
|-
 
|-
 
! scope="row"| 5
 
! scope="row"| 5
| Adafruit Ultimate GPS Breakout
+
| GPS Antenna
| Adafruit [https://www.adafruit.com/product/746]
+
| Adafruit[https://www.adafruit.com/product/960]
 
| 1
 
| 1
| $39.95
+
| 19.95  
 
|-
 
|-
 
! scope="row"| 6
 
! scope="row"| 6
| Adafruit Triple-axis Accelerometer+Magnetometer
+
| RPSMA female to mhf4
| Adafruit [https://www.adafruit.com/product/1120]
+
| Superbat[https://www.amazon.com/dp/B08N6C7XGD/ref=cm_sw_r_cp_api_i_THK732JGSBBCCZFEPF58?_encoding=UTF8&psc=1]
 
| 1
 
| 1
| $14.95
+
| 7.99
 
|-
 
|-
! scope="row"|7
+
! scope="row"| 7
| Deans Connector
+
| HC05 bluetooth RF Transceiver
| Amazon [https://www.amazon.com/gp/product/B07QM1WS2J/ref=ox_sc_act_title_1?smid=A1JTH8JAMM4IYJ&psc=1]
+
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]
 
| 1
 
| 1
| $8.99 + Tax
+
| 15.99
 
|-
 
|-
! scope="row"|8
+
! scope="row"| 8
| Pololu 5V Voltage Regulator
+
| Triple-axis Accelerometer
| Pololu [https://www.pololu.com/product/2836]
+
| Adafruit[https://www.adafruit.com/product/1120]
 
| 1
 
| 1
| $10.83
+
| 14.95
 
|-
 
|-
! scope="row"|9
+
! scope="row"| 9
| PCB
+
| Traxxas RPM Sensor
| JLCPCB [https://jlcpcb.com/]
+
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]
 
| 1
 
| 1
| $40.00 
+
| 13.76
 
|-
 
|-
! scope="row"|10
+
! scope="row"| 10
| CAN transceiver
+
| Traxxas Battery and Charger
| Amazon [https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/ref=sr_1_1?dchild=1&keywords=can+waveshare&qid=1622233988&sr=8-1]
+
|Traxxas[https://www.amazon.com/Traxxas-Battery-Charger-Completer-2-amp/dp/B074FXXP5J/ref=asc_df_B074FXXP5J/?tag=hyprod-20&linkCode=df0&hvadid=312136795426&hvpos=&hvnetw=g&hvrand=9135382788468531733&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=9032144&hvtargid=pla-493010666784&psc=1]
| 4
+
|1
| $40.00 
+
|62.95
 +
|-
 +
! scope="row"| 11
 +
| Voltage Regulator
 +
|Valefod[https://www.amazon.com/dp/B076H3XHXP?ref_=cm_sw_r_cp_ud_dp_5HTAVWPZJ2QS6AMXTM93]
 +
|6
 +
|10.99
 +
|-
 +
! scope="row"| 12
 +
| Headlights
 +
|Hobbypark[https://www.amazon.com/dp/B01GY8VFIM?ref_=cm_sw_r_cp_ud_dp_PK32ZA2HM4DRWMGV55YC]
 +
|1
 +
|7.96
 
|-
 
|-
! scope="row"|11
 
| Maxbotix MB1010 LV-MaxSonar-EZ1 Ultra Sonic Sensors
 
| Maxbotix [https://www.maxbotix.com/Ultrasonic_Sensors/MB1010.htm]
 
| 5
 
| $121.50 
 
 
|}
 
|}
  
Line 430: Line 496:
 
== Printed Circuit Board  ==
 
== Printed Circuit Board  ==
  
We started with a very basic design for our RC car on a breadboard. All the components were integrated on the breadboard for testing purposes.
+
Initially we started our testing with mounting all our hardware on the breadboard (yes, it was messy and unstable!).
 
+
<div><ul>
 +
<li style="display: inline-block;">[[File:Initial_Car.jpeg|400px|thumb|Centre|Initial_Hardware]] </li>
 +
</ul></div>
  
[[File:Breadboard Wiring.jpeg|1000px|center|thumb|Breadboard Wiring]]
 
  
 +
<h4>PCB Schematic</h4>
  
=== Challenges ===
+
<div><ul>
The wiring on the breadboard succeeded on the first attempt but later when we kept adding the components as per the requirements the wiring became a complete mess and was entangling everywhere due to which the car could not navigate properly. Every time the car collided, the wires used to get disconnected. So reconnecting the wires and debugging the hardware every time after the collision was the main challenge. So we decided to go with PCB.
+
<li style="display: inline-block;">[[File:Final_Sch.png|500px|thumb|Left|Schematic]] </li>
 +
<li style="display: inline-block;">[[File:Final_PCB.png|500px|thumb|Right|Final_Board]] </li>
 +
</ul></div>
  
<hr>
 
<br>
 
  
 +
<h4>PCB Board</h4>
  
We later had a PCB manufactured. In our design we minimized the use of surface mount components and additional passive components.  We reused the CAN transceiver modules we all purchased and the only passive components on the board were the two 120Ω termination resistors needed at each end of the CAN bus.  The remainder of the PCB used a combination of male and female pin headers to connect all components together. This design and implementation were succeeded in the first attempt.
+
<div><ul>
 +
<li style="display: inline-block;">[[File:Final_Top_Side.png|500px|thumb|Left|Top_Side]]</li>
 +
<li style="display: inline-block;">[[File:Final_Bottom_Side.png|500px|thumb|Right|Bottom_Side]] </li>
 +
</ul></div>
  
 +
<h4>Challenges </h4>
 +
* 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.
  
[[File:Schematic UTAH final.png|1000px|center|thumb|PCB Schematic]]
+
<h4>Solution  </h4>
 
+
* Finally we decided to use the prototype board for mounting all the components and stabilizing our hardware.
 
+
<div><ul>  
[[File:Layout.PNG|1000px|center|thumb|PCB Layout showing traces (red are front side, blue are back side)]]
+
<li style="display: inline-block;">[[File:Final_Hardware_Physical.jpeg|500px|thumb|Left|Protoype_Board]]</li>
 
+
</ul></div>
[[File:PCB.PNG|1000px|center|thumb|PCB Rendering front side]]
 
 
 
 
 
To overcome all the challenges which were faced on the breadboard we designed the PCB on EasyEDA. EasyEDA allows the creation and editing of schematic diagrams, and also the creation and editing of printed circuit board layouts and, optionally, the manufacture of printed circuit boards. So we implemented the custom PCB using EasyEDA software in which we implemented all the four controller connections. The four controllers included Master Controller, Geo Controller, Sensor Controller, and Motor Controller. The communication of these four controllers is done via a CAN bus. The GPS and Compass are connected to the Geo controller. The four Matbotix Ultrasonic sensors (three in front and one in rear) and the Bluetooth module are connected to the sensor controller board, while the LCD and LEDs are connected to Master Controller. RPM sensor, DC motor, and Servo motor are connected to Motor Controller. Also, all four CAN transceivers are connected to their respective board.
 
 
 
==Fabrication==
 
 
 
Using the EasyEDA we designed a 2 layer PCB. PCB was sent to fabrication to JLCPCB China which provided PCB within 7 days with MOQ of 5. The dimension of the PCB was 12.5" * 4.5" (332.61mm * 129.54mm). The four controllers were placed at the four corners of the PCB while the other components were placed at the center.
 
 
 
'''PCB Properties:''' <br/>
 
Size: 332.61mm * 129.54mm <br/>
 
Signal Layers: 2 <br/>
 
Componenets: 35 <br/>
 
Routing width: 0.254mm <br/>
 
Track Width: 1mm <br/>
 
Clearance: 0.3mm <br/>
 
Via diameter: 0.61mm <br/>
 
Via Drill Diameter: 0.31mm <br/>
 
Vias: 20 <br/>
 
 
 
==Power Management==
 
 
 
The main power came from a 7.4v Lipo battery. This 7.4v from the battery was given to ECS. ESC gave a power output of 6V. This 6V was given to the Pololu voltage regulator. We used 5V Step-Up/Step-Down Voltage Regulator S9V11F5 for powering our four controllers and their respective components. The S9V11F5 helps in switching step-up/step-down regulator efficiently to produces 5V from input voltages between 2 V and 16 V. Its ability to convert both higher and lower input voltages makes it useful for applications where the power supply voltage can vary greatly, it's suitable for application where we use a battery. The Pololu is a very compact (0.3″ × 0.45″) module and also has a typical efficiency of over 90% and can supply a typical output current of up to 1.5 A when the input voltage is around 5 V.
 
 
 
 
 
[[File:Power IC.jpg|300px|center|Pololu 5V Power IC]]
 
 
 
==Challenges==
 
1. Calculating the power requirement for each device. <br/>
 
2. Getting the pinout information for every controller. <br/>
 
3. Using only one battery was a challenge.<br/>
 
4. Splitting the power to 3.3V, 5V, 6V from one battery to different components.<br/>
 
5. Finding the pitch and dimensions of each component and placing them in the correct place and orientation.<br/>
 
6. Finding the correct power IC which can serve all the requirements.<br/>
 
7. Routing the wires on the PCB. <br/>
 
 
 
<HR>
 
<BR/>
 
  
 
== CAN Communication ==
 
== 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
  
Our message IDs were chosen based upon an agreed priority scheme.  We assigned high priority IDs to messages that controlled the movement of the car, followed by sensor and GEO messages, and lowest priority messages were for debug and status.
 
  
Debug and status messages were sent in the 1Hz, and a few in the 10Hz, callbacks.  The sensor and driver boards send data at the fastest rate (20Hz), so receiving all messages is done at 20Hz as well.
+
'''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.
  
Each board managed MIAs using the auto generated API.  Each board received all messages in one function call, and the service MIA function would be executed if messages a board was expecting did not arrive.  The increment and threshold values for MIA were in units of milliseconds, so it was easy to adjust threshold values if we wanted a MIA to occur earlier or later.
+
'''Bit Stuffing''': CAN bus stuffs extra bits when a long chain of multiple 1's or 0's occur to improve CAN integrity.
 +
[[File:High level diagram.png|thumb|600px|middle|center|Project Can Bus Diagram]]
  
=== Hardware Design ===
 
<Show your CAN bus hardware design>
 
<br>
 
  
 
=== DBC File ===
 
=== 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.
  
  
[https://gitlab.com/infallibleprogrammer/utah/-/blob/user/infallibleprogrammer/%238/Geo_Controller_For_GEO_Lab/dbc/project.dbc DBC File Link]
+
{| class="wikitable"
 +
|-
 +
! scope="col"| Sr. No
 +
! scope="col"| Message ID
 +
! scope="col"| Message function
 +
! scope="col"| Receivers
 +
|-
 +
|-
 +
|-
 +
|-
 +
! colspan="4"| Driver Heartbeat
 +
|-
 +
|-
 +
|1
 +
|100
 +
|Driver Heartbeat
 +
|Motor, Sensor, Geo
 +
|-
 +
! colspan="4"| Start Stop signal from Android app to Driver
 +
|-
 +
|-
 +
|1
 +
|101
 +
|Bridge Sensor
 +
|Driver
 +
|-
 +
! colspan="4"| Ultrasonic sensors data transmit
 +
|-
 +
|-
 +
|2
 +
|200
 +
|Sensor sonars from front, back, left ,right sensor
 +
|Driver
 +
|-
 +
! colspan="4"| Destination Location
 +
|-
 +
|-
 +
|4
 +
|250
 +
|Bridge Sensor
 +
|Geo
 +
|-
 +
|-
 +
! colspan="4"| Driver to Motor Command
 +
|-
 +
|-
 +
|5
 +
|300
 +
|Speed and steering direction for the motor
 +
|Motor
 +
|-
 +
|-
 +
! colspan="4"| Geo Controller
 +
|-
 +
|-
 +
|6
 +
|400
 +
|Bearing, Heading and Distance
 +
|Driver
 +
|-
 +
|-
 +
! colspan="4"| Motor Controller
 +
|-
 +
|-
 +
|7
 +
|600
 +
|Motor speed
 +
|Driver
 +
|-
 +
|-
 +
! colspan="4"| Debug messages
 +
|-
 +
|-
 +
|8
 +
|700
 +
|Driver Debug
 +
|BRIDGE_SENSOR,MOTOR,GEO
 +
|-
 +
|-
 +
|9
 +
|750
 +
|Geo Debug
 +
|BRIDGE_SENSOR,MOTOR,DRIVER
 +
|-
 +
|-
 +
|}
 +
 
 
<pre>
 
<pre>
 
VERSION ""
 
VERSION ""
 
 
NS_ :
 
NS_ :
BA_
+
    BA_
BA_DEF_
+
    BA_DEF_
BA_DEF_DEF_
+
    BA_DEF_DEF_
BA_DEF_DEF_REL_
+
    BA_DEF_DEF_REL_
BA_DEF_REL_
+
    BA_DEF_REL_
BA_DEF_SGTYPE_
+
    BA_DEF_SGTYPE_
BA_REL_
+
    BA_REL_
BA_SGTYPE_
+
    BA_SGTYPE_
BO_TX_BU_
+
    BO_TX_BU_
BU_BO_REL_
+
    BU_BO_REL_
BU_EV_REL_
+
    BU_EV_REL_
BU_SG_REL_
+
    BU_SG_REL_
CAT_
+
    CAT_
CAT_DEF_
+
    CAT_DEF_
CM_
+
    CM_
ENVVAR_DATA_
+
    ENVVAR_DATA_
EV_DATA_
+
    EV_DATA_
FILTER
+
    FILTER
NS_DESC_
+
    NS_DESC_
SGTYPE_
+
    SGTYPE_
SGTYPE_VAL_
+
    SGTYPE_VAL_
SG_MUL_VAL_
+
    SG_MUL_VAL_
SIGTYPE_VALTYPE_
+
    SIGTYPE_VALTYPE_
SIG_GROUP_
+
    SIG_GROUP_
SIG_TYPE_REF_
+
    SIG_TYPE_REF_
SIG_VALTYPE_
+
    SIG_VALTYPE_
VAL_
+
    VAL_
VAL_TABLE_
+
    VAL_TABLE_
 
 
 
BS_:
 
BS_:
  
BU_: DBG DRIVER IO MOTOR SENSOR GEO
+
BU_: DRIVER MOTOR BRIDGE_SENSOR GEO DEBUG
 
 
 
 
BO_ 100 BRIDGE_APP_COMMANDS: 1 SENSOR
 
SG_ APP_COMMAND : 0|2@1+ (1,0) [0|0] "" GEO,DRIVER
 
 
BO_ 101 MOTOR_CHANGE_SPEED_AND_ANGLE_MSG: 2 DRIVER
 
SG_ DC_MOTOR_DRIVE_SPEED_sig : 0|8@1+ (0.1,-10) [-10|10] "kph" MOTOR
 
SG_ SERVO_STEER_ANGLE_sig : 8|8@1+ (1,-45) [-45|45] "degrees" MOTOR
 
 
 
BO_ 102 SENSOR_SONARS_ROUTINE: 5 SENSOR
 
SG_ SENSOR_SONARS_left : 0|10@1+ (1,0) [0|0] "inch" DRIVER
 
SG_ SENSOR_SONARS_right : 10|10@1+ (1,0) [0|0] "inch" DRIVER
 
SG_ SENSOR_SONARS_middle : 20|10@1+ (1,0) [0|0] "inch" DRIVER
 
SG_ SENSOR_SONARS_rear : 30|10@1+ (1,0) [0|0] "inch" DRIVER
 
 
 
BO_ 300 GPS_DESTINATION_LOCATION: 8 SENSOR
 
SG_ DEST_LATITUDE : 0|32@1+ (0.000001,-90.000000) [-90|90] "Degrees" GEO
 
SG_ DEST_LONGITUDE : 32|32@1+ (0.000001,-180.000000) [-180|180] "Degrees" GEO
 
 
 
BO_ 301 COMPASS_HEADING_DISTANCE: 6 GEO
 
SG_ CURRENT_HEADING : 0|12@1+ (0.1,0) [0|359.9] "Degrees" DRIVER,SENSOR
 
SG_ DESTINATION_HEADING: 12|12@1+ (0.1,0) [0|359.9] "Degrees" DRIVER,SENSOR
 
SG_ DISTANCE : 24|17@1+ (0.01,0) [0|0] "Meters" DRIVER,SENSOR
 
 
 
BO_ 501 GPS_CURRENT_INFO: 8 GEO
 
SG_ GPS_CURRENT_LAT : 0|32@1+ (0.000001,-90.000000) [-90|90] "degrees" DRIVER,SENSOR,MOTOR
 
SG_ GPS_CURRENT_LONG : 32|32@1+ (0.000001,-180.000000) [-180|180] "degrees" DRIVER,SENSOR,MOTOR
 
 
 
BO_ 502 GPS_COMPASS_STATUS : 1 GEO
 
SG_ COMPASS_LOCK_VALID: 0|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER, SENSOR
 
SG_ GPS_LOCK_VALID : 1|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER,SENSOR,MOTOR
 
 
 
BO_ 503 GPS_CURRENT_DESTINATIONS_DATA: 8 GEO
 
SG_ CURRENT_DEST_LATITUDE : 0|32@1+ (0.000001,-90.000000) [-90|90] "Degrees" DRIVER
 
SG_ CURRENT_DEST_LONGITUDE : 32|32@1+ (0.000001,-180.000000) [-180|180] "Degrees" DRIVER
 
 
 
BO_ 504 RC_CAR_SPEED_READ_MSG: 2 MOTOR
 
  SG_ RC_CAR_SPEED_sig : 0|8@1+ (0.1,-10) [-10|10] "kph" DRIVER,SENSOR
 
 
 
BO_ 750 DBG_RAW_COMPASS_DATA: 4 GEO
 
  SG_ SIGNED_REGISTER_VAL_MAG_X : 0|16@1+ (1.0,0) [-2048|2047] "GAUSSIAN" DRIVER,SENSOR
 
  SG_ SIGNED_REGISTER_VAL_MAG_Y : 16|16@1+ (1.0,0) [-2048|2047] "GAUSSIAN" DRIVER,SENSOR
 
  
BO_ 751 DBG_CONFIRM_RECEIVED_DESTINATION: 8 GEO
+
BO_ 100 DRIVER_HEARTBEAT: 1 DRIVER
SG_ RECEIVED_DEST_LATITUDE : 0|32@1+ (0.000001,-90.000000) [-90|90] "Degrees" SENSOR
+
  SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" BRIDGE_SENSOR,MOTOR,GEO
SG_ RECEIVED_DEST_LONGITUDE : 32|32@1+ (0.000001,-180.000000) [-180|180] "Degrees" SENSOR
 
  
BO_ 775 DBG_GPS_COMPASS_LOCK_LED_CHECK: 1 GEO
+
BO_ 101 DRIVE_STATUS: 1 BRIDGE_SENSOR
SG_ COMPASS_LED_STATUS: 0|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER, SENSOR, MOTOR
+
  SG_ DRIVE_START_STOP : 0|8@1+ (1,0) [0|0] "" DRIVER
SG_ GPS_LED_STATUS : 1|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER, SENSOR, MOTOR
 
  
BO_ 780 DBG_GEO_CAN_STATUS: 3 GEO
+
BO_ 200 SENSOR_SONARS: 5 BRIDGE_SENSOR
  SG_ DBG_CAN_INIT_STATUS: 0|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER, SENSOR, MOTOR
+
  SG_ SENSOR_SONARS_left : 0|10@1+ (1,0) [0|0] "cm" DRIVER
  SG_ DBG_CAN_RX_DROP_COUNT : 1|16@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER,SENSOR,MOTOR
+
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_ 781 DBG_SENSOR_CAN_STATUS: 3 SENSOR
+
BO_ 250 DESTINATION_LOCATION: 8 BRIDGE_SENSOR
  SG_ DBG_CAN_INIT_STATUS: 0|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER, GEO, MOTOR
+
  SG_ DEST_LATITUDE : 0|28@1+ (0.000001,-90.000000) [-90|90] "degrees" GEO
  SG_ DBG_CAN_RX_DROP_COUNT : 1|16@1+ (1,0) [0|0] "drops" DRIVER,GEO,MOTOR
+
  SG_ DEST_LONGITUDE : 28|28@1+ (0.000001,-180.000000) [-180|180] "degrees" GEO
  
BO_ 782 DBG_MOTOR_CAN_STATUS: 3 MOTOR
+
BO_ 300 DRIVER_TO_MOTOR: 2 DRIVER
SG_ DBG_CAN_INIT_STATUS: 0|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER, SENSOR, GEO
+
SG_ DRIVER_TO_MOTOR_speed : 0|8@1+ (1,0) [-30|30] "kmph" MOTOR
  SG_ DBG_CAN_RX_DROP_COUNT : 1|16@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER,SENSOR,GEO
+
  SG_ DRIVER_TO_MOTOR_direction : 8|8@1- (1,-2) [-2|2] "degrees" MOTOR
  
BO_ 783 DBG_DRIVER_CAN_STATUS: 3 DRIVER
+
BO_ 400 GEO_CONTROLLER_COMPASS: 8 GEO
SG_ DBG_CAN_INIT_STATUS: 0|1@1+ (1,0) [0|0] "TRUE_FALSE" GEO, SENSOR, MOTOR
+
  SG_ HEADING : 0|12@1+ (0.1,0) [0|359.9] "degrees" DRIVER, BRIDGE_SENSOR
SG_ DBG_CAN_RX_DROP_COUNT : 1|16@1+ (1,0) [0|0] "TRUE_FALSE" GEO,SENSOR,MOTOR
+
  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_ 784 DBG_MOTOR_INFO_MSG: 4 MOTOR
+
BO_ 600 MOTOR_SPEED: 2 MOTOR
  SG_ DBG_DC_MOTOR_CURRENT_PWM_sig: 0|8@1+ (0.1,0) [10|20] "duty percent" DRIVER
+
SG_ MOTOR_SPEED_info : 0|8@1+ (0.1,-10) [-10|10] "kmph" DRIVER, BRIDGE_SENSOR
  SG_ DBG_SERVO_MOTOR_CURRENT_PWM_sig : 8|8@1+ (0.1,0) [10|20] "duty percent" DRIVER
 
  SG_ DBG_PID_OUTPUT_VALUE_sig : 16|8@1+ (0.1,0) [0|0] "kph" DRIVER
 
  SG_ DBG_MOTOR_SELF_TEST_sig : 24|1@1+ (1,0) [0|0] "TRUE_FALSE" DRIVER
 
  
BO_ 001 DRIVER_HEARTBEAT: 1 DRIVER
 
SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR,MOTOR
 
  
BO_ 002 SENSOR_HEARTBEAT: 1 SENSOR
+
BO_ 700 DRIVER_DEBUG: 2 DEBUG
SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR,MOTOR
+
  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_ 003 GEO_HEARTBEAT: 1 GEO
+
BO_ 750 GEO_CONTROLLER_DEBUG_MESG: 10 DEBUG
  SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR,MOTOR
+
  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
BO_ 004 MOTOR_HEARTBEAT_MSG: 1 MOTOR
+
SG_ RAW_HEADING : 56|12@1+ (0.1,0) [0|359.9] "degrees" DEBUG
  SG_ MOTOR_HEARTBEAT_sig : 0|8@1+ (1,0) [0|255] "pulse" DRIVER
 
  
 
CM_ BU_ DRIVER "The driver controller driving the car";
 
CM_ BU_ DRIVER "The driver controller driving the car";
Line 631: Line 712:
 
CM_ BU_ SENSOR "The sensor controller of the car";
 
CM_ BU_ SENSOR "The sensor controller of the car";
 
CM_ BO_ 100 "Sync message used to synchronize the controllers";
 
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";
 
CM_ SG_ 100 DRIVER_HEARTBEAT_cmd "Heartbeat command from the driver";
  
BA_DEF_ "BusType" STRING ;
+
VAL_ 300 DRIVER_TO_MOTOR_direction -2 "MOTOR_direction_HARD_LEFT" -1 "MOTOR_direction_SOFT_LEFT" 0 "MOTOR_direction_STRAIGHT" 1 "MOTOR_direction_SOFT_RIGHT" 2 "MOTOR_direction_HARD_RIGHT" ;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0;
+
VAL_ 700 car_steering_status 2 "RIGHT" 1 "LEFT" 0 "STRAIGHT";
BA_DEF_ SG_ "FieldType" STRING ;
+
VAL_ 700 car_driving_status 2 "BACKWARD" 1 "FORWARD" 0 "STOPPED";
 
 
BA_DEF_DEF_ "BusType" "CAN";
 
BA_DEF_DEF_ "FieldType" "";
 
BA_DEF_DEF_ "GenMsgCycleTime" 0;
 
 
 
BA_ "GenMsgCycleTime" BO_ 100 1000;
 
BA_ "GenMsgCycleTime" BO_ 200 50;
 
BA_ "FieldType" SG_ 100 DRIVER_HEARTBEAT_cmd "DRIVER_HEARTBEAT_cmd";
 
 
 
VAL_ 100 DRIVER_HEARTBEAT_cmd 2 "DRIVER_HEARTBEAT_cmd_REBOOT" 1 "DRIVER_HEARTBEAT_cmd_SYNC" 0 "DRIVER_HEARTBEAT_cmd_NOOP" ;
 
 
</pre>
 
</pre>
<HR>
 
<BR/>
 
  
== Sensor ECU ==
+
=== Technical Challenges ===
https://gitlab.com/infallibleprogrammer/utah/-/tree/user/jtran1028/%2311/refresh-one-sensor-per-20hz
+
* The CAN transceivers that we bought had inbuilt 120 ohm resistor each, which we didn't notice. And every time we interfaced all the four nodes the data won't show up in the busmaster software. We found this very late and until then we thought it's hardware/dbc file issue and wasted potential amount of time in debugging.So we de-soldered those termination resistors and we were able to see our data smoothly on busmaster.
 +
* As an advice, make sure at the end of all four nodes after adding termination resistors of 120 ohm on both sides, the resultant resistance is 60 ohms. Only then all four nodes can communicate over CAN bus.
  
 +
== Sensor and Bluetooth ECU ==
 
=== Hardware Design ===
 
=== Hardware Design ===
The sensor of choice for UTAH, was the LV-MAXSonar-EZ1 MB1010. The LV-MAXSonar-EZ1 comes in five different models for the ultrasonic sensor. These models are the MB1000, MB1010, MB1020, MB1030, and MB1040. The models are based on the beam width of the sensor. MB1000 has the widest beam pattern where as MB1040 has the narrowest. It was decided that the MB1010 model was better suited for object detection. If the beam pattern is too wide given the MB1000, there is a greater chance of cross talk between sensors. If the beam pattern is too narrow, there may be blind spots which must be accounted for. Thus, four LV-MAXSonar-EZ1 MB1010 sensors were used. Three sensors were placed in the front and one in the rear of the vehicle. It will be noted that the SJTWO board is configured to have three ADC channels. Thus to account for a fourth sensor, the DAC was configured to be an ADC channel. More of this configuration will be discussed in the software design.
 
 
<br/>
 
{| style="margin-left: auto; margin-right: auto; border: none;"
 
|[[File:LV-EZ-Ultrasonic-Range-Finder-600x600.jpg|165px|left|thumb|upright=0.4|Front view of the MB1010 LV-MAXSonar-EZ1]]
 
|
 
|[[File:LV-MaxSonar-EZ1_PINS.png|200px|left|thumb|upright=0.4|Rear view of the MB1010 LV-MAXSonar-EZ1 with pin labels]]
 
|
 
|}
 
[[File:Sensor Controller.png|750px|center|thumb|Sensor Hardware Design]]
 
  
<h5>Sensor Mounts and Placement</h5>
+
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 waves every few seconds. When ultrasonic waves collide and come back and strikes with this membrane a pulse is generated which is used for sensing.
Sensor mounts were 3D printed and attached to the front and rear bumper of the RC car. The prints were created such that GoPro mounts were attachable. The GoPro mounts allowed the sensors to tilt and rotate to a desired position. The 3D prints were created by David Brassfield. David was not a part of team UTAH, however, his contribution to our project was crucial. Thus, we deeply appreciate his craftsmanship and his contribution to our project.  
 
  
The sensors were positioned and angled away from eachother to minimize cross talk. Whereas, the GoPro mounts allowed the sensors to be tilted away from the ground to avoid an object being "detected". During initial testing without the mounts, objects were being "detected" as the pulse of the sensors would collide with the ground. However, tilting the sensors upward may cause objects to not be detected or be seen as further away. Through trial and error, the correct tilt was found and fixed to that position for each sensor.
 
  
<br/>
+
[[File:Sensor_Node.png|left|400px|thumb|Sensor Controller Diagram]]
{| style="margin-left: auto; margin-right: auto; border: none;"
 
|[[File:Front_Bumper_View.jpg|400px|left|thumb|Front Sensor Mount]] || [[File:Rear_Bumper_View.jpg|300px|right|thumb|Rear Sensor Mount]]
 
|
 
|}
 
  
<h5>Sensor Range Readings Extraction</h5>
+
[[File:Ultrasonic99.png|center|400px|thumb|Sensor Pins]]
  
To extract range readings from the MB1010, the "AN" pin which represents analog output was utilized. A range reading is commanded by triggering the "RX" pin high for 20us or more.  The output analog voltage is based on a scaling factor of (Vcc/512) per inch. All four of the sensors were powered from the SJTWO board, thus a 3.3v VCC was supplied to each sensor. According to the LV-MaxSonar-EZ datasheet, with 3.3v source, the analog output was expected to be roughly 6.4mV/inch. However, when initially testing the output range readings, the output was completely inaccurate. It was soon found out that the ADC channels for the SJTWO are configured at start up to have an internal pull up resistor. Disabling this pull up resistor will be discussed more in Software Design. Once this solution was resolved, the range readings were more accurate. The readings were tested by having multiple objects placed in front of each sensor and measuring the distance of the object to the sensors. Although the range readings were more accurate, it was found that the range readings did not necessarily follow the expected 6.4mV/inch. As a result, range readings were off by roughly +/- 6 inches. For instance, an object placed 25 inches could have been detected as 31 inches. To account for this, the scaling was adjusted to 8mV/inch. This value was extracted by placing objects around the sensors and checking if the analog output to inch conversion matched to the actual measured distance. The readings with stationary objects were roughly +/- 1 inch which was deemed suitable for object detection.
 
  
=== Software Design ===
 
The software design is split into two parts. An ultra sonic sensor module (1.) and a  sensor controller module (2.). The ultra sonic module contains functions to initialize the adc channels, initialize the sensors sensors ,and to extract range readings. The sensor controller utilizes the ultra sonic sensor module to initialize and extract range readings from the ultra sonic sensors. In addition, the sensor controller contains the logic to transmit the readings for the front, left, right, and rear sensors over CAN to the driver controller.
 
  
<h5>1. Ultra Sonic Sensor Module</h5>
 
The ultra_sonic_sensors.h file can be seen below. This module contains an enumeration to specify the position of each sensor. In addition, an ultra_sonic_sensor struct was created to specify trigger pins, positions using the enum, and etc. The module contains basic functions to initialize the adc channels, to initialize the sensors,and to extract range readings. In addition, a median function was added to return the median of the last three data range readings for a given ultra_sonic_sensor.
 
  
<br/>
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
{| style="margin-left: auto; margin-right: auto; border: none;"
+
|+Pin connections between board and sensor:
|[[File:ultra_sonic_sensors_header_file.PNG|700px|left|thumb|ultra_sonic_sensors.h]]
+
|-
|
+
! scope="col"| Sl No.
 +
! scope="col"| SJ2 board Pin No.
 +
! scope="col"| Ultrasonic sensor Pin No.
 +
! scope="col"| Function
 +
|-
 +
! scope="row"| 1.
 +
| ADC Pin 1.30
 +
| AN(Front left sensor)
 +
| Input to ADC channel 4
 +
|-
 +
! scope="row"| 2.
 +
| ADC Pin 1.31
 +
| AN(Front right sensor)
 +
| Input to ADC channel 5
 +
|-
 +
! scope="row"| 3.
 +
| ADC Pin 1.26
 +
| AN(Front sensor)
 +
| Input to ADC channel 3
 +
|-
 +
! scope="row"| 4.
 +
| ADC Pin 1.25
 +
| AN(Rear sensor)
 +
| Input to ADC channel 3
 +
|-
 +
! scope="row"| 5.
 +
| GPIO Pin 0.6
 +
| Rx(Front left sensor)
 +
| Triggering pulse for left sensor
 +
|-
 +
! scope="row"| 6.
 +
| GPIO Pin 0.8
 +
| Rx(Front right sensor)
 +
| Triggering pulse for right sensor
 +
|-
 +
! scope="row"| 7.
 +
| GPIO Pin 0.9
 +
| Rx(Front sensor)
 +
| Triggering pulse for front sensor
 +
|-
 +
! scope="row"| 8.
 +
| GPIO Pin 0.7
 +
| Rx(Rear sensor)
 +
| Triggering pulse for rear sensor
 +
|-
 
|}
 
|}
  
<h6>Initializing the ADC channels</h6>
 
This section is added as a tip for future CMPE 243 students. The SJ2 board is configured for three ADC channels and a single DAC channel. To modify the DAC to be a fourth ADC channel, Preet's ADC API was modified in adc.c. In addition, the source file was modified to disable pull-up resistors. The IOCON registers can be configured following the table descriptions below. Table 86. shows that P0.26 which was configured as a DAC, can be configured for ADC0[3]. Table 85., shows the bit patterns to disable pull-up resistors and to enable analog mode.
 
  
<br/>
+
Apart from the pin connections for the Sensor node the important thing is to mount the sensors at particular angles. The angle placement is critical for left and right sensor as we faced lot of problems while detecting the walls. We chose the angle by error and trial method by simply placing the sensors at different angles. We tried keeping the angle above the 45 degrees so that to provide wider angle for the obstacles to detect.
{|
 
|[[File:IOCON_register_ADC.PNG |600px|left|thumb|LPC User Manual Table Showing ADC configurations]] || [[File:ADC_pin_configuration.PNG|700px|center|thumb|LPC User Manual Table Showing Pin Configurations]]
 
|
 
|}
 
  
 +
=== Software Design ===
  
<h5>2. Sensor Controller</h5>
+
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.  
The sensor controller module contains logic to initialize the sensors using the ultra_sonic_sensor_module. In addition, it contains the logic to transmit the range readings over CAN to the driver controller. Sensor_Controller_Init() initializes the adc channels and the ultra sonic sensors using the ultra_sonic_sensor module. Sensor_Controller_100hz_handler contains the logic to trigger sensor pins to command a range reading and to transmit range readings for each sensor over CAN to the driver controller. Each range reading per sensor is updated every 50ms to avoid cross talk. More on this is discussed in the "Accounting for Cross Talk" section.
 
  
To trigger each sensor for each call to Sensor_Controller_100hz_handler, an array ultra_sonic_sensor sensor[4] was created for the front, left, right, and rear sensor. A count labeled current_index, keeps track of which sensor distance reading to update.
+
====== Receive sensor values ======
  
The logic for Sensor_Controller_100hz_handler goes as follows:
+
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.
  
* 1.) get_ultra_sonic_distances(&sensor[current_sensor_index]);
+
====== Sending sensor values in terms of distance to CAN ======
* 2.) get_median_distance(&sensor[current_sensor_index]);
 
* 3.) Update the distance reading for the ultra sonic sensor and transmit it over the CAN BUS
 
* 4.) set current_sensor_index  equal to (current_sensor_index + 1) % 4
 
* 5.) Command a range reading for sensor[current_sensor_index]. The reading will be available after 50ms, thus the next callback for get_ultra_sonic_distances() will have an updated range reading
 
  
<h5>Algorithm</h5>
+
The raw values coming from the sensor needs to be filtered before sending on the CAN bus. The more information about filtering is mentioned in the techical challenges section. The below diagram shows the detailed flowchart of software design implemented for the sensor node.
The following functions are called in periodic callbacks. Discussion on the bridge controller is found in its respective section. The flow chart of the software can be seen below.
 
  
<h6>Periodic Callbacks Initialize:</h6>
 
* initialize can bus
 
* Call Sensor_Controller_init()
 
* Call Bridge_Controller_init()
 
  
<h6>Periodic Callbacks 1Hz:</h6>
+
[[File:f8.png|center|6600px|thumb|Sensor Controller Diagram]]
* Call Bridge_Controller__1hz_handler()
 
* Call can_Bridge_Controller__manage_mia_msgs_1hz()
 
  
<h6>Periodic Callbacks 100Hz:</h6>
+
=== Technical Challenges ===
* Call Sensor_Controller__100hz_handler() at 20Hz
+
*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  particular 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.
  
<br/>
 
{|
 
|[[File:Sensor_flow_chart.jpg |750px|center|thumb|Sensor flow chart]]
 
|
 
|}
 
 
 
<h5>Accounting for Cross Talk</h5>
 
Originally, each sensor was triggered simultaneously within a 50ms time frame. By doing this, there seemed to be an increase in cross talk between sensors. The range readings can be seen in the plot below, for when no object was placed in front of the sensors and for when an object was placed about 30 inches away from the right sensor. From these plots, we can see the cross talk occurs when an object was placed in front of a sensor. The cross talk causes the left sensor to see an object near the given range in which the object was placed in front of the right sensor. Although the cross talk occurs a few times, this will cause an object to be "detected", thus the car will sway to dodge the object. As a result, if an object is detected on the right sensor, the left sensor may detect an object. Thus, for example, the object avoidance algorithm will call for the RC car to reverse instead of moving left to dodge the object on the right. It will be noted that the rear sensor can be ignored in the plot as it was isolated and moved away for testing purposes. To minimize the cross talk, each sensor are individually triggered every 50ms. This gives each sensor a 50ms time frame to extract a range reading with less interference.
 
<br/>
 
{| style="margin-left: auto; margin-right: auto; border: none;"
 
|[[File:Cross_talk_plot_object_on_right.PNG |400px|left|thumb|Range Readings showing cross talk between sensors with an object placed 30 inches away from the right sensor]] || [[File:Cross_talk_plot_no_object.PNG|400px|center|thumb|Range Readings showing cross talk between sensors without objects near sensors]]
 
|
 
|}
 
 
=== Technical Challenges ===
 
The biggest challenge was cross talk. The median function was added as a filtering mechanism. Although cross talk was minimized by having the sensors angled away from each other, there was still occurrences of objects being "detected" even when no objects were within a threshold for object avoidance. This may be a result of movement of the vehicle. Thus, if an object was to be "detected", the RC car will maneuver to avoid the object even if no object was in close proximity. The median function would return the median of the last three range readings. This minimized the chance of false positives occurring for object avoidance. However, this introduced new issues. As each sensor is updated individually every 50ms, all sensors will have updated values after 200ms. With the median filter taking into account the pass three range readings, this will cause a huge delay between readings. Thus, if an object is to be detected below a threshold, the previous value must have also been below the threshold in order for the object to be avoided. Therefore, two range readings will be needed to trigger a response. Which worse case can be 400ms. A better approach would have been to keep track of the previous value and keep a delta value in which the current sensor reading can be deemed as valid compared to the previous value.
 
  
 
<HR>
 
<HR>
Line 753: Line 815:
  
 
== Motor ECU ==
 
== 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.
[https://gitlab.com/infallibleprogrammer/utah/-/tree/user/amritpal_sidhu/%2310/Motor_Controller_Refine_PID Motor Source Code]
+
The RPM sensor sends its output to motor ECU by which the actual speed of the wheels is calculated.
 
 
 
=== Hardware Design ===
 
=== Hardware Design ===
 +
{| style="margin-left: auto; margin-right: auto; border: none;"
 +
|[[File: Motor_HW_design.jpg|center|600px|thumb|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.
  
[[File:Wiring diagram.jpg|750px|center|thumb|Motor hardware wiring]]
+
'''The car can be operated in the following 3 modes:'''
 +
<br/>
 +
Sport mode(100% Forward, 100% Brakes, 100% Reverse)
 +
<br/>
 +
Racing mode(100% Forward, 100% Brakes, No Reverse)
 +
<br/>
 +
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.
 +
<br/>
 +
PWM 10 to 14.9 for reverse.
 +
<br/>
 +
PWM 15 for neutral.
 +
<br/>
 +
PWM 15.1 to 20 for the forward.
  
 
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
[[File:Motor controller.png|750px|center|thumb|Motor hardware Design]]
+
|+ESC Pinout
 
 
 
 
 
 
Motor Controller includes the controlling of the DC motor, Servo motor, Electronic speed control (ESC), and the wheel encoder. The job of the motor controller is both to steer and spin the wheels in order to move the RC car to the target destination.
 
The DC motor, servo motor, and ESC(Traxxas ESC XL-05) were provided with the Traxxas RC car. The wheel encoder was purchased separately from Traxxas's website.
 
The job of the DC motor is to control the spinning of the rear 2 wheels through the utilization of ESC and wheel encoder whereas the job of the servo motor is to control the steering of the front 2 wheels.
 
 
 
{| class="wikitable" style="margin-center: auto; margin-center: auto; text-align:center;"
 
|+ Motor Board Pinout
 
 
|-
 
|-
! SJ2 Board Pin !! Description
+
! scope="col"| Wires on ESC
 +
! scope="col"| Description
 +
! scope="col"| Wire Color
 
|-
 
|-
| 5V || Input power
+
! scope="row"| PWM(P2.1)
|-
+
| Takes PWM input from SJ2-Board
| 3.3V || CAN transceiver power
+
| WHITE
|-
 
| PWM2 P2.1 || DC Motor Speed Control
 
|-
 
| PWM5 P2.4 || Servo Motor Control
 
|-
 
| CAP0 P2.6 || Input Capture for RPM Sensor
 
|-
 
| CAN1 TX || CAN Module Tx
 
|-
 
| CAN1 RX || CAN Module Rx
 
 
|-
 
|-
| GND || Grounding
+
! scope="row"| VDD(6V)
|}
+
| Power Output
 
 
 
 
==== DC Motor and ESC  ====
 
 
 
The DC motor and ESC were provided with RC car. The DC motor is controlled by the ESC using PWM signals which were provided by the motor controller board for forward, neutral, and reverse movements. The ESC is powered ON using a 7.4 LiPo battery. The ESC converts this 7.4V to 6V and provides input to DC Motor. 
 
 
 
 
 
[[File:DC motor.jpg|350px|center|thumb|DC Motor]]
 
 
 
 
 
{| class="wikitable" style="text-align: center;"
 
|-
 
! scope="col"| ESC wires
 
! scope="col"| Description
 
! scope="col"| Wire Color                                                                   
 
|-
 
! scope="row"| Vout
 
| Output Power (6V)
 
 
| RED
 
| RED
 
|-
 
|-
Line 815: Line 858:
 
| Ground
 
| Ground
 
| BLACK
 
| BLACK
|-
 
! scope="row"| PWM
 
| PWM input from SJ2-Board (P2.1)
 
| WHITE
 
 
|-
 
|-
 
|}
 
|}
  
The car can be operated at 100Hz in the following 3 modes :
+
 
 +
 
 
<br/>
 
<br/>
Sport Mode (100% Forward, 100% Brakes, 100% Reverse)
+
{| style="margin-left: auto; margin-right: auto; border: none;"
<br/>
+
|[[File:ESC.jpg|center|300px|thumb|Traxxas ESC]]
Racing Mode (100% Forward, 100% Brakes, No Reverse)
+
|
<br/>
+
|[[File:DCMotor.jpg|center|300px|thumb|Traxxas Brushless DC Motor]]
Training Mode (50% Forward, 100% Brakes, 50% Reverse)
+
|
<br><br>
+
|}
The PWM frequency for our Traxxas ESC needed to be 100Hz.  An idle (motor stopped) duty cycle is 15%.  The full duty cycle range is [10%, 20%], where [10%, 15%) is the reverse range, and (15%, 20%] is the forward range.  We ended up limiting the duty cycle range to [13%, 17%] since the RC car had more power than we needed.
 
<br>
 
  
 
==== Servo Motor ====
 
==== Servo Motor ====
  
[[File:Servo motor.jpg|350px|center|thumb|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.
 +
<br/>
 +
PWM 15 for straight.
 +
<br/>
 +
PWM 15.1 to 20 for turning right.
  
{| class="wikitable" style="text-align: center;"
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
 +
|+Servo Pinout
 
|-
 
|-
! scope="col"| Servo Wires
+
! scope="col"| Wires on ESC
 
! scope="col"| Description
 
! scope="col"| Description
 
! scope="col"| Wire Color
 
! scope="col"| Wire Color
 
|-
 
|-
! scope="row"| Vin
+
! scope="row"| PWM(P2.0)
| Input Voltage (6V)
+
| Takes PWM input from SJ2-Board
 +
| WHITE
 +
|-
 +
! scope="row"| VDD(6V)
 +
| Power Input
 
| RED
 
| RED
 
|-
 
|-
Line 851: Line 899:
 
| Ground
 
| Ground
 
| BLACK
 
| BLACK
|-
 
! scope="row"| PWM
 
| PWM input from SJ2-Board (P2.4)
 
| WHITE
 
 
|-
 
|-
 
|}
 
|}
  
The PWM frequency for our Traxxas Servo motor also needed to be 100Hz.  An idle (wheel's pointing forward) duty cycle is 15%.  The full duty cycle range is [10%, 20%], where [10%, 15%) is the steer left range, and (15%, 20%] is the steer right.
+
{| style="margin-left: auto; margin-right: auto; border: none;"
<br>
+
[[File:Servotrx.jpg|300px|centre|thumb|Traxass Servo Motor(2075)]]
  
==== Wheel Encoder ====
+
==== 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.
 +
<br/>
 +
'''Mounting the sensor:'''
 +
<br/>
 +
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.
 +
<br/>
 +
'''How the sensor works:'''
 +
<br/>
 +
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.
  
For speed sensing we purchased a Traxxas RPM sensor as it mounted nicely in the gearbox.  The RPM sensor works by mounting a magnet to the spur gear and a hall effect sensor fixed to the gearbox.  To get the revolutions per second we used Timer2 as an input capture. <br>
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
 
+
|+RPM Pinout
 
 
[[File:RPM.jpg|350px|center|thumb|Servo Motor]]
 
 
 
 
 
{| class="wikitable" style="text-align: center;"
 
 
|-
 
|-
! scope="col"| RPM Sensor Wires
+
! scope="col"| Wires on ESC
 
! scope="col"| Description
 
! scope="col"| Description
 
! scope="col"| Wire Color
 
! scope="col"| Wire Color
 
|-
 
|-
! scope="row"| Vin
+
! scope="row"| GPIO(P0.6)
| Input Voltage (6V)
+
| Provides pulses to Motor SJ2-Board
 +
| WHITE
 +
|-
 +
! scope="row"| VDD(3.3V)
 +
| Power Input
 
| RED
 
| RED
 
|-
 
|-
Line 883: Line 935:
 
| BLACK
 
| BLACK
 
|-
 
|-
! scope="row"| Sensor Output
+
|}
| Input Capture to SJ2-Board (P2.6)
+
 
| WHITE
+
<br/>
|-
+
{| style="margin-left: auto; margin-right: auto; border: none;"
 +
|[[File:Rpm_sensor.jpg|center|300px|thumb|Traxxas RPM Sensor]]
 +
|
 +
|[[File:Trigger_magnet.jpg|center|300px|thumb|Trigger Magnet]]
 +
|
 
|}
 
|}
  
 
=== Software Design ===
 
=== Software Design ===
The motor controller code modules consisted of 3 main parts, which are: 1. PWM drivers and motor logic, 2. RPM/speed sensor, 3. PID controller.
+
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.
  
<h6>1. PWM drivers and motor logic</h6>
+
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 PWM drivers were fairly easy to write since the SJ2 project provided an API for the low level function calls.  Converting speed and angle values to duty cycle values was done by simply linearly mapping one onto the other. This worked fine for steering control, but due to varying grades the car needs to drive on, the PID is needed. The Traxxas ESC, as other students have discovered in the past, has safeguards to prevent damage to the motor by not allowing duty cycle to abruptly change from a forward signal to a reverse.  The Traxxas transmitter uses a trigger for this, but as other students suggested, we used a state machine to transition into opposite directions.  We found that going from reverse to forward simply requires stopping (15% duty cycle) the car first, while going from forward to reverse required sending the following signals: STOP, REVERSE, STOP, REVERSE. Since we did not consult with Traxxas, this logic was created through trial and error. Transitioning into the opposite direction might simply just require stopping first, and then delay until a speed is reached, then change directions.  We had access to an oscilloscope, however we did not capture what actually happens to the DC motor duty cycle when the transmitter does the same transition.
 
  
We created a separate module that encapsulated the motor's drive logic, such as getting speed feedback to compute PID value, updating the DC motor and servo motor's PWM in a state machine, and doing the start up self test.  Another feature we incorporated was to have the motor controller listen for a message from the Bridge/App, so we could easily start and stop the car remotely.  This feature was very helpful in testing.
+
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.
  
Later on we also added the feature to run the Traxxas ESC setup by pushing a push button at start up.  You need to hold the ESC button when you turn on the car until the green light turns red, then push SW3 on the motor board to run the ESC setup.  The setup is fairly simple, it puts the DC motor PWM in full forward (20%) for 3 seconds, full reverse (10%) for 3 seconds, then neutral (15%) for 3 seconds before returning a true for finishing.  The function is called in a periodic and the counts are kept track of internally by the function.  The 3 seconds was a guess, but it seemed to work fine.
+
'''The period_callbacks__initialize() function calls the following functions:'''
 +
* can_bus_initializer: Initializes CAN buffers and sets baud rate
 +
* initialize_speed_sensor_interrupts: sets up GPIO pin as hardware interrupt
 +
* motor_init_pwm: initializes pwm pin.
  
<h6>2. RPM/speed sensor</h6>
+
'''The period_callbacks__1Hz() function calls the following function:'''
To count the time interval between pulses the RPM sensor makes, we used one of the LPC's peripheral timers that allowed for an input capture feature.  We configured the hardware registers such that a capture register is written the value of the timer count register when the input capture (pulse from RPM sensor) occurs.  This required writing a low level API so that we could unit test the hardware reading and writing.  An interrupt also triggers on a capture event to reset the timer counter, to make the value in the capture register easy to convert to revolutions per second.  The circumference of the car's tire and spur gear ratio are needed to determine a scalar value to convert the revolutions per second to conventional speed units. Many students said the RPM sensor from Traxxas was inconsistent and unreliable for speed feedback.  We thought that this might be because of how the sensor is measuring the speed of the spur gear and that the differential of the car might cause variation, however when the car goes in a straight line that should not be a problem.  When we integration tested the software design with the PID using the above approach, the speed readings seemed stable enough for use with the PID.
+
* can_handler__handle_all_incoming_messages_1hz: handles the incoming messages based on mesg ID.
 +
* can_handler__transmit_messages_1hz: sends the motor speed to Driver controller.
  
<h6>3. PID controller</h6>
+
'''The period_callbacks__10Hz() function calls the following functions:'''
For situations where the DC motor needs to do more or less work (e.g. driving uphill or downhill) the linear mapping will not work.  The proportional, integral, derivative (PID) controller is a widely used control mechanism to ensure a machine maintains a set point, and responds quickly and smoothly upon disturbances. In discrete time the integration becomes a summation and the derivative becomes a difference. The controller is based on an error from the set point, which is why the RPM sensor is needed to get feedback.  The PID algorithm is fairly simple, as is tuning the gainsWe found that the proportional and integral gains were enough to get the car to maintain speed.
+
* pwm1__set_duty_cycle: to calibrate the ESC by sending neutral signal for few seconds.
 +
* clear_rotations: clears interrupt counter every 0.5 seconds
 +
* can_handler__handle_all_incoming_messages: receives any message frame sent on the CAN bus.
 +
   
  
The way we tuned the PID was to start off by only using the proportional controller at a unity gain.  We had the car drive on level ground and tested at 3kph and 5kph drive speeds.  We varied the proportional gain until we saw the car have a "stop and go" motion.  Then we dropped the proportional gain in half and tested again with a low integral gain.  We now started testing on ground with a grade to see if speed could be maintained.  We varied the integral gain until we were satisfied with the DC motor's response to varying terrain.
+
<br/>
 +
[[File: Motor_SW_design.jpg|center|700px|thumb|Speed Control Flowchart]]
  
 +
=== Technical Challenges ===
  
Below is our design for the motor controller's periodic callbacks.
+
* 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 a higher frequency helped in reducing the response time in obstacle avoidance compared to previously when it was being received at 10Hz.
 +
<br/>
 +
<HR>
 +
<BR/>
  
<div style="margin-left:1.5%;">
+
== Geographical And Bridge Controller ==
<h6>Periodic Callbacks Initialize:</h6>
 
* Initialize:
 
** CAN bus
 
** DC motor PWM
 
** Servo motor PWM
 
** RPM sensor input capture
 
** PID
 
** Motor logic
 
  
 +
=== Hardware Design ===
  
<h6>Periodic Callbacks 1Hz</h6>
+
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.
* Reset CAN bus if bus goes off
 
** Have LED indicate CAN bus running status
 
* Transmit motor debug message
 
* Transmit motor CAN status
 
  
 +
<li style="display: inline-block;"> [[File:Geo_Node_Schematic.jpg|500px|thumb|centre|]] </li>
 +
<li style="display: inline-block;">[[File:compass_Firebolt.jpg|300px|thumb|center|3 Axis Magnetometer (eCompass)]] </li>
  
<h6>Periodic Callbacks 10Hz</h6>
+
<li style="display: inline-block;"> [[File:GPS_Firebolt.jpg|300px|thumb|centre|GPS Module]] </li>
* At 2Hz transmit motor speed
 
* Update steering angle and drive speed
 
** Run ESC setup once user pushes button (Optional, can be bypassed)
 
** At board power up a self test routine is ran (Also optional, but usually ran)
 
** After the self test, Driver & Bridge/App controller commands are followed
 
  
  
<h6>Periodic Callbacks 100Hz</h6>
 
* At 20Hz receive all messages from CAN bus and update local motor data structure
 
</div>
 
 
[[File:motor_logic__run_once__picture.jpg|350px|left|thumb|motor_logic__run_once() flowchart]]
 
[[File:motor_logic__update_motor_state_once_picture.jpg|350px|center|thumb|motor_logic__update_motor_state_once() flowchart (see code, or description above, for more details on state machine)]]
 
 
=== Technical Challenges ===
 
 
* Getting the state machine right for the DC motor to transition between forward and reverse, and vice versa, took some experimentation.  Luckily other student's reports were available for us to get hints on what we needed to do.
 
* When first tuning the PID our boards were attached via jumper wires and breadboard on a piece of plexiglass.  The plexiglass was not rigidly secured to the car either, which resulted in collisions with walls and wires becoming undone.  All this led to more hardware issues and had us backtrack to get the PID tuned.  Making sure the hardware is sound before doing full integration tests will save you time.  This requires planning out the hardware early on, and preferably just getting a PCB manufactured.
 
* We were having problems during integration testing where the motors would not run.  It's hard to say what the solution was for certain, but slowing down the rate we updated the PWMs (from 20Hz to 10Hz) seemed to be it.
 
* We damaged the ESC somehow and needed to purchase another.  This cost us time and money.  Make sure you don't accidentally short the ESC!
 
* Some unit tests were not written until after integration testing.  This goes against test driven development, but due to deadlines we had to make a choice.  Had we thought out the use cases of our modules and wrote unit tests sooner, I'm sure we would have avoided some in the field debugging.
 
* The code had to be redesigned for modularity and readability later on.  Make sure to avoid software anti-patterns, like "blob," and use dependency injection to prevent tightly coupled code modules.
 
* We damaged one of the LiPo batteries we purchased because we drained the voltage below 3V per cell.  Luckily we had another LiPo for testing, but having a voltage sensor to indicate to the app the battery level could be a good idea.
 
 
<HR>
 
<BR/>
 
 
== Geographical Controller ==
 
https://gitlab.com/infallibleprogrammer/utah/-/tree/master/projects/GEO_Controller
 
<Picture and link to Gitlab>
 
 
=== Hardware Design ===
 
The geographical controller runs all the processing for compass data as well as GPS data. The purpose of the controller is to interface with the Adafruit Ultimate GPS Breakout using UART which provides accurate GPS data formatted in GPGGA. The controller utilizes I2C protocol to interface with the Adafruit Magnetometer with tilt compensation for the purpose of finding our heading and where the car needs to point in order to get closer to its destination. The Adafruit magnetometer was able to give us accurate data with a possible deviation of up to 3 degrees in any direction. This was possible by using a software filter to normalize our data and create a standard.
 
 
[[File:Geo Akash.png|750px|center|thumb|Geo Hardware Design]]
 
 
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
 
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
|+Table 5. Geographical Node Pinout
+
|+Geographical Node Pinout
 
|-
 
|-
 
! scope="col"| SJTwo Board
 
! scope="col"| SJTwo Board
 
! scope="col"| GPS/Compass Module
 
! scope="col"| GPS/Compass Module
 
! scope="col"| Description
 
! scope="col"| Description
! scope="col"| Protocol/Bus
 
 
|-
 
|-
| P4.28 (TX3)
+
| P0.15 (TX3)
 
| RX  
 
| RX  
 
| Adafruit GPS Breakout  
 
| Adafruit GPS Breakout  
| UART 3
 
 
|-
 
|-
| P4.29 (RX3)
+
| P0.16 (RX3)
 
| TX  
 
| TX  
 
| Adafruit GPS Breakout
 
| Adafruit GPS Breakout
| UART 3
 
 
|-
 
|-
| P0.10 (SDA2)
+
| P0.10 (SDA)
 
| SDA  
 
| SDA  
 
| Adafruit Magnetometer  
 
| Adafruit Magnetometer  
| I2C 2
 
 
|-
 
|-
| P0.10 (SCL2)
+
| P0.11 (SCL)
 
| SCL
 
| SCL
 
| Adafruit Magnetometer
 
| Adafruit Magnetometer
| I2C 2
 
 
|-
 
|-
| P0.1 (SCL1)
+
| P0.1
 
| CAN transceiver (Tx)
 
| CAN transceiver (Tx)
 
| CAN transmit  
 
| CAN transmit  
| CAN
 
 
|-
 
|-
| P0.0 (SDA1)
+
| P0.0
 
| CAN transceiver (Rx)
 
| CAN transceiver (Rx)
 
| CAN  receive
 
| CAN  receive
| CAN
 
 
|-
 
|-
 
| Vcc 3.3V
 
| Vcc 3.3V
 
| Vcc  
 
| Vcc  
 
| Vcc  
 
| Vcc  
|
 
 
|-
 
|-
 
| GND  
 
| GND  
 
| GND  
 
| GND  
 
| Ground  
 
| Ground  
|
 
 
|-
 
|-
 
|}
 
|}
 +
 +
<BR/>
  
 
=== Software Design ===
 
=== Software Design ===
The GEO controller consisted of 4 main parts which are: 1. GPS Driver and Processing, 2. Compass Processing, 3.Waypoints Algorithm, and 4. Geo Logic. The geo logic takes data from parts 1 to 3 and determines where the car should be moving. This data is sent to the driver controller via the canbus.
+
The GEO controller consisted of 4 main parts which are:  
 +
 
 +
*1. GPS  
 +
*2. Compass  
 +
*3. Waypoints
 +
*4. Geo Logic
 +
 
 +
====Overview====
  
<h5>1. GPS Driver and Processing</h5>
+
These code 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 GPS module uses UART3 to communicate with our SJ2 board. The API call for the GPS driver requires setting up the gps registers to only allow GPGGA data as well as refresh data every 10hz(100ms) instead of 1hz(1 second). This solve a lot of initial issues with getting stale data as the car moved. The main API function is called gps__run_once() which digests data from the physical GPS hardware. Inside gps__run_once(), we call two functions that help with parsing the gps coordinates. The first is taking using a line buffer for the UART characters that are digested during operation and checking if they are in fact a full GPGGA string. The second function parses those coordinates from the line buffer and converts them from GPGGA minutes data to polar coordinates. Once the function is called, global static variables located in gps.c are used while a gps__get_coorindate() function is called whenever the API's data wants to be used outside of the gps.c file. In order to check if there is a gps fix, we created a function that checks if certain GPGGA bits are set or not. If the are set, than we have a fix. This was more accurate than the FIX pin located on the GPS module because of that pin toggles every 150ms even when their is a fix.
 
  
<h5>2.Compass Processing</h5>
+
'''The period_callbacks__initialize() function calls the following functions:'''
The compass module was one of the trickiest parts of the GEO controller due to the necessary calibrations that came with the code. The compass is initialized to use I2C as a method for communicating with the SJ2 board. The API is primarily one function to get the latest, compass__run_once_get_heading(). This float function is split into three parts: get magnetometer data, get accelerometer data, and use both of those datasets to figure out the heading. The accelerometer was not used in the initial stages of development but was required to accommodate for tilt when the car was moving at high speeds. The compass required a lot of calculations to determine heading, and accommodate for tilt.
 
  
<h6>Heading Computation:</h6>
+
*can_bus_initializer__init(): initializes the CAN bus to handle MIA and messages(CAN).  
The lsm303DLHC magnetometer and acceletometer require tilt compensation to ensure accurate readings. If there is not tilt compensation, the compass heading can be up to 60 degrees off making it widely inaccurate. Once proper software based calculations were made, the compass was at most 3 degrees off. A software model was used to normalize the data and reduced noise related to bad readings.
+
*gps__init(): initializes the GPS interface(UART).
[https://www.pololu.com/file/0J434/LSM303DLH-compass-app-note.pdf#page=6 Compass Tilt Calculation]
+
*geo_compass__setup_magnetometer(): initializes the compass interface(I2C).
[https://www.instructables.com/Tilt-Compensated-Compass-With-LSM303DHLC/ Software Model for Compass]
 
  
<h6>Normalize Data: </h6>
+
'''The period_callbacks__1Hz() function calls the following function:'''
  float alpha = 0.25; // alpha to create base for software optimizations
 
  static float Mxcnf;
 
  static float Mycnf;
 
  static float Mzcnf;
 
  static float Axcnf;
 
  static float Aycnf;
 
  static float Azcnf;
 
  
  float norm_m =
+
* can_handler__handle_all_incoming_messages_1hz(): handles the incoming messages based on mesg ID.  
      sqrtf(magnetometer_processed.x * magnetometer_processed.x + magnetometer_processed.y * magnetometer_processed.y +
+
* gps__setup_command_registers(): sends command to GPS module to receive only GPGGA string.  
            magnetometer_processed.z * magnetometer_processed.z); // normalize data between all 3 axis
+
* can_handler__transmit_messages_10hz(): sends the heading ,bearing and distance to Driver controller.
  float Mxz = magnetometer_processed.z / norm_m;
 
  float Mxy = magnetometer_processed.y / norm_m;
 
  float Mxx = magnetometer_processed.x / norm_m;
 
  float norm_a = sqrtf(accel_raw_data.x * accel_raw_data.x + accel_raw_data.y * accel_raw_data.y +
 
                      accel_raw_data.z * accel_raw_data.z);
 
  float Axz = accel_raw_data.z / norm_a;
 
  float Axy = accel_raw_data.y / norm_a;
 
  float Axx = accel_raw_data.x / norm_a;
 
  
  Mxcnf = Mxx * alpha + (Mxcnf * (1.0 - alpha));
+
'''The period_callbacks__10Hz() function calls the following functions:'''
  Mycnf = Mxy * alpha + (Mycnf * (1.0 - alpha));
 
  Mzcnf = Mxz * alpha + (Mzcnf * (1.0 - alpha));
 
  
  // Low-Pass filter accelerometer
+
*gps_run_once(): parses the NMEA string to get current coordinates
  Axcnf = Axx * alpha + (Axcnf * (1.0 - alpha));
+
[[File:FlowChart_Geo_Logic.jpg|center|700px|thumb|Geo Logic Flowchart]]
  Aycnf = Axy * alpha + (Aycnf * (1.0 - alpha));
 
  Azcnf = Axz * alpha + (Azcnf * (1.0 - alpha));
 
*Notes:
 
** Mxcnf: Normalized Magnetometer X Data
 
** Mycnf: Normalized Magnetometer Y Data
 
** Mzcnf: Normalized Magnetometer Z Data
 
** Axcnf: Normalized Accelerometer X Data
 
** Aycnf: Normalized Accelerometer Y Data
 
** Azcnf: Normalized Accelerometer Z Data
 
  
The normalize data model shown above takes the magnetometer and accelerometer data that has been bit shifted and saved to a static function located in compass.c. The data is divided by the normalized data set for all 3 axis. This occurs for both the accelerometer and magnetometer. Once this data is taken, a low-pass filter is applied where the previous value of the data is used to check for deviation and offsets. An alpha of .25 is used to accommodate for a 75% threshold for deviations in the data during a given time frame. This data is later fed into the tilt compensation algorithm.
+
====GPS====
 +
*In the initialization process of the GPS, the line buffer module is configured to parse the GPS messages, the GPIOs P0.15(Tx) and P0.16(Rx) are configured, UART interrupt queues enabled, and the UART is configured at a baudrate of 9600(GPS standard).
 +
 
 +
*Configuration
 +
In the gps__run_once_10Hz() the GPS is initially configured once to disable all NMEA messages except GPGGA which is message chosen to parse the coordinates and GPS lock.
 +
 
 +
*Parsing NMEA GPGGA messages
 +
The GPS module constantly transmits NMEA GPGGA messages over UART to the SJ2 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. 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
 +
Although the GPS module has fix indication , but GPGGA string has field for FIX status also. Getting the Fix/Lock status using the string is much easier than using GPIO pins to get
 +
the Lock status using FIX led of the GPS module. The Lock status/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 LSM303DLHC magnetometer and accelerometer registers over I2C bus to default settings using default gain and single mode.
 +
 
 +
*Heading degree computation
 +
The compass heading degree is computed by using the tilt compensation algorithm and the pitch and roll values of LSM303DLHC accelerometer. The tilt compensation algorithm ensures
 +
that the values of the compass heading are precise. The formulae used to calibrate the compass are mentioned below:
 +
 
 +
*Pitch and Roll:<br/>
 +
 
 +
  pitch = asin(-acc_x / sqrt(acc_y * acc_y + acc_z * acc_z + acc_x * acc_x)) <br/>
 +
  roll = asin((acc_y / sqrt(acc_y * acc_y + acc_z * acc_z + acc_x * acc_x)) / cos(pitch))
  
<h6>Tilt Calculations: </h6>
 
  float pitch = asin(-Axcnf);
 
  float roll = asin(Aycnf / cos(pitch));
 
  float Xh = Mxcnf * cos(pitch) + Mzcnf * sin(pitch);
 
  float Yh = Mxcnf * sin(roll) * sin(pitch) + Mycnf * cos(roll) -
 
            Mzcnf * sin()roll) * cos(pitch);
 
  current_compass_heading = (atan2(Yh, Xh)) * 180 / PI;
 
  current_compass_heading += 13;
 
  if (current_compass_heading < 0) {
 
    current_compass_heading = 360 + current_compass_heading;
 
  }
 
  
Pitch and roll are a fundamental part of calculating the tilt. Pitch accounts for deviations in terms of the Y axis while roll is around the X axis. In the calculation seen above, pitch takes the asin of the negation of Axcnf(normalized x axis data for the accelerometer). Roll on the other hand is the ration of normalized y axis data over the cosine of pitch. These are used for the formula seen directly below it. The compass heading is adjusted 13 degrees due to our offset from true north. We need to use the true north value because the data sent to us by google maps compensates for true north. If we encounter an angle below 360, than we get its complement by adding 360 to ensure the rest of our calculations are correct.
+
*Tilt compensated magnetic sensor values:<br/>
  
<h5>3.Waypoints</h5>
+
  mag_x = mag_x * cos(pitch) + mag_z * sin(pitch)
The waypoints algorithm worked in a very simple way but was proven to be affective. The usage of waypoints are used as a way to 3D map obstacles related to the terrain of the SJSU 10th street garage.  As shown in the map below, we had 11 overall waypoints and a majority of them are located around the ramp located on the left side of the map. As shown in the map, we utilized waypoints in such a way to ensure that they went around the ramp, rather than through it. This was to avoid the hazard of the RC car believing it can go straight when in fact it can not due to the circular ramp. The points were also created in a line so that the RC car did not unnecessarily go towards the ramp because it was the closest waypoint. If we had a line of points, than it would calculate the point closest to itself and go towards the one. We also wanted to avoid redundant waypoints so we reduced the original 20 waypoints to 11. The checkpoint API looked flow is shown below.
+
  mag_y = mag_y * cos(roll) + mag_x * sin(roll) * sin(pitch) - mag_z * sin(roll) * cos(pitch)
 +
  mag_z = -mag_x * cos(roll) * sin(pitch) + mag_y * sin(roll) + mag_z * cos(roll) * cos(pitch)
  
[[File:Waypoint algorithm.png|200px|middle|Figure #. Waypoint API Flow]]
 
[[File:UTAH Waypoints map.png|500px|middle|Figure #. Waypoint Map]]
 
  
<h6>Distance Calculations: </h6>
+
Luckily our module had no offset but it might need to be compensated for the offset if there is any.
  // a = sin²(Δlatitude/2) + cos(destination_lat) * cos(origin_lat) * sin²(Δlongitude/2)
+
  // c = 2 * atan2(sqrt(a), sqrt(1−a))
+
*Heading angle
  // d = (6371 *1000) * c
 
  const int Earth_Radius_in_km = 6371;
 
  const float delta_lat = (origin.latitude - destination.latitude) * (PI / 180);
 
  const float delta_long = (origin.longitude - destination.longitude) * (PI / 180);
 
  float a = pow(sinf(delta_lat / 2), 2) +
 
            cosf(destination.latitude * (PI / 180)) * cosf(origin.latitude * (PI / 180)) * pow(sin(delta_long / 2), 2);
 
  float c = 2 * atan2f(sqrt(a), sqrt(1 - a));
 
  return (float)(Earth_Radius_in_km * c * 1000);
 
  
In order to get the calculation for distance, we must accommodate for the curvature of the Earth as well as the radius. In the equation above, we see haversine translated into C code which allows us the compute the distance in meter. This is done in the find_next_point() API call where we calculate the distance from origin to waypoint and waypoint to destination. We are looking for closest point that reduce the distance to the destination. If both of those statements are true, then we set that as our waypoint.
+
heading = atan2(mag_y, mag_x) * r2d
 +
r2d is radian to degree conversion function
  
<h5>4.Geo Logic</h5>
+
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
The geo logic was the primary API that allows the GEO controller to function. It takes data from waypoints.c, gps.c, and compass.c. The data is used and processed such that it may be send on the canbus. The geo_logic.c file primarily outputs dbc structs that are utilized in the can_module.c. With the implementation of waypoints, a lot of the calculation in geo_logic.c is no longer needed and will be editted out in the near future. At its current state the main functions in the API are geo_controller_processs_GEO_current_location() which gets the current GPS location for the RC car, geo_controllerprocess_geo_dat() which takes in the gps_destination sent by the bridge controller, and determine_destination_location() which tells the car where to go.
+
it in the range from 0 to 360 degrees.
  
[[File:GEO logic.jpg|250px|center|Figure #. GEO_Logic]]
+
====Checkpoints====
  
The geo logic was kept simple on purpose. We get our current location, then find out if a destination was sent to our static array. If no, new destination was received than we continue to determine if a waypoint is required to the destination. If the waypoint is used, then those values will be used for get_bearing(). We continue to process the read repeatedly for the 200ms cycle of the periodic scheduler. The task is that simple. If a new destination is appended then we add it and compute if we should go to that new destination first. The maximum allowed destinations is 5 by user design.
+
In real world, the source and destination are not on a straight line. The car has to find the best possible and smallest route to its final destination. In this project keeping that in mind we have used checkpoint algorithm. These waypoints are known coordinates which are given according to the destination and source path. The car needs to follow the route determined by the waypoints from source to destination.
  
Geo Controller Periodics:
+
We choose 10 points over a known location and hardcoded these coordinates in GEO node logic. Once our car gets the destination coordinates from Bridge and Sensor controller, it starts giving Heading , Bearing and Distance values to Driver Node. This waypoint must satisfy the below conditions:
<div style="margin-left:1.5%;">
+
* It is the closest waypoint to the current location of the car.
<h6>Periodic Callbacks Initialize:</h6>
+
* Waypoint to destination distance is less than the current coordinate to the final coordinate distance.
* Initialize:
+
[[File:Checkpoint.jpg]]
** CAN bus
 
** gps__init
 
** compass__init
 
  
<h6>Periodic Callbacks 1Hz</h6>
+
So when the algorithm finds the destination coordinates, then bearing is calculated with that particular coordinate, so that car can be further instructions to move towards that particular point. As shown in the figure below, our algorithm keeps finding new coordinates with time (orange ones) and at last go to the final destination coordinates. The algorithm is mentioned below in the form of flowchart and code:
* If not sent yet, send the GPS instructions to only receive GPGGA data and 10hz refresh rate
 
* Get compass update values
 
* Send debug messages every 1 second
 
  
<h6>Periodic Callbacks 10Hz</h6>
+
The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.
* Run the API gps__run_once() to fetch the latest data.
+
The heading and bearing is also computed using the Haversine formula and is sent over the CAN bus for heading correction.*
* Use data to determine bearing and heading of first waypoint/destination
+
Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.
** Send this information to the driver for processing
 
*Receive all messages on the canbus that are designated for us
 
  
</div>
+
To calculate the geographical distance between the two points the haversine formula was used which is called periodically from the waypoints.c module. Below is the formula used:
  
=== Technical Challenges ===
+
a = sin²(ΔlatDifference/2) + cos(lat1) * cos(lt2) * sin²(ΔlonDifference/2)
 +
c = 2 * atan2(sqrt(a), sqrt(1−a))
 +
d = R * c
  
* Adafruit GPS
+
*where:
** Problem: The data from the GPS was being refreshed every second which was causing issues for the RC car. It was swerving too much because of the stale data.
+
**ΔlatDifference = latitude 2 - latitude 1 (difference of latitude)
*** Solution: Send the command to the GPS for a higher refresh rate(10hz) and only send the SJ2 board GPGGA data.
+
**ΔlonDifference = longitude 2 - longitude 1 (difference of longitude)
** Problem: It would take way too long for the GPS to have a fix causing a 3-5 minute way when indoors and over 45 seconds when outside
+
**R = 6371000.0 meters = radius of earth
*** Solution: Utilize the external antenna. It was able to get a fix inside in under a minute while outside within 25 seconds.
+
**d = distance computed between two points
 +
**a and c are intermediate steps
  
* Compass
 
** Problem: The heading was widely inaccurate when attempting to see compass reading
 
*** Solution: When calibrating the sensor, do not have any electronics near you. Ensure you have enough distance between the controller and the compass when in the calibration step. This ensures accurate calibration and readings.
 
** Problem: The data on the compass was very inaccurate when compensating for tilt
 
*** Solution: Utilized magviewer to get proper bias rating for the compass sensor which we used. Data was with 3 degrees of the intended degree
 
  
== Communication Bridge Controller & LCD ==
+
*Bearing Angle computation
https://gitlab.com/infallibleprogrammer/utah/-/tree/master/projects/Sensor_Controller
 
  
=== Hardware Design ===
+
The bearing which is the angle towards our desired destination is computed using the formulas below referenced at this [https://www.igismap.com/formula-to-find-bearing-or-heading-angle-between-two-points-latitude-longitude/ link].
The bridge controller and sensor controllers were merged together on one board. For the hardware pinout, view the schematic located in the sensor controller section.
 
  
The hardware for the controller is a very straight forward design. The HC-05 Bluetooth modules is connected to the bridge controller via UART. The phone used for testing purposes must have a Bluetooth capabilities. For this reason, an emulated phone was unable to be used for anything except graphics and viewing purposes.
+
X = cos θb * sin ∆L
 +
Y = cos θa * sin θb – sin θa * cos θb * cos ∆L
  
To configure the HC-05, a Raspberry Pi 4 was setup to terminal into the HC-05 over UART. This site was helpful in the setup: https://www.instructables.com/Modify-The-HC-05-Bluetooth-Module-Defaults-Using-A/. One note, a few sites showed the command for setting the baud rate to be +AT+BAUD=____. This was invalid for the HC-05 and requires the +AT_UART= Baud, stop, parity.
+
β = atan2(X,Y)
  
=== Software Design ===
+
*where:
 +
**θa = current latitude
 +
**θb = destination latitude
 +
**∆L = destination longitude - current longitude
 +
**β = heading degree in radians
  
=== Bridge Controller ===
+
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.
To avoid mismatching data, a sort of semi brute force method was used for the messaging.
 
All messages are decoded in the 10hz periodic every cycle. The Bluetooth messages are sent in chunks in the 10 Hz periodic to avoid the overlapping of the messages, sending groups of messages at one time. The grouping is as follows: Driver and motor messages, GEO, then Sensors.
 
MIA checks for all messages is done in the 1 Hz periodic. This setup was extremely helpful for identifying if a board was flashed with the incorrect code or stopped sending messages that were supposed to be sent.  
 
  
 
=== Technical Challenges ===
 
=== Technical Challenges ===
  
There were only a few challenges faced with the Bridge Controller.
+
<HR>
 +
* Adafruit GPS
 +
** Problem: The data from the GPS was being refreshed every second which was causing issues for the controller.
 +
*** Solution: Send the command to the GPS module only send the SJ2 board GPGGA data.
 +
** Problem: It would take way too long for the GPS to have a fix causing a 3-5 minute way when indoors and over 45 seconds when outside
 +
*** Solution: Utilize the external antenna. It was able to get a fix inside in under a minute while outside within 25 seconds. Using separate battery can reduce the fix time.
 +
 
 +
* Compass
 +
** Problem: Standalone testing of the controller gave correct data but when integrated with all modules the data was inaccurate (not 0 to 360 degrees).
 +
*** Solution: When mounting the compass module on RC car, mount it away from Motor controller and mount it on some height to avoid any interference with other nodes.
  
The largest problem was actually sending data to the App in a timely manner. Converting all of the messages to strings to send through bluetooth was found to be too slow and would result in messages crossing over on top of one another. Even with the UART baud rate increased to the maximum speed of 115,200 for the HC-05, the messages would blur together at times. The easiest fix was to only populate the some of the messages in a given 10hz callback. Only two of the boards were able to be grouped together to send, motor and driver. The other controllers' messages were sent in one time slot.
+
*General
 +
** Problem: The Geo node needs extensive testing with other nodes, if not unit tested and integration tested, it is not going to work properly.
  
The other difficult part was working in tandem with the Sensor Controller code and ensure both of us were using the correct branch and most updated code.
+
== 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.
  
<HR>
+
=== Hardware ===
<BR/>
+
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.
 +
 
 +
<li style="display: inline-block;">[[File:SJTWO.jpg|400px|thumb|Left|Sjtwo-board]] </li>
 +
<li style="display: inline-block;">[[File:LCD_DIS.jpg|400px|thumb|Right|LCD Display]] </li>
 +
<li style="display: inline-block;">[[File:Final_Sch2.png|400px|thumb|Right|Pinouts]] </li>
 +
 
 +
=== Software Architecture Driver Logic===
 +
 
 +
<div><ul>
 +
<li style="display: inline-block;">[[File:Driver_logic.png|600px|thumb|Left|Basic_Logic]] </li>
 +
<li style="display: inline-block;">[[File:OAL.png|600px|thumb|Center|Obstacle Avoidance Logic]] </li>
 +
<li style="display: inline-block;">[[File:Reverse_func.png|600px|thumb|Right|Reverse Functionality]] </li>
 +
</ul></div>
  
== Master Module ==
 
  
https://gitlab.com/infallibleprogrammer/utah/-/tree/master/projects/Master_Controller
+
=== Obstacle Avoidance Logic ===
  
=== Hardware Design ===
+
<pre>
The Master node is primarily responsible for issuing commands to the Motor node to go towards target waypoints. It takes information from both the Geo and Sensor nodes and preforms its own calculations based on that information to make the proper turns and speed changes. It is also responsible for outputting relevant data such as Distance to target, Current Heading, and Speed to the connected RPIgear LCD screen for easy viewing of the data while the car is in motion
+
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);
  
[[File:Master controller.png|750px|center|thumb|Master controller Hardware Design]]
+
        } 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();
  
{| style="margin-left: auto; margin-right: auto; border: none;"
+
          debug_values.car_driving_status = STOPPED;
|-
+
          debug_values.car_steering_status = STRAIGHT;
|
+
        }
{| class="wikitable"
+
</pre>
|+ Table 6. Driver Node Pinout: CAN Transceiver
 
|-
 
! SJTwo Board
 
! CAN Board
 
|-
 
| P0.0
 
| CAN RX
 
|-
 
| P0.1
 
| CAN TX
 
|-
 
| Vin
 
| 3.3
 
|-
 
| GND
 
| GND
 
|}
 
|
 
|
 
|
 
|
 
{| class="wikitable"
 
|+ Table 7. Driver Node Pinout: RPIgear LCD Screen
 
|-
 
! SJTwo Board
 
! CAN Board
 
|-
 
| P4.28
 
| UART - RX
 
|-
 
| P4.29
 
| UART - TX
 
|-
 
| Vin
 
| 3.3
 
|-
 
| GND
 
| GND
 
|}
 
|}
 
  
=== Software Design ===
 
[[File:Driver_logic_UTAH.jpg|center|thumb|Master controller Code Logic]]
 
  
Driver begins its navigation when the Geo controller locks onto a waypoint to move towards and begins its navigation process there, any other time it remains still awaiting mobile commands. When it is sent this waypoint it goes through the navigation process
+
'''''Steer Left and Right'''''
 +
<pre>
 +
  if (obstactle_on_right == true) {
 +
    motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_LEFT;
 +
    motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
 +
    if (obstacle_in_right_far()) {
 +
      motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_SOFT_LEFT;
 +
      motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
 +
    } else if (obstacle_in_right_near()) {
 +
      motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_LEFT;
 +
      motor_signal.DRIVER_TO_MOTOR_speed = reduced_speed;
 +
    }
  
<h3>Navigation code: </h3>
+
  } else {
  void driver__process_geo_controller_directions(dbc_COMPASS_HEADING_DISTANCE_s *geo_heading) {
+
    motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_RIGHT;
  received_heading.CURRENT_HEADING = geo_heading->CURRENT_HEADING;
+
    motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
  received_heading.DESTINATION_HEADING = geo_heading->DESTINATION_HEADING;
+
    if (obstacle_on_left_far()) {
  received_heading.DISTANCE = geo_heading->DISTANCE;
+
      motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_SOFT_RIGHT;
 +
      motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
 +
    } else if (obstacle_on_left_near()) {
 +
      motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_RIGHT;
 +
      motor_signal.DRIVER_TO_MOTOR_speed = reduced_speed;
 +
    }
 
   }
 
   }
   dbc_MOTOR_CHANGE_SPEED_AND_ANGLE_MSG_s driver__get_motor_commands(void) {
+
   motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
  bool is_object_on_right = false;
+
   // motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
   if (check_whether_obstacle_detected()) {
+
}
    if (internal_sensor_data.SENSOR_SONARS_left <= distance_for_object &&
+
 
        internal_sensor_data.SENSOR_SONARS_middle <= distance_for_object &&
+
</pre>
        internal_sensor_data.SENSOR_SONARS_right <= distance_for_object) {
+
 
      reverse_car_and_turn();
+
'''''Reverse and Steer'''''
    } else if ((internal_sensor_data.SENSOR_SONARS_left <= distance_for_object &&
+
<pre>
                internal_sensor_data.SENSOR_SONARS_middle <= distance_for_object) ||
+
  if (!obstacle_on_rear()) {
              internal_sensor_data.SENSOR_SONARS_left <= distance_for_object) {
+
     motor_signal.DRIVER_TO_MOTOR_direction = 0;
      is_object_on_right = false;
+
     motor_signal.DRIVER_TO_MOTOR_speed = reverse_speed;
      change_angle_of_car(is_object_on_right);
+
    update_lights(10, taillight_left);
    } else if ((internal_sensor_data.SENSOR_SONARS_right <= distance_for_object &&
+
    update_lights(10, taillight_right);
                internal_sensor_data.SENSOR_SONARS_middle <= distance_for_object) ||
 
              internal_sensor_data.SENSOR_SONARS_right <= distance_for_object) {
 
      is_object_on_right = true;
 
      change_angle_of_car(is_object_on_right);
 
     } else if (internal_sensor_data.SENSOR_SONARS_rear <= distance_for_object) {
 
      is_object_on_right =
 
          (internal_sensor_data.SENSOR_SONARS_right < internal_sensor_data.SENSOR_SONARS_left) ? true : false;
 
      change_angle_of_car(is_object_on_right);
 
      forward_drive();
 
     } else if (internal_sensor_data.SENSOR_SONARS_middle <= distance_for_object) {
 
      is_object_on_right =
 
          (internal_sensor_data.SENSOR_SONARS_right < internal_sensor_data.SENSOR_SONARS_left) ? true : false;
 
      // change_angle_of_car(is_object_on_right);
 
      // forward_drive();
 
      reverse_car_and_turn();
 
    } else {
 
      // do nothing, should not reach this point, object is detected case should be handled
 
    }
 
 
   } else {
 
   } else {
     // Drive towards what geo points me to
+
     stop_the_car();
    turn_towards_destination();
 
    set_ideal_forward();
 
 
   }
 
   }
  return internal_motor_data;
+
</pre>
}
+
 
 +
=== 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.
  
In this Code block Sensor Information is first processed in the initial if statement. Each of the 4 sensors is evaluated to see what combination have been tripped. Depending on this combination the car will have to either turn left or right if free or reverse and backup. If all sensors return no obstacles, then the turn_towards_destination() function is run to turn the car to a checkpoint.
+
<pre>
 +
if (heading_difference >= 350 && heading_difference <= 10) {
 +
    gps_navigation_direction = straight;
 +
    heading_difference = fabs(heading_difference);
  
<h3>Calculate Turning angle </h3>
+
    debug_values.car_driving_status = FORWARD;
  static void turn_towards_destination(void) {
+
    debug_values.car_steering_status = STRAIGHT;
  turn_direction = right;
+
   } else if (heading_difference > 180) {
  heading_difference = received_heading.DESTINATION_HEADING - received_heading.CURRENT_HEADING;
+
     gps_navigation_direction = left;
   if (heading_difference > 180) {
 
     turn_direction = left;
 
 
     heading_difference = 360 - heading_difference;
 
     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) {
 
   } else if (heading_difference < 0 && heading_difference > -180) {
     turn_direction = left;
+
     gps_navigation_direction = left;
 
     heading_difference = fabs(heading_difference);
 
     heading_difference = fabs(heading_difference);
   } else if (heading_difference < -180) {
+
 
     turn_direction = right;
+
    debug_values.car_driving_status = FORWARD;
     heading_difference = fabs(360 + heading_difference);
+
    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) {
 
   } else if (heading_difference > 0 && heading_difference <= 180) {
     turn_direction = right;
+
     gps_navigation_direction = right;
 +
 
 +
    debug_values.car_driving_status = FORWARD;
 +
    debug_values.car_steering_status = RIGHT;
 
   }
 
   }
   tell_motors_to_move(turn_direction, heading_difference, received_heading.DISTANCE);
+
</pre>
   }
+
 
This function takes the current heading and subtracts out destination heading. The absolute value is then taken to get the magnitude of the turn required. The direction is determined by the sign of the difference. These are then sent to the tell_motors_to_move function.
+
 
 +
=== Periodic Callbacks ===
 +
 
 +
The period_callbacks__initialize() function calls the following functions:
 +
<pre>
 +
   can__bus_initializer(can1);
 +
   lcd__init();
 +
  head_tail_lights_init();
 +
  debug_led_init();
 +
</pre>
  
<h3>Tell Motors To Move </h3>
+
The period_callbacks__1Hz() function calls the following function:
  static void tell_motors_to_move(direction_t direction_to_turn, float turn_magnitude, float distance_magnitude) {
+
<pre>
  if (distance_magnitude > 10) {
+
  can_bus_handler_tx_debug_messsages(can1);
    if (turn_magnitude > max_angle_threshold) {
+
  static uint8_t count = 0;
      internal_motor_data.SERVO_STEER_ANGLE_sig = max_angle_threshold / 2;
+
  if (count == 0) {
    } else if (turn_magnitude > mid_angle_threshold) {
+
     lcd__communication_init();
      internal_motor_data.SERVO_STEER_ANGLE_sig = mid_angle_threshold / 2;
 
    }
 
    if (turn_magnitude > mid_angle_threshold) {
 
      internal_motor_data.SERVO_STEER_ANGLE_sig = mid_angle_threshold;
 
    } else if (turn_magnitude > 5) {
 
      internal_motor_data.SERVO_STEER_ANGLE_sig = 0;
 
    }
 
  } else {
 
     if (internal_motor_data.SERVO_STEER_ANGLE_sig > 20) {
 
      internal_motor_data.SERVO_STEER_ANGLE_sig = 20;
 
    }
 
    else {
 
      internal_motor_data.SERVO_STEER_ANGLE_sig = turn_magnitude;
 
    }
 
 
   }
 
   }
   if (direction_to_turn == left) {
+
   count = 1;
    internal_motor_data.SERVO_STEER_ANGLE_sig *= -1;
+
   print_info_on_lcd();
    internal_motor_data.SERVO_STEER_ANGLE_sig -= 5;
+
</pre>
   }
 
  /**
 
  * The idea with this is to go slower on sharp turns.  Going faster on straight aways
 
  * is fine too.
 
  */
 
  if (abs(internal_motor_data.SERVO_STEER_ANGLE_sig) <= min_angle_threshold) {
 
    internal_motor_data.DC_MOTOR_DRIVE_SPEED_sig = go_fast;
 
  } else if (abs(internal_motor_data.SERVO_STEER_ANGLE_sig) <= mid_angle_threshold) {
 
    internal_motor_data.DC_MOTOR_DRIVE_SPEED_sig = go_medium;
 
  } else if (abs(internal_motor_data.SERVO_STEER_ANGLE_sig) <= max_angle_threshold) {
 
    internal_motor_data.DC_MOTOR_DRIVE_SPEED_sig = go_slow;
 
  }
 
  if (distance_magnitude < 10) {
 
    internal_motor_data.DC_MOTOR_DRIVE_SPEED_sig = go_slow;
 
  }
 
}
 
  
There are a few peculiarities that were run into when testing driver code. First was the reliability of the compass. We found the compass to be quite noisy and not as reliable as first anticipated. The result was to only go half of the angle calculated before, and only at discrete angles, as shown above. This was one of the largest contributing factor to the smoothness of the drive of the car. The variables were all set at the top of the file and allowed for ease of change for testing purposes.
+
The period_callbacks__10Hz() function calls the following functions:
 +
<pre>
 +
  can_bus_handler__process_all_received_messages(can1);
 +
  can_bus_handler__manage_mia();
 +
  can_bus_handler_tx_messages(can1);
 +
</pre>
  
 
=== Technical Challenges ===
 
=== 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.  
The biggest challenge face with the Master Controller is the reliability of the data coming in. We incorrectly assumed that the data would be nearly perfect and that descisions could be made quickly on that data. Once we began to filter most of the data and not allow the Master to over compensate, the driving became a lot smoother.
+
* 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.  
 
<HR>
 
<HR>
 
<BR/>
 
<BR/>
  
 
== Mobile Application ==
 
== Mobile Application ==
https://gitlab.com/jbeard79/UTAH_APP/-/tree/user/jbeard79/%231/SensorReading
+
The MIT App inventor 2 is an open-source web application available for free use to develop basic android mobile applications. It circumvents the need to program and develop applications using Java or Kotlin by providing block-based coding and UI development features. It uses a Graphical user Interface (GUI) like the Scratch programming language. Anyone using the web-app would just need to drag and drop blocks to design the UI and use functional blocks to develop logic, functions and flow control.
  
[[File: UTAH_App1.JPG|300px]]
+
MIT App inventor for android was originally developed by Google and released in 2010. The development team was led by Hal Abelson and Mark Friedman. “In the second half of 2011, Google released the source code, terminated its server, and provided funding to create The MIT Center for Mobile Learning, led by App Inventor creator Hal Abelson and fellow MIT professors Eric Klopfer and Mitchel Resnick. The MIT version was launched in March 2012.”
[[File: UTAH_App2.jpg|300px]]
+
 
[[File:UTAH AppConnectBT.jpg|300px]]
+
App Inventor has a mobile application called the MIT AI Companion app which can be used to download a server cached version of your app under development. This makes it extremely easy and convenient to test intermediate functions and bug testing as changes can be observed in real-time. Once done with the development, users can download a “.apk” file after building. This is an installable file for the android OS which allows the user to test their app as a standalone android app.
=== Hardware Design ===
+
 
The phone used was an older LG Tracfone running Android OS.
+
The Web app provides two important sections for mobile app development:
 +
<li>The Designer page</li>
 +
<li>The Blocks page</li>
 +
 
 +
===User Interface===
 +
<br/>
 +
<li style="display: inline-block;"> [[File: App UI.jpeg|center|300px|thumb|App User Interface]]</li>
 +
<br/>
 +
 
 +
<li style="display: inline-block;">[[File: App_flowchart.jpeg|center|300px|thumb|Flow of the App]] </li>
 +
<br/>
 +
 
 +
 
 +
<br/>
 +
<li style="display: inline-block;">[[File: MIT_app_inventor.jpeg|left|600px|thumb|UI development page - the “Designer page”]] </li>
 +
 
 +
<li style="display: inline-block;">[[File: MIT_app_inventor_backend.jpeg|right|600px|thumb|Function and flow development page - the “Blocks page”]] </li>
 +
<br/>
 +
 
 +
=== Bluetooth Block ===
 +
 
 +
The firebolt app uses the bluetooth client block to establish a connection with the HC-05 bluetooth module onboard the car. It is necessary to establish connection and connect to a bluetooth pair to send and receive messages.
 +
 
 +
<li style="display: inline-block;">[[File: bluetooth_block.jpeg|right|600px|thumb|MIT App inventor block to connect and disconnect from a bluetooth devic]] </li>
 +
<br/>
 +
 
 +
=== Map and Marker Blocks ===
 +
 
 +
The map block is used to create and display a 2D map of the world for location, navigation and other map functions. It uses an open-source map library which is very similar to Google Maps. The Map bloc has several functions including display, zoom, direction, distance, coordinate calculation. Fireblot uses this block to locate a destination location for the car and send the corresponding latitude and longitude values. This is made possible by the marker block. Markers can be placed on any location on the map and the pinpointed location coordinates can be received as floating point integers. These values are displayed on the app and also used to send as a bluetooth message to the HC-05 module when required.
  
=== Software Design ===
+
<li style="display: inline-block;">[[File: maps_and_markers.jpeg|right|600px|thumb|Map and Marker blocks used in the firebolt app. ]] </li>
[[File: UTAH_AppSoftwareFlow.jpg]]
 
  
When the app first opens the Bluetooth socket that is created is checked if it is NULL, which it should be with startup. If this occurs the Bluetooth connection screen will be brought up, shown as the far right picture above, and the user will need to tap a device to attempt a connection. If the connection fails, the screen will again be brought up. Once a connection is established with the Bridge Controller the main screen, shown as the far left picture, will be brought up.
+
=== Testing and Downloading  ===
The first thing that can be seen is the Map. A few precautions were taken so nothing would happen to the map's camera when the user attempts to click on the map while the GPS is not sending accurate data. A blue pin is used to represent the car's current location once good data is being received. When this data is updated, this pin's location is refreshed and redrawn onto the map. A default destination is used for the 10th street garage for some ease of testing and to accommodate camera repositioning. The camera is repositioned to the averaged of the destination and the current location.
 
Once the desired destination is selected, the latitude and longitude of the selection will be displayed under the map. The car can be started by pressing the Send Coordinates button located at the bottom of the scroll window. This will send coordinates, truncated down to a float instead of a double, onto the can bus.
 
  
For the messaging system, the can bus ID's were used along with a sub number to tell which part of the message was being sent: XXXY_____ where xxx is the can message id, y is which portion of the message it is, and the underline s are the message data. The messages all corresponded to a TextView and a data structure was made to hold up to 4 views. All of these message blocks of views was put into an array for ease of operation. A simple for loop was then used to check the ID of the incoming message against the IDs in the array. The sub ID then was used to identify which view.
+
MIT App inventor projects can be accessed for testing on the MIT AI companion app or built into a downloadable APK file. It can also be exported as a file to be later imported. The file extension for an app inventor project is “.aia”.
  
The last key piece to the app is the kill button. When pressed the app will send a 1 to the bridge controller, which will relay that onto the bus. The motor's logic has checking built in that will understand if the command is a 1 stop operation.
+
==Bluetooth==
  
=== Technical Challenges ===
+
Gitlab link: https://gitlab.com/Ritika_Beniwal_/firebolt/-/tree/Bluetooth_and_app
 +
<br>
 +
 +
The HC-05 module is an easy to use bluetooth module that can be used to interface with devices using its Serial Port Protocol. Bluetooth is used for wireless network transmission of data. The HC-05 has several features:
 +
<li>UART interface with programmable baud rate </li>
 +
<li>With integrated antenna </li>
 +
<li>Auto-connect to the last device on power as default. </li>
 +
<li>Can act as a slave or master device for transmission</li>
  
Connecting to google maps was much easier than anticipated. The tutorial here: https://developers.google.com/maps/documentation/android-sdk/start, is a great way to add the map portion in.
+
<br>
 +
<li style="display: inline-block;">[[File: bluetooth_module.jpeg|right|600px|thumb|The HC-05 bluetooth module. ]] </li>
 +
<br>
  
Thinking about message format and structure early was key. Setting up with good modular design saved a lot of time after it was implemented and made the code much easier to read.
+
The AT commands allow the module to have a modifiable set of characteristic parameters. This can be achieved by enabling the EN pin on the module and serially sending some strings based on the requirement. When on the default mode, the module shows upon other device scans for bluetooth devices under the identifier "HC-05". To begin using serial transmission, you first need to pair the module to your device. During the pairing process, the password request encountered should be expecting one of the default passwords "1234" or "0000". You can change this password using one of the AT commands.
  
One other thing to note when using google maps, an account must be setup and a key is used for the app to connect. That key is located in the googlemapsapi file, and is ignored in git by default when using Android Studios. Double checking that your key is not included in your pushes is helpful to ensure your key is not leaked.
+
=== Technical Challenges and solutions===
  
 +
<li>Some initial challeneges we faced while using the bluetooth module is trying to pair it certain smartphones. It sometimes did not show up on any bluetooth scan list even though it was powered on and working with some other devices. We later found out that the module can sometimes take a long time to become an available slave device again. We fixed this problem by making sure the device previously connected to it, disconnected before trying  a new device.</li>
 +
<li>We also had issues while sending out and receiveing data from the smartphone app. Since the UART queue by default accepts only string we decided to send all information from the app as a string. We then parsed the string to extract data.</li>
 +
<BR/>
 +
<HR>
 +
<HR>
 
<BR/>
 
<BR/>
  
 
== Conclusion ==
 
== Conclusion ==
 +
This is not a project where only writing best code for our controller is not good enough. This project tests overall personality. As a team we were not prepared to spend more time on this and due to some mismanagement we were always falling behind. But we tried our best to complete the project with few team members. We learnt different aspect of a product development:
 +
* People Management: We were more focused on our node but review is equally important. Well defined roles and responsibilities will contribute to the success and timely completion of the project.
 +
* Finance Management: We bought components just by referring the previous years project. Before ordering we should have read the proper descriptions and then order according to requirement. There was another mistake which should have been avoided was we should have ordered some spare components like voltage regulators, batteries, SJ2 board. Few components got damaged and without figuring out problems we were only ordering and repeating the same mistake.
 +
* Software skills: We learnt CAN protocol and Unit testing. The Unit tested modules gave us the confidence. The most important aspect that we learnt, don't trust the software which failed even one time out of hundred times, it has potential to bring you back to the starting point.
 +
* Time Management: Well defined agenda for every week to test and develop could have made our tasks easier. Doing some home work before coming for the team meeting may have helped us to complete the project before time giving us time for more integration testing. Team meetings are meant to discuss problems and do integration.
  
This is a challenging project on its own, but despite the additional difficulties that came with remote learning we were able to finish many of our objectives and learned many lessons along the way.  This project covers multiple disciplines, from mechanical engineering, electrical engineering, computer science, and even project management, some of which none of us had prior experience in.  During our time working on this project we furthered our understanding of embedded systems and good software design patterns, such as test driven development, while learning new information as well.  Interfacing with ultrasonic sensors and doing signal processing on the data, interfacing with a GPS module, determining heading from a magnetometer and incorporate tilt compensation using an accelerometer, write firmware for a Bluetooth module and communicate with and Android application that we made, interface with electric motors using PWM and create a PID to control speed, designing a PCB, not to mention our deep dive into the CAN protocol and not only learning the intricacies of the protocol but designing our own CAN messages in a DBC file and writing firmware to have our controllers communicate.  Many of these tasks required research to get an understanding of concepts before we could even implement anything.
 
 
All these tasks were made more challenging with the remote learning as some of us were not always in close proximity to the campus so that we could troubleshoot problems quickly and with access to labs.  Some of us were working full time jobs while taking the course, making time management hard and creating exhaustion.  We had moments of frustration when integration testing threw roadblocks our way, but we managed to persevere and get a functional demo by the end of the class.
 
  
 
Looking back, we could have probably created a better plan earlier on.  Defining milestones for different nodes, and if they were not reached, shift our attention to get them done to progress the overall project.  We overlooked a lot of the mechanical aspects of the RC car and how it would impact the compass and accelerometer.  Improving our mounting and spending more time refining the process of determining heading would have likely helped a lot.  Refining driver logic to deal with some variability in steering, that we did not notice until integration testing near the final weeks, earlier on could also have helped in the performance of the car in the final demo.  These are learning points that we will keep in mind for future projects and add to the takeaways from the course.
 
Looking back, we could have probably created a better plan earlier on.  Defining milestones for different nodes, and if they were not reached, shift our attention to get them done to progress the overall project.  We overlooked a lot of the mechanical aspects of the RC car and how it would impact the compass and accelerometer.  Improving our mounting and spending more time refining the process of determining heading would have likely helped a lot.  Refining driver logic to deal with some variability in steering, that we did not notice until integration testing near the final weeks, earlier on could also have helped in the performance of the car in the final demo.  These are learning points that we will keep in mind for future projects and add to the takeaways from the course.
  
 +
We did our hardware setup much later, we wasted a lot of time in doing connections again and again. A better strategy would have been to get familiar with hardware connections and make a prototype setup to complete the milestones. We were waiting for PCB, which till the end was not completed and had some issues. It was a complete hassle to finalize our hardware in the end and test individual modules again. We got very less time for integration testing, our Geo navigation could have done much better if we would have done proper integration testing. 
  
  
 +
=== Project Video ===
  
=== Project Video ===
+
https://youtu.be/lGZTV-ZGHd8
[https://www.youtube.com/watch?v=iyOFE1iFbg4 Youtube]
 
[https://www.youtube.com/watch?v=ZJXLpv5U6vM Youtube link for test drive]
 
  
 
=== Project Source Code ===
 
=== Project Source Code ===
https://gitlab.com/infallibleprogrammer/utah - Boards
+
https://gitlab.com/ritupatil1/firebolt/-/tree/master
  
https://gitlab.com/jbeard79/UTAH_APP - Application
+
https://gitlab.com/Ritika_Beniwal_/firebolt/-/tree/master
  
 
=== Advise for Future Students ===
 
=== Advise for Future Students ===
1. It is advised to order the parts as soon as possible and determine the pin/ports which are needed to begin the designing and ordering of the PCB. <br/>
+
* 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.
2. Select good quality components. Don't go for cheap quality components. The cheaper the component, the more you'll have to compensate typically. <br/>
+
* Make use of the holidays and spring break. If you have your basic framework of the software and hardware completed by the end of spring break you can start testing ASAP.
3. Always have extra components. You never know which component will stop working. Having extra components saves a lot of time.<br/>
+
* Start researching as soon as possible and collect all the information related to the module that has been assigned to you, as there is no single book or manual to refer to. Go through all the problems faced by previous teams as they are a treasure trove of information. If you are facing a problem, it is very likely that some team in previous semesters has faced it. It will save you some precious days.  
4. Use all the CAN transceivers of the same manufacturer.<br/>
+
*Make sure to get a power supply which gives a steady 5V and 1A current so you don't lose boards due to sudden power surge. When all the car's subsystems are running, the current draw may be higher than expected. Make sure to have a common ground for all the components related to a single ECU.
5. Try to use one power source instead of two for the entire project. In this way, you can reduce the overall weight of your RC car.<br/>
+
*The most critical hardware connection is for motor node. We used the receiver , which we used to calibrate the ESC for Servo, DC and RPM power supply. We did that 1 week before our demo, and the motor node was fine.  
6. Select your Power Regulator IC wisely. You need to have sufficient current to drive all the controllers and the components.<br/>
+
* Can Transceiver: Our CAN bus data was not coming on Bus Master but every node was receiving the data, we were using same module which previous groups used. Later we found out the termination was the problem. Each Can transceiver had 120 ohm resistor. Debugging without Bus Master was a nightmare.
7. Don't underestimate the magnitude of mechanical design and work that is required to get things working smoothly.<br/>
+
* It is always better to buy new and quality components. The RC Car performance depends on what components you are using. The better and reliable components makes your life easier.
8. Buy a physical compass to use while testing to ensure your seeing the correct headings.<br/>
 
  
 
=== Acknowledgement ===
 
=== Acknowledgement ===
We would like to thank Preet and Vidushi for making the best out of the bad situation of remote learning.
 
  
We would also like to thank David Brassfield, for assisting with 3D printing and design.
+
We want to express our gratitude to Professor Preetpal Kang for sharing valuable inputs and knowledge throughout the duration of the project. We would also like to thank the project groups of previous years, which helped us to avoid the mistakes made by them which that we saved some time to understand the concepts better.
  
 
=== References ===
 
=== References ===
 +
http://socialledge.com/sjsu/index.php/Industrial_Application_using_CAN_Bus
 +
 +
Bridge Sensor ECU
 +
*[https://www.mpja.com/download/hc-sr04_ultrasonic_module_user_guidejohn.pdf HCSR-04]
 +
 +
Motor ECU
 +
* https://www.youtube.com/watch?v=-26ZSgDqwQQ&ab_channel=Traxxas
 +
* https://www.youtube.com/watch?v=ix-J85uRFjE&ab_channel=Traxxas
 +
 +
Geographical ECU
 +
*[https://www.igismap.com/formula-to-find-bearing-or-heading-angle-between-two-points-latitude-longitude/ Bearing Formula]
 +
*[https://www.igismap.com/haversine-formula-calculate-geographic-distance-earth/ Haversine Formula]
 +
*https://cdn-shop.adafruit.com/product-files/1059/CD+PA1616D+Datasheet+v.05.pdf
 +
*[https://www.pololu.com/file/0J434/LSM303DLH-compass-app-note.pdf Compass Heading Tilt Compensated]
  
'''Motor Controller'''
 
  
* [https://traxxas.com/support/Programming-Your-Traxxas-Electronic-Speed-Control ESC]
+
Mobile Application
 +
* http://ai2.appinventor.mit.edu/
 +
* https://www.youtube.com/watch?v=aQcJ4uHdQEA

Latest revision as of 06:54, 11 June 2022

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
  • High Level Hardware

Introduction

The controllers for the project are divided in 5 parts. Each controller has different tasks and communicate with each other over CAN bus.

  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
  • Integration Testing
  • Wiki Page Update

Ritu Patil LinkedIn'

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

Ritika Beniwal LinkedIn'

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

Utsav Savaliya LinkedIn'

  • Sensor Controller
  • Integration Testing
  • Wiki Page Update
  • Bluetooth integration with Sensor

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 Heartbeat
1 100 Driver Heartbeat Motor, Sensor, Geo
Start Stop signal from Android app to Driver
1 101 Bridge Sensor Driver
Ultrasonic sensors data transmit
2 200 Sensor sonars from front, back, left ,right sensor Driver
Destination Location
4 250 Bridge Sensor Geo
Driver to Motor Command
5 300 Speed and steering direction for the motor Motor
Geo Controller
6 400 Bearing, Heading and Distance Driver
Motor Controller
7 600 Motor speed Driver
Debug messages
8 700 Driver Debug BRIDGE_SENSOR,MOTOR,GEO
9 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+ (1,0) [-30|30] "kmph" MOTOR
 SG_ DRIVER_TO_MOTOR_direction : 8|8@1- (1,-2) [-2|2] "degrees" MOTOR

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_ 300 DRIVER_TO_MOTOR_direction -2 "MOTOR_direction_HARD_LEFT" -1 "MOTOR_direction_SOFT_LEFT" 0 "MOTOR_direction_STRAIGHT" 1 "MOTOR_direction_SOFT_RIGHT" 2 "MOTOR_direction_HARD_RIGHT" ;
VAL_ 700 car_steering_status 2 "RIGHT" 1 "LEFT" 0 "STRAIGHT";
VAL_ 700 car_driving_status 2 "BACKWARD" 1 "FORWARD" 0 "STOPPED";

Technical Challenges

  • The CAN transceivers that we bought had inbuilt 120 ohm resistor each, which we didn't notice. And every time we interfaced all the four nodes the data won't show up in the busmaster software. We found this very late and until then we thought it's hardware/dbc file issue and wasted potential amount of time in debugging.So we de-soldered those termination resistors and we were able to see our data smoothly on busmaster.
  • As an advice, make sure at the end of all four nodes after adding termination resistors of 120 ohm on both sides, the resultant resistance is 60 ohms. Only then all four nodes can communicate over CAN bus.

Sensor and Bluetooth ECU

Hardware Design

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 waves every few seconds. When ultrasonic waves collide and come back and strikes with this membrane a pulse is generated which is used for sensing.


Sensor Controller Diagram
Sensor Pins



Pin connections between board and sensor:
Sl No. SJ2 board Pin No. Ultrasonic sensor Pin No. Function
1. ADC Pin 1.30 AN(Front left sensor) Input to ADC channel 4
2. ADC Pin 1.31 AN(Front right sensor) Input to ADC channel 5
3. ADC Pin 1.26 AN(Front sensor) Input to ADC channel 3
4. ADC Pin 1.25 AN(Rear sensor) Input to ADC channel 3
5. GPIO Pin 0.6 Rx(Front left sensor) Triggering pulse for left sensor
6. GPIO Pin 0.8 Rx(Front right sensor) Triggering pulse for right sensor
7. GPIO Pin 0.9 Rx(Front sensor) Triggering pulse for front sensor
8. GPIO Pin 0.7 Rx(Rear sensor) Triggering pulse for rear sensor


Apart from the pin connections for the Sensor node the important thing is to mount the sensors at particular angles. The angle placement is critical for left and right sensor as we faced lot of problems while detecting the walls. We chose the angle by error and trial method by simply placing the sensors at different angles. We tried keeping the angle above the 45 degrees so that to provide wider angle for the obstacles to detect.

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.

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.

Sending sensor values in terms of distance to CAN

The raw values coming from the sensor needs to be filtered before sending on the CAN bus. The more information about filtering is mentioned in the techical challenges section. The below diagram shows the detailed flowchart of software design implemented for the sensor node.


Sensor Controller Diagram

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 particular 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.

ESC Pinout
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.

Servo Pinout
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.

RPM Pinout
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.

The period_callbacks__initialize() function calls the following functions:

  • can_bus_initializer: Initializes CAN buffers and sets baud rate
  • initialize_speed_sensor_interrupts: sets up GPIO pin as hardware interrupt
  • motor_init_pwm: initializes pwm pin.

The period_callbacks__1Hz() function calls the following function:

  • can_handler__handle_all_incoming_messages_1hz: handles the incoming messages based on mesg ID.
  • can_handler__transmit_messages_1hz: sends the motor speed to Driver controller.

The period_callbacks__10Hz() function calls the following functions:

  • pwm1__set_duty_cycle: to calibrate the ESC by sending neutral signal for few seconds.
  • clear_rotations: clears interrupt counter every 0.5 seconds
  • can_handler__handle_all_incoming_messages: receives any message frame sent on the CAN bus.



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 a higher frequency helped in reducing the response time in obstacle avoidance compared to previously when it was being received at 10Hz.




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

  • 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
    • 2. Compass
    • 3. Waypoints
    • 4. Geo Logic

    Overview

    These code 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(CAN).
    • gps__init(): initializes the GPS interface(UART).
    • geo_compass__setup_magnetometer(): initializes the compass interface(I2C).

    The period_callbacks__1Hz() function calls the following function:

    • can_handler__handle_all_incoming_messages_1hz(): handles the incoming messages based on mesg ID.
    • gps__setup_command_registers(): sends command to GPS module to receive only GPGGA string.
    • can_handler__transmit_messages_10hz(): sends the heading ,bearing and distance to Driver controller.

    The period_callbacks__10Hz() function calls the following functions:

    • gps_run_once(): parses the NMEA string to get current coordinates
    Geo Logic Flowchart

    GPS

    • In the initialization process of the GPS, the line buffer module is configured to parse the GPS messages, the GPIOs P0.15(Tx) and P0.16(Rx) are configured, UART interrupt queues enabled, and the UART is configured at a baudrate of 9600(GPS standard).
    • Configuration
    In the gps__run_once_10Hz() the GPS is initially configured once to disable all NMEA messages except GPGGA which is message chosen to parse the coordinates and GPS lock.
    
    • Parsing NMEA GPGGA messages
    The GPS module constantly transmits NMEA GPGGA messages over UART to the SJ2 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. 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
    Although the GPS module has fix indication , but GPGGA string has field for FIX status also. Getting the Fix/Lock status using the string is much easier than using GPIO pins to get 
    the Lock status using FIX led of the GPS module. The Lock status/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 LSM303DLHC magnetometer and accelerometer registers over I2C bus to default settings using default gain and single mode.
    
    • Heading degree computation
    The compass heading degree is computed by using the tilt compensation algorithm and the pitch and roll values of LSM303DLHC accelerometer. The tilt compensation algorithm ensures 
    that the values of the compass heading are precise. The formulae used to calibrate the compass are mentioned below:
    
    • Pitch and Roll:
     pitch = asin(-acc_x / sqrt(acc_y * acc_y + acc_z * acc_z + acc_x * acc_x)) 
    roll = asin((acc_y / sqrt(acc_y * acc_y + acc_z * acc_z + acc_x * acc_x)) / cos(pitch))


    • Tilt compensated magnetic sensor values:
     mag_x = mag_x * cos(pitch) + mag_z * sin(pitch)
     mag_y = mag_y * cos(roll) + mag_x * sin(roll) * sin(pitch) - mag_z * sin(roll) * cos(pitch)
     mag_z = -mag_x * cos(roll) * sin(pitch) + mag_y * sin(roll) + mag_z * cos(roll) * cos(pitch)
    


    Luckily our module had no offset but it might need to be compensated for the offset if there is any.

    • Heading angle
    heading = atan2(mag_y, mag_x) * r2d 
    r2d is radian to degree conversion function
    
    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.
    

    Checkpoints

    In real world, the source and destination are not on a straight line. The car has to find the best possible and smallest route to its final destination. In this project keeping that in mind we have used checkpoint algorithm. These waypoints are known coordinates which are given according to the destination and source path. The car needs to follow the route determined by the waypoints from source to destination.

    We choose 10 points over a known location and hardcoded these coordinates in GEO node logic. Once our car gets the destination coordinates from Bridge and Sensor controller, it starts giving Heading , Bearing and Distance values to Driver Node. This waypoint must satisfy the below conditions:

    • It is the closest waypoint to the current location of the car.
    • Waypoint to destination distance is less than the current coordinate to the final coordinate distance.

    Checkpoint.jpg

    So when the algorithm finds the destination coordinates, then bearing is calculated with that particular coordinate, so that car can be further instructions to move towards that particular point. As shown in the figure below, our algorithm keeps finding new coordinates with time (orange ones) and at last go to the final destination coordinates. The algorithm is mentioned below in the form of flowchart and code:

    The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS. The heading and bearing is also computed using the Haversine formula and is sent over the CAN bus for heading correction.* Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.

    To calculate the geographical distance between the two points the haversine formula was used which is called periodically from the waypoints.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


    • 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.

    Technical Challenges


    • Adafruit GPS
      • Problem: The data from the GPS was being refreshed every second which was causing issues for the controller.
        • Solution: Send the command to the GPS module only send the SJ2 board GPGGA data.
      • Problem: It would take way too long for the GPS to have a fix causing a 3-5 minute way when indoors and over 45 seconds when outside
        • Solution: Utilize the external antenna. It was able to get a fix inside in under a minute while outside within 25 seconds. Using separate battery can reduce the fix time.
    • Compass
      • Problem: Standalone testing of the controller gave correct data but when integrated with all modules the data was inaccurate (not 0 to 360 degrees).
        • Solution: When mounting the compass module on RC car, mount it away from Motor controller and mount it on some height to avoid any interference with other nodes.
    • General
      • Problem: The Geo node needs extensive testing with other nodes, if not unit tested and integration tested, it is not going to work properly.

    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
  • Pinouts
  • 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) {
        motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_LEFT;
        motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
        if (obstacle_in_right_far()) {
          motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_SOFT_LEFT;
          motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
        } else if (obstacle_in_right_near()) {
          motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_LEFT;
          motor_signal.DRIVER_TO_MOTOR_speed = reduced_speed;
        }
    
      } else {
        motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_RIGHT;
        motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
        if (obstacle_on_left_far()) {
          motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_SOFT_RIGHT;
          motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
        } else if (obstacle_on_left_near()) {
          motor_signal.DRIVER_TO_MOTOR_direction = MOTOR_direction_HARD_RIGHT;
          motor_signal.DRIVER_TO_MOTOR_speed = reduced_speed;
        }
      }
      motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
      // motor_signal.DRIVER_TO_MOTOR_speed = ideal_speed;
    }
    
    

    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;
      }
    


    Periodic Callbacks

    The period_callbacks__initialize() function calls the following functions:

      can__bus_initializer(can1);
      lcd__init();
      head_tail_lights_init();
      debug_led_init();
    

    The period_callbacks__1Hz() function calls the following function:

      can_bus_handler_tx_debug_messsages(can1);
      static uint8_t count = 0;
      if (count == 0) {
        lcd__communication_init();
      }
      count = 1;
      print_info_on_lcd();
    

    The period_callbacks__10Hz() function calls the following functions:

      can_bus_handler__process_all_received_messages(can1);
      can_bus_handler__manage_mia();
      can_bus_handler_tx_messages(can1);
    

    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

    The MIT App inventor 2 is an open-source web application available for free use to develop basic android mobile applications. It circumvents the need to program and develop applications using Java or Kotlin by providing block-based coding and UI development features. It uses a Graphical user Interface (GUI) like the Scratch programming language. Anyone using the web-app would just need to drag and drop blocks to design the UI and use functional blocks to develop logic, functions and flow control.

    MIT App inventor for android was originally developed by Google and released in 2010. The development team was led by Hal Abelson and Mark Friedman. “In the second half of 2011, Google released the source code, terminated its server, and provided funding to create The MIT Center for Mobile Learning, led by App Inventor creator Hal Abelson and fellow MIT professors Eric Klopfer and Mitchel Resnick. The MIT version was launched in March 2012.”

    App Inventor has a mobile application called the MIT AI Companion app which can be used to download a server cached version of your app under development. This makes it extremely easy and convenient to test intermediate functions and bug testing as changes can be observed in real-time. Once done with the development, users can download a “.apk” file after building. This is an installable file for the android OS which allows the user to test their app as a standalone android app.

    The Web app provides two important sections for mobile app development:

  • The Designer page
  • The Blocks page
  • User Interface


  • App User Interface

  • Flow of the App



  • UI development page - the “Designer page”
  • Function and flow development page - the “Blocks page”

  • Bluetooth Block

    The firebolt app uses the bluetooth client block to establish a connection with the HC-05 bluetooth module onboard the car. It is necessary to establish connection and connect to a bluetooth pair to send and receive messages.

  • MIT App inventor block to connect and disconnect from a bluetooth devic

  • Map and Marker Blocks

    The map block is used to create and display a 2D map of the world for location, navigation and other map functions. It uses an open-source map library which is very similar to Google Maps. The Map bloc has several functions including display, zoom, direction, distance, coordinate calculation. Fireblot uses this block to locate a destination location for the car and send the corresponding latitude and longitude values. This is made possible by the marker block. Markers can be placed on any location on the map and the pinpointed location coordinates can be received as floating point integers. These values are displayed on the app and also used to send as a bluetooth message to the HC-05 module when required.

  • Map and Marker blocks used in the firebolt app.
  • Testing and Downloading

    MIT App inventor projects can be accessed for testing on the MIT AI companion app or built into a downloadable APK file. It can also be exported as a file to be later imported. The file extension for an app inventor project is “.aia”.

    Bluetooth

    Gitlab link: https://gitlab.com/Ritika_Beniwal_/firebolt/-/tree/Bluetooth_and_app

    The HC-05 module is an easy to use bluetooth module that can be used to interface with devices using its Serial Port Protocol. Bluetooth is used for wireless network transmission of data. The HC-05 has several features:

  • UART interface with programmable baud rate
  • With integrated antenna
  • Auto-connect to the last device on power as default.
  • Can act as a slave or master device for transmission

  • The HC-05 bluetooth module.

  • The AT commands allow the module to have a modifiable set of characteristic parameters. This can be achieved by enabling the EN pin on the module and serially sending some strings based on the requirement. When on the default mode, the module shows upon other device scans for bluetooth devices under the identifier "HC-05". To begin using serial transmission, you first need to pair the module to your device. During the pairing process, the password request encountered should be expecting one of the default passwords "1234" or "0000". You can change this password using one of the AT commands.

    Technical Challenges and solutions

  • Some initial challeneges we faced while using the bluetooth module is trying to pair it certain smartphones. It sometimes did not show up on any bluetooth scan list even though it was powered on and working with some other devices. We later found out that the module can sometimes take a long time to become an available slave device again. We fixed this problem by making sure the device previously connected to it, disconnected before trying a new device.
  • We also had issues while sending out and receiveing data from the smartphone app. Since the UART queue by default accepts only string we decided to send all information from the app as a string. We then parsed the string to extract data.




  • Conclusion

    This is not a project where only writing best code for our controller is not good enough. This project tests overall personality. As a team we were not prepared to spend more time on this and due to some mismanagement we were always falling behind. But we tried our best to complete the project with few team members. We learnt different aspect of a product development:

    • People Management: We were more focused on our node but review is equally important. Well defined roles and responsibilities will contribute to the success and timely completion of the project.
    • Finance Management: We bought components just by referring the previous years project. Before ordering we should have read the proper descriptions and then order according to requirement. There was another mistake which should have been avoided was we should have ordered some spare components like voltage regulators, batteries, SJ2 board. Few components got damaged and without figuring out problems we were only ordering and repeating the same mistake.
    • Software skills: We learnt CAN protocol and Unit testing. The Unit tested modules gave us the confidence. The most important aspect that we learnt, don't trust the software which failed even one time out of hundred times, it has potential to bring you back to the starting point.
    • Time Management: Well defined agenda for every week to test and develop could have made our tasks easier. Doing some home work before coming for the team meeting may have helped us to complete the project before time giving us time for more integration testing. Team meetings are meant to discuss problems and do integration.


    Looking back, we could have probably created a better plan earlier on. Defining milestones for different nodes, and if they were not reached, shift our attention to get them done to progress the overall project. We overlooked a lot of the mechanical aspects of the RC car and how it would impact the compass and accelerometer. Improving our mounting and spending more time refining the process of determining heading would have likely helped a lot. Refining driver logic to deal with some variability in steering, that we did not notice until integration testing near the final weeks, earlier on could also have helped in the performance of the car in the final demo. These are learning points that we will keep in mind for future projects and add to the takeaways from the course.

    We did our hardware setup much later, we wasted a lot of time in doing connections again and again. A better strategy would have been to get familiar with hardware connections and make a prototype setup to complete the milestones. We were waiting for PCB, which till the end was not completed and had some issues. It was a complete hassle to finalize our hardware in the end and test individual modules again. We got very less time for integration testing, our Geo navigation could have done much better if we would have done proper integration testing.


    Project Video

    https://youtu.be/lGZTV-ZGHd8

    Project Source Code

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

    https://gitlab.com/Ritika_Beniwal_/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.
    • Make use of the holidays and spring break. If you have your basic framework of the software and hardware completed by the end of spring break you can start testing ASAP.
    • Start researching as soon as possible and collect all the information related to the module that has been assigned to you, as there is no single book or manual to refer to. Go through all the problems faced by previous teams as they are a treasure trove of information. If you are facing a problem, it is very likely that some team in previous semesters has faced it. It will save you some precious days.
    • Make sure to get a power supply which gives a steady 5V and 1A current so you don't lose boards due to sudden power surge. When all the car's subsystems are running, the current draw may be higher than expected. Make sure to have a common ground for all the components related to a single ECU.
    • The most critical hardware connection is for motor node. We used the receiver , which we used to calibrate the ESC for Servo, DC and RPM power supply. We did that 1 week before our demo, and the motor node was fine.
    • Can Transceiver: Our CAN bus data was not coming on Bus Master but every node was receiving the data, we were using same module which previous groups used. Later we found out the termination was the problem. Each Can transceiver had 120 ohm resistor. Debugging without Bus Master was a nightmare.
    • It is always better to buy new and quality components. The RC Car performance depends on what components you are using. The better and reliable components makes your life easier.

    Acknowledgement

    We want to express our gratitude to Professor Preetpal Kang for sharing valuable inputs and knowledge throughout the duration of the project. We would also like to thank the project groups of previous years, which helped us to avoid the mistakes made by them which that we saved some time to understand the concepts better.

    References

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

    Bridge Sensor ECU

    Motor ECU

    Geographical ECU


    Mobile Application