Difference between revisions of "S22: Firebolt"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Printed Circuit Board)
(Team Members & Responsibilities)
 
(549 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== FireBolt RC Car ==
+
[[File:Firebolt2.jpeg|500px|thumb|right| The RC Car]]
 
 
  
 
== Abstract ==
 
== Abstract ==
The Firebolt project is a path finding and obstacle avoiding RC car. The RC Car 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
  
[[Priyanka Rai]]
+
<div><ul>
 +
<li style="display: inline-block;">[[File:High_Level_Implementation2.png|600px|thumb|Center|High Level Hardware]] </li>
 +
</ul></div>
  
** Geographical Controller
+
==== Introduction ====
** Master Controller
+
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
  
[[Ritu Patil]]
+
=== Team Members & Responsibilities ===
 
+
<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>
[[Ritika Beniwal]]
+
<font color="black"> '''Priyanka Rai  [https://www.linkedin.com/in/priyanka-rai-009ba975/  LinkedIn]''''''
 
+
* Geo Controller
** Master Controller
+
*  GPS and Compass Interfacing
 
+
*  Integration Testing
[[Utsav Savaliya]]
+
* Wiki Page Update
 
 
** Sensors Controller
 
  
[[Dhanush Babu]]
+
<font color="black"> '''Ritu Patil    [https://www.linkedin.com/in/ritu-patil/  LinkedIn]''''''
 +
*  Motor Controller
 +
*  RPM Sensor
 +
*  Integration Testing
 +
*  Wiki Page Update
  
** Hardware Integration
+
<font color="black"> '''Ritika Beniwal  [https://www.linkedin.com/in/ritikabeniwal03/  LinkedIn]''''''
** PCB Designing
+
* Driver Node
 +
* LCD interfacing
 +
Integration Testing
 +
* Wiki Page Update
  
 +
<font color="black"> '''Utsav Savaliya  [https://www.linkedin.com/in/utsav-savaliya-7383ab15b/ LinkedIn]''''''
 +
*  Sensor Controller
 +
*  Integration Testing
 +
*  Wiki Page Update
 +
*  Bluetooth integration with Sensor
  
 +
<font color="black"> '''Dhanush Babu  [https://www.linkedin.com/in/dhanushsbabu/ LinkedIn]''''''
 +
*  Bluetooth module interfacing
 +
*  Motor Controller
 +
*  Android App
 +
*  Integration Testing
  
 
== Schedule ==
 
== Schedule ==
Line 58: 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"| Actual Completion
+
! scope=:col"| Completion Date
 
! scope="col"| Status
 
! scope="col"| Status
 
|-
 
|-
! scope="row"| 1  
+
! scope="row"| Week 1  
03/01 to 03/07
 
<font color = "sienna"> ''Start of Phase 1''</font color>
 
 
|
 
|
* 03/01
+
* 03/06
* 03/04
+
* 03/08
* 03/05
+
* 03/12
 
|
 
|
* 03/04
+
* 03/10
* 03/07
+
* 03/10
* 03/07
+
* 03/12
 
|
 
|
 
* Study and discuss previous project reports
 
* Study and discuss previous project reports
Line 79: Line 92:
 
* Identify and order/purchase the required components  
 
* Identify and order/purchase the required components  
 
|
 
|
* 03/04
+
* 03/10
* 03/07
+
* 03/10
*<font color = "maroon"> 03/09
+
* 03/12
 
|  
 
|  
*<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"| 2
+
! scope="row"| Week 2
03/08 to 03/14
 
 
|
 
|
* 03/08
+
* 03/13
* 03/08
+
* 03/13
* 03/11
+
* 03/14
* 03/12
 
 
|
 
|
* 03/08
 
* 03/08
 
* 03/14
 
 
* 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
 
* Create and setup Gitlab Repository
* Create and setup Confluence for document collaboration
 
* Study the datasheets and manual of acquired components
 
* Distribute initial roles among the team members
 
 
|
 
|
* 03/04
+
* 03/14
* 03/07
+
* 03/18
* 03/17
+
* 03/18
* 03/15
 
 
|  
 
|  
*<font color = "green"> Completed
+
*<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"| 3
+
! scope="row"| Week 3
03/15 to 03/21
 
 
|
 
|
* 03/15
+
* 03/20
* 03/15
+
* 03/22
* 03/19
+
* 03/20
* 03/18
 
* 03/15
 
 
|
 
|
* 03/18
+
* 03/25
* 03/18
+
* 03/26
* 03/21
+
* 03/24
* 03/21
 
* 03/27
 
 
|
 
|
* Interface ultrasonic sensors and test the functionality
+
* Write basic driver for ultrasonic sensor
* Interface GPS and Compass and test the functionality
 
 
* Analyze and decide the hardware placement of the RC Car
 
* Analyze and decide the hardware placement of the RC Car
 
* Create SENSOR and DRIVER nodes to transmit and receive data
 
* Create SENSOR and DRIVER nodes to transmit and receive data
* Identify the Android app requirements and start studying the Android framework
 
 
|
 
|
* 03/18
+
* 03/26
* <font color = 'maroon'> 03/22 </font>
+
* 03/23
* 03/20
 
* 03/21
 
 
* 03/25
 
* 03/25
 
|  
 
|  
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
 
*<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"| 4
+
! scope="row"| Week 4
03/22 to 03/28
 
 
|
 
|
* 03/22
 
* 03/22
 
* 03/25
 
 
* 03/27
 
* 03/27
* 03/22
+
* 03/27
 +
* 03/27
 
|
 
|
* 03/25
+
* 04/04
* 03/24
+
* 04/01
* 03/28
 
* 03/31
 
 
* 03/28
 
* 03/28
 
|
 
|
 
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass  
 
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass  
* Interface the Bluetooth module to communicate with SJ-two board
 
 
* Create the MOTOR node to drive the RC Car
 
* Create the MOTOR node to drive the RC Car
* Start designing the DBC file
+
* Design DBC file and create CAN signals for every node
* Develop an initial version of the Android app
 
 
|
 
|
* <font color = 'maroon'>03/24</font>
+
* 04/02
* 03/24
+
* 04/04
* 03/28
+
* 04/01
* 03/30
 
* 03/28
 
 
|  
 
|  
*<font color = "green"> Completed
+
*<font color = "Green"> Completed
*<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"| 5
+
! scope="row"| Week 5
03/29 to 04/04
 
<font color = "sienna"> ''End of Phase 1''</font color>
 
 
|
 
|
 
* 04/02
 
* 04/02
* 03/29
+
* 04/02
* 03/29
+
* 04/02
* 03/29
+
* 04/02
* 03/31
 
* 04/03
 
 
|
 
|
* 04/03
+
* 04/08
* 04/01
+
* 04/08
* 04/01
+
* 04/08
* 04/01
+
* 04/08
* 04/03
 
* 04/04
 
 
|
 
|
 
* Finalize the DBC file  
 
* Finalize the DBC file  
 
* Design obstacle avoidance and steering logic on the DRIVER node
 
* Design obstacle avoidance and steering logic on the DRIVER node
 
* Design motor driving logic on the MOTOR node with the encoder
 
* Design motor driving logic on the MOTOR node with the encoder
* Interface the LCD module with the DRIVER node to display messages
+
* Start and design the Bluetooth app xml for destination.
* Integrate sensor data on the SENSOR node
+
 
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color>
 
 
|
 
|
* <font color = 'maroon>04/05</font>
+
* 04/09
* 04/01
+
* 04/09
* 04/01
+
* 04/09
* 04/01
+
* 04/09
* <font color = 'maroon'>04/04</font>
 
* 04/04
 
 
|  
 
|  
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
Line 220: Line 194:
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
|-
 
|-
! scope="row"| 6
+
! scope="row"| Week 6
04/05 to 04/11
 
<font color = "magenta">''Start of Phase 2''</font color>
 
 
|
 
|
* 04/05
+
* 04/09
* 04/05
+
* 04/09
* 04/08
+
* 04/09
* 04/10
+
* 04/09
 +
* 04/09
 
|
 
|
* 04/08
+
* 04/15
* 04/08
+
* 04/15
* 04/10
+
* 04/15
* 04/11
+
* 04/15
 +
* 04/15
 
|
 
|
* Tune the SENSOR and DRIVER nodes to drive the RC car
+
* Integrate GPS module with compass to get the current location.
* Communicate to the DRIVER node over Bluetooth via Android app
+
* Write UART interface for Bluetooth integration on sensor node.
* Debug and revise the integrated modules with necessary improvements
+
* Get raw sensor data from the ultrasonic sensor.
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color>
+
* 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/08
+
* 04/15
* 04/08
+
* 04/15
* 04/08
+
* 04/15
* 04/08
+
* 04/15
 +
* 04/15
 
|  
 
|  
*<font color = "green"> Completed
+
*<font color = "green">Completed
*<font color = "green"> Completed
+
*<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"| 7
+
! scope="row"| Week 7
04/12 to 04/18
 
 
|
 
|
* 04/12
+
* 04/16
* 04/15
+
* 04/16
* 04/12
+
* 04/16
* 04/17
+
* 04/16
 +
* 04/16
 +
* 04/16
 
|
 
|
* 04/15
+
* 04/23
* 04/18
+
* 04/23
* 04/16
+
* 04/23
* 04/18
+
* 04/23
 +
* 04/23
 +
* 04/23
 
|
 
|
* Integrate GEO node to DRIVER node for navigation
+
* Communicate to the GEO node over Bluetooth via Android app
 +
* Complete Driver obstacle logic
 
* Design driving decision logic based on the navigation data
 
* Design driving decision logic based on the navigation data
* Design a dashboard on the LCD to display the values
+
* Lay out basic PCB Board design for mounting the ECUs
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color>
+
* Filtering ultrasonic sensor data and sending processed data to Driver
 +
* RPM Sensor logic and testing.
 
|
 
|
* 04/15
+
* 04/26
* 04/18
+
* 04/26
* 04/16
+
* 04/26
* 04/18
+
* 04/26
 +
* 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
*<font color = "green"> Completed
+
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 8
+
! scope="row"| Week 8
04/19 to 04/25
 
<font color = "magenta">''End of Phase 2''</font color>
 
|
 
* 04/19
 
* 04/19
 
* 04/19
 
* 04/19
 
 
|
 
|
 
* 04/25
 
* 04/25
Line 290: Line 269:
 
* 04/25
 
* 04/25
 
* 04/25
 
* 04/25
|
 
* Add functionalities to display various sensor data on the Android app
 
* Design and 3D print the required components
 
* Design and order PCB
 
* Test and improve the RC car performance based on the changes
 
|
 
* 04/25
 
*
 
 
* 04/25
 
* 04/25
 
* 04/25
 
* 04/25
|
 
*<font color = "green"> Completed
 
*<font color = "red"> Incomplete
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
|-
 
! scope="row"| 9
 
04/26 to 05/02
 
<font color = "Tomato">''Start of Phase 3''</font color>
 
|
 
* 04/26
 
* 04/26
 
* 04/26
 
* 05/01
 
 
|
 
|
 
* 04/30
 
* 04/30
 
* 04/30
 
* 04/30
 
* 04/30
 
* 04/30
* 05/02
+
* 04/30
 +
* 04/30
 +
* 04/30
 
|
 
|
* Design individual architecture diagrams and algorithms for documentation
+
* Design a dashboard on the LCD to display the values
* Make any necessary improvements based on previous test results
+
* Driver logic for sensor data and geo data on busmaster.
* Complete the final version of the Android app
+
* Add functionality for pinning location on maps and extracting latitude and longitude
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color>
+
* 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>
 
|
 
|
 +
* 04/29
 +
* 04/27
 
* 04/30
 
* 04/30
 
* 04/30
 
* 04/30
 
* 04/30
 
* 04/30
* 05/02
+
* 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
*<font color = "green"> Completed
+
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 10
+
! scope="row"| Week 9
05/03 to 05/09
 
 
|
 
|
* 05/03
+
* 05/01
* 05/03
+
* 05/01
* 05/03
+
* 05/01
* 05/08
+
* 05/01
 +
* 05/01
 
|
 
|
 
* 05/07
 
* 05/07
 
* 05/07
 
* 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''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color>
 +
 +
|
 +
* 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"| Week 10
 +
|
 +
* 05/09
 +
* 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
 
* Replace the circuits with their corresponding PCBs and assemble
 
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1
 
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1
 
* Refactor the code modules with necessary improvements
 
* Refactor the code modules with necessary improvements
* '''Collective Test 5:'''<font color = "DarkGreen">''' Test the Prototype 1 with the aim of sending the car to return Preet's PCAN Dongle'''</font color>
+
* '''Collective Test 3:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color>
 
|
 
|
* 05/07
+
* 05/20
* 05/07
+
* 05/20
* 05/07
+
* 05/20
* 05/09
+
* 05/20
 
|
 
|
*<font color = "green"> Completed
+
*<font color = "green">Completed
*<font color = "green"> Completed
+
*<font color = "green">Completed
*<font color = "green"> Completed
+
*<font color = "green">Completed
*<font color = "brown"> Deferred
+
*<font color = "green">Completed
 
|-
 
|-
! scope="row"| 11
+
! scope="row"| Week 11
05/10 to 05/16
 
<font color = "Tomato">''End of Phase 3''</font color>
 
|
 
* 05/10
 
* 05/10
 
* 05/10
 
* 05/15
 
 
|
 
|
 
* 05/16
 
* 05/16
Line 376: Line 366:
 
* 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
 
* Revise and improve the wiki report to cover all the aspects of design and implementation
 
* Fix all the errors and make improvements
 
* Fix all the errors and make improvements
 
* Final testing of all the modules and car
 
* Final testing of all the modules and car
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color>
+
* '''Collective Test 4:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color>
 +
|
 +
* 05/22
 +
* 05/22
 +
* 05/22
 +
* 05/22
 +
|
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
*<font color = "green">Completed
 +
|-
 +
! scope="row"| Week 12
 
|
 
|
* 05/16
+
* 05/25
* 05/16
+
* 05/25
* 05/16
+
|
* 05/16
+
* 05/27
 +
* 05/27
 +
|
 +
* Demo
 +
* Final Wiki Page Update with addition of all the problems faced during the development
 
|
 
|
*<font color = "green"> Completed
+
* 05/25
*<font color = "green"> Completed
+
* 05/26
 +
|
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
 
*<font color = "green"> Completed
Line 403: Line 415:
 
! scope="col"| Vendor
 
! scope="col"| Vendor
 
! scope="col"| Qty
 
! scope="col"| Qty
! scope="col"| Cost
+
! scope="col"| Price($)
 
|-
 
|-
 
! scope="row"| 1
 
! scope="row"| 1
Line 409: Line 421:
 
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]
 
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]
 
| 1
 
| 1
| $250.00
+
|280
 
|-
 
|-
 
! scope="row"| 2
 
! scope="row"| 2
Line 415: Line 427:
 
| 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]
 
