Difference between revisions of "S20: Tesla Model RC"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Circuit Boards)
(Software Design)
Line 690: Line 690:
 
<u>Ultrasonics and GPIO Interrupts module</u><br/>
 
<u>Ultrasonics and GPIO Interrupts module</u><br/>
  
Ultrasonic sensors are initialized where each sensor has a trigger and echo pin.  A trigger pin is used to initiate ranging from activating the trigger pin for 10 microseconds then setting it back to inactive.  This will release an ultrasonic wave in the air that travels at the speed of sound.  The reflection of the ultrasonic wave is sampled by the echo pin until the falling edge of an interrupt occurs where the time of flight of this wave is calculated from the time the range was initiated from the activation of the trigger.  The ultrasonic ranging calculation is (where tof = time of flight, sos = speed of sound):<br/>
+
Ultrasonic sensors are initialized where each sensor has a trigger and echo pin.  A trigger pin is used to initiate ranging from activating the trigger pin for 10 microseconds then setting it back to inactive.  This will release an ultrasonic wave in the air that travels at the speed of sound.  The reflection of the ultrasonic wave is sampled by the echo pin until the falling edge of an interrupt occurs where the time of flight of this wave is calculated from the time the range (half of the round trip time is obtained from dividing by 2 as the distance is calculated as soon as the ultrasonic wave transmits and reflects from an obstacle) was initiated from the activation of the trigger and the speed of sound for converting to the distance traveled.  The ultrasonic ranging calculation is (where tof = time of flight, sos = speed of sound):<br/>
  
 
ranging calculation in inches = tof * sos / 2 = tof * (13503.9 in/s / 1000000 us) / 2 = tof * 0.00675195 in = (tof / 148.105) in
 
ranging calculation in inches = tof * sos / 2 = tof * (13503.9 in/s / 1000000 us) / 2 = tof * 0.00675195 in = (tof / 148.105) in

Revision as of 22:26, 22 May 2020

Model RC

Contents

Tesla Model RC

Tesla model RC front.jpg Tesla model RC back new.jpg Tesla model RC app LCD.jpg Tesla model RC inside.jpg




Abstract

Tesla Model RC is an electric, battery-powered, self-navigating RC car. The aim is to navigate to the destination set on the Android application by utilizing GPS navigation. The car combines the data received from multiple sensors to perceive its surroundings to avoid obstacles in its path.

Introduction

The project was divided into 5 modules:

  • Bridge and Sensor Controller
  • Motor Controller
  • Geographical Controller
  • Driver and LCD controller
  • Android Application

Team Members & Responsibilities

Team picture.jpg


Profile-Picture.jpeg

  • Salvatore Nicosia Gitlab
    • Motor Controller
    • Geographical Controller
    • System Integration and Testing
    • RC Car Design: 3D Printing


<Member picture>


Bridge Sensor Node


As bio.jpg


Ak bio.jpeg




Schedule

Week# Start Date End Date Task Status
1
  • 03/08/2020
  • 03/15/2020
  • Read previous projects, gather information and discuss among the group members.
  • Distribute modules to each team member.
  • Completed
2
  • 03/16/2020
  • 03/16/2020
  • 03/18/2020
  • 03/17/2020
  • 03/22/2020
  • 03/22/2020
  • Acquire parts: RC Car, Wheel encoders, Ultrasonic Sensors, GPS, Compass, Spare Battery, ESP8266, LCD
  • Define CAN DBC
  • Create a mobile application and define protocol between Network node
  • Completed
  • Completed
  • Completed
