Difference between revisions of "S21: (RC)^2"
Proj user10 (talk | contribs) (→Technical Challenges) |
Proj user10 (talk | contribs) (→OLED Hardware Design) |
||
Line 619: | Line 619: | ||
=== OLED Hardware Design === | === OLED Hardware Design === | ||
− | The hardware design of the OLED module was very straightforward as the physical display uses i2c to communicate to the SJ2Board. We needed to determine which board the OLED should be extended from, and we thought it would be best to extend it from the driver node to be able to have access to what the driver itself is receiving from the CAN bus. | + | The hardware design of the OLED module was very straightforward as the physical display uses i2c to communicate to the SJ2Board. We needed to determine which board the OLED should be extended from, and we thought it would be best to extend it from the driver node to be able to have access to what the driver itself is receiving from the CAN bus. Below is an image of the OLED module that we used. |
− | |||
+ | [[File:OledImage.jpg|200px|left|alt text]] | ||
=== OLED Software Design === | === OLED Software Design === |
Revision as of 02:59, 29 May 2021
Contents
(RC)2
(RC)2 <Add Pictures of it here!>
Abstract
Team (RC)² built an RC car capable of navigating to a destination controlled by an Android application while avoiding obstacles that may be in its path. The RC car is composed of various nodes that each have a specific task such as reading sensor data, controlling the motor, and attaining compass values. These individual nodes communicate and share pertinent information regarding the car’s operation with each other over a CAN bus.
Introduction
The project was divided into five main components that were important to the RC car as a whole:
- Sensor Node
- Motor Node
- Geographic Controller
- Communication Bridge/OLED
- Driver Node
Team Members & Responsibilities
<Team Picture>
Gitlab Project Link - https://gitlab.com/rc-2/sjtwo-c
- Sensor
- Huy - https://gitlab.com/vyhuy2004
- Prabjyot - https://gitlab.com/PrabjyotObhi
- Driver
- Motor
- Jesse - https://gitlab.com/JessePhams
- Michael - https://gitlab.com/mwmichaelwang
- Geographical
- Brian - https://gitlab.com/Brian1234132
- Arun - https://gitlab.com/arunhiremath92
- Communication Bridge Controller & LCD
- Prabjyot - https://gitlab.com/PrabjyotObhi
- Arun - https://gitlab.com/arunhiremath92
Schedule
Week# | Start Date | End Date | Task | Status |
---|---|---|---|---|
1 | 03/01/2021 | 03/07/2021 |
|
Complete |
2 | 03/08/2021 | 03/14/2021 |
|
Complete |
3 | 03/15/2021 | 03/21/2021 |
|
Complete |
4 | 03/22/2021 | 03/28/2021 |
|
Complete |
5 | 03/29/2021 | 04/04/2021 |
|
Complete |
6 | 04/05/2021 | 04/11/2021 |
|
Complete |
7 | 04/12/2021 | 04/18/2021 |
|
Complete |
8 | 04/19/2021 | 04/25/2021 |
|
Complete |
9 | 04/26/2021 | 05/02/2021 |
|
Complete |
10 | 05/03/2021 | 05/09/2021 |
|
Complete |
11 | 05/10/2021 | 05/16/2021 |
|
Complete |
12 | 05/17/2021 | 05/23/2021 |
|
Complete |
13 | 05/24/2021 | 05/26/2021 |
|
Complete |
Parts List & Cost
TODO: Check Drive and add to this table
Item# | Part Desciption | Vendor | Qty | Cost |
---|---|---|---|---|
1 | RC Car | Traxxas | 1 | $129.99 |
2 | CAN Transceivers MCP2551-I/P | Microchip [2] | 8 | Free Samples |
3 | GPS Module | Adafruit [3] | 1 | $59.99 |
4 | Compass | Adafruit [4] | 1 | $14.95 |
5 | ESP8266 (WiFi) | DIYmall [5] | 1 | $14.95 |
6 | HC-020K (Wheel Encoder) | Hilitchi [6] | 1 | $8.99 |
7 | URM09 Ultrasonic Sensor (I²C) | DFRobot [7] | 4 | $12.90 |
8 | SJ2 Board Microcontroller | SCE [8] | 5 | $250.00 |
9 | Male/Female Headers | DEPEPE [9] | 1 | $5.00 |
10 | Screw Terminal Block Connectors | DZGGI [10] | 1 | $7.99 |
11 | CR1220 Lithium Battery | Energizer [11] | 1 | $5.90 |
Printed Circuit Board
CAN Communication
Priority Logic:
- Our two highest priority signals are DRIVE_STOP and DRIVE_START, and we prioritized stopping the car over starting the car as a matter of safety.
- GPS_DESTINATION_LOCATION is the next highest signal because we would need to have a valid location to be able to properly navigate the car.
- SONAR_VALUES has a priority right below GPS_DESTINATION_LOCATION because once the destination is set, the car would need to read sensor data to avoid potential obstacles.
- COMPASS_HEADING_DISTANCE would be the signal with a priority below the SONAR_VALUES signal as the car would need a proper heading in order to navigate to a destination.
- MOTOR_VALUE is the signal sending from Driver Node to the Motor Node to actuate the car
- The signals with the lowest priority are those that we used in our debugging process over Busmaster.
Missing-In-Action Management:
- Driver: stop the car when missing the Sensor information when the frame is missing for more than 500ms
- Motor: straighten the car out and stop the car
- Geo: <insert version>
Hardware Design
Our initial CAN bus was based on a breadboard that contained a lot of jumper/dupont wires. This design was sufficient for testing purposes as we worked to meet the in-class checkpoints; however, as we developed our RC car, we realized that a handful of connections were troublesome to the development of the car. As opposed to continuously rewiring and checking connections, we decided to invest time into PCB design to minimize connections and fix hardware issues. Below is a before and after comparison of our RC Car.
DBC File
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_: DBG DRIVER IO MOTOR SENSOR GEO BRIDGE BO_ 101 DRIVE_STOP: 1 BRIDGE SG_ DRIVE_STOP : 0|8@1+ (1,0) [0|0] "" DRIVER BO_ 102 DRIVE_START: 1 BRIDGE SG_ DRIVE_START : 0|8@1+ (1,0) [0|0] "" DRIVER BO_ 121 GPS_DESTINATION_LOCATION: 8 BRIDGE SG_ DEST_LATITUDE : 0|28@1+ (0.000001,-90.000000) [-90|90] "deg" GEO SG_ DEST_LONGITUDE : 28|29@1+ (0.000001,-180.000000) [-180|180] "deg" GEO BO_ 131 SONAR_VALUES: 8 SENSOR SG_ SONAR_VALUES_left : 0|8@1+ (1,0) [0|150] "cm" DRIVER SG_ SONAR_VALUES_right : 8|8@1+ (1,0) [0|150] "cm" DRIVER SG_ SONAR_VALUES_front : 16|8@1+ (1,0) [0|150] "cm" DRIVER SG_ SONAR_VALUES_back : 24|8@1+ (1,0) [0|150] "cm" DRIVER BO_ 141 COMPASS_HEADING_DISTANCE: 8 GEO SG_ HEADING : 0|12@1+ (0.1,0) [0|359.9] "deg" DRIVER,BRIDGE SG_ BEARING : 12|12@1+ (0.1,0) [0|359.9] "deg" DRIVER,BRIDGE SG_ DISTANCE : 24|17@1+ (0.01,0) [0|0] "m" DRIVER,BRIDGE BO_ 151 MOTOR_VALUES: 3 DRIVER SG_ MOTOR_VALUES_speed : 0|8@1+ (1,-25) [-25|25] "kph" MOTOR SG_ MOTOR_VALUES_steering : 8|6@1+ (0.1,-2.1) [-2.1|2.1] "deg" MOTOR BO_ 161 MOTOR_VALUES_TO_DRIVER: 3 MOTOR SG_ MOTOR_VALUES_TO_DRIVER_speed : 0|8@1+ (1,-25) [-25|25] "kph" DRIVER BO_ 171 GPS_DESTINATION_REACHED: 1 GEO SG_ DESTINATION_REACHED : 0|1@1+ (1,0) [0|1] "bool" DRIVER,BRIDGE BO_ 181 GPS_RAW_DATA: 8 GEO SG_ CURR_LATITUDE : 0|28@1+ (0.000001,-90.000000) [-90|90] "deg" BRIDGE SG_ CURR_LONGITUDE : 28|29@1+ (0.000001,-180.000000) [-180|180] "deg" BRIDGE SG_ GPS_QUALITY : 57|2@1+ (1,0) [0|2] "val" BRIDGE BO_ 182 COMPASS_ACCEL_RAW_DATA: 6 GEO SG_ ACCEL_X : 0|16@1+ (0.01,-162.01) [-162.01|162.01] "ms^2" BRIDGE SG_ ACCEL_Y : 16|16@1+ (0.01,-162.01) [-162.01|162.01] "ms^2" BRIDGE SG_ ACCEL_Z : 32|16@1+ (0.01,-162.01) [-162.01|162.01] "ms^2" BRIDGE BO_ 183 COMPASS_MAG_RAW_DATA: 6 GEO SG_ MAG_X : 0|16@1+ (0.01,-162.01) [-162.01|162.01] "mT" BRIDGE SG_ MAG_Y : 16|16@1+ (0.01,-162.01) [-162.01|162.01] "mT" BRIDGE SG_ MAG_Z : 32|16@1+ (0.01,-162.01) [-162.01|162.01] "mT" BRIDGE BO_ 191 DRIVER_HEARTBEAT: 1 DRIVER SG_ DRIVER_HEARTBEAT_cmd : 0|8@1+ (1,0) [0|0] "" SENSOR, MOTOR, GEO 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_ 191 "Sync message used to synchronize the controllers"; CM_ SG_ 191 DRIVER_HEARTBEAT_cmd "Heartbeat command from the driver"; BA_DEF_ "BusType" STRING ; BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0; BA_DEF_ SG_ "FieldType" STRING ; BA_DEF_DEF_ "BusType" "CAN"; BA_DEF_DEF_ "FieldType" ""; BA_DEF_DEF_ "GenMsgCycleTime" 0; BA_ "GenMsgCycleTime" BO_ 100 1000; BA_ "GenMsgCycleTime" BO_ 200 50; BA_ "FieldType" SG_ 100 DRIVER_HEARTBEAT_cmd "DRIVER_HEARTBEAT_cmd"; VAL_ 100 DRIVER_HEARTBEAT_cmd 2 "DRIVER_HEARTBEAT_cmd_REBOOT" 1 "DRIVER_HEARTBEAT_cmd_SYNC" 0 "DRIVER_HEARTBEAT_cmd_NOOP" ;
Sensor ECU
The sensor node is responsible for gathering information from the 4 surrounding sensors. Our team decided to keep the sensor node by itself as avoiding obstacles is more critical than other tasks in our design. Thus, keeping an ECU free of any other task and only responsible for gathering sensor data and push it onto the CAN bus is our solution for a worry-free sensor reading
Hardware Design
1. CAN Transceiver
- This module will be used to communicate with the Driver Node to send data sensor values through CAN communication protocol. The CAN transceiver will be powered by a +3.3V source with its Transmit Line (Tx) connected to GPIO Pin P0.1 and its Receive Line (Rx) connected to GPIO Pin P0.0.
2. Ultrasonic Sensor
- Getting the right distance requires some research on each team depends on your project requirement. Our team settle for a no-frill Ultrasonic Sensor from DFRobots due to its easy implementation and its cost-effective. As Preet always mentioned in class: Think like an engineering being paid $100/hour, don't waste your time on cheap part that can take you way too long to implement. This sensor from DFRobots have different communication protocol that your team can choose based on your own experience. We want to focus on other node so we decided to choose the I2C package that makes configuring and reading value sensor from this node simple.
Software Design
The Sensor Node consists of 3 main modules: can_bus_message_handler, ultrasonic_system, and ultrasonic_sensor
1. The ultrasonic_sensor module This module is written to provide the user with access to our sensor. I simplified the driver to provide users with only 3 main functions:
- 'void ultrasonic_sensor__init_i2c_port(i2c_e i2c_number)'
- Initialize the i2c port that is used for the sensors
- 'void ultrasonic_sensor__enable_burst_mode(i2c_e i2c_number, uint8_t sensor_address)'
- Enable burst measuring mode for our sensor
- 'uint8_t ultrasonic_sensor__get_value(i2c_e i2c_number, uint8_t sensor_address)'
- Get the sensor reading provides the sensor address
2. The ultrasonic_system module This module is built on top of the ultrasonic_sensor module above so that it can be implemented with the whole system. It provides the user with 2 main functions:
- 'void ultrasonic_system__init(void)'
- This function is responsible for initiating the 4 ultrasonic sensors with their addresses and configure the i2c communication
- 'dbc_SONAR_VALUES_s ultrasonic_system__get_all_values(void)'
- This function is responsible for getting all the ultrasonic sensors, storing them in a local sensor struct created by the auto-generated code from the DBC file, and return that struct back to the user
3. The can_bus_message_handler module This module is designed to be simple. Thus, the only function needs in this case is:
- 'bool can_bus_message_handler__transmit_sensor(void)'
- This function is responsible for calling the ultrasonic_system__get_all_values as discussed above and send the data over the CAN bus
Technical Challenges
1. Bad ultrasonic sensor
- Although there are several economical ultrasonic sensors out there, we think it is not worth the time debugging an ultrasonic sensor that may fail at any given time. Our initial ultrasonic sensor gives us decent readings but it occasionally fails to read the distance. We did some research on other sensors and found the one from DFRobots which is easy to implement and provide a decent reading with our range of application.
1. Integration with Bridge node
- When we order our PCB, we decided to combine the Bridge node and the Ultrasonic node together. However, our test shows that the structure of our programs is not in sync, which made the ultrasonic sensor froze for some time during its operation. We decided to separate the two nodes. Should the 2 nodes are developed with the same structures at the beginning, we could potentially get it working. Nonetheless, these Nodes are designed differently hence integrating it requires a complete rewrite of the nodes which we decided not to pursue
Motor ECU
Hardware Design
The hardware design for the motor node requires four main components to be connected to the SJ2 Board:
1. CAN Transceiver
- This module will be used to communicate with the Driver Node to receive the desired speed and steering angle through CAN communication protocol. This module will also be used to transmit the car's current speed to the Driver Node. The CAN transceiver will be powered by a +3.3V source with its Transmit Line (Tx) connected to GPIO Pin P0.1 and its Receive Line (Rx) connected to GPIO Pin P0.0.
2. RC Transmit Controller
- Due to the Electronic Speed Controller (ESC) being completely resined into the RC Car's base, there was no direct method of controlling the provided ESC with the SJ2 Board. The team decided to control the ESC using the transmit controller by measuring the internal potentiometer's voltage signal line to the transmit circuit and replicating those voltage values with a Digital-to-Analog Converter (DAC). This transmit controller takes in two input lines to its ports:
- CON2 PORT
- This port takes in one input, which controls the steering angle of the car. The voltage value for the steering to be straight was measured at +2.0V. Lower voltage values steer the car left and higher voltage values steer the car right. The voltage input to this port comes from the External DAC.
- CON3 PORT
- This port takes in one input, which controls the speed of the car. The voltage value for the car to be stationary was measured at approximately +1.5V. Lower voltage values accelerated the car forward and higher voltage values accelerated the car backwards. The voltage input to this port comes from the SJ2 Board's DAC pin P0.26.
3. External DAC
- Since the SJ2 Board has only one DAC pin, which is used to control the motor speed, an additional external DAC is needed to control the car's servo motor for steering.
4. Wheel Encoder
- This module is used by the motor node to measure the car's speed by keeping track of how many revolutions the rotary revolves around the sensor. The rotary contains twenty hole slits, so a full revolution will "tick" the sensor twenty times.
Software Design
The motor node is designed to receive a desired speed and a desired steering angle from the driver node. These values will be used to adjust the RC Car's motor speed and servo motor angle to align with those requested values.
There are four public functions that are provided in the motor node.
1. void motors__init(void)
- This function is used by the periodic callback to initialize the required peripherals used to control the motor speed as well as the servo motor angle.
2. void motors__run(void)
- This function is used by the periodic callback to set the motor speed and the servo motor angle. This public function will invoke two private functions, motors__speed_handler() which handles the motor speed of the car, and motors__steering_handler() which handles the steering angle of the car.
- motors__speed_handler()
- This private function controls the RC Car's speed, which is calculated by measuring the circumference of the car's wheel and finding out how many times it rotates within a given time frame. Setting the time frame and obtaining the circumference of the wheel is trivial, however, obtaining the amount of rotations required additional effort. We used an HC-020K Wheel Encoder to measure how many times the wheel rotated around its axle and connected the +5V output to one of the SJ2's GPIO pins. This pin was then attached to an interrupt service, which incremented the static variable holding the number of times the wheel has rotated. The sample code to calculate the speed of the car is shown below.
static int8_t motors__private_get_speed_kmh(void) {
int8_t motor_speed = current_speed_kmh;
uint64_t current_time_ms = sys_time__get_uptime_ms();
uint64_t time_elapsed_ms = current_time_ms - wheel_encoder_previous_time_ms;
if (time_elapsed_ms >= 100U) {
wheel_encoder_previous_time_ms = current_time_ms;
if (time_elapsed_ms > 0) {
float number_of_wheel_cycles = (float)wheel_encoder_number_of_ticks / (float)WHEEL_ENCODER_TICKS_PER_CYCLE;
float distance_travelled_cm = (float)(number_of_wheel_cycles * WHEEL_CIRCUMFERENCE_CM);
motor_speed =
(distance_travelled_cm / CENTIMETERS_IN_ONE_KILOMETER) / ((float)time_elapsed_ms / MILLISECONDS_IN_ONE_HOUR);
wheel_encoder_number_of_ticks = 0U;
if (MOTORS__DIRECTION_REVERSE == current_motor_direction) {
motor_speed *= -1;
}
}
}
return motor_speed;
}
- motors__steering_handler()
- This private function controls the RC Car's steering angle.
- The steering driver works in a similar way to how the motor driver works in the sense that it makes use of a digital to analog converter (DAC) to send signals to the motor transceiver to tell the car how much to steer. First, the motor node receives a CAN message through the CAN bus that contains a float value from within the range of -2.1 (full lock to the left) to 2.1 (full lock to the right). The steering driver then converts this float to an integer number used to write to the 12-bit DAC through I2C communication. Essentially, the range [-2.1, 2.1] which has 42 steps, is mapped to the range of [0, 4096] using the equation: (input + 2.1) * 10 * 4096 / 42.
3. void motors__set_speed_and_steering_values(dbc_MOTOR_VALUES_s *motor_values)
- This function is used by the CAN Bus Message Handler to set the desired speed and steering angle. When the CAN Bus Message Handler module receives a CAN package, it will decode the motor values and call this function. This function is also used by the MIA handler as well to stop the RC Car if it doesn't receive any CAN messages from the driver node ten times in a 10Hz periodic callback.
4. dbc_MOTOR_VALUES_TO_DRIVER_s motors__get_motor_values(void)
- This function is used by the CAN Bus Message Handler to transmit the current speed of the car.
Technical Challenges
- Electronic Speed Controller (ESC)
- When opening the RC car, the team found that the ESC was fully resined into the car's base. This prevented the team from directly controlling the ESC, so the team decided to control the RC car's speed and steering through the RC car's remote transceiver. The remote transceiver was taken apart and the team discovered that the user controlled the speed and steering through the use of two potentiometers, which sent specific voltage values to the transceiver's circuit and sent those values to the ESC remotely via Bluetooth. The team developed an internal DAC driver and an external DAC driver to send controlled voltage values to the transceiver to simulate the potentiometer output values.
- Wheel Encoder Issues
- During the integration of the wheel encoder, our team encountered various issues regarding its positioning on the car and its debouncing circuitry.
- Due to the shape of the RC car's plastic base, it was difficult to find a position on the car to place the wheel encoder such that it could accurately read the amount of revolutions the rotary wheel has made. The encoder must be placed near the axle of the wheel, however, there was no platform large enough to fix the encoder onto. The team purchased a metal "L" bracket and fixated the bracket onto one of the base's thin plastic platforms. This bracket was used as a new platform to mount the wheel encoder onto for better positioning and reading accuracy.
- Additionally, mounting the rotary wheel onto the axle was another issue. Initially, the rotary wheel had to be broken apart and crudely super-glued together. However, this solution resulted in a less accurate encoder reading due to the rotary being warped from the initial break. The team 3D printed a new rotary wheel in two separate pieces to resolve the warping issue from breaking it ourselves. This resulted in a more consistent, accurate encoder reading.
- Motor startup sequence
- Initially, when starting up the car, the team faced an issue where although voltage values are being sent to accelerate the car, the car would remain stationary. The solution to this issue was found in the user manual. According to the RC Car's user manual, both the acceleration and the steering triggers must be neutral when powering on the car. This means that when starting up, both the motor and the servo motor must be set to specific voltage values. The team measured the potentiometer's voltage value outputs when the triggers were in a neutral position and used those voltage values when starting up.
Geographical Controller
<Picture and link to Gitlab>
Hardware Design
Software Design
<List the code modules that are being called periodically.>
Technical Challenges
1. One of the largest challenges we had with the geo_node was processing the heading value to send over the CAN bus. This was an issue because the heading value would change drastically when the car itself would shake, which is a common occurrence while driving. This resulted in occasional sporadic heading values causing the car to behave chaotically.
Solution: The heading issue turned out to be related to the PCB integration. When testing the compass separately connecting by only dupont cables it performed as expected. This raises the importance of “unit testing” components, before integration to more easily isolate the problem.
2. Another challenge involved calibration of the compass. There are a variety of tutorials with varying difficulties online regarding magnetometer and accelerometer calibration. Magnetometer calibration in particular was extremely complex.
Solution: For our compass calibration we ended up implementing all the algorithms we could find. The two most prominent methods are the “simple” two-point style calibration and the magmaster / magneto ardruino method. The magmaster method was the more extensive of the two and not extremely complicated when utilizing the Arduino program developed by YuriMat.
Communication Bridge Controller & OLED
<Picture and link to Gitlab>
OLED Hardware Design
The hardware design of the OLED module was very straightforward as the physical display uses i2c to communicate to the SJ2Board. We needed to determine which board the OLED should be extended from, and we thought it would be best to extend it from the driver node to be able to have access to what the driver itself is receiving from the CAN bus. Below is an image of the OLED module that we used.
OLED Software Design
The goal with our software design was to have one function being called periodically that would handle displaying all of the messages that we wanted to display. We created a high-level function called display_all_data_on_OLED, which would be called in the 1 Hz periodic callback. We wanted to create the software this way because it would allow us to write the periodic_callback once and not alter it when we wanted to change what was displayed. This type of development also made unit-testing the functions much easier than if we had to continuously alter the function.
We eventually used this mentality of separating functions to improve unit-testing ability to minimize bugs throughout the OLED code modules. This allowed us to easily write, test, and verify the oled code worked properly.
OLED Technical Challenges
Initially there were a handful of problems that stemmed from a general lack of documentation. Based on the names of the pin connections, we knew the OLED used i2c; however, we did not know any of the pertinent addresses due to the lack of documentation. Once we found reliable source documentation, we were able to display messages on the OLED, but this led us to what values we wanted to display and what process would be best to get them from the system. Once this was decided, we were able to successfully display pertinent information on to the OLED display.
During one of our code reviews, we realized that the code was incredibly bloated, and a handful of functions were very long. We decided to separate functionality into five main components: oled, display, get_values_to_display, process_data, and debug_statements. Each of these modules are focused on a specific portion of the previous iteration of bloated code. The oled module handles the initialization of the oled display itself as well as all of the functions that are required for the oled to function properly, display is a high-level module that simply calls functions that would display the desired information, get_values_to_display is a module that would attain the values that would need to be displayed, process_data is a module that processes data from the CAN bus, and debug_statements is a module that creates the statements themselves to be displayed.
Bridge Hardware Design
- Bridge Hardware Words
Bridge Software Design
- Bridge Software Words
Bridge Technical Challenges
- Bridge Technical Words
Driver Module
The Driver node is responsible for receiving data from the Sensor Node, Geo Node, and Bridge Node to issue appropriate commands to the Motor Node.
Hardware Design
1. CAN Transceiver
- This module will be used to communicate with the Motor Node by sending the Motor command through CAN communication protocol. In order to send the correct Motor command, the Driver Node also receives data from the Sensor Node, the GEO Node, and the Bridge Node. The CAN transceiver will be powered by a +3.3V source with its Transmit Line (Tx) connected to GPIO Pin P0.1 and its Receive Line (Rx) connected to GPIO Pin P0.0.
Software Design
The Driver Node receive and decode these 4 CAN frame:
+ SONAR_VALUES: Ultrasonic sensor values from the Sensor Node.
+ COMPASS_HEADING_DISTANCE: Geo-location information(Heading angle, Bearing angle, and Distance to destination) from the GEO Node.
+ GPS_DESTINATION_REACHED: A bit to signify if it has reached its destination from the GEO Node.
+ DRIVE_START: Used to Start or Stop sending the Motor frame to the Motor Node, this frame is received from the Bridge Node.
At the top level, the periodic_callbacks.c only calls 3 functions in the 10hz periodic callback:
+(void)can_bus_message_handler__receive(): Receive and decode CAN dataframe from the Sensor Node, GEO Node, and the Bridge Node. Then generate the Motor command based on those frames.
+(void)can_bus_message_handler__transmit(): Transmit the Motor command onto the CAN bus.
+(void)can_handler__manage_mia_10hz(): Check if any dataframe is missing and handle it via the MIA handlers
The main part of the Driver Node is how it can generate the appropriate Motor Command given all the data from the other 3 nodes. The workflow(Represented by the above diagram) can be understood as:
+ Check if there is any obstacle based on the Sensor values
+ If there is an obstacle, update the steering value to avoid the obstacle
+ If not, update the steering to head to destination based on the Geo Node frame
+ Set the speed of the car
In our final version of (RC)²
Technical Challenges
< List of problems and their detailed resolutions>
Mobile Application
<Picture and link to Gitlab>
Software Design
<List the code modules that are being called periodically.>
Technical Challenges
The mobile app had quite a lot of challenges as none of us had experience with android development. We did not know where to start, what the app should look like, how it should function, nor what features we wanted it to have. We also did not know how to interface the mobile application with the rest of the car for it to be able to receive and send signals on the CAN bus via the ESP chip.
Once we designed and developed the app, it was rather unreliable as it would randomly crash at random intervals.
Involving the Google Maps API was difficult.
Conclusion
Conclusion <Organized summary of the project>
To conclude, (RC)^2 was a success and we are proud of the RC car. <write more>
<What did you learn?>
- CAN Communication Protocol
- Code modularization
- DBC Files
- Unit Test
- Debugging
- Mobile Application Design
<write more>
Project Video
Project Source Code
- Git Project Link: RC²
Advice for Future Students
<Bullet points and discussion>
Acknowledgement
- Arun's roommate?
=== References ===