| 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]
 
| 5
 
| 5
| $7.00
+
| 8.99
 
|-
 
|-
 
! scope="row"| 3
 
! scope="row"| 3
 
| Ultrasonic Sensors
 
| Ultrasonic Sensors
 
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]
 
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]
| 5
+
| 4
| $150.00
+
| 24.95
 
|-
 
|-
 
! scope="row"| 4
 
! scope="row"| 4
| GPS and Antenna
+
| GPS Breakout Board
| Adafruit[https://www.amazon.com/Adafruit-Ultimate-GPS-Breakout-External/dp/B00I6LZW4O/ref=sr_1_7?dchild=1&keywords=adafruit+gps&qid=1622071143&sr=8-7]
+
| Adafruit[https://www.adafruit.com/product/746]
 
| 1
 
| 1
| $60.00
+
| 29.95
 
|-
 
|-
 
! scope="row"| 5
 
! scope="row"| 5
| HC05 bluetooth RF Transreceiver
+
| GPS Antenna
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]
+
| Adafruit[https://www.adafruit.com/product/960]
 
| 1
 
| 1
| $12.59
+
| 19.95
 
|-
 
|-
 
! scope="row"| 6
 
! scope="row"| 6
| Triple-axis Accelerometer
+
| 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
| $21.40
+
| 7.99
 
|-
 
|-
 
! scope="row"| 7
 
! scope="row"| 7
| Traxxas RPM Sensor
+
| HC05 bluetooth RF Transceiver
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]
+
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]
 