3
  • 03/23/2020
  • 03/23/2020
  • 03/23/2020
  • 03/23/2020
  • 03/23/2020
  • 03/23/2020
  • 03/29/2020
  • 03/29/2020
  • 03/29/2020
  • 03/29/2020
  • 03/29/2020
  • 03/29/2020
  • Motor alignment on wheels from finding min/max throttle and steering threshold of Motor node
  • Integrate WiFi driver into Bridge and Sensor node by setting up access points.
  • Integrate GPS and compass into Geographical node and compare functionality to a real GPS module.
  • Integrate ultrasonic drivers into the Sensor node and define maximum distance..
  • Create a WiFi-connected Android App base project and upload it to the git repo.
  • 3D print shell of RC car.
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
4
  • 03/30/2020
  • 03/30/2020
  • 03/30/2020
  • 03/30/2020
  • 03/30/2020
  • 03/31/2020
  • 04/05/2020
  • 04/05/2020
  • 04/05/2020
  • 04/05/2020
  • Work on the Electronic speed controller of the RC car to control the motor and servos.
  • Create circuit boards schematics.
  • Integrate Google Maps API into Android App
  • Establish CoAP server and client
  • Establish connection between the LCD and the Driver node
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
5
  • 04/06/2020
  • 04/06/2020
  • 04/06/2020
  • 04/06/2020
  • 04/06/2020
  • 04/06/2020
  • 04/06/2020
  • 04/06/2020
  • 04/12/2020
  • 04/12/2020
  • 04/12/2020
  • 04/12/2020
  • 04/12/2020
  • 04/12/2020
  • 04/12/2020
  • 04/12/2020
  • Order circuit boards components
  • Assemble components to circuit boards
  • Extensively test circuit boards in two rounds
  • Driver node CAN synchronize, logging, and PCAN dongle test of Sensor node
  • Create RC car base and extra accessories
  • Driver node CAN synchronize, logging, and PCAN dongle test of PID output of the motor node
  • Strip down RC car and mount 3D prints
  • Finish testing and validation of the LCD.
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
  • Completed
6
  • 04/13/2020
  • 04/13/2020
  • 04/13/2020
  • 04/13/2020
  • 04/19/2020
  • 04/19/2020
  • 04/19/2020
  • 04/19/2020
  • Integrate circuit boards and check proper connections to the components and the microcontrollers.
  • Parse client data(Compass/GPS/Sensor) and display on Android App
  • Driver node test obstacle avoidance algorithm
  • Improve Android application User Interface
  • Completed
  • Completed
  • Completed
  • Completed
7
  • 04/20/2020
  • 04/20/2020
  • 04/20/2020
  • 04/26/2020
  • 04/26/2020
  • 04/26/2020
  • Integrate Driver, Geo, Bridge sensor, and Motor nodes.
  • Check for the corner cases of navigation under various conditions.
  • Check the PCAN dongle reading to test CAN communication between all boards.
  • Completed
  • Completed
  • Completed
8
  • 04/27/2020
  • 04/27/2020
  • 04/27/2020
  • 04/27/2020
  • 05/03/2020
  • 05/03/2020
  • 05/03/2020
  • 05/03/2020
  • Test for the proper outdoor drive.
  • Test for the proper LCD display of information during the outdoor drive.
  • Test for the proper state information communication to the driver.
  • Update the wiki page.
  • Completed
  • Completed
  • Completed
  • Completed
9
  • 05/04/2020
  • 05/04/2020
  • 05/10/2020
  • 05/10/2020
  • Test outdoor drive with corner conditions.
  • Make relevant changes to all the nodes and based on testing results.
  • Completed
  • Completed
10
  • 04/11/2020
  • 05/17/2020
  • Test outdoor drive with corner conditions.
  • Final update of all the nodes and its testing
  • Completed
  • Completed
11
  • 05/18/2020
  • 05/18/2020
  • 05/18/2020
  • 05/18/2020
  • 05/24/2020
  • 05/24/2020
  • 05/24/2020
  • 05/24/2020
  • Final Demo
  • Update Gitlab repo with final code.
  • Update test video.
  • Update the wiki page.
  • Completed
  • In progress
  • In progress
  • In progress


Parts List & Cost