| 1
 
| 1
| $12
+
| 15.99
 
|-
 
|-
 
! scope="row"| 8
 
! scope="row"| 8
| Discrete Electronic Components
+
| Triple-axis Accelerometer
| Generic[http://www.excesssolutions.com/]
+
| Adafruit[https://www.adafruit.com/product/1120]
 
| 1
 
| 1
| $28.75
+
| 14.95
 
|-
 
|-
 
! scope="row"| 9
 
! scope="row"| 9
| Buck-Boost Voltage Regulator
+
| Traxxas RPM Sensor
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]
+
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]
 
| 1
 
| 1
| $11.99
+
| 13.76
 
|-
 
|-
 
! scope="row"| 10
 
! scope="row"| 10
| Traxxas Telemetry Trigger magnet & holder
+
| Traxxas Battery and Charger
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]
+
|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]
| 1
+
|1
| $6.35
+
|62.95
 
|-
 
|-
 
! scope="row"| 11
 
! scope="row"| 11
| Acrylic Sheet
+
| Voltage Regulator
| Tap Plastic
+
|Valefod[https://www.amazon.com/dp/B076H3XHXP?ref_=cm_sw_r_cp_ud_dp_5HTAVWPZJ2QS6AMXTM93]
| 1
+
|6
| $12
+
|10.99
 
|-
 
|-
 
! scope="row"| 12
 
! scope="row"| 12
| Battery
+
| Headlights
| Amazon[https://www.amazon.com/dp/B07LGZGG7T?ref=ppx_pop_mob_ap_share]
+
|Hobbypark[https://www.amazon.com/dp/B01GY8VFIM?ref_=cm_sw_r_cp_ud_dp_PK32ZA2HM4DRWMGV55YC]
| 1
+
|1
| $26.99
+
|7.96
|-
 
! scope="row"| 13
 
| Traxxas Battery and Charger
 
| Amazon[https://www.amazon.com/dp/B074FXXP5J/ref=cm_sw_r_wa_api_glt_fabc_TQCR9J50NFX7VYE33PWB?_encoding=UTF8&psc=1]
 
| 1
 
| $55.94
 
 
|-
 
|-
 
|}
 
|}
Line 489: Line 495:
  
 
== Printed Circuit Board  ==
 
== Printed Circuit Board  ==
 +
 +
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>
 +
 +
 
<h4>PCB Schematic</h4>
 
<h4>PCB Schematic</h4>
  
<h4>PCB Design</h4>
+
<div><ul>
 +
<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>
 +
 
 +
 
 +
<h4>PCB Board</h4>
 +
 
 +
<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.
 +
 
 +
<h4>Solution  </h4>
 +
* Finally we decided to use the prototype board for mounting all the components and stabilizing our hardware.
 +
<div><ul>
 +
<li style="display: inline-block;">[[File:Final_Hardware_Physical.jpeg|500px|thumb|Left|Protoype_Board]]</li>
 +
</ul></div>
  
 
== CAN Communication ==
 
== CAN Communication ==
We use controller area network to broadcast data between the 4 nodes. All nodes are connected to each other through a physically conventional two wire bus. The wires are a twisted pair with 120 Ω resistors at each ends of the bus. 1s and 0s are transmitted as CAN High(0V difference) and Can Low(2v difference).  
+
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:
 
A CAN frame has the following contents:
 
* Data Length Code (4bits)
 
* Data Length Code (4bits)
Line 504: Line 538:
  
  
'''Arbitration''': No two nodes will transmit at the same time because if arbitration. A lower Message-ID has a Higher priority on the CAN bus since 0 is the dominant bit.
+
'''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.
 
'''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]]
 +
 +
 +
=== 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.
 +
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 518: Line 558:
 
|-
 
|-
 
|-
 
|-
! colspan="4"| Driver Controller
+
! colspan="4"| Driver Heartbeat
 
|-
 
|-
 
|-
 
|-
 
|1
 
|1
|300
+
|100
|speed and steering direction for the motor.
+
|Driver Heartbeat
|Motor
+
|Motor, Sensor, Geo
 +
|-
 +
! colspan="4"| Start Stop signal from Android app to Driver
 
|-
 
|-
|2
 
|310
 
|Destination reached
 
|Sensor
 
 
|-
 
|-
 +
|1
 +
|101
 +
|Bridge Sensor
 +
|Driver
 
|-
 
|-
! colspan="4"| Sensor Controller
+
! colspan="4"| Ultrasonic sensors data transmit
 
|-
 
|-
 
|-
 
|-
|1
+
|2
 
|200
 
|200
 
|Sensor sonars from front, back, left ,right sensor
 
|Sensor sonars from front, back, left ,right sensor
 
|Driver
 
|Driver
 
|-
 
|-
 +
! colspan="4"| Destination Location
 
|-
 
|-
! colspan="4"| Motor Controller
+
|-
 +
|4
 +
|250
 +
|Bridge Sensor
 +
|Geo
 +
|-
 +
|-
 +
! colspan="4"| Driver to Motor Command
 
|-
 
|-
 
|-
 
|-
|8
+
|5
|700
+
|300
|motor speed, motor direction
+
|Speed and steering direction for the motor
|Driver
+
|Motor
 
|-
 
|-
 
|-
 
|-
! colspan="4"| Geo and Bridge Controller
+
! colspan="4"| Geo Controller
 
|-
 
|-
 
|-
 
|-
|1
+
|6
 
|400
 
|400
 
|Bearing, Heading and Distance
 
|Bearing, Heading and Distance
 +
|Driver
 +
|-
 +
|-
 +
! colspan="4"| Motor Controller
 +
|-
 +
|-
 +
|7
 +
|600
 +
|Motor speed
 
|Driver
 
|Driver
 
|-
 
|-
Line 562: Line 621:
 
|-
 
|-
 
|-
 
|-
|1
+
|8
|851
+
|700
 
|Driver Debug
 
|Driver Debug
|SENSOR,MOTOR,GEO_AND_BRIDGE
+
|BRIDGE_SENSOR,MOTOR,GEO
|-
 
|-
 
|1
 
|811
 
|Motor Debug
 
|SENSOR,MOTOR,GEO_AND_BRIDGE
 
 
|-
 
|-
 
|-
 
|-
|1
+
|9
|801
+
|750
|Sensor Debug
+
|Geo Debug
|SENSOR,MOTOR,GEO_AND_BRIDGE
+
|BRIDGE_SENSOR,MOTOR,DRIVER
 
|-
 
|-
 
|-
 
|-
 
|}
 
|}
  
 +
<pre>
 +
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
  
=== Hardware Design ===
+
BO_ 100 DRIVER_HEARTBEAT: 1 DRIVER
 +
  SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" BRIDGE_SENSOR,MOTOR,GEO
  
[[File:roadstercan.png|center|500px|thumb|CAN Bus Design]]
+
BO_ 101 DRIVE_STATUS: 1 BRIDGE_SENSOR
 +
  SG_ DRIVE_START_STOP : 0|8@1+ (1,0) [0|0] "" DRIVER
  
<br/>
+
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
  
=== DBC File ===
+
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
  
<syntaxhighlight lang=c>
+
BO_ 300 DRIVER_TO_MOTOR: 2 DRIVER
VERSION ""
+
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
  
NS_ :
+
BO_ 400 GEO_CONTROLLER_COMPASS: 8 GEO
BA_
+
  SG_ HEADING : 0|12@1+ (0.1,0) [0|359.9] "degrees" DRIVER, BRIDGE_SENSOR
BA_DEF_
+
  SG_ BEARING : 12|12@1+ (0.1,0) [0|359.9] "degrees" DRIVER,BRIDGE_SENSOR
BA_DEF_DEF_
+
  SG_ DISTANCE_TO_DESTINATION: 24|32@1+ (0.01,0) [0|359.9] "meters" DRIVER,BRIDGE_SENSOR
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_:
+
BO_ 600 MOTOR_SPEED: 2 MOTOR
 +
SG_ MOTOR_SPEED_info : 0|8@1+ (0.1,-10) [-10|10] "kmph" DRIVER, BRIDGE_SENSOR
  
BU_: DRIVER MOTOR SENSOR GEO_AND_BRIDGE DEBUG
 
  
BO_ 200 SENSOR_SONARS: 5 SENSOR
+
BO_ 700 DRIVER_DEBUG: 2 DEBUG
SG_ SENSOR_SONARS_left : 0|10@1+ (1,0) [0|800] "cm" DRIVER
+
  SG_ car_driving_status: 0|8@1+ (1,0) [0|0] "" DEBUG
SG_ SENSOR_SONARS_right : 10|10@1+ (1,0) [0|0] "cm" DRIVER
+
  SG_ car_steering_status: 8|8@1+ (1,0) [0|0] "" DEBUG
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_ 300 DRIVER_TO_MOTOR: 2 DRIVER
+
BO_ 750 GEO_CONTROLLER_DEBUG_MESG: 10 DEBUG
  SG_ MOTOR_speed : 0|8@1+ (0.1,-12.5) [-12.5|12.5] "m/s" MOTOR
+
  SG_ CURR_LATITUDE : 0|28@1+ (0.000001,-90.000000) [-90|90] "degrees" DEBUG
  SG_ MOTOR_direction : 8|7@1+ (1,-45) [-45|45] "degree" MOTOR
+
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
  
BO_ 310 DRIVER_BROADCAST: 1 DRIVER
+
CM_ BU_ DRIVER "The driver controller driving the car";
SG_ DEST_reached : 0|8@1+ (1,0) [0|0] "flag" SENSOR
+
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";
  
BO_ 400 GEO_CONTROLLER_COMPASS: 6 GEO_AND_BRIDGE
+
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" ;
  SG_ HEADING : 0|12@1+ (1,0) [0|359] "Degrees" DRIVER
+
VAL_ 700 car_steering_status 2 "RIGHT" 1 "LEFT" 0 "STRAIGHT";
  SG_ BEARING : 12|12@1+ (1,0) [0|359] "Degrees" DRIVER
+
VAL_ 700 car_driving_status 2 "BACKWARD" 1 "FORWARD" 0 "STOPPED";
  SG_ DISTANCE : 24|17@1+ (0.01,0) [0|0] "Meters" DRIVER
+
</pre>
  
BO_ 401 GEO_CONTROLLER_COMPASS_DEBUG: 9 GEO_AND_BRIDGE
+
=== Technical Challenges ===
  SG_ WAYPOINT_COUNT : 0|8@1+ (1,0) [0|16] "" DEBUG
+
* 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.
  SG_ STATUS : 8|8@1+ (1,0) [0|359] "Degrees" DEBUG
+
* 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.
  SG_ DISTANCE_TO_WAYPOINT : 16|12@1+ (0.01,0) [0|0] "Meters" DEBUG
 
  SG_ HEADING_TO_WAYPOINT : 28|12@1+ (1,0) [0|359] "Degrees" DEBUG
 
  SG_ BEARING_TO_WAYPOINT : 40|12@1+ (1,0) [0|359] "Degrees" DEBUG
 
  SG_ HEADING_RAW : 52|12@1+ (1,0) [0|359] "Degrees" DEBUG
 
  SG_ WAYPOINT_CURRENT : 64|8@1+ (1,0) [0|16] "" DEBUG
 
  
BO_ 700 MOTOR_TO_DRIVER: 8 MOTOR
+
== Sensor and Bluetooth ECU ==
SG_ MOTOR_speed:0|8@1+ (0.1,-12.5) [-12.5|12.5] "m/s" DRIVER
+
=== Hardware Design ===
SG_ MOTOR_direction : 8|7@1+ (1,-45) [-45|45] "degree" DRIVER
 
  
BO_ 851 DRIVER_DEBUG_DATA: 1 DEBUG
+
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.
SG_ forwardDrivingState:0|2@1+ (1,0) [0|0] "" SENSOR,MOTOR,GEO_AND_BRIDGE
 
SG_ reverseDrivingState: 2|2@1+ (1,0) [0|0] "" SENSOR,MOTOR,GEO_AND_BRIDGE
 
SG_ isRightSteeringPossible:4|2@1+ (1,0) [0|0] "" SENSOR,MOTOR,GEO_AND_BRIDGE
 
SG_ isLeftSteeringPossible:6|2@1+ (1,0) [0|0] "" SENSOR,MOTOR,GEO_AND_BRIDGE
 
 
BO_ 801 SENSOR_DEBUG_DATA: 8 DEBUG
 
SG_ LEFT_sensor_raw:0|16@1+ (1,0) [0|0] "cm" SENSOR,MOTOR,GEO_AND_BRIDGE
 
SG_ RIGHT_sensor_raw: 16|16@1+ (1,0) [0|0] "cm" SENSOR,MOTOR,GEO_AND_BRIDGE
 
SG_ FRONT_sensor_raw: 32|16@1+ (1,0) [0|0] "cm" SENSOR,MOTOR,GEO_AND_BRIDGE
 
SG_ REAR_sensor_raw: 48|16@1+ (1,0) [0|0] "cm" SENSOR,MOTOR,GEO_AND_BRIDGE
 
  
BO_ 811 MOTOR_DEBUG_DATA: 8 DEBUG
 
SG_ MOTOR_rps_value:0|32@1+ (1,0) [0|0] "rps value" SENSOR,DRIVER,GEO_AND_BRIDGE
 
SG_ MOTOR_pwm_value:32|8@1+ (0.01,0) [0|0] "dc motor pwm value" SENSOR,DRIVER,GEO_AND_BRIDGE
 
  
BO_ 1000 DRIVER_HEARTBEAT: 1 DRIVER
+
[[File:Sensor_Node.png|left|400px|thumb|Sensor Controller Diagram]]
SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR,MOTOR,GEO_AND_BRIDGE
 
  
BO_ 1100 MOTOR_HEARTBEAT: 1 DRIVER
+
[[File:Ultrasonic99.png|center|400px|thumb|Sensor Pins]]
SG_ MOTOR_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR,DRIVER,GEO_AND_BRIDGE
 
  
BO_ 1200 SENSOR_HEARTBEAT: 1 DRIVER
 
SG_ SENSOR_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" MOTOR,DRIVER,GEO_AND_BRIDGE
 
  
BO_ 1300 GEO_HEARTBEAT: 1 DRIVER
 
SG_ GEO_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR,MOTOR,DRIVER
 
  
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_ SG_ 100 DRIVER_HEARTBEAT_cmd "Heartbeat command from the driver";
 
  
BA_DEF_ "BusType" STRING ;
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0;
+
|+Pin connections between board and sensor:
BA_DEF_ SG_ "FieldType" STRING ;
+
|-
 +
! 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
 +
|-
 +
|}
  
BA_DEF_DEF_ "BusType" "CAN";
 
BA_DEF_DEF_ "FieldType" "";
 
BA_DEF_DEF_ "GenMsgCycleTime" 0;
 
  
BA_ "GenMsgCycleTime" BO_ 100 1000;
+
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.
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" ;
+
=== Software Design ===
</syntaxhighlight>
 
  
 +
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.
  
<HR>
+
====== Receive sensor values ======
<BR/>
 
  
== Sensor ECU ==
+
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.
<Picture and link to Gitlab>
 
Gitlab link to Sensor Node Firmware: https://gitlab.com/nimit.patel/roadster/-/tree/Main/Sensor_Node
 
  
The sensor controller node is responsible for interfacing with Ultrasonic sensors to know obstacles’ distance from the vehicle. We have used MaxBotix 1010 LV-EZ1 sensors for the right and left positions and MaxBotix 1000 LV-EZ0 sensor in the middle front position (To have a wider beam range of obstacle detection in blind spots).
+
====== Sending sensor values in terms of distance to CAN ======
  
[[File:Sensor_Node.png|center|800px|thumb|Sensor Controller Diagram]]
+
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. 
  
Below is the beam pattern for both sensors.
 
  
[[File:Beam_Pattern_MB1000_EZ0.gif|left|500px|thumb|Beam Pattern MaxBotix MB1000 EZ0]]
+
[[File:f8.png|center|6600px|thumb|Sensor Controller Diagram]]
[[File:Beam_Pattern_MB1010_EZ1.gif|center|500px|thumb|Beam Pattern MaxBotix MB1010 EZ1]]
 
  
 +
=== 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.
  