Item# Part Desciption Vendor Qty Cost
1 RC Car 1/10 Scale Redcat Racing [1] 1 $99.99 + Tax
2 CAN Transceivers TJA1050 LIVISN [2] 5 $6.39 + Tax
3 GPS Module Built-in Compass Readytosky [3] 1 $28.89 + Tax
4 HC-SR04 Ultrasonic Module ELEGOO [4] 5 $9.98 + Tax
5 HC-020K Wheel Encoder Module Hilitchi [5] 1 $9.99 + Tax
6 ESP8266 WiFi Module DIYmall [6] 1 $6.55 + Tax
7 Extra 7.2V 5000mAh NiMH battery Melasta [7] 1 $29.99 + Tax
8 Micro-USB to USB cable Walmart [8] 4 $4.00 + Tax
9 EL-CP-004 120pcs Multicolored Dupont Wire ELEGOO [9] 1 pack $6.98 + Tax
10 SJTwo Microcontroller SCE at SJSU [10] 4 $160
11 Black PLA Filament Hatchbox [11] 1 $22.99 + Tax
12 120 Ω Resistor Excess Solutions 2 $0.30
13 1 MΩ Resistor Excess Solutions 1 $0.15
13 100 kΩ Resistor Excess Solutions 1 $0.15
14 DB9 Female Connector Right Angle Mount Excess Solutions 1 $0.30
15 2.54 Male Header Strip 36 Pin Excess Solutions [12] 1 $0.36
16 5x7cm Prototype Board uxcell [13] 3 $7.09 + Tax
17 2.54mm JST-XHP 2 Pin Housing with 2.54mm JST XH Female Connector QLOUNI [14] 8
18 12mm Waterproof Push Button Momentary On Off Switch PP-NEST [15] 1
19 #22 Gauge Wire Elenco [16] As needed
20 LM2596 Buck Converter DC to DC D-PLANET [17] 1 $5.95 + Tax
21 11 in. x 14 in. x .093 in. Acrylic Sheet The Home Depot [18] 1 $6.67 + Tax
22 20x4 LCD Display Module LCD [19] 1 $29.99
23 6-32 Brass Motherboard Standoffs Hantof [20] 36 $14.58 + Tax
24 Metallic Aluminium Spray Paint Walmart [21] 1 $3.96 + Tax
25 Metallic Dark Metal Spray Paint Walmart [22] 1 $4.96 + Tax
26 Plastidip Black Spray Paint Walmart [23] 1 $5.82 + Tax
27 Total $


Circuit Boards

Two circuit boards were designed to reduce the amount of wires and the necessity to use external power banks to delivery power to various modules. Both boards use #22 gauge wire which provides sufficient current flow to all the modules. The CAN board schematic shown below groups all the CAN transceivers in one a single place so that the +5V power is shared among the CAN transceivers and are all close to the CAN bus. The power delivery board schematic shows how the power is taken from the main battery of the RC car and goes through a DC-DC buck converter to reduce the voltage to +5V from +7.2V. The +5V output of the buck converter delivers power to the CAN board, four SJTwo boards, 5 ultrasonic sensors, and wheel encoder. The output of the ESC in addition to powering the motor it also power the servo. Lastly, the power deliver board has a voltage reading point to monitor the voltage of the battery which is connected to the bridge sensor node.

CAN Bus Board & Power Delivery Schematic

Below are the two boards assembled. The CAN Bus board uses two 120Ω termination resistors, 2.54 male headers in which one of the them is connected to a DB9 connector to monitor and debug the state of the car through busmaster.


CAN Bus Board

The power deliver board uses 2.54mm male headers for easier connection to the various modules and 4 JST 2-pin female connector to connect the micro USB cables that power the SJTwo boards.


Power Delivery Board




Integrated System

In figure shown below, is the integrated system connected to the SJTwo boards, CAN board, power deliver board, wheel encoder, motor, servo, GPS / Compass, and ultrasonic sensors. The WiFi module is directly placed on the dedicated pins of the SJTwo board of the bridge sensor node.

Integrated System




3D Printed Parts

Cybertruck 3D Model

This 3D model was modified and rescaled to fit the chassis of our car. Credit goes to the designer of the model in which can be found on thingiverse at this link. The shell was sliced into 6 parts to fit the building plate of the printer and make it easier to print the parts with minimal supports. Shown below are pictures of the 3D model as well as the printed and finished result of the shell.

Tesla model RC shell front.png Tesla model RC shell back.png Tesla model RC shell printed.jpg Tesla model RC shell primer.jpg Tesla model RC shell front finished.jpg Tesla model RC shell back finished.jpg

Shell Supports

These supports were designed to allow the shell to sit in place on the chassis by using 6 small magnets for each of the four corners. 4 magnets are inserted in each of these supports and 2 are attached in each corner to the plexiglass surface where the boards are mounted.

Tesla model RC shell support.png Tesla model RC shell support printed.jpg

Ultrasonic Sensor Supports

The ultrasonic support 3D model was slightly resized to fit the HC-SR04 sensor. Credit goes to the designer of the model which can be found on thigiverse at this link.