=== Hardware Design ===
+
*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.
  
==== Sensor Controller Schematic ====
 
  
 +
<HR>
 +
<BR/>
  
[[File:SensorSch.png|center|800px|thumb|Sensor Controller Node Schematic]]
+
== 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 ===
 +
{| 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.
  
==== Board Pin Connections ====
+
'''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)
  
Sensors are interfaced with combination of GPIO, ADC Pins on SJTWo board. Below is the descriptive pin layout:
+
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" style="text-align: center; width: 400px; height: 200px;"
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
|+ Sensors pin layout
+
|+ESC Pinout
 
|-
 
|-
! Sr. No.
+
! scope="col"| Wires on ESC
! SJTwo board Pin
+
! scope="col"| Description
! Maxbotix sensor Pin
+
! scope="col"| Wire Color
! Function
 
 
|-
 
|-
! 1
+
! scope="row"| PWM(P2.1)
| ADC2-P0.25 || AN(Front sensor) || ADC input from front sensor
+
| Takes PWM input from SJ2-Board
 +
| WHITE
 
|-
 
|-
! 2
+
! scope="row"| VDD(6V)
| ADC3-P0.26 || AN(Rear Sensor) || ADC input from rear sensor
+
| Power Output
 +
| RED
 
|-
 
|-
! 3
+
! scope="row"| GND
| ADC4-P1.30 || AN(Left Sensor) || ADC input from left sensor
+
| Ground
 +
| BLACK
 +
|-
 +
|}
 +
 
 +
 
 +
 
 +
<br/>
 +
{| style="margin-left: auto; margin-right: auto; border: none;"
 +
|[[File:ESC.jpg|center|300px|thumb|Traxxas ESC]]
 +
|
 +
|[[File:DCMotor.jpg|center|300px|thumb|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.
 +
<br/>
 +
PWM 15 for straight.
 +
<br/>
 +
PWM 15.1 to 20 for turning right.
 +
 
 +
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
 +
|+Servo Pinout
 
|-
 
|-
! 4
+
! scope="col"| Wires on ESC
| ADC5-P1.31 || AN(Right Sensor) || ADC input from right sensor
+
! scope="col"| Description
 +
! scope="col"| Wire Color
 
|-
 
|-
! 5
+
! scope="row"| PWM(P2.0)
| GPIO-P0.6 || RX(Left Sensor) || Trigger for left sensor
+
| Takes PWM input from SJ2-Board
 +
| WHITE
 
|-
 
|-
! 6
+
! scope="row"| VDD(6V)
| GPIO-P0.7 || RX(Front Sensor) || Trigger for front sensor
+
| Power Input
 +
| RED
 
|-
 
|-
! 7
+
! scope="row"| GND
| GPIO-P0.8 || RX(Right Sensor) || Trigger for right sensor
+
| Ground
 +
| BLACK
 
|-
 
|-
! 8
 
| GPIO-P0.9 || RX(Rear Sensor) || Trigger for rear sensor
 
 
|}
 
|}
  
=== <font color="0000FF">Software Design </font>===
+
{| style="margin-left: auto; margin-right: auto; border: none;"
 +
[[File:Servotrx.jpg|300px|centre|thumb|Traxass Servo Motor(2075)]]
  
The sensor node mainly does two activity viz. 1) Read sensor values, 2) Transmit obstacle distance over CAN bus. Both of these activities happen in a 20Hz periodic callback.  
+
==== 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.  
  
1. Read Sensor Values
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
 +
|+RPM Pinout
 +
|-
 +
! scope="col"| Wires on ESC
 +
! scope="col"| Description
 +
! scope="col"| Wire Color
 +
|-
 +
! scope="row"| GPIO(P0.6)
 +
| Provides pulses to Motor SJ2-Board
 +
| WHITE
 +
|-
 +
! scope="row"| VDD(3.3V)
 +
| Power Input
 +
| RED
 +
|-
 +
! scope="row"| GND
 +
| Ground
 +
| BLACK
 +
|-
 +
|}
  
*  Sensors are mounted at four locations as mentioned below diagram. To read these sensor values, we initialized and configured 4 sensors using 4 ADCs viz ADC2, ADC3, ADC4, and ADC5. Considering the front 3 sensors' close proximity and possible beam interference, we decided to range extreme front sensors at a time and the middle front next in sequence while in a 20 Hz loop. And the rear sensor is triggered regularly. All the sensor values are digitally converted in the range of 0 to 4096 (12 bit ADC). These values are converted to distance format in centimeter unit using formula '''conv_val = (raw_val * 0.3182) - 0.3959'''.
+
<br/>
[[File:Sensor_placement.png|center|400px|thumb|Sensors Placement location]]
+
{| 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]]
 +
|
 +
|}
  
*  Now, to avoid frequent noise pulses, we used a median filter. We created an array of 10 elements for each sensor and maintained a write index to track the current update position. Thus, all read values have been updated in the buffer which acts as a circular buffer as we start overwriting from the start index.
+
=== 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.
  
2. Transmit obstacle distance over CAN bus:
+
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.
  
*  Sensor node is responsible for broadcasting all four sensor values in terms of distance in centimeter over CAN bus. To broadcast filtered values, it first sorts the existing values in the respective allocated sensor buffer. Then it takes the mean of five median values. It does the same thing for all four sensors. Finally, it transmits those values over CAN bus. Below flow chart gives the detailed flow of code at a high level.
+
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.
  
[[File:Sensor_Node_flow_chart.png|center|600px|thumb|Sensor Node Controller Flow Chart]]
+
'''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.
  
=== <font color="0000FF">Technical Challenges </font>===
+
'''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.
  
==== Neighboring Sensor Interference: ====
+
'''The period_callbacks__10Hz() function calls the following functions:'''
* As explained above, we have mounted three ultrasonic sensors in the front, and those were configured to range in continuous mode, in which sensors were continuously measuring distance by transmitting beam. Out of 3, the middle sensor is of type with wider beam to detect blind spots ahead.
+
* pwm1__set_duty_cycle: to calibrate the ESC by sending neutral signal for few seconds.
* Most of the time, we observed that the obstacle in the middle sensor range used also gets detected by the left/right sensor, which disturbs driving logic. This used to happen due to sensor beam interference among three sensors.
+
* clear_rotations: clears interrupt counter every 0.5 seconds
* To solve this problem, we decided to trigger sensor beams in such time intervals that they won’t interfere with neighboring ones. We used the Rx pin of the sensor to trigger ranging and scheduled to trigger left and right sensor at one time and middle sensor next time. This sequence helped us avoid interference altogether.
+
* can_handler__handle_all_incoming_messages: receives any message frame sent on the CAN bus.
 +
   
  
==== Frequent noisy measurements: ====
+
<br/>
*  While reading the obstacle distance, it used to change suddenly to some random value, and that used to disturb driving logic. To get noise-free readings from sensors, we implemented a median filter. All the read values from sensors have been collected in the respective buffer of 10 elements. While sending obstacle distance on CAN bus, the median filter sort the buffer and takes an average of 5 median values. This way, it helped us to remove almost all noisy values.
+
[[File: Motor_SW_design.jpg|center|700px|thumb|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.
 +
<br/>
 
<HR>
 
<HR>
 
<BR/>
 
<BR/>
  
== Motor ECU ==
+
== Geographical And Bridge Controller ==
[[File:MotorSch.png|center|800px|thumb| Motor Node Schematic]]
 
  
 
=== Hardware Design ===
 
=== Hardware Design ===
[[File:XL5esc.png|300px|thumb|left|Traxass ESC XL5]]
 
[[File:Servotrx.jpg|300px|right|thumb|Traxass Servo Motor]]
 
[[File:Rpmsens.jpg|300px|center|thumb|Traxass RPM Sensor]]
 
<BR/>
 
  
The motor node(SJ-2) interfaces primarily interfaces with:
+
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.
* Traxass Motor ESC over PWM
+
 
* Traxass RPM Sensor over GPIO Interrupt
+
<li style="display: inline-block;"> [[File:Geo_Node_Schematic.jpg|500px|thumb|centre|]] </li>
* Traxass Servo Motor over PWM
+
<li style="display: inline-block;">[[File:compass_Firebolt.jpg|300px|thumb|center|3 Axis Magnetometer (eCompass)]] </li>
 +
 
 +
<li style="display: inline-block;"> [[File:GPS_Firebolt.jpg|300px|thumb|centre|GPS Module]] </li>
  
All these three components have 3 pins each. The functionalities of these pins are mentioned in the table below.
 
  
{| class="wikitable"
+
{| class="wikitable" width="auto" style="text-align: center; margin-left: auto; margin-right: auto; border: none;"
 +
|+Geographical Node Pinout
 +
|-
 +
! scope="col"| SJTwo Board
 +
! scope="col"| GPS/Compass Module
 +
! scope="col"| 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
 
|-
 
|-
! scope="col"| Module
+
| P0.0
! scope="col"| Black
+
| CAN transceiver (Rx)
! scope="col"| Red
+
| CAN  receive
! scope="col"| White
 
 
|-
 
|-
! scope="row"| ESC
+
| Vcc 3.3V
| Ground
+
| Vcc
| Vout : 6 V
+
| Vcc
| PWM Input
 
 
|-
 
|-
! scope="row"| Servo
+
| GND
| Ground
+
| GND
| Vin : 6 V
+
| Ground
| PWM Input
 
 
|-
 
|-
! scope="row"| RPM Sensor
 
| Ground
 
| Vin : 6 V
 
| Pulse Output
 
 
|}
 
|}
 +
 +
<BR/>
  
 
=== Software Design ===
 
=== 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
 +
[[File:FlowChart_Geo_Logic.jpg|center|700px|thumb|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:<br/>
  
The motor node acts based on the speed and direction received over CAN bus from the Driver Node. The positive speed values are treated as forward motion and the negative speed values are considered to be the reverse motion of the RC car.
+
  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))
  
The steering angles are divided into 5-degree segments and the motor node sends the pre-defined pwm duty cycle of the particular segment to the servo motor depending on the angle value received from the driver node.
 
  
[[File:Flowchartmotor.png|800px|thumb|center|Motor Node - Software Flowchart]]
+
*Tilt compensated magnetic sensor values:<br/>
 +
 
 +
  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)
  
=== Technical Challenges ===
 
  
* Firstly, the Traxxas motor ESC and other Traxass parts are members of the Traxxas Hobby Parts family, and they are not intended for development purposes. This is why there are no technical specification documents or any program/development guides available. One needs to test the motor ESC by feeding the PWM duty cycles in various sequences at various duty cycle percentages. We used the Remote control to reproduce some scenarios where the ESC was behaving unexpectedly.
+
Luckily our module had no offset but it might need to be compensated for the offset if there is any.
* The ESC configuration changes to the Lipo battery state if the Lipo battery is used. If one switches back to the NiMH battery, then the ESC starts flashing the led in a green-red repeated sequence, and the ESC power button stops working. In this scenario, there is a calibration process that can save your boat and can make the ESC function normally again. Follow this procedure : [https://www.youtube.com/watch?v=1br9_h1OsV8 ESC Calibration]
+
*Another challenge with the motor node program development is that you cannot rely on unit testing. Whoever works on the motor node, should make sure that the sequence of the duty cycles being fed to the ESC produces the expected results on the motor as well. The forward-reverse transitioning and the speed controlling both can be a bit tricky. Also, the hard brake logic can take a while to get working properly.
+
*Heading angle
* Some useful reference values for the ESC are : 15% -> Neutral; 15.8%-> Minimum forward speed, 10%->Full reverse speed.
 
<HR>
 
<BR/>
 
  
== Geographical And Bridge Controller ==
+
heading = atan2(mag_y, mag_x) * r2d
 +
r2d is radian to degree conversion function
  
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''
+
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.
  
=== Hardware Design ===
+
====Checkpoints====
[[File:GeoSch.png|650px|thumb|center|Geo Node Schematic]]
 
<BR/>
 
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]
 
[[File:GPS.jpg|400px|thumb|right|GPS Module]]
 
[[File:compass_roadster.jpg|400px|thumb|center|3 Axis Magnetometer (eCompass)]]
 
<BR/>
 
[[File:Votlage Divider.jpg|400px|thumb|right|Battery Monitoring]]
 
  
<BR/>
+
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.
 +
[[File:Checkpoint.jpg]]
  
The SJ2 board communicates with:
+
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:
* Bluettoth transreceiver over UART
 
* LSM303DLHC over I2C
 
* GPS model over UART
 
* Battery monitoring
 
  
Considering the orientation of the car changes as it travel along the land, tilt compensation logic for heading calculation using the magnetometer is a must for accurate measurement. Without the tilt compensation algorithm which uses the onboard accelorometer, the heading computation can have error up to 60 degrees, which has the potential to send the car off course.
+
The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.
<BR/>
+
The heading and bearing is also computed using the Haversine formula and is sent over the CAN bus for heading correction.*
<BR/>
+
Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.
For battery monitoring, the values for the voltage divider should be chosen such that the full range of the onboard ADC can be efficiently used. Depending one the cell type of the battery, the discharge curve can be use to map the charge state corresponding to voltage level. This method has its flaws and sophisticated techniques involving Coulomb count yields far better results, however, the technique discussed above suffices the needs of our project. Charge state of battery transmitted over Mobile app, greatly facilitates the charging schedule while testing and final demo day.
 
  
<BR/>
+
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:
<BR/>
 
  
=== Software Design ===
+
a = sin²(ΔlatDifference/2) + cos(lat1) * cos(lt2) * sin²(ΔlonDifference/2)
The periodic scheduler for Geo Controller Node does the following functionalities:
+
c = 2 * atan2(sqrt(a), sqrt(1−a))
*  In 10Hz periodic callback:
+
  d = R * c
** gps__update() : Fetch GPS data from GPS controller.
 
** geo_compass__periodic_send() : Reads the Magnetometer and accelerometer values from Compass controller and convert those to current heading data.
 
* In 100Hz periodic callback:
 
** bluetooth__run_once() : Send specified data to android application via Bluetooth.
 
  
The GEO controller is divided into 5 parts.
+
*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
  
*The current location of the car is determined using the GPS.
 
  
*The current magnetic heading of car is determined using the on board compass.
+
*Bearing Angle computation
  
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.
+
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 heading is also computed using the Haversine formula and the difference between the actual and required is sent over the CAN bus for heading correction.
+
X = cos θb * sin ∆L
 +
Y = cos θa * sin θb – sin θa * cos θb * cos ∆L
  
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.
+
β = atan2(X,Y)
  
 +
*where:
 +
**θa = current latitude
 +
**θb = destination latitude
 +
**∆L = destination longitude - current longitude
 +
**β = heading degree in radians
  
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) 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.
  
 
=== Technical Challenges ===
 
=== Technical Challenges ===
  
* The GPS module sends data at 9600 baud rate, updating the data every one second. The data update rate needs to be updated to 10Hz for fast maneuvering and course correction of the car. If the update frequency is updated, the data sent over the UART is higher than it can handle in 10Hz periodic function. Hence, only GPGGA messages should be enabled to extract the required data and reduce the time spent in parsing the incoming string. NEMA (PMTK) messages should be correctly configured on the module for desired functioning.
 
* Heading calculation without the tilt compensation logic using the onboard accelorometer of LSM303 is in accurate. Reading accelorometer values requires and offset of 0x80 to the byte addressing of the accelorometer read. Magnetometer need no such offset. This is weird, considering both the I2C devices reside on the same physical chip.
 
*Using data type as float as opposed to double, utilizes the onboard FPU, which is faster. Double utilizes software implementation, which takes more clock cycle. Considering extensive use of math library in distance/heading measurement and tilt compensation algorithm, completing the task with the periodic is of at most importance.
 
* GPS fix is best when when there are no obstruction above the module. Module requires clear wide view of sky for a fast fix and error free location detection.
 
* LSM303DLHC is sensitive to even weak magnetic field interference. Place the chip devoid of such active/passive magnetic fields.
 
* Calibrating LSM303 is a must to get accurate heading values. 2-point calibration worked just fine for our team. More sophisticated methods are available too.
 
 
<HR>
 
<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.
 +
 +
*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 ==
https://gitlab.com/nimit.patel/roadster/-/tree/Main/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.
 +
 
 +
<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>
  
=== Hardware Design ===
 
The Driver Node has one peripheral connected to it and that is the LCD screen.
 
  
[[File:Driver_Node_HW_Design.png|thumb|700px|caption|left|Driver Node Schematic]]
+
=== Obstacle Avoidance Logic ===
[[File:DriverSch.png|thumb|700px|caption|center|Driver Node Schematic]]
+
 
 +
<pre>
 +
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;
 +
        }
 +
</pre>
 +
 
 +
 
 +
'''''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;
 +
    }
 +
 
 +
  } 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;
 +
}
 +
 
 +
</pre>
 +
 
 +
'''''Reverse and Steer'''''
 +
<pre>
 +
  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();
 +
  }
 +
</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.
 +
 
 +
<pre>
 +
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;
 +
  }
 +
</pre>
 +
 
  
=== Software Design ===
+
=== Periodic Callbacks ===
The driver node controls the logic of steering the car in the right direction based on the data received from the Sensor and Geo Nodes. The following flowchart describes that process.
 
*Driver Node Flow Chart
 
  
[[File:FlowChartDriverNode.png|thumb|1000px|caption|center|Driver Node Flow Chart]]
+
The period_callbacks__initialize() function calls the following functions:
 +
<pre>
 +
  can__bus_initializer(can1);
 +
  lcd__init();
 +
  head_tail_lights_init();
 +
  debug_led_init();
 +
</pre>
  
In case there are obstacles in the path where the car wants to move to, the following obstacle avoid logic would kick in.
+
The period_callbacks__1Hz() function calls the following function:
*Driver Node Obstacle Avoidance Logic
+
<pre>
 +
  can_bus_handler_tx_debug_messsages(can1);
 +
  static uint8_t count = 0;
 +
  if (count == 0) {
 +
    lcd__communication_init();
 +
  }
 +
  count = 1;
 +
  print_info_on_lcd();
 +