Tesla model RC ultrasonic mount.png Tesla model RC ultrasonic mount printed.jpg



CAN Communication

<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.>

Hardware Design

<Show your CAN bus hardware design> High Level Hardware Diagram

DBC File

https://gitlab.com/tesla-model-rc/sjtwo-c/-/blob/dev/dbc/tesla_model_rc.dbc



Bridge Sensor ECU

https://gitlab.com/tesla-model-rc/sjtwo-c/-/tree/dev/projects/sensor
https://gitlab.com/tesla-model-rc/esp8266-coap-server

Hardware Design

Figure #. Bridge Sensor Node
Table #. Bridge-Sensor Node Pinout
SJTwo Board Module Description Protocol/Bus
P4.28 (TX3) RX (ESP8266) ESP8266 Rx data line UART 3
P4.29 (RX3) TX (ESP8266) ESP8266 Tx data line UART 3
P0.6 Trigger (Ultrasonic) Front sensor
P2.0 Echo (Ultrasonic) Front sensor
P0.7 Trigger (Ultrasonic) Rear sensor
P2.1 Echo (Ultrasonic) Rear sensor
P0.8 Trigger (Ultrasonic) Left sensor
P2.2 Echo (Ultrasonic) Left sensor
P0.9 Trigger (Ultrasonic) Right sensor
P2.4 Echo (Ultrasonic) Right sensor
P0.25 (ADC2) Voltage reading (S) Output of voltage divider
P0.1 (SCL1) CAN transceiver (Tx) CAN transmit CAN
P0.0 (SDA1) CAN transceiver (Rx) CAN receive CAN
5V (Ultrasonics) Vcc
GND GND Ground

Software Design

Bridge and Sensor Node

The Bridge and Sensor node interfaces with four ultrasonic sensors (front, back, left, and right) and the ESP8266 Wifi module for bridging connection with a mobile application to control the car and display ultrasonic ranging diagnostics.

Sensor Node and CAN Bus Periodics Handler module

The CAN bus handler has periodicially running functions specific to a task and is called in the Periodics module. Debug messages that may be enabled are sent at 1Hz. The handler of all incoming messages (including Wifi messages) is parsed in 10Hz, along with MIA management and the transmission of CAN messages. Unique to this node is the 100Hz functions that initiates and records Ultrasonic sensor rangings at this rate along with the Wifi character parser which fills the message buffer. This module wraps the Sensor Node module.

The Sensor Node module creates the sensing messages that are sent over the CAN bus. These messages include battery voltage level and all four ultrasonic ranging distances. Furthermore, the GPS longitude and latitude value and start/stop state changes parsed from Wifi transmissions are sent as well. This module handles MIA messages of the Driver node's heartbeat message. On not receiving the Driver node's heartbeat message, this module will not send messages over CAN bus and brighten LED0 indicating the node is not synchronized with the Driver node.

Wifi module

The Wifi module initializes UART channel 3 peripheral and the line buffer module. The line buffer module is used for parsing and handling Wifi messages transmitted over UART from the ESP8266. The Wifi line buffer has 128 bytes of allocated space and is filled at a rate of 100Hz from the UART queue. Then, at 10Hz the Wifi line buffer handler parses all lines found in the line buffer based upon the identifier found from a new-line delimiter sequence of messages. These messages are specified in the ESP8266 section and set variables received from the mobile application to messages over CAN bus. The Wifi module also sends all four ultrasonic ranging values to the ESP8266 over UART allowing the mobile application to query ultrasonic diagnostics.

Battery Tracking module

The Battery Tracking module is simply an ADC that receives the battery output as input. The ADC has a voltage reference of 3.3V and has a 12 bit resolution. Thus, the ADC conversion is 3.3V / 4095. The voltage divider set for the receiving battery voltage is a divider where R1 = 1M ohm and R2 = 100k ohm. Thus, the received ADC binary representation along with the ADC conversion value and the voltage multiplier gives the current battery voltage and is sent over the CAN bus.

Ultrasonics and GPIO Interrupts module