</pre>
  
[[File:ObstacleAvoidanceDriverNode.png|thumb|1200px|caption|center|Driver Node Obstacle Avoidance Logic]]
+
The period_callbacks__10Hz() function calls the following functions:
The work in the Driver Node is done using two different periodic tasks. Here is a description of those periodic tasks and what they do.
+
<pre>
*1 Hz Loop:
+
  can_bus_handler__process_all_received_messages(can1);
**Transmit debug messages over the CAN bus
+
  can_bus_handler__manage_mia();
**Transmit messages on the LCD
+
  can_bus_handler_tx_messages(can1);
**Transmit destination reached flag over the CAN Bus
+
</pre>
*20 Hz Loop:
 
**Receive Sensor Data
 
**Receive Geo Data
 
**Process and Transmit Data(Motor Direction and Speed) to Motor Node
 
*LCD Interface
 
The LCD interface on the Driver is used to print some important information about the car. This is what it prints.
 
**Car Speed
 
**Distance from the Destination
 
**Car State (Car Stopped from the App, Car Moving, Destination Reached)
 
  
 
=== Technical Challenges ===
 
=== Technical Challenges ===
*The Driver Node did not have much hardware interfaced on it apart from LCD. So from the hardware side there were no technical challenges. On the software front as well there were not many challenges as unit tests helped debug most of the issues then and there.
+
* 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.
*We initially used GLCD which was configured via GPIOs and it was working perfectly. Hence we created our PCB as per this LCD. But, while testing our car with various speeds and PID logic, it got toppled and damaged the LCD. So, we had to change to SJ Valley LCD, which was configured via the UART interface, at the last moment. So, we used the same location on the PCB to place the LCD and soldered wires below PCB. Hence, this correction was not visible on our end product.
+
* 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/srikarreddy.narapureddy/roadster-app Gitlab]''
+
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.
We created a lightweight mobile app to navigate our car, It can communicate with the car via Bluetooth and is capable of sending Destination co-ordinates along with checkpoints. Receive and Update live location on Google Maps, send Start, Stop and Clear commands, Receive and Display Debug Data.
+
 
 +
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.
  
<div><ul>
+
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.  
<li style="display: inline-block;">[[File:Roadsterintro.jpeg|thumb|none|220px| Splash screen]] </li>
 
<li style="display: inline-block;">[[File:roadsterapp1.jpg|thumb|none|220px| Data from roadster]] </li>
 
<li style="display: inline-block;">[[File:roadsterapp2.jpg|thumb|none|220px| Checkpoints]] </li>
 
  
</ul></div>
+
The Web app provides two important sections for mobile app development:
 +
<li>The Designer page</li>
 +
<li>The Blocks page</li>
  
 
===User Interface===
 
===User Interface===
The app has minimal buttons on the same screen as Google Maps View to confirm the cars current state and location before sending the commands.
+
<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 ===
  
        connect_Btn.setOnClickListener(new View.OnClickListener() {
+
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.
            @Override
 
            public void onClick(View v) {
 
                listPairedDevices(v);
 
            }
 
        });
 
        clear.setOnClickListener(new View.OnClickListener() {
 
            @Override
 
            public void onClick(View v) {
 
                try {
 
                    if(!state) {
 
                        mConnectedThread.write("--,\n");
 
                        mMap.clear();
 
                        checkpoints.clear();
 
                        sending_status.setText("Waiting");
 
                    }
 
                    else{
 
                        Toast.makeText(getApplicationContext(),"Stop the car First",Toast.LENGTH_SHORT).show();
 
                    }
 
                }
 
                catch (Exception e)
 
                {
 
                    Toast.makeText(getApplicationContext(),"Connect to Roadster First",Toast.LENGTH_SHORT).show();
 
                }
 
            }
 
        });
 
        stop.setOnClickListener(new View.OnClickListener() {
 
            @Override
 
            public void onClick(View v) {
 
                try {
 
                    mConnectedThread.write("!!,\n");
 
                    state=false;
 
                    move_camera=false;
 
                    car_status.setText("  stopped");
 
                }
 
                catch (Exception e)
 
                {
 
                    Toast.makeText(getApplicationContext(),"Connect to Roadster First",Toast.LENGTH_SHORT).show();
 
                }
 
            }
 
        });
 
        start.setOnClickListener(new View.OnClickListener() {
 
            @Override
 
            public void onClick(View v) {
 
                try {
 
                    mConnectedThread.write("##,\n");
 
                    state=true;
 
                    move_camera=true;
 
                    car_status.setText("  started");
 
                }
 
                catch (Exception e)
 
                {
 
                    Toast.makeText(getApplicationContext(),"Connect to Roadster First",Toast.LENGTH_SHORT).show();
 
                }
 
            }
 
        });
 
        send_cpts.setOnClickListener(new View.OnClickListener() {
 
            @Override
 
            public void onClick(View v) {
 
                try {
 
                    sending_status.setText("....");
 
                for(int i=0;i<checkpoints.size();i++) {
 
                    String cpt="GPS,"+checkpoints.get(i).latitude+","+checkpoints.get(i).longitude+"\n";
 
                    mConnectedThread.write(cpt);
 
                }
 
                sending_status.setText("Sent");
 
                }
 
                catch (Exception e)
 
                {
 
                    Toast.makeText(getApplicationContext(),"Connect to Roadster First",Toast.LENGTH_SHORT).show();
 
                }
 
            }
 
        });
 
  
=== Software Design ===
+
<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>
This app has mainly two activities, The main activity and maps activity.
+
<br/>
  
===Maps Activity===
+
=== Map and Marker Blocks ===
This is the only functional activity for the app and is responsible for the Google Maps and Bluetooth related Tasks. User can also dynamically select multiple checkpoints and send them to the bridge node. This is achieved using java vector and OnMapclickListener setup to read each marker placed by the user.
 
  
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
+
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.
            @Override
 
            public void onMapClick(LatLng latLng) {
 
                int precision = (int) Math.pow(10,6);
 
                double new_latitude = (double)((int)(precision*latLng.latitude))/precision;
 
                double new_longitude = (double)((int)(precision*latLng.longitude))/precision;
 
                LatLng myloc = new LatLng(latLng.latitude, latLng.longitude);
 
                mMap.addMarker(new MarkerOptions().position(myloc).title("Destination"));
 
                mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(myloc,20));
 
                checkpoints.add(new LatLng(new_latitude,new_longitude));
 
                destination_coordinates = "GPS," + new_latitude + "," + new_longitude +"\n";
 
            }
 
        });
 
  
===Bluetooth===
+
<li style="display: inline-block;">[[File: maps_and_markers.jpeg|right|600px|thumb|Map and Marker blocks used in the firebolt app. ]] </li>
The Bluetooth connection is initially set up by reading the id and MAC addresses of the selected device, The available devices are displayed on a listView under the connect button. Once the socket is established, Bluetooth module provides read() and write() API used to communicate.  
 
  
 +
=== Testing and Downloading  ===
  
            if(!mBTAdapter.isEnabled()) {
+
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”.
                Toast.makeText(getBaseContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
 
                return;
 
            }
 
            mBluetoothStatus.setText("Connecting...");
 
            // Get the device MAC address, which is the last 17 chars in the View
 
            String info = ((TextView) v).getText().toString();
 
            final String address = info.substring(info.length() - 17);
 
            final String name = info.substring(0,info.length() - 17);
 
            new Thread()
 
            {
 
                public void run() {
 
                    boolean fail = false;
 
                    BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
 
                    try {
 
                        mBTSocket = createBluetoothSocket(device);
 
                    } catch (IOException e) {
 
                        fail = true;
 
                        Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
 
                    }
 
                    // Establish the Bluetooth socket connection.
 
                    try {
 
                        mBTSocket.connect();
 
                    } catch (IOException e) {
 
                        try {
 
                            fail = true;
 
                            mBTSocket.close();
 
                            mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
 
                                    .sendToTarget();
 
                        } catch (IOException e2) {
 
                            Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
 
                        }
 
                    }
 
                    if(fail == false) {
 
                        mConnectedThread = new ConnectedThread(mBTSocket);
 
                        mConnectedThread.start();
 
                        mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
 
                                .sendToTarget();
 
                    }
 
  
 +
==Bluetooth==
  
The Bridge node sends data in string format with end of line chars, The Bluetooth handler concatenates the received data and waits for the "end of line" before trying to parse it. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node.  
+
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>
  
                    if(readMessage.indexOf("\n")>0) {
+
<br>
                        message = new StringTokenizer(readMessage, "\n");
+
<li style="display: inline-block;">[[File: bluetooth_module.jpeg|right|600px|thumb|The HC-05 bluetooth module. ]] </li>
                        StringTokenizer st;
+
<br>
                        while (message.hasMoreTokens()) {
 
                            st = null;
 
                            received_line = message.nextToken();
 
                            st = new StringTokenizer(received_line, ",");
 
                            try {
 
                                read = st.nextToken();
 
                            } catch (Exception e) {
 
                                continue;
 
                            }
 
                            if (read.compareTo("GPS") == 0) {
 
                                try {
 
                                    LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));
 
                                    waypoint.setText(st.nextToken("\n").replace(",", ""));
 
                                    prev.remove();
 
                                    prev = mMap.addMarker(new
 
                                          MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")
 
                                          .icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));
 
                            if (state || init) {
 
                                        mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));
 
                                        if (current_location.latitude != 0) init = false;
 
                                    }
 
                                } catch (Exception e) {
 
                                }
 
                            } else if (read.compareTo("speed") == 0) {
 
                                try {
 
                                    speed.setText(st.nextToken("\n").replace(",", "") + "m/s");
 
                                } catch (Exception e) {
 
                                }
 
                            } else if (read.compareTo("sens") == 0) {
 
                                try {
 
                                    left.setText(st.nextToken() + "cm");
 
                                    right.setText(st.nextToken() + "cm");
 
                                    center.setText(st.nextToken() + "cm");
 
                                    back.setText(st.nextToken("\n").replace(",", "") + "cm");
 
                                } catch (Exception e) {
 
                                }
 
                            } else if (read.compareTo("comp") == 0) {
 
                                try {
 
                                    compass.setText(st.nextToken());
 
                                    String compass_s=st.nextToken("\n").replace(",", "");
 
                                    compass_raw.setText(compass_s);
 
                                    compass_value =Integer.parseInt(compass_s);
 
                                    prev.setAnchor(0.5f,0.5f);
 
                                    prev.setRotation(compass_value);
 
                                } catch (Exception e) {
 
                                }
 
                            } else if (read.compareTo("dist") == 0) {
 
                                try {
 
                                    String dis=st.nextToken("\n").replace(",", "");
 
                                    distance.setText(dis+"m");
 
                                    //int prog=(int)Float.parseFloat(dis)%200;
 
                                    //progress.setProgress(prog);
 
                                } catch (Exception e) {
 
                                }
 
                            } else if (read.compareTo("mot") == 0) {
 
                                try {
 
                                    rps.setText(st.nextToken());
 
                                    pwm.setText(st.nextToken("\n").replace(",", ""));
 
                                } catch (Exception e) {
 
                                }
 
                            }
 
                            else if(read.compareTo("bat")==0){
 
                                try{
 
                                    battery.setText(st.nextToken("\n").replace(",", "")+"%");
 
                                }catch (Exception e){
 
                                }
 
                            }
 
                      }
 
                        readMessage="";
 
  
=== Technical Challenges ===
+
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.
Given no experience in Android Development, we had to start from the basics about the activities, message passing etc. The initial challenge was to understand the google maps API and generate the API key to access google cloud to implement the map view and markers. Implementing Bluetooth communication required scanning the list of paired devices and acquire the MAC address required to open a socket using the provided API. Fortunately, there are many example implementations to go through. We decided to use a similar line buffer that is used in the Geo node to read the debug data sent from the app, this helped solve the challenge of parsing the group of variables sent by the bridge node by reading from the CAN bus.
 
  
 +
=== 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/>
 
<BR/>
 
<HR>
 
<HR>
Line 1,199: Line 1,419:
  
 
== 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.
 +
 +
 +
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. 
  
* Embedded project are generally single board projects. The mandatory use of CAN bus required a great deal of collaboration, where all board are interdependent and the system design should be robust to make it work every single time, the car is used for its intended purpose.
 
*Unit testing helps in early phase of the  project, where the hardware setup is not ready yet, but one needs to start coding to get ahead of the curve and start building logic. This helps in troubleshooting the hardware as well.
 
  
 
=== Project Video ===
 
=== Project Video ===
  
https://youtu.be/Q24ghJRe9VM
+
https://youtu.be/lGZTV-ZGHd8
  
 
=== Project Source Code ===
 
=== Project Source Code ===
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''
+
https://gitlab.com/ritupatil1/firebolt/-/tree/master
''[https://gitlab.com/srikarreddy.narapureddy/roadster-app  Repository for Android App]''
+
 
 +
https://gitlab.com/Ritika_Beniwal_/firebolt/-/tree/master
  
 
=== Advise for Future Students ===
 
=== Advise for Future Students ===
* Get the hardware modules and test the same with SJ2 (Before the Mid Semester exams). Once this is done, create a PCB and mount devices and then start the extensive software testing. Considering the car is  moving object, temporary connections over bread board and zero PCB might work, but reliability will remain a doubt at the back of the head. Eliminate the same by creating the PCB early. You might even want to iterate to a second PCB, once you are a few weeks into testing and want to change amend previous mistakes/improve existing layout and placements. The time and effort this will save is worth it.
+
* 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.
*Once the hardware is nearing its completion, the Mobile app should be ready in its rudimentary form. Having a hand held debug device is more useful, compared to using PCAN dongle which is great for static testing.
+
* 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.
* The software will take multiple iteration by testing your car in various field scenarios. This is not a project which can be completed a night before demo. Keep a healthy amount of time for testing.
+
* 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.  
* The sole working power socket available in university outside of the university buildings is available on the top floor of the tenth street car garage. This is especially useful when testing in field.
+
*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 ===
 
=== Acknowledgement ===
* Building a hardware project without the availability of a electronics lab of the university which had been shut, due to COVID-19 pandemic tested our resourcefulness to our extremes.Considering the remote nature of course work, resource availability in any shape or form from university was sadly non existent. All the team members should be appreciated for their unwavering enthusiasm to make this a success story.
+
 
* Preet's advice for buying quality hardware parts should be followed to the line.
+
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
 
http://socialledge.com/sjsu/index.php/Industrial_Application_using_CAN_Bus
<Br>
+
 
 +
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]
 +
 
 +
 
 +
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