Ultrasonic sensors are initialized where each sensor has a trigger and echo pin. A trigger pin is used to initiate ranging from activating the trigger pin for 10 microseconds then setting it back to inactive. This will release an ultrasonic wave in the air that travels at the speed of sound. The reflection of the ultrasonic wave is sampled by the echo pin until the falling edge of an interrupt occurs where the time of flight of this wave is calculated from the time the range (half of the round trip time is obtained from dividing by 2 as the distance is calculated as soon as the ultrasonic wave transmits and reflects from an obstacle) was initiated from the activation of the trigger and the speed of sound for converting to the distance traveled. The ultrasonic ranging calculation is (where tof = time of flight, sos = speed of sound):

ranging calculation in inches = tof * sos / 2 = tof * (13503.9 in/s / 1000000 us) / 2 = tof * 0.00675195 in = (tof / 148.105) in

Average Buffer module

Ultrasonic smoothing is done by averaging a set amount of past ultrasonic values and sending out the averaged value over the CAN bus. This averages ranges that may be invalid due to an outlier. Ranges are collected at a 100Hz rate and are sent over CAN bus through a 10Hz function using a 10 slot sliding window average buffer where this buffer will be filled before the message is sent over CAN bus. A low-pass filter is implemented where zeroed values are replaced with the average value from the sliding window buffer. Zeroed ranges is a special case where a sensor receives ultrasonic waves immediately after the start of a trigger caused by scattered reflection of other ultrasonic waves in the air.

ESP8266

Bridging between ESP8266 and mobile application is done through the creation of an access point on the ESP8266. Furthermore, the ESP8266 opens a server socket through CoAP allowing other CoAP clients to transmit or receive data from a created resource (/topics). The mobile application serves as the CoAP client and currently performs:

(GET) /heartbeat will receive string: "tmrc:heartbeat"
(GET) /getRadars will receive string: "aa,bb,cc,dd" where a is front radar, b is left radar, c is right radar, and d is back radar
(PUT) /setStatus will send string - either "$stop\n" or "$start\n"
(PUT) /setCoordinates will send coordinates as string - i.e. "#Sxxx.xxxxxx,Syyy.yyyyyy\n" where S is the sign and x is latitude and y is longitude

/getRadars resource will update through UART from a microcontroller. The string must follow the format: "^%02,%02,%02,%02" where '^' is the identifier for setting this resource. This length is also fixed where each radar data must have a width of no more than 2.
/setStatus resource has an identifier of '$', while /setCoordinates resource has an identifier of '#'. Both resources require appending a new line character at the end of string. This is essential for parsing strings on microcontroller side as the ESP8266 echoes received data over UART.

Project Setup
This project is built with ESP8266 RTOS SDK for programming the ESP8266. FreeRTOS, UART, Wifi with CoAP libraries are fully utilized in this project.
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.

Wifi Access Point module
ESP8266 opens an access point for other wireless devices to connect too. This access point follows adaptation of this example:
https://github.com/espressif/ESP8266_RTOS_SDK/tree/master/examples/wifi/getting_started/softAP.

UART Configuration module
UART is simply transmitted over UART0 TX/RX pins. This example is integrated.

CoAP Server module
CoAP server would startup a daemon task, create resources and receive data from CoAP clients and transmit data to CoAP clients. This server follows adaptation of a couple examples:

https://github.com/espressif/ESP8266_RTOS_SDK/tree/master/examples/protocols/coap_server
https://github.com/obgm/libcoap-minimal/blob/master/server.cc
https://github.com/obgm/libcoap/blob/develop/examples/coap-server.c

The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained networks in the Internet of Things.
The protocol is designed for machine-to-machine (M2M) applications such as smart energy and building automation.
Please refer to RFC7252 for more details.

Technical Challenges

Ultrasonic Sensors Smoothing and Filtering

The average buffer module had to be implemented as ultrasonics ranging values from a fixed distance had varying values. The average buffer module smoothed out ranging values by using an average sliding window of the last 10 ranges as the value sent over the CAN bus. In parallel to this average buffer, a low-pass filter is implemented where a value of zero would be replaced by the average of the sliding window buffer. This further smoothed the ultrasonic ranges by removing values that occurred upon reception of a radar wave right after a range is initiated through the trigger pin.

ESP8266 Flashing

Figure #. Software Flow diagram

When flashing the ESP8266 be extremely observant about which mode the SPI should be configured. Different vendors will have SPI flash modes.



Motor ECU

https://gitlab.com/tesla-model-rc/sjtwo-c/-/tree/dev/projects/motor_node

Hardware Design

Figure #. Motor Node
Table #. Motor Node Pinout
SJTwo Board Module Description Protocol/Bus
P2.0 (PWM1) Motor (S) Control signal for motor speed
P2.4 (PWM5) Servo (S) Control signal for servo steering
P0.22 (PWM1) Wheel encoder (Out) Output signal of wheel encoder
P0.1 (SCL1) CAN transceiver (Tx) CAN transmit CAN
P0.0 (SDA1) CAN transceiver (Rx) CAN receive CAN
6V Motor and Servo Vcc
5V Wheel encoder Vcc
GND GND Ground
Wheel Encoder
Figure #. Wheel Encoder

Software Design

<List the code modules that are being called periodically.>

Technical Challenges

< List of problems and their detailed resolutions>



Geographical ECU

https://gitlab.com/tesla-model-rc/sjtwo-c/-/tree/dev/projects/geo_node

Hardware Design

The geographical controller is interfaced to the readytosky GPS with built-in compass and a CAN transceiver as shown in figure #. The readytosky module uses the Ublox NEO-M8N GPS which provides great accuracy and customization. In addition, it uses the 3-Axis compass HMC5883L magnetometer which provides an 1 to 2 degrees compass heading accuracy. The Ublox GPS module communicates with SJTwo board via UART whereas the HMC5883L communicates with the SJTwo board via I2C. The CAN transceiver is interfaced to the CAN Bus and allows reception and sending of CAN messages via the CAN pins on the SJTwo board.

Figure #. Geo Node
Table #. Geographical Node Pinout
SJTwo Board GPS/Compass Module Description Protocol/Bus
P4.28 (TX3) RX (Yellow Wire) Ublox M8N Rx data line UART 3
P4.29 (RX3) TX (Green Wire) Ublox M8N Tx data line UART 3
P0.10 (SDA2) SDA (White wire) HCM5883L SDA I2C 2
P0.10 (SCL2) SCL (Orange wire) HCM5883L SCL I2C 2
P0.1 (SCL1) CAN transceiver (Tx) CAN transmit CAN
P0.0 (SDA1) CAN transceiver (Rx) CAN receive CAN
Vcc 3.3V Vcc (Red wire) Vcc
GND GND (Black wire) Ground

Software Design

Overview

The geographical node calls periodically the following code modules:

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

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

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

GPS

Initialization

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

Configuration

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

Parsing NMEA GNGGA messages

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

GPS lock

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

Compass

Initialization

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

Heading degree computation

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

Pitch and Roll:

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

Tilt compensated magnetic sensor values for x and y:

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

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

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

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

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

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

Heading angle

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

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

Geological.c module

Initialization

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

Run once at 10Hz

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

Bearing Angle computation

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

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

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

Checkpoints Algorithm

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

Figure #. Checkpoints Algorithm Figure #. Checkpoints North Garage


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

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

Technical Challenges

GPS (Ublox Neo-M8N)

  • Problem:The enabled 2-stop bits in uart.c were causing communication problems between the SJTwo MCU and the Ublox M8N GPS module.
    • Solution:To solve the 2 stop bits configuration was disabled in uart.c in the uart__init() function as shown in figure # and issue was solved.


Figure #. 2-stop-bit configuration


  • Problem:GPS module did not retain configurations and were lost after being powered off for many hours going back back to default settings. This problem was crucial since it was causing the SJ2 to parse the latitude and longitude incorrectly from other messages other than NMEA GNGGA.
    • Solution: To solve this configuration problem u-center which is an interface for the GPS Ublox module was used to read which strings the program sends over UART to configure the GPS module. This solution was implemented in the gps.c module creating a function called gps__private_configure_for_nmea_gngga() in which holds a char array with the hex representation of the configurations needed to disable all of the NMEA messages except GNGGA. This function then sends this configuration values back to the GPS module over UART and the GPS module responds back with an ACK message (8μ.......) from every configuration message meaning that the configurations were successfully applied as shown in figure #. The function gps__private_configure_for_nmea_gngga() could not be called in the periodic_callbacks__initialize() function has it required more time to properly configure the GPS. As a solution, a bool flag indicating that the configuration was done was used along with calling gps__private_configure_for_nmea_gngga() in the gps_run_once_10Hz() to allow it properly configure the GPS module.


Figure #. GPS Module NMEA Configuration


Compass (HMC5883L 3-Axis Magnetometer)

  • Problem:SJTwo MCU could not detect the slave address of the HMC5883L magnetometer on the I2C Bus 2.
    • Solution:Upon reading the HMC5883L datasheet it was mentioned that it works at 400KHz. However, this was not the case as changing the speed in peripherals__init.c module from 400KHz to 100KHz solved the issue and the SJTwo board successfully detected the HMC5883L 3-Axis Magnetometer. In Figure # is shown the function a long with change it was made. In addition, changing the speed did not affect the other modules using I2C Bus 2.


Figure #. peripherals__init.c


  • Problem:Compass heading degree true north was off by about 90 degree when compared to the compass of smart phone. This problem was due the fact the compass had to be completely flat to show proper values. In addition, the default calibration seemed also to be a problem in providing an accurate heading degree a long with hard iron and soft iron interferences.
    • Solution:To solve these problems a function to calibrate the compass was implemented in which calculates offset and scale correcting for hard iron and soft iron interferences respectively. The process to calibrate consisted in turning the compass at different angles to collect as many sample points as possible and store offsets values of x and y axes in const variables which were then used in the equations to compute the heading degree. Although this corrected some of the imprecision problems, not having the compass completely flat still provided results that were not precise. To solve this issue the compass was compensated for tilt by using the built-in accelerometer of the SJTwo board which provides roll and pitch and the tilt compensation algorithm described at this link. The challenge in making this work properly was that the axes of the magnetometer and the axes of the accelerometer need to be perfectly aligned. However, after finalizing the place of the compass on the RC car it was fairly easy to align the axes. The tilt compensation system for the compass is shown in figure #. After including the tilt compensation algorithm the compass heading degree was off by 1-2 degrees when tilted in all directions drastically improving the accuracy from non-compensated in which the heading was off by 60-90 degrees when the compass was not held flat.


Figure #. Tilt Compensated Compass System


  • Problem:Compass heading degree was decreasing when turning clock-wise rather then increasing.
    • Solution:To solve this problem, the Azimuth rather then being calculated as atan2(Y / X) was calculated as atan2(X / Y). This fixed the Azimuth orientation however, North degree was shown as 180 degrees which was incorrect. Finally to compensate for this, π was subtracted from the Azimuth = atan2(X / Y) - π to show the correct decimal degree for true North which is 0 degrees.




Driver Controller & LCD

The driver node is the heart of the designed RC car. It receives appropriate messages from the bridge-sensor node and geo node and processes the signals before sending speed and steering values to the motor node.

https://gitlab.com/tesla-model-rc/sjtwo-c/-/tree/dev/projects/driver_controller_node

Hardware Design

Figure #. Driver Node
Table #. Driver Node Pinout
SJTwo Board LCD Module Description Protocol/Bus
P4.28 (TX3) RX LCD Rx data line UART 3
P4.29 (RX3) TX LCD Tx data line UART 3
P0.1 (SCL1) CAN transceiver (Tx) CAN transmit CAN
P0.0 (SDA1) CAN transceiver (Rx) CAN receive CAN
Vcc 3.3V Vcc (Red wire) Vcc
GND GND (Black wire) Ground

Software Design

  • LCD display
    • The LCD is used to display a few important signal values, which will help us monitor the car behavior when it's moving.
    • The communication with LCD is established using UART.
    • We have used a 20x4 LCD whose behavior was to print individual lines at a time.
    • Three screens were designed for the LCD depending on the state of the car.
    • The first screen displayed all node heartbeat values. The car will wait on this screen if any one of the node heartbeats is zero.

Technical Challenges

< List of problems and their detailed resolutions>



Mobile Application

https://gitlab.com/tesla-model-rc/mobile-app-CoAP-client

Figure #. Software Flow diagram Figure #. Software Flow diagram

Application Communication

Our App communicates with the Bridge/Sensor node through WiFi using the Constrained Application Protocol (CoAP). CoAP protocol has the benefits of transmitting smaller message packets since its underlying transport is UDP. CoAP works extremely well for point to point communication and doesn't require the full feature sets from TCP transportation.

Because our App was written in Java, requirements were set such that the CoAP library to be imported must also be written in Java to be compatible with the App. After days of research we found several Java candidates of this protocol. Californium is a library that is constantly being updated and has the most documentation and most active community. WS4D was also a strong candidate because of its simple interface design. We chose WS4D over Californium because WS4D provides an interface for a CoAP Client that gave us the most flexibility on how we connect to end points and send/receive data.

Pros and Cons
  • The ESP8266 WiFi module was able to communicate with the App over very long distances. We were able to send POST messages from approximately 50 meters away. However power consumption on the App from the frequent message requests were draining the battery on the phone faster than normal. Bluetooth and Bluetooth LE has the advantage of being able to drain less power and run for longer periods of time on the App as well as the RC car.
  • The length of the payload, or response to a GET request, has a maximum length of 16 bits. Any string data before being decoded, must fit this requirement. If a message fails to reach its destined end point, CoAP protocol will attempt to resend the message three times, before sending a failure response. One problem that arose was sending GET requests without verifying connection to the ESP8266 server. The buffer of unsent messages overflowed causing the Bridge node to receive unintentional error messages.
  • Connecting to the WiFi Server was extremely easy. The network SSID and WPA2 key were hard coded parameters supplied to WifiManager object. You could also save the network on your phone as you would with your home WiFi. All the user would have to do is enable WiFi, since on start up, the app will disable current WiFi connections. If the auto-connect option for the network is checked, you would be able to instantly connect to the 'tesla_model_rc' access point.

One cool feature was that up to 3 phones could connect to the car at the same time and each send "start","stop", or send GPS coordinates.

Application Design

Three fragments were created. Main Fragment, Sensor Fragment, and Map Fragment. The Sensor and Map fragment were embedded inside the Main Fragment. The design decision behind this was so that the Main fragment could easily access any layout resource defined in the .xml files of the Map fragment and Sensor Fragment. A TabLayout was used to switch between the Map fragment and Sensor Fragment. Each fragment had an Activity associated with its respective fragment. In the background, a Service is running. A Service must be bound to an application, in our case it was bound to the MainActivity and starts running when the app is opened. Its sole function is to obtain the CoAP Client instance and send GET requests to the /getRadars resource and /heartbeat resource at a frequency of 10hz.

Software Design

Figure #. Software Flow diagram

Technical Challenges

  • I had no prior experience programming an Android App, let alone having any experience in dealing with network applications. The main challenges I had were not realizing the difference between a Fragment and an Activity. I had created my Fragments without realizing they needed to exist within an Activity, so when my onClick methods for buttons weren't registering, it was because there was no underlying Activity attached with the Fragment. I would suggest to have a getInstance method for all the Fragments so that different Fragments can access or call different methods.
  • I also had a problem with the Progress bars not updating based off the sensor values from the Sensor node. Solution was to update the Progress bars inside a handler that accessed the main UI thread.
  • There was a problem with the App not functioning properly on different Android Devices. Some buttons would not show up. I realized there are some button attributes in the layout file that caused this bug.
  • Stackoverflow will be your best friend and make sure to consider every single answer, even the ones wit 0 upvotes.

Future Advice

Before even touching any Android Studio code, read the following documents:

If the App requires a periodic task such as sending GET requests, I recommend to use a Service. It doesn't instantiate a new thread and runs off the main thread.

You can verify that you can query POST/GET messages by creating a Server on the main thread and a Client on another thread within the same App. On the main thread, create a resource and an arbitrary payload value for that resource. The newly created thread acting as the Client should send a GET request to the Server running on the main thread and be able to receive the arbitrary payload value. The very first time I connected to the ESP8266, communication worked perfectly because I was able to verify it beforehand.





Conclusion

<Organized summary of the project>

<What did you learn?>

Project Video

Project Source Code

Advise for Future Students

  • Communication is key. Every member should know the progress of every other member. What they are working on, how they are doing, and progress updates in general. Bi-Weekly meetings of at least 10 minutes between all group members would be extremely beneficial. Be proactive and ask your teammates for advice on any implementation detail. All members should know the basic functionality of all the modules. If you think you are done with your part, you aren't. There is always room for improvements and don't stop there. Ask other members if they need assistance.


Acknowledgement

References

Bridge Sensor ECU

Motor ECU

Geographical ECU

Driver Controller and LCD

Mobile Application