http://socialledge.com/sjsu/api.php?action=feedcontributions&user=Proj+user3&feedformat=atomEmbedded Systems Learning Academy - User contributions [en]2024-03-28T18:32:55ZUser contributionsMediaWiki 1.27.1http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66734F21: Skeh-lleybones2021-12-18T03:39:32Z<p>Proj user3: /* Parts List & Cost */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|-<br />
| SJ2 Development Board<br />
| [https://www.amazon.com/Generic-SJTwo-SJ2-SJSU/dp/B08G9LRPZ8/ref=sr_1_2?keywords=SJ2&qid=1639798706&sr=8-2 Amazon]<br />
| $50<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart( main_game_logic ). A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
<br />
The above flow chart takes a look inside the 'GAME' or playing state at a high level. The functions that are called within the dotted box are only called once upon each state transition. This is done such that the main UI is initialized only once which greatly reduces the amount of data being written to our display buffer. We designed each module such that it only updates the part of the display it is affecting rather than simply rewriting the whole buffer. Most of the functions do exactly as their names suggest and aren't very in-depth besides game_state_machine__update_ball_position which is covered below. <br />
<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
The above flowchart goes over the majority of the logic required to run our game. Collisions with the top of the game area, left wall, right wall, paddle, and blocks are all calculated and acted upon here. First we calculate the next position of the ball as if there were no blocks. Based on this calculated position, we check for collision with any blocks by checking the current value of the coordinate in the matrix buffer. If there is a value other than zero, we know we have some sort of collision with one of the various objects within the game area. If it is not a block, then we simply handle the bounce logic based on the current direction the ball is travelling. <br />
<br />
Once we decide if the collision is with a block, we then check if the current position of the ball is in the corner of two or more blocks. This is to decide how many blocks are hit in the case of being in a corner. If it is determined that the ball is not in a corner, we hit a block and handle the bounce logic. If the ball is in a corner, we hit up to three blocks then send the ball in the opposite direction from which it came. We also implemented the concept of block lives based on their color so one more check is required before updating the ball's position. this check involves the color of the LED in the expected next position. We expose an API from the LED Matrix driver which will return the current color at that position. If this is determined to be BLACK or CYAN, we update the position and light up the LED using CYAN. If not, then we do not update the ball position. If we did update the position, then the block(s) which were hit would then be missing a pixel at that location causing an issue with detecting collisions going forward.<br />
<br />
Block lives were one of the features we decided to implement. This was tracked using the color of the block and keeping these colors in a block array. The colors of a block could be the following: RED, GREEN, YELLOW, BLUE, PURPLE. With RED meaning the block has one life left and PURPLE having five. When we hit a block we decrease the life by simply decrementing the index of that block based on the array. Scoring was implemented in the same function and we simply added 100 each time a block was either hit or deleted, depending on its color. Since we had scoring implemented, we also wanted to keep track of the hiscores to add a competitive aspect. A sorted five element array of scores was used to do so. Going forward, we would have wrote this to the SJ2's on board flash memory to have a persistent record rather than having a new list each time the game was powered on/off.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
<br />
Software and hardware challenges were faced and solved throughout this project.<br />
<br />
=== Block Corners ===<br />
<br />
Block corners were a constant problem in our game. The issue was with how collisions were detected and handled based on the next calculated position of the ball and the direction of travel. Using these two parameters meant that a corner had to be either considered part of a row or a column and the logic for each of these was different. This didn’t matter for cases where there was no connected block to the one being hit; but in the case of two blocks stacked on top of each other or two blocks side by side, it created corner cases we didn't originally expect. To overcome this, we decided to handle all corners as part of the column rather than part of a row. By doing so, we were able to create a consistent result which allowed the game to run more fluidly and not have unexpected bounces in directions the user wouldn’t expect. We tested treating corners as rows and found that the behavior of the algorithm resulted in unexpected bounces when interacting with multiple blocks.<br />
<br />
=== Testing ===<br />
<br />
Testing of the project’s game logic was a real problem. The solution used that worked for us was print statement debugging. That being said, if we were to do this project again prints would not be used. As the project and code base scaled in size, so did the amount of print statements to effectively debug each scenario and the size of the logs that we needed to debug with. Designing the code with modularity in mind helped and several interactions of refactoring were done to achieve the modularity, but using unit testing would have greatly reduced development time and would be used if the project were to be done again and all future projects.<br />
<br />
=== Code Modularity ===<br />
<br />
The code was no initially designed with modularity in mind. This became our biggest problem very quickly. Not only did it slow down debugging, it also made the code more difficult to read through. We made attempts to increase modularity through refactoring which helped a lot. More refactoring can still be done to raise the code quality.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66724F21: Skeh-lleybones2021-12-18T03:34:43Z<p>Proj user3: /* Testing & Technical Challenges */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart( main_game_logic ). A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
<br />
The above flow chart takes a look inside the 'GAME' or playing state at a high level. The functions that are called within the dotted box are only called once upon each state transition. This is done such that the main UI is initialized only once which greatly reduces the amount of data being written to our display buffer. We designed each module such that it only updates the part of the display it is affecting rather than simply rewriting the whole buffer. Most of the functions do exactly as their names suggest and aren't very in-depth besides game_state_machine__update_ball_position which is covered below. <br />
<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
The above flowchart goes over the majority of the logic required to run our game. Collisions with the top of the game area, left wall, right wall, paddle, and blocks are all calculated and acted upon here. First we calculate the next position of the ball as if there were no blocks. Based on this calculated position, we check for collision with any blocks by checking the current value of the coordinate in the matrix buffer. If there is a value other than zero, we know we have some sort of collision with one of the various objects within the game area. If it is not a block, then we simply handle the bounce logic based on the current direction the ball is travelling. <br />
<br />
Once we decide if the collision is with a block, we then check if the current position of the ball is in the corner of two or more blocks. This is to decide how many blocks are hit in the case of being in a corner. If it is determined that the ball is not in a corner, we hit a block and handle the bounce logic. If the ball is in a corner, we hit up to three blocks then send the ball in the opposite direction from which it came. We also implemented the concept of block lives based on their color so one more check is required before updating the ball's position. this check involves the color of the LED in the expected next position. We expose an API from the LED Matrix driver which will return the current color at that position. If this is determined to be BLACK or CYAN, we update the position and light up the LED using CYAN. If not, then we do not update the ball position. If we did update the position, then the block(s) which were hit would then be missing a pixel at that location causing an issue with detecting collisions going forward.<br />
<br />
Block lives were one of the features we decided to implement. This was tracked using the color of the block and keeping these colors in a block array. The colors of a block could be the following: RED, GREEN, YELLOW, BLUE, PURPLE. With RED meaning the block has one life left and PURPLE having five. When we hit a block we decrease the life by simply decrementing the index of that block based on the array. Scoring was implemented in the same function and we simply added 100 each time a block was either hit or deleted, depending on its color. Since we had scoring implemented, we also wanted to keep track of the hiscores to add a competitive aspect. A sorted five element array of scores was used to do so. Going forward, we would have wrote this to the SJ2's on board flash memory to have a persistent record rather than having a new list each time the game was powered on/off.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
<br />
Software and hardware challenges were faced and solved throughout this project.<br />
<br />
=== Block Corners ===<br />
<br />
Block corners were a constant problem in our game. The issue was with how collisions were detected and handled based on the next calculated position of the ball and the direction of travel. Using these two parameters meant that a corner had to be either considered part of a row or a column and the logic for each of these was different. This didn’t matter for cases where there was no connected block to the one being hit; but in the case of two blocks stacked on top of each other or two blocks side by side, it created corner cases we didn't originally expect. To overcome this, we decided to handle all corners as part of the column rather than part of a row. By doing so, we were able to create a consistent result which allowed the game to run more fluidly and not have unexpected bounces in directions the user wouldn’t expect. We tested treating corners as rows and found that the behavior of the algorithm resulted in unexpected bounces when interacting with multiple blocks.<br />
<br />
=== Testing ===<br />
<br />
Testing of the project’s game logic was a real problem. The solution used that worked for us was print statement debugging. That being said, if we were to do this project again prints would not be used. As the project and code base scaled in size, so did the amount of print statements to effectively debug each scenario and the size of the logs that we needed to debug with. Designing the code with modularity in mind helped and several interactions of refactoring were done to achieve the modularity, but using unit testing would have greatly reduced development time and would be used if the project were to be done again and all future projects.<br />
<br />
=== Code Modularity ===<br />
<br />
The code was no initially designed with modularity in mind. This became our biggest problem very quickly. Not only did it slow down debugging, it also made the code more difficult to read through. We made attempts to increase modularity through refactoring which helped a lot. More refactoring can still be done to raise the code quality.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66721F21: Skeh-lleybones2021-12-18T03:23:31Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart( main_game_logic ). A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
<br />
The above flow chart takes a look inside the 'GAME' or playing state at a high level. The functions that are called within the dotted box are only called once upon each state transition. This is done such that the main UI is initialized only once which greatly reduces the amount of data being written to our display buffer. We designed each module such that it only updates the part of the display it is affecting rather than simply rewriting the whole buffer. Most of the functions do exactly as their names suggest and aren't very in-depth besides game_state_machine__update_ball_position which is covered below. <br />
<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
The above flowchart goes over the majority of the logic required to run our game. Collisions with the top of the game area, left wall, right wall, paddle, and blocks are all calculated and acted upon here. First we calculate the next position of the ball as if there were no blocks. Based on this calculated position, we check for collision with any blocks by checking the current value of the coordinate in the matrix buffer. If there is a value other than zero, we know we have some sort of collision with one of the various objects within the game area. If it is not a block, then we simply handle the bounce logic based on the current direction the ball is travelling. <br />
<br />
Once we decide if the collision is with a block, we then check if the current position of the ball is in the corner of two or more blocks. This is to decide how many blocks are hit in the case of being in a corner. If it is determined that the ball is not in a corner, we hit a block and handle the bounce logic. If the ball is in a corner, we hit up to three blocks then send the ball in the opposite direction from which it came. We also implemented the concept of block lives based on their color so one more check is required before updating the ball's position. this check involves the color of the LED in the expected next position. We expose an API from the LED Matrix driver which will return the current color at that position. If this is determined to be BLACK or CYAN, we update the position and light up the LED using CYAN. If not, then we do not update the ball position. If we did update the position, then the block(s) which were hit would then be missing a pixel at that location causing an issue with detecting collisions going forward.<br />
<br />
Block lives were one of the features we decided to implement. This was tracked using the color of the block and keeping these colors in a block array. The colors of a block could be the following: RED, GREEN, YELLOW, BLUE, PURPLE. With RED meaning the block has one life left and PURPLE having five. When we hit a block we decrease the life by simply decrementing the index of that block based on the array. Scoring was implemented in the same function and we simply added 100 each time a block was either hit or deleted, depending on its color. Since we had scoring implemented, we also wanted to keep track of the hiscores to add a competitive aspect. A sorted five element array of scores was used to do so. Going forward, we would have wrote this to the SJ2's on board flash memory to have a persistent record rather than having a new list each time the game was powered on/off.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
<br />
Software and hardware challenges were faced and solved throughout this project.<br />
<br />
=== Block Corners ===<br />
<br />
Block corners were a constant problem in our game. The issue was with how collisions were detected and handled based on the next calculated position of the ball and the direction of travel. Using these two parameters meant that a corner had to be either considered part of a row or a column and the logic for each of these was different. This didn’t matter for cases where there was no connected block to the one being hit; but in the case of two blocks stacked on top of each other or two blocks side by side, it created corner cases we didn't originally expect. To overcome this, we decided to handle all corners as part of the column rather than part of a row. By doing so, we were able to create a consistent result which allowed the game to run more fluidly and not have unexpected bounces in directions the user wouldn’t expect. We tested treating corners as rows and found that the behavior of the algorithm resulted in unexpected bounces when interacting with multiple blocks.<br />
<br />
=== Testing ===<br />
<br />
Testing of the project’s game logic was a real problem. The solution used that worked for us was print statement debugging. That being said, if we were to do this project again prints would not be used. As the project and code base scaled in size, so did the amount of print statements to effectively debug each scenario and the size of the logs that we needed to debug with. Designing the code with modularity in mind helped and several interactions of refactoring were done to achieve the modularity, but using unit testing would have greatly reduced development time and would be used if the project were to be done again and all future projects.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66718F21: Skeh-lleybones2021-12-18T03:19:50Z<p>Proj user3: /* Testing & Technical Challenges */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart( main_game_logic ). A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
<br />
The above flow chart takes a look inside the 'GAME' or playing state at a high level. The functions that are called within the dotted box are only called once upon each state transition. This is done such that the main UI is initialized only once which greatly reduces the amount of data being written to our display buffer. We designed each module such that it only updates the part of the display it is affecting rather than simply rewriting the whole buffer. Most of the functions do exactly as their names suggest and aren't very in-depth besides game_state_machine__update_ball_position which is covered below. <br />
<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
The above flowchart goes over the majority of the logic required to run our game. Collisions with the top of the game area, left wall, right wall, paddle, and blocks are all calculated and acted upon here. First we calculate the next position of the ball as if there were no blocks. Based on this calculated position, we check for collision with any blocks by checking the current value of the coordinate in the matrix buffer. If there is a value other than zero, we know we have some sort of collision with one of the various objects within the game area. If it is not a block, then we simply handle the bounce logic based on the current direction the ball is travelling. <br />
<br />
Once we decide if the collision is with a block, we then check if the current position of the ball is in the corner of two or more blocks. This is to decide how many blocks are hit in the case of being in a corner. If it is determined that the ball is not in a corner, we hit a block and handle the bounce logic. If the ball is in a corner, we hit up to three blocks then send the ball in the opposite direction from which it came. We also implemented the concept of block lives based on their color so one more check is required before updating the ball's position. this check involves the color of the LED in the expected next position. We expose an API from the LED Matrix driver which will return the current color at that position. If this is determined to be BLACK or CYAN, we update the position and light up the LED using CYAN. If not, then we do not update the ball position. If we did update the position, then the block(s) which were hit would then be missing a pixel at that location causing an issue with detecting collisions going forward.<br />
<br />
Block lives were one of the features we decided to implement. This was tracked using the color of the block and keeping these colors in a block array. The colors of a block could be the following: RED, GREEN, YELLOW, BLUE, PURPLE. With RED meaning the block has one life left and PURPLE having five. When we hit a block we decrease the life by simply decrementing the index of that block based on the array. Scoring was implemented in the same function and we simply added 100 each time a block was either hit or deleted, depending on its color.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
<br />
Software and hardware challenges were faced and solved throughout this project.<br />
<br />
=== Block Corners ===<br />
<br />
Block corners were a constant problem in our game. The issue was with how collisions were detected and handled based on the next calculated position of the ball and the direction of travel. Using these two parameters meant that a corner had to be either considered part of a row or a column and the logic for each of these was different. This didn’t matter for cases where there was no connected block to the one being hit; but in the case of two blocks stacked on top of each other or two blocks side by side, it created corner cases we didn't originally expect. To overcome this, we decided to handle all corners as part of the column rather than part of a row. By doing so, we were able to create a consistent result which allowed the game to run more fluidly and not have unexpected bounces in directions the user wouldn’t expect. We tested treating corners as rows and found that the behavior of the algorithm resulted in unexpected bounces when interacting with multiple blocks.<br />
<br />
=== Testing ===<br />
<br />
Testing of the project’s game logic was a real problem. The solution used that worked for us was print statement debugging. That being said, if we were to do this project again prints would not be used. As the project and code base scaled in size, so did the amount of print statements to effectively debug each scenario and the size of the logs that we needed to debug with. Designing the code with modularity in mind helped and several interactions of refactoring were done to achieve the modularity, but using unit testing would have greatly reduced development time and would be used if the project were to be done again and all future projects.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66716F21: Skeh-lleybones2021-12-18T03:19:00Z<p>Proj user3: /* Testing & Technical Challenges */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart( main_game_logic ). A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
<br />
The above flow chart takes a look inside the 'GAME' or playing state at a high level. The functions that are called within the dotted box are only called once upon each state transition. This is done such that the main UI is initialized only once which greatly reduces the amount of data being written to our display buffer. We designed each module such that it only updates the part of the display it is affecting rather than simply rewriting the whole buffer. Most of the functions do exactly as their names suggest and aren't very in-depth besides game_state_machine__update_ball_position which is covered below. <br />
<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
The above flowchart goes over the majority of the logic required to run our game. Collisions with the top of the game area, left wall, right wall, paddle, and blocks are all calculated and acted upon here. First we calculate the next position of the ball as if there were no blocks. Based on this calculated position, we check for collision with any blocks by checking the current value of the coordinate in the matrix buffer. If there is a value other than zero, we know we have some sort of collision with one of the various objects within the game area. If it is not a block, then we simply handle the bounce logic based on the current direction the ball is travelling. <br />
<br />
Once we decide if the collision is with a block, we then check if the current position of the ball is in the corner of two or more blocks. This is to decide how many blocks are hit in the case of being in a corner. If it is determined that the ball is not in a corner, we hit a block and handle the bounce logic. If the ball is in a corner, we hit up to three blocks then send the ball in the opposite direction from which it came. We also implemented the concept of block lives based on their color so one more check is required before updating the ball's position. this check involves the color of the LED in the expected next position. We expose an API from the LED Matrix driver which will return the current color at that position. If this is determined to be BLACK or CYAN, we update the position and light up the LED using CYAN. If not, then we do not update the ball position. If we did update the position, then the block(s) which were hit would then be missing a pixel at that location causing an issue with detecting collisions going forward.<br />
<br />
Block lives were one of the features we decided to implement. This was tracked using the color of the block and keeping these colors in a block array. The colors of a block could be the following: RED, GREEN, YELLOW, BLUE, PURPLE. With RED meaning the block has one life left and PURPLE having five. When we hit a block we decrease the life by simply decrementing the index of that block based on the array. Scoring was implemented in the same function and we simply added 100 each time a block was either hit or deleted, depending on its color.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
=== Block Corners ===<br />
<br />
Block corners were a constant problem in our game. The issue was with how collisions were detected and handled based on the next calculated position of the ball and the direction of travel. Using these two parameters meant that a corner had to be either considered part of a row or a column and the logic for each of these was different. This didn’t matter for cases where there was no connected block to the one being hit; but in the case of two blocks stacked on top of each other or two blocks side by side, it created corner cases we didn't originally expect. To overcome this, we decided to handle all corners as part of the column rather than part of a row. By doing so, we were able to create a consistent result which allowed the game to run more fluidly and not have unexpected bounces in directions the user wouldn’t expect. We tested treating corners as rows and found that the behavior of the algorithm resulted in unexpected bounces when interacting with multiple blocks.<br />
<br />
=== Testing ===<br />
<br />
Testing of the project’s game logic was a real problem. The solution used that worked for us was print statement debugging. That being said, if we were to do this project again prints would not be used. As the project and code base scaled in size, so did the amount of print statements to effectively debug each scenario and the size of the logs that we needed to debug with. Designing the code with modularity in mind helped and several interactions of refactoring were done to achieve the modularity, but using unit testing would have greatly reduced development time and would be used if the project were to be done again and all future projects.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66697F21: Skeh-lleybones2021-12-18T02:10:52Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart( main_game_logic ). A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
<br />
The above flow chart takes a look inside the 'GAME' or playing state at a high level. The functions that are called within the dotted box are only called once upon each state transition. This is done such that the main UI is initialized only once which greatly reduces the amount of data being written to our display buffer. We designed each module such that it only updates the part of the display it is affecting rather than simply rewriting the whole buffer. Most of the functions do exactly as their names suggest and aren't very in-depth besides game_state_machine__update_ball_position which is covered below. <br />
<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
The above flowchart goes over the majority of the logic required to run our game. Collisions with the top of the game area, left wall, right wall, paddle, and blocks are all calculated and acted upon here. First we calculate the next position of the ball as if there were no blocks. Based on this calculated position, we check for collision with any blocks by checking the current value of the coordinate in the matrix buffer. If there is a value other than zero, we know we have some sort of collision with one of the various objects within the game area. If it is not a block, then we simply handle the bounce logic based on the current direction the ball is travelling. <br />
<br />
Once we decide if the collision is with a block, we then check if the current position of the ball is in the corner of two or more blocks. This is to decide how many blocks are hit in the case of being in a corner. If it is determined that the ball is not in a corner, we hit a block and handle the bounce logic. If the ball is in a corner, we hit up to three blocks then send the ball in the opposite direction from which it came. We also implemented the concept of block lives based on their color so one more check is required before updating the ball's position. this check involves the color of the LED in the expected next position. We expose an API from the LED Matrix driver which will return the current color at that position. If this is determined to be BLACK or CYAN, we update the position and light up the LED using CYAN. If not, then we do not update the ball position. If we did update the position, then the block(s) which were hit would then be missing a pixel at that location causing an issue with detecting collisions going forward.<br />
<br />
Block lives were one of the features we decided to implement. This was tracked using the color of the block and keeping these colors in a block array. The colors of a block could be the following: RED, GREEN, YELLOW, BLUE, PURPLE. With RED meaning the block has one life left and PURPLE having five. When we hit a block we decrease the life by simply decrementing the index of that block based on the array. Scoring was implemented in the same function and we simply added 100 each time a block was either hit or deleted, depending on its color.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66689F21: Skeh-lleybones2021-12-18T01:40:22Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
[[File:State_transition_diagram.PNG|300px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|300px|align|center|thumb|Main Game Logic Flowchart]]<br />
[[File:Update_ball_position.PNG|300px|align|center|thumb|Updating Ball Position Flowchart]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66680F21: Skeh-lleybones2021-12-18T01:31:16Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
{{multiple image<br />
| align = center<br />
| total_width = 900<br />
<br />
<br />
| image1 = State_transition_diagram.PNG<br />
| caption1 = State Transition Diagram<br />
<br />
| image2 = Main_game_logic_flow.PNG<br />
| caption2 = Main game logic flowchart<br />
<br />
| image3 = Update_ball_position.PNG<br />
| caption3 = Update ball position flowchart<br />
}}<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66677F21: Skeh-lleybones2021-12-18T01:23:12Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66673F21: Skeh-lleybones2021-12-18T01:19:17Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG|600px|align|center|thumb|State Transition Diagram]]<br />
[[File:Main_game_logic_flow.PNG|600px|align|left|thumb|State Transition Diagram]] [[File:Update_ball_position.PNG|600px|align|right|thumb|State Transition Diagram]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=File:Main_game_logic_flow.PNG&diff=66670File:Main game logic flow.PNG2021-12-18T01:16:15Z<p>Proj user3: Game logic flow chart</p>
<hr />
<div>Game logic flow chart</div>Proj user3http://socialledge.com/sjsu/index.php?title=File:Update_ball_position.PNG&diff=66669File:Update ball position.PNG2021-12-18T01:15:42Z<p>Proj user3: Flow chart of game_state_machine__update_ball_position()</p>
<hr />
<div>Flow chart of game_state_machine__update_ball_position()</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66653F21: Skeh-lleybones2021-12-18T00:51:34Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG|600px|align|center|thumb|State Transition Diagram]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66652F21: Skeh-lleybones2021-12-18T00:51:22Z<p>Proj user3: /* Design & Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG|600px|align|left|thumb|State Transition Diagram]]<br />
<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66651F21: Skeh-lleybones2021-12-18T00:50:48Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG|600px|align|left|thumb|State Transition Diagram]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=File:State_transition_diagram.PNG&diff=66635File:State transition diagram.PNG2021-12-17T23:52:08Z<p>Proj user3: Proj user3 uploaded a new version of File:State transition diagram.PNG</p>
<hr />
<div>state_transition_diagram</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66634F21: Skeh-lleybones2021-12-17T23:50:29Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG|600px|align|center|thumb|VS1053B]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66633F21: Skeh-lleybones2021-12-17T23:50:15Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG|align|center|thumb|VS1053B]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66632F21: Skeh-lleybones2021-12-17T23:49:46Z<p>Proj user3: /* Game Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
<br />
The game was implemented using a state machine. The main driving function, ‘game_state_machine__run_game()’ is outlined in the below flow chart. A state machine design was chosen for two reasons. First, states did not simply flow down from one state to the next as shown in the state transition diagram below. Using switch and case statements is also much easier from a code readability standpoint then a large if-else block. <br />
<br />
[[File:State_transition_diagram.PNG]]<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=File:State_transition_diagram.PNG&diff=66631File:State transition diagram.PNG2021-12-17T23:48:39Z<p>Proj user3: state_transition_diagram</p>
<hr />
<div>state_transition_diagram</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66621F21: Skeh-lleybones2021-12-17T23:33:38Z<p>Proj user3: /* LED Matrix Driver */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
Below you can find the coded implementation used to drive the LED Matrix based on the control method described in the above section.<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66620F21: Skeh-lleybones2021-12-17T23:31:33Z<p>Proj user3: /* LED Matrix Driver */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
<syntaxhighlight lang="cpp"><br />
for (int i = 0; i < 32; i++) {<br />
led_driver__disable_latch();<br />
led_driver__enable_output();<br />
for (int j = 0; j < 64; j++) {<br />
led_driver__map_color_code_to_color_select_pins_top(led_matrix[i][j]);<br />
led_driver__map_color_code_to_color_select_pins_bottom(led_matrix[i + 32][j]);<br />
led_driver__clock_toggle();<br />
}<br />
led_driver__enable_latch();<br />
led_driver__disable_output();<br />
((i)&0x01) ? gpio__set(A) : gpio__reset(A);<br />
((i)&0x02) ? gpio__set(B) : gpio__reset(B);<br />
((i)&0x04) ? gpio__set(C) : gpio__reset(C);<br />
((i)&0x08) ? gpio__set(D) : gpio__reset(D);<br />
((i)&0x10) ? gpio__set(E) : gpio__reset(E);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Game Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66617F21: Skeh-lleybones2021-12-17T23:28:54Z<p>Proj user3: /* Design & Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== LED Matrix Driver ===<br />
<br />
=== Game Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66612F21: Skeh-lleybones2021-12-17T23:26:33Z<p>Proj user3: /* Acknowledgement */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== Game Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis, Ameer, and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66603F21: Skeh-lleybones2021-12-17T23:16:37Z<p>Proj user3: /* Software Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== Game Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66601F21: Skeh-lleybones2021-12-17T23:16:11Z<p>Proj user3: /* Implementation */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== Software Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=66595F21: Skeh-lleybones2021-12-17T23:06:14Z<p>Proj user3: /* Software Design */</p>
<hr />
<div>[[File:skeh-block_breaker_cover_pic.jpg|thumb|right|300px|Block Breaker]]<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Abstract ==<br />
As the capstone project for this class, we were instructed to create a video game using a few required elements. As the cornerstone of development in this class, we were required to use the SJ2 development board. Additionally, we were required to use a LED matrix as means of displaying the video game movement. Finally, we were required to facilitate the usage of an external peripheral or sensor that would contribute to the end result in a meaningful way.<br />
<br />
== Introduction ==<br />
In order to realize the requirements of this project, we constructed a plan to verbally prototype a few different elements of the project:<br />
<br />
* The idea of the game - we discussed two player snake as a potential idea, but ultimately decided on block breaker.<br />
* The task logic - it made sense to run a single task that would serve as the "clock" task to operate the game at a stable refresh rate. Another task could serve to update the data structure that held the state of the LED matrix at any given moment in time.<br />
* The LED matrix driver - because of the nature of the LED matrix's operation, a consistent order of operations is required to update each pixel. More on this will be discussed in later sections.<br />
* The enclosure - since we had access to a 3D printer, we concluded that a tabletop arcade cabinet would serve to house all necessary components.<br />
* The music - we decided to use the theme song from the video game Geometry Dash since we used rectangular blocks and doing so pull us in scope of using the theme song.<br />
<br />
== Objectives & Introduction ==<br />
In order to accomplish the objective of the game, we split the project into a few sub-topics that could be tackled individually:<br />
<br />
* Main "clock" task for updating the LED matrix.<br />
* Main gameplay loop task that would update the position of the ball, paddle, and blocks.<br />
* Design of various game screens via a state machine.<br />
* Game logic to determine the ball's bounce relative to its current trajectory.<br />
* Design of PCB to utilize a ground plane and avoid excessive loose wiring.<br />
* Design of a 3D printed enclosure to display a clean look.<br />
* MP3 background track during gameplay.<br />
* Speaker volume adjustment based on user proximity to enclosure.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabjyot Obhi<br />
* Core MP3 module driver development.<br />
* Task logic for sending music data to MP3 module.<br />
Justin Stokes<br />
* Core game logic development.<br />
* Debugging and testing of game logic and LED Matrix functionalities. <br />
Manas Abhyankar<br />
* Develop LED Matrix driver.<br />
* Design and print enclosure for project.<br />
* Design and send PCB for manufacturing.<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:green">Completed</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable" <br />
|- style="background-color:#34ff34;"<br />
! Part<br />
! Link<br />
! Price<br />
! Quantity<br />
|-<br />
| LED Matrix<br />
| [https://www.sparkfun.com/products/14824 Sparkfun]<br />
| $80<br />
| 1<br />
|-<br />
| Power Supply<br />
| [https://www.adafruit.com/product/658 Adafruit]<br />
| $30<br />
| 1<br />
|-<br />
| Barreljack connector<br />
| [https://www.adafruit.com/product/373 Adafruit]<br />
| $0.95<br />
| 1<br />
|-<br />
| Joystick<br />
| [https://www.sparkfun.com/products/9182 Sparkfun]<br />
| $16.95<br />
| 1<br />
|-<br />
| Button<br />
| [https://www.adafruit.com/product/3489 Adafruit]<br />
| $2.50<br />
| 2<br />
|-<br />
| Quick connect wires<br />
| [https://www.adafruit.com/product/1152 Adafruit]<br />
| $4.95<br />
| 1<br />
|-<br />
| Resistors/Capacitors<br />
| N/A<br />
| N/A<br />
| 3 of each<br />
|-<br />
| Ultrasonic Sensor<br />
| [https://www.adafruit.com/product/4019 Adafruit]<br />
| $3.95<br />
| 1<br />
|-<br />
| MP3 Module<br />
| [https://www.adafruit.com/product/1788 Adafruit]<br />
| $34.95<br />
| 1<br />
|-<br />
| Speakers<br />
| [https://www.adafruit.com/product/1669 Adafruit]<br />
| $7.50<br />
| 1<br />
|-<br />
| 3D Printed Enclosure<br />
| To be 3D printed<br />
| N/A<br />
| 1<br />
|-<br />
| 40-pin ribbon cable<br />
| [https://www.adafruit.com/product/1988 Adafruit]<br />
| $2.95<br />
| 2<br />
|}<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
# SJ2 Interconnect<br />
# SJ2 connection to LED matrix<br />
# SJ2 connection to VS1053b<br />
# SJ2 connection to ultrasonic sensor, buttons, joysticks<br />
[[File:top-level-diagram.png|thumb|center|500px|A hardware block diagram of the project]]<br />
[[File:skeh-hardware_schematic.jpg|thumb|center|500px|A hardware block diagram using the EasyEDA schematic designer]]<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
<br />
Below are the list of the tasks we used to create our project. This includes, the task name, task priority, and high-level view of what the task performed. <br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold;"<br />
! Task Name<br />
! Task Priority<br />
! Comments<br />
|-<br />
| left_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the left button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| right_button_task<br />
| PRIORITY_HIGH<br />
| This task was used to receive inputs from the right button. Used interrupts to send binary semaphore on each press.<br />
|-<br />
| joystick_task<br />
| PRIORITY_MEDIUM<br />
| This task was used to monitor movement of the joystick. This task was polled rather than using interrupts<br />
|-<br />
| game_state_machine_task<br />
| PRIORITY_HIGH<br />
| Task responsible for running the game. Accessed the main state machine used to drive the game logic.<br />
|-<br />
| update_display_task<br />
| PRIORITY_HIGH<br />
| Updated the physical matrix based on the 2D array in code.<br />
|-<br />
| check_for_speed_up_task<br />
| PRIORITY_MEDIUM<br />
| Checked if the 'current power up' was a speed related power up. If yes, changed the delay of game_state_machine_task to reflect the speed up/down.<br />
|}<br />
<br />
=== Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
<br />
=== MP3 and Ultrasonic Hardware Design and Interface ===<br />
<br />
The overall hardware design of the MP3 module was very straightforward as the means of communication between the SJ2 and the VS1053B board was an SPI interface. The MP3 control pins such as CS, DCS, DREQ, and RESET were simple GPIO pins that were available on the SJ2 board. The largest component was to select which GPIO pins and SPI interface to employ as everyone had to be consistent due to the fact that this would be connected onto a PCB. The thought process behind selecting pins to choose was the spacing between each grouping of pins as well the ease of putting wires in. <br />
<br />
The pins that we decided to use for the MP3 control signals are as follows: DREQ to 2.2, RESET to 2.5, DCS to 2.7, and CS to 2.9. We chose these pins because they are in a straight line. Also, the MP3 pins are away from the SPI pins which are as follows: Clock to 0.7, MISO to 0.8, and MOSI to 0.9. Below are images of the VS1053B connected to the SJ2 Board <br />
*insert image of wires on SJ2*<br />
<br />
[[File:Vs1053b_module.jpg|400px|align|center|thumb|VS1053B]]<br />
<br />
<br />
Once all of the wires were set up we had to use the 3.5-millimeter wire to connect the module to different speakers, headphones, and other audio devices to ensure that we could hear the music being played and that the quality of the sound was decent. This is shown below.<br />
<br />
*Insert Image*<br />
<br />
<br />
<br />
The final component was the ultrasonic sensor, and we initially used a spare $4 component. We quickly realized it would be easier to simply use a higher quality, better sensor for our project. Luckily, we were able to take apart a previous project which used a better ultrasonic sensor to use for this. Below is an image of the cheap ultrasonic sensor and the more expensive, easier to use ultrasonic sensor. <br />
<br />
[[File:Cheap_ultra_sonic.jpg|400px|align|left|thumb|Cheap Ultrasonic]] [[File:Good_ultra_sonic_sensor.PNG|400px|align|center|thumb| Good Ultrasonic]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The ultrasonic sensor that we ended up using utilized I2C to communicate with the SJ2 board. Initially, we tried to use I2C1 because we had recently finished the I2C lab and when we used I2C busses to communicate on one board, and thought we could continue the process. We quickly realized that we could simply use the I2C2 bus because it would already be initialized and ready to use to read data.<br />
<br />
=== MP3 and Ultrasonic Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it.<br />
<br />
On startup, there is only one task that is created in main, namely the ultrasonic_sensor_task. This task reads the value that the ultrasonic sensor is sensing, and when the value is below 25, three tasks related to MP3 playback are created and begin running. There is a mp3_reader task, a mp3_player_task, and a mp3_contoller task. The controller task combs through the songlist and sends the name to the mp3_reader task to begin reading, and ultimately played. The reason this methodology was used was to make sure that the song title did not need to be hardcoded, so anyone could name their files whatever they wanted and the song would still play. The mp3_reader reads the data from an SD card to a buffer which will be transmitted to the mp3_player_task via a queue. Finally, the mp3_player_task sends the data to the MP3 module to be played. <br />
<br />
Below are two snippets, one of our reader task, and another of the player task.<br />
<br />
<syntaxhighlight lang="cpp"><br />
Reader Task:<br />
if (FR_OK == result) {<br />
fprintf(stdout, "File opened: %s\nPlaying: %s", song_name_reader, song_name_reader);<br />
while (!f_eof(&file)) {<br />
f_read(&file, song_data, sizeof(song_data), &br);<br />
.<br />
.<br />
.<br />
xQueueSend(Q_songdata, &song_data[0], portMAX_DELAY);<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang="cpp"><br />
Player Task:<br />
<br />
.<br />
. <br />
.<br />
while (true) {<br />
xQueueReceive(Q_songdata, &song_data[0], portMAX_DELAY);<br />
for (int i = 0; i < sizeof(song_data); i++) {<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
spi_send_data_to_mp3_decoder(song_data[I]);<br />
.<br />
.<br />
.<br />
</syntaxhighlight><br />
<br />
<br />
The ultrasonic_sensor_task is also the means of pausing, replaying, and restarting the song that is being played. Once a song is playing, if the person playing the game wants to pause the music he/she would have to wave their hand approximately 4-10 millimeters away from the ultrasonic sensor. Since the ultrasonic_sensor_task sleeps for 500 milliseconds, the user would need to make sure that their hand goes in and out at a reasonable pace. He/She would need to ensure that they do not keep their hand in front of the sensor for too long as that would cause the playback to pause and play continuously. <br />
<br />
Finally, if the player wants to restart the song, he/she would need to be within 3 millimeters of the ultrasonic sensor. The most brute force way that this was done was to essentially create a situation where the SJ2 would reboot itself and restart main and in turn the ultrasonic_sensor_task. This worked in our situation, but we would not recommend this form to restart playing the song.<br />
<syntaxhighlight lang="cpp"><br />
static void ultrasonic_sensor_task(void *p) {<br />
bool pause = true;<br />
// MP3_START_PLAYING = false;<br />
<br />
while (1) {<br />
int value_from_sensor = get_sensor_value_for_task();<br />
fprintf(stderr, "Value = %u\n", value_from_sensor);<br />
// MP3_START_PLAYING = false;<br />
<br />
if (!MP3_START_PLAYING) {<br />
if (value_from_sensor < 25) {<br />
MP3_START_PLAYING = true;<br />
song_list__refresh();<br />
for (size_t song_number = 0; song_number < song_list__get_item_count(); song_number++) {<br />
printf("Song %3d: %3ld: %s\n", (1 + song_number), song_count + 1, song_list__get_name_for_item(song_number));<br />
song_count++;<br />
}<br />
<br />
xTaskCreate(mp3_reader_task, "reader", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
xTaskCreate(mp3_player_task, "player", (6 * kilobyte) / sizeof(void *), NULL, PRIORITY_HIGH,<br />
&mp3_player_task_handle);<br />
xTaskCreate(mp3_control_task, "control", (8 * kilobyte) / sizeof(void *), NULL, PRIORITY_LOW, NULL);<br />
}<br />
} else if (MP3_START_PLAYING && value_from_sensor <= 10 && value_from_sensor >= 4) {<br />
pause ? vTaskSuspend(mp3_player_task_handle) : vTaskResume(mp3_player_task_handle);<br />
pause = !pause;<br />
.<br />
.<br />
.<br />
.<br />
vTaskDelay(500);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== MP3 and Ultrasonic Implementation ===<br />
We don't want to give too much information here, but at a high level, the process of initializing requires the initialization of the SPI1 bus, the SPI1 peripherals, and the mp3_initialization. The communication between the SJ2 and the decoder is through SPI, so this was similar to the SPI lab. The most important portion of the SPI communication is to ensure that we are waiting until the MP3 decoder is no longer busy. Much of this can be seen in the following code snippets.<br />
<br />
<syntaxhighlight lang="cpp"><br />
void spi1__init(uint32_t max_clock_mhz) {<br />
spi1__init_pins();<br />
spi1__init_peripherals(max_clock_mhz);<br />
mp3_decoder__init();<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
static void mp3_decoder__init(void) {<br />
mp3_decoder_rst();<br />
mp3_set_volume(0x0);<br />
uint16_t mp3_mode = mp3_read_register(SCI_MODE);<br />
uint16_t mp3_status = mp3_read_register(SCI_STATUS);<br />
uint16_t mp3_volume = mp3_read_register(SCI_VOL);<br />
mp3_write_register(SCI_CLOCKF, 0xc800); // 12.288 * 3.5 = 43.0108/7 = 6.1444Mhz<br />
uint16_t mp3_clock = mp3_read_register(SCI_CLOCKF);<br />
fprintf(stderr, "Mode:0x%04x Status:0x%04x Clock:0x%04x Vol:0x%04x\n", mp3_mode, mp3_status, mp3_clock, mp3_volume);<br />
spi1__init_clock_prescalar(7);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="cpp"><br />
void mp3_write_register(uint8_t address_byte, uint16_t data) {<br />
uint8_t low_byte = data;<br />
uint8_t high_byte = data >> 8;<br />
uint8_t write_op = 0x02;<br />
while (!mp3_decoder_needs_data()) {<br />
;<br />
}<br />
mp3_decoder_cs_activate();<br />
(void)spi1__exchange_byte(write_op);<br />
(void)spi1__exchange_byte(address_byte);<br />
(void)spi1__exchange_byte(high_byte);<br />
(void)spi1__exchange_byte(low_byte);<br />
mp3_decoder_cs_deactivate();<br />
}<br />
</syntaxhighlight><br />
<br />
The communication between the ultrasonic sensor and the SJ2 is a simple I2C write to a register on the ultrasonic and read back. As the sensor would be directly in front of the player, we only need to read the lower bits of the distance register due to proximity. <br />
<br />
<syntaxhighlight lang="cpp"><br />
uint8_t ultrasonic_sensor__get_value(void) {<br />
uint8_t sensor_value = 0;<br />
uint8_t value_to_write = 1;<br />
i2c__write_slave_data(I2C__2, 0x24, 0x08, &value_to_write, 1);<br />
i2c__read_slave_data(I2C__2, 0x24, 0x04, &sensor_value, 1);<br />
return sensor_value;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Ultimately, we were able to fully replicate the block breaker game with a geometry dash soundtrack that the player would be able to control. This a was a fun project that allowed us to employ all of the knowledge that we learned about in class. We used a handful of the communication protocols in the project, and these would most definitely be used in industry as they are foundational pieces of knowledge. Regardless of if people decide to pursue this field, there are still characteristics that are shown through the project that would be useful in other areas. <br />
<br />
Advice for Future Students:<br />
<br />
The largest piece of advice for future students is to decide on and order your hardware quickly. The chip shortage may have had an impact, but our packages took quite a long time to arrive. It’s very difficult to make progress on a project when you do not have the necessary hardware to even start the project. Also, we received multiple defective matrices throughout the semester, so the sooner you order these the sooner you can return bad ones. Finally, getting a head start on your parts allows you to start designing your PCB, which may need to do multiple iterations due to an error you did not expect, like a noisy ground. <br />
<br />
What we learned/Where we improved:<br />
*PCB Design<br />
*3D Printing <br />
*Software Design<br />
*Software Planning<br />
*Communication <br />
*Debugging<br />
<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
[https://gitlab.com/manasabhyankar/block-breaker-project Block Breaker project source code]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
We'd like to thank Preet for giving us the opportunity to develop and learn through an interactive team project. We would also like to acknowledge the TAs Ellis and Tirth for their feedback throughout the semester.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=65516F21: Skeh-lleybones2021-11-08T06:08:40Z<p>Proj user3: /* Schedule */</p>
<hr />
<div>=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
== Objectives & Introduction ==<br />
Show list of your objectives. This section includes the high level details of your project. You can write about the various sensors or peripherals you used to get your project completed.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabhjyot Obhi<br />
* Objectives here <br />
Justin Stokes<br />
* Objectives here <br />
Manas Abhyankar<br />
* Objectives here <br />
<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 11/1/2021<br />
|<br />
* 11/5/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
* Finalize Parts list<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
* <span style="color:green">Completed</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*11/5/2021 <br />
| <br />
*11/9/2021 <br />
|<br />
<br />
* All parts ordered<br />
* Decide final pinout<br />
* PCB generated and ordered<br />
|<br />
* <span style="color:green">Completed</span><br />
* <span style="color:orange">In progress</span><br />
* <span style="color:orange">In progress</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*11/9/2021<br />
|<br />
*11/12/2021<br />
|<br />
* Simple display driver finished (display pixel at given coordinate)<br />
* Finalize game design (powerups, scoring system, boss?)<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 4<br />
|<br />
* 11/12/2021<br />
|<br />
* 11/17/2021<br />
|<br />
* Fully functional display driver<br />
* Game menu finish<br />
* Preliminary enclosure design<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/17/2021<br />
|<br />
*11/26/2021<br />
|<br />
* Basic game implementation finished<br />
* Verify PCB<br />
* Enclosure design finalized<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/26/2021 <br />
| <br />
*12/3/2021<br />
|<br />
* Enclosure printed and tested<br />
* Final game implementation finished<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 12/3/2021<br />
| <br />
* 12/10/2021<br />
|<br />
* Free week to allow for schedule shifting<br />
* Bug fixes<br />
|<br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 12/10/2021<br />
| <br />
* 12/16/2021<br />
|<br />
* Finish wiki report<br />
|<br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/16/2021<br />
| <br />
* 12/18/2021<br />
|<br />
* Demo<br />
|<br />
* <span style="color:red">Not started</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
**PLACEHOLDER**<br />
It worked out well when we put a table here that listed various things, like our part name, a description, purchase source, and price.<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
Discuss your hardware design here. Show detailed schematics, and the interface here.<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it. <br />
<br />
=== Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Conclude your project here. You can recap your testing and problems. You should address the "so what" part here to indicate what you ultimately learnt from this project. How has this project increased your knowledge?<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
* [https://sourceforge.net/projects/sjsu/files/CmpE_S2016/ Sourceforge Source Code Link]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
Any acknowledgement that you may wish to provide can be included here.<br />
<br />
=== References Used ===<br />
List any references used in project.<br />
<br />
=== Appendix ===<br />
You can list the references you used.</div>Proj user3http://socialledge.com/sjsu/index.php?title=F21:_Skeh-lleybones&diff=65483F21: Skeh-lleybones2021-10-21T02:48:13Z<p>Proj user3: /* Schedule */</p>
<hr />
<div>=== Grading Criteria ===<br />
<font color="green"><br />
* How well is Software & Hardware Design described?<br />
* How well can this report be used to reproduce this project?<br />
* Code Quality<br />
* Overall Report Quality:<br />
** Software Block Diagrams<br />
** Hardware Block Diagrams<br />
**: Schematic Quality<br />
** Quality of technical challenges and solutions adopted.<br />
</font><br />
<br />
== Block Breaker ==<br />
Block Breaker is a fun game in which you control a paddle and destroy blocks with a moving ball. The player controlled paddle deflects the ball at different angles to target different blocks and destroy them.<br />
<br />
== Objectives & Introduction ==<br />
Show list of your objectives. This section includes the high level details of your project. You can write about the various sensors or peripherals you used to get your project completed.<br />
<br />
=== Team Members & Responsibilities ===<br />
Prabhjyot Obhi<br />
* Objectives here <br />
Justin Stokes<br />
* Objectives here <br />
Manas Abhyankar<br />
* Objectives here <br />
<br />
<br />
== Schedule ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1<br />
| <br />
* 10/18/2021<br />
* 10/18/2021<br />
|<br />
* 10/22/2021<br />
* 10/22/2021<br />
|<br />
* Read previous projects, gather information and discuss among the group members.<br />
* Create GitLab repository for project<br />
| <br />
* <span style="color:green">Completed</span><br />
* <span style="color:orange">In progress</span><br />
|-<br />
! scope="row"| 2<br />
| <br />
*10/18/2021 <br />
| <br />
*10/29/2021 <br />
|<br />
<br />
*Order necessary parts<br />
|<br />
* <span style="color:orange">In progress</span><br />
|-<br />
! scope="row"| 3<br />
|<br />
*10/20/2021<br />
|<br />
*10/29/2021<br />
|<br />
*Read and familiarize with LED Matrix Datasheet, test to make sure it is functional<br />
|<br />
* <span style="color:red">Not started</span><br />
<br />
<br />
|-<br />
! scope="row"| 4<br />
|<br />
* 10/27/2021<br />
|<br />
* 11/03/2021<br />
|<br />
* Develop graphics driver for LED matrix and implement initial game objects<br />
|<br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 5<br />
|<br />
*11/01/2021<br />
*11/01/2021<br />
*11/xx/2021<br />
*11/01/2020<br />
|<br />
*11/09/2021<br />
*11/05/2021<br />
*11/xx/2021<br />
*11/xx/2021<br />
|<br />
* Finalize wiki schedule<br />
* Order circuit boards components and complete the design for printing<br />
* circuit board and component assembly and testing<br />
* Additional accessories if required and finalization of hardware<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 6<br />
|<br />
*11/16/2021 <br />
| <br />
*11/22/2021<br />
|<br />
*Integration of circuit boards and microcontroller<br />
* Game logic development<br />
* Testing and debugging the game logic<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 7<br />
| <br />
* 11/23/2021<br />
<br />
| <br />
* 11/29/2021<br />
|<br />
* Integrate game logic code with LED matrix<br />
* Integrate game sounds with game logic <br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 8<br />
| <br />
* 11/30/2021<br />
| <br />
* 12/06/2021<br />
|<br />
<br />
* Integrate subsystem<br />
* Finalizing the video game <br />
* Update the wiki page.<br />
* Test pause/play functionality<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 9<br />
| <br />
* 12/07/2021<br />
| <br />
* 12/14/2021<br />
|<br />
* Address bugs during testing of integrated system<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
! scope="row"| 10<br />
| <br />
*12/15/2021<br />
*12/16/2021<br />
*12/16/2021<br />
*12/16/2021<br />
| <br />
*12/15/2021<br />
*12/16/2021<br />
*12/16/2021<br />
*12/16/2021<br />
|<br />
<br />
*Final Demo<br />
*Update Gitlab repo with final code.<br />
*Update test video.<br />
*Update the wiki page.<br />
|<br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
* <span style="color:red">Not started</span><br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
**PLACEHOLDER**<br />
It worked out well when we put a table here that listed various things, like our part name, a description, purchase source, and price.<br />
<br />
== Design & Implementation ==<br />
The design section can go over your hardware and software design. Organize this section using sub-sections that go over your design and implementation.<br />
<br />
=== Hardware Design ===<br />
Discuss your hardware design here. Show detailed schematics, and the interface here.<br />
<br />
=== Hardware Interface ===<br />
In this section, you can describe how your hardware communicates, such as which BUSes used. You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.<br />
<br />
=== Software Design ===<br />
Show your software design. For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code. For example, do not show exact code, but you may show psuedocode and fragments of code. Keep in mind that you are showing DESIGN of your software, not the inner workings of it. <br />
<br />
=== Implementation ===<br />
This section includes implementation, but again, not the details, just the high level. For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash. You can include sub-sections for each of your component implementation.<br />
<br />
== Testing & Technical Challenges ==<br />
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?<br />
Make a smooth transition to testing section and described what it took to test your project.<br />
<br />
Include sub-sections that list out a problem and solution, such as:<br />
<br />
=== <Bug/issue name> ===<br />
Discuss the issue and resolution.<br />
<br />
== Conclusion ==<br />
Conclude your project here. You can recap your testing and problems. You should address the "so what" part here to indicate what you ultimately learnt from this project. How has this project increased your knowledge?<br />
<br />
=== Project Video ===<br />
Upload a video of your project and post the link here.<br />
<br />
=== Project Source Code ===<br />
* [https://sourceforge.net/projects/sjsu/files/CmpE_S2016/ Sourceforge Source Code Link]<br />
<br />
== References ==<br />
=== Acknowledgement ===<br />
Any acknowledgement that you may wish to provide can be included here.<br />
<br />
=== References Used ===<br />
List any references used in project.<br />
<br />
=== Appendix ===<br />
You can list the references you used.</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64766S21: Roadster2021-05-27T21:12:25Z<p>Proj user3: /* Introduction */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into 5 modules:<br />
<br />
* Sensor Node- Detecting obstacles in the vicinity of the car to avoid hitting the obstacle and maneuver around the same.<br />
* Geo Node- Provide heading for car to reach destination. Communicate over blue tooth with mobile application. Battery state.<br />
* Driver Node- Manipulate turn angles and forward/reverse speed based on the inputs from Sensor and Geo nodes<br />
* Motor Node- PID control logic to attain the said speed/direction desired by driver node.<br />
* Android Application- Dashboard for real time data from car. Send instruction such as destination, way points and start/stop.<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
* LSM303DLHC is sensitive to even weak magnetic field interference. Place the chip devoid of such active/passive magnetic fields.<br />
* 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.<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64765S21: Roadster2021-05-27T21:10:31Z<p>Proj user3: /* Introduction */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into 5 modules:<br />
<br />
* Sensor Node- Detecting obstacles in the vicinity of the car to avoid hitting the obstacle.<br />
* Geo Node- Provide heading for car to reach destination. Communicate over blue tooth with mobile application.<br />
* Driver Node- Manipulate turn angles and forward/reverse speed based on the inputs from Sensor and Geo nodes<br />
* Motor Node- PID control logic to attain the said speed/direction desired by driver node.<br />
* Android Application- Dashboard for real time data from car. Send instruction such as destination, way points and start/stop.<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
* LSM303DLHC is sensitive to even weak magnetic field interference. Place the chip devoid of such active/passive magnetic fields.<br />
* 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.<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64764S21: Roadster2021-05-27T21:01:33Z<p>Proj user3: /* Technical Challenges */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into 5 modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
* LSM303DLHC is sensitive to even weak magnetic field interference. Place the chip devoid of such active/passive magnetic fields.<br />
* 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.<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64763S21: Roadster2021-05-27T21:00:07Z<p>Proj user3: /* Technical Challenges */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into 5 modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
* LSM303DLHC is sensitive to even weak magnetic field interference. Place the chip devoid of such active/passive magnetic fields.<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64762S21: Roadster2021-05-27T20:58:46Z<p>Proj user3: /* Software Design */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into 5 modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64761S21: Roadster2021-05-27T20:48:06Z<p>Proj user3: /* Introduction */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into 5 modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64760S21: Roadster2021-05-27T20:41:58Z<p>Proj user3: /* Advise for Future Students */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64759S21: Roadster2021-05-27T20:40:32Z<p>Proj user3: /* Acknowledgement */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
* Preet's advice for buying quality hardware parts should be followed to the line.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64757S21: Roadster2021-05-27T20:34:59Z<p>Proj user3: /* Team Members & Responsibilities */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64756S21: Roadster2021-05-27T20:32:52Z<p>Proj user3: /* Acknowledgement */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64755S21: Roadster2021-05-27T20:30:49Z<p>Proj user3: /* Advise for Future Students */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.All the team members should be appreciated for their unwavering enthusiasm to make this a success story.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64752S21: Roadster2021-05-27T20:25:48Z<p>Proj user3: /* Acknowledgement */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
* 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.All the team members should be appreciated for their unwavering enthusiasm to make this a success story.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64750S21: Roadster2021-05-27T20:20:24Z<p>Proj user3: /* Conclusion */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
*All the team members should be appreciated for their unwavering enthusiasm to make this a success story. 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.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64749S21: Roadster2021-05-27T20:19:42Z<p>Proj user3: /* Conclusion */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
* 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.<br />
*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.<br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
*All the team members should be appreciated for their unwavering enthusiasm to make this a success story. 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.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64748S21: Roadster2021-05-27T20:14:19Z<p>Proj user3: /* Acknowledgement */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
*All the team members should be appreciated for their unwavering enthusiasm to make this a success story. 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.<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64747S21: Roadster2021-05-27T20:07:54Z<p>Proj user3: /* Technical Challenges */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
* 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. <br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64746S21: Roadster2021-05-27T20:05:30Z<p>Proj user3: /* Geographical Controller */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
<BR/><br />
<BR/><br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64745S21: Roadster2021-05-27T20:05:05Z<p>Proj user3: /* Hardware Design */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
<BR/><br />
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 />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64744S21: Roadster2021-05-27T20:04:39Z<p>Proj user3: /* Hardware Design */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<BR/><br />
<br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
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 />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64743S21: Roadster2021-05-27T20:04:19Z<p>Proj user3: /* Hardware Design */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
* Battery monitoring <br />
<br />
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.<br />
<BR/><br />
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 />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
<br />
=== References ===</div>Proj user3http://socialledge.com/sjsu/index.php?title=S21:_Roadster&diff=64742S21: Roadster2021-05-27T19:57:43Z<p>Proj user3: /* Hardware Design */</p>
<hr />
<div>== Roadster ==<br />
<br />
[[File:System_design_roadster.png|center|800px| System Design]]<br />
<br />
== Abstract ==<br />
Roadster is a battery powered autonomous car, that drives itself to a specified destination and avoids any obstacles that comes its way. The car infrastructure has four Nodes (Geo, Sensor, Driver and Motor) that communicate over the CAN bus and an android application interface to set the destination location. In order to make an informed decision the car processes Geo and Sensor Node’s data which is used to steer the car in the right direction.<br />
<br />
=== Introduction ===<br />
<br />
The project was divided into N modules:<br />
<br />
* Sensor Node<br />
* Geo Node<br />
* Driver Node<br />
* Geo Node<br />
* Android Application<br />
<br />
=== Team Members & Responsibilities ===<br />
<Team Picture><br />
<br />
Tejas Pidwalkar<br />
*Sensor Node<br />
*Driver Node<br />
Nimit Patel<br />
*Geo Node <br />
Tirth Pandya<br />
*Motor Node<br />
*PCB design <br />
Srikar Reddy<br />
*Android Application<br />
Sourab Gupta<br />
*Driver Node<br />
<br />
<br />
[https://gitlab.com/nimit.patel/roadster/-/tree/master Gitlab Repository]<br />
<BR/><br />
<br />
<Provide ECU names and members responsible><br />
<One member may participate in more than one ECU><br />
<br />
* Sensor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Geo Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Driver Node<br />
** [https://gitlab.com/nimit.patel/roadster/-/tree/Main/Driver_Node DriverNode Gitlab Repository]<br />
<br />
* Motor Node<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Android Application<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
* Testing Team<br />
** Link to Gitlab user1<br />
** Link to Gitlab user2<br />
<br />
<HR><br />
<BR/><br />
<br />
== Schedule ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Week#<br />
! scope="col"| Start Date<br />
! scope="col"| End Date<br />
! scope="col"| Task<br />
! scope=:col"| Actual Completion<br />
! scope="col"| Status<br />
|-<br />
! scope="row"| 1 <br />
03/01 to 03/07 <br />
<font color = "sienna"> ''Start of Phase 1''</font color><br />
|<br />
* 03/01<br />
* 03/04<br />
* 03/05<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/07<br />
|<br />
* Study and discuss previous project reports<br />
* Brainstorm on the requirements for the project<br />
* Identify and order/purchase the required components <br />
|<br />
* 03/04<br />
* 03/07<br />
*<font color = "maroon"> 03/09<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 2<br />
03/08 to 03/14<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/11<br />
* 03/12<br />
|<br />
* 03/08<br />
* 03/08<br />
* 03/14<br />
* 03/14<br />
|<br />
* Create and setup Gitlab Repository<br />
* Create and setup Confluence for document collaboration<br />
* Study the datasheets and manual of acquired components<br />
* Distribute initial roles among the team members<br />
|<br />
* 03/04<br />
* 03/07<br />
* 03/17<br />
* 03/15<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 3<br />
03/15 to 03/21<br />
|<br />
* 03/15<br />
* 03/15<br />
* 03/19<br />
* 03/18<br />
* 03/15<br />
|<br />
* 03/18<br />
* 03/18<br />
* 03/21<br />
* 03/21<br />
* 03/27<br />
|<br />
* Interface ultrasonic sensors and test the functionality <br />
* Interface GPS and Compass and test the functionality<br />
* Analyze and decide the hardware placement of the RC Car<br />
* Create SENSOR and DRIVER nodes to transmit and receive data<br />
* Identify the Android app requirements and start studying the Android framework<br />
|<br />
* 03/18<br />
* <font color = 'maroon'> 03/22 </font><br />
* 03/20<br />
* 03/21<br />
* 03/25<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 4<br />
03/22 to 03/28<br />
|<br />
* 03/22<br />
* 03/22<br />
* 03/25<br />
* 03/27<br />
* 03/22<br />
|<br />
* 03/25<br />
* 03/24<br />
* 03/28<br />
* 03/31<br />
* 03/28<br />
|<br />
* Create the GEO node to get coordinates and cardinal directions from GPS and Compass <br />
* Interface the Bluetooth module to communicate with SJ-two board<br />
* Create the MOTOR node to drive the RC Car<br />
* Start designing the DBC file<br />
* Develop an initial version of the Android app<br />
|<br />
* <font color = 'maroon'>03/24</font> <br />
* <br />
* 03/28<br />
* 03/30<br />
* 03/28<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 5<br />
03/29 to 04/04<br />
<font color = "sienna"> ''End of Phase 1''</font color><br />
|<br />
* 04/02<br />
* 03/29<br />
* 03/29<br />
* 03/29<br />
* 03/31<br />
* 04/03<br />
|<br />
* 04/03<br />
* 04/01<br />
* 04/01<br />
* 04/01<br />
* 04/03<br />
* 04/04<br />
|<br />
* Finalize the DBC file <br />
* Design obstacle avoidance and steering logic on the DRIVER node<br />
* Design motor driving logic on the MOTOR node with the encoder<br />
* Interface the LCD module with the DRIVER node to display messages<br />
* Integrate sensor data on the SENSOR node<br />
* '''Collective Test 1:'''<font color = "DarkGreen"> '''Integrate all the completed modules and test on BusMaster''' </font color><br />
|<br />
* <font color = 'maroon>04/05</font><br />
* 04/01<br />
*<br />
* <br />
* <font color = 'maroon'>04/04</font><br />
* 04/04<br />
| <br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "blue"> ''In Progress''<br />
*<font color = "green"> Completed<br />
*<font color = "green"> Completed<br />
|-<br />
! scope="row"| 6<br />
04/05 to 04/11<br />
<font color = "magenta">''Start of Phase 2''</font color><br />
|<br />
* 04/05<br />
* 04/05<br />
* 04/08<br />
* 04/10<br />
|<br />
* 04/08<br />
* 04/08<br />
* 04/10<br />
* 04/11<br />
|<br />
* Tune the SENSOR and DRIVER nodes to drive the RC car<br />
* Communicate to the DRIVER node over Bluetooth via Android app<br />
* Debug and revise the integrated modules with necessary improvements<br />
* '''Collective Test 2''':<font color = "DarkGreen">''' Drive the car to a hardcoded GPS destination'''</font color> <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 7<br />
04/12 to 04/18<br />
|<br />
* 04/12<br />
* 04/15<br />
* 04/12<br />
* 04/17<br />
|<br />
* 04/15<br />
* 04/18<br />
* 04/16<br />
* 04/18<br />
|<br />
* Integrate GEO node to DRIVER node for navigation<br />
* Design driving decision logic based on the navigation data<br />
* Design a dashboard on the LCD to display the values<br />
* '''Collective Test 3''':<font color = "DarkGreen">''' Test the car driving with navigation data from the Android app'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 8<br />
04/19 to 04/25<br />
<font color = "magenta">''End of Phase 2''</font color><br />
|<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
* 04/19<br />
|<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
* 04/25<br />
|<br />
* Add functionalities to display various sensor data on the Android app<br />
* Design and 3D print the required components<br />
* Design and order PCB<br />
* Test and improve the RC car performance based on the changes <br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 9<br />
04/26 to 05/02<br />
<font color = "Tomato">''Start of Phase 3''</font color><br />
|<br />
* 04/26<br />
* 04/26<br />
* 04/26<br />
* 05/01<br />
|<br />
* 04/30<br />
* 04/30<br />
* 04/30<br />
* 05/02<br />
|<br />
* Design individual architecture diagrams and algorithms for documentation<br />
* Make any necessary improvements based on previous test results<br />
* Complete the final version of the Android app<br />
* '''Collective Test 4:'''<font color = "DarkGreen">''' Test car on various terrains and slopes'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
| <br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 10<br />
05/03 to 05/09<br />
|<br />
* 05/03<br />
* 05/03<br />
* 05/03<br />
* 05/08<br />
|<br />
* 05/07<br />
* 05/07<br />
* 05/07<br />
* 05/09<br />
|<br />
* Replace the circuits with their corresponding PCBs and assemble<br />
* Complete the RC Car structure and assembly with the 3D printed parts - Prototype 1<br />
* Refactor the code modules with necessary improvements<br />
* '''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><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|-<br />
! scope="row"| 11<br />
05/10 to 05/16<br />
<font color = "Tomato">''End of Phase 3''</font color><br />
|<br />
* 05/10<br />
* 05/10<br />
* 05/10<br />
* 05/15<br />
|<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
* 05/16<br />
|<br />
* Revise and improve the wiki report to cover all the aspects of design and implementation<br />
* Fix all the errors and make improvements<br />
* Final testing of all the modules and car<br />
* '''Collective Test 6:'''<font color = "DarkGreen">''' Have the final version of the project tested with all the functionalities'''</font color><br />
|<br />
* <br />
* <br />
* <br />
* <br />
|<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
*<font color = "gray"> N/A<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Parts List & Cost ==<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Item#<br />
! scope="col"| Part Desciption<br />
! scope="col"| Vendor<br />
! scope="col"| Qty<br />
! scope="col"| Cost<br />
|-<br />
! scope="row"| 1<br />
| RC Car <br />
| Traxxas [https://www.amazon.com/gp/product/B07DFXN118/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1]<br />
| 1<br />
| $250.00<br />
|-<br />
! scope="row"| 2<br />
| CAN Transceivers MCP2551-I/P<br />
| 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]<br />
| 5<br />
| $7.00<br />
|-<br />
! scope="row"| 3<br />
| Ultrasonic Sensors<br />
| Max Botix[https://www.amazon.com/gp/product/B07Q588SBP/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1]<br />
| 5<br />
| $150.00<br />
|-<br />
! scope="row"| 4<br />
| GPS and Antenna<br />
| 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]<br />
| 1<br />
| $60.00<br />
|-<br />
! scope="row"| 5<br />
| HC05 bluetooth RF Transreceiver<br />
| HiLetgo[https://www.amazon.com/HiLetgo-Bluetooth-Transceiver-Integrated-Communication/dp/B07VL725T8/]<br />
| 1<br />
| $12.59<br />
|-<br />
! scope="row"| 6<br />
| Triple-axis Accelerometer<br />
| Adafruit[https://www.adafruit.com/product/1120]<br />
| 1<br />
| $21.40<br />
|-<br />
! scope="row"| 7<br />
| Traxxas RPM Sensor<br />
| Traxxas[https://www.amazon.com/Traxxas-6520-RPM-Sensor-long/dp/B006IRXEZM]<br />
| 1<br />
| $12<br />
|-<br />
! scope="row"| 8<br />
| Discrete Electronic Components<br />
| Generic[http://www.excesssolutions.com/]<br />
| 1<br />
| $28.75<br />
|-<br />
! scope="row"| 9<br />
| Buck-Boost Voltage Regulator<br />
| Generic[https://www.amazon.com/Adjustable-Converter-Automatic-Voltage-Regulator/dp/B07NTXSJHB/]<br />
| 1<br />
| $11.99<br />
|-<br />
! scope="row"| 10<br />
| Traxxas Telemetry Trigger magnet & holder<br />
| Traxxas[https://www.amazon.com/Traxxas-Telemetry-Trigger-Magnet-Holder/dp/B00864A3T0/]<br />
| 1<br />
| $6.35<br />
|-<br />
! scope="row"| 11<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 12<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 13<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
! scope="row"| 14<br />
| <br />
| Amazon[]<br />
| 1<br />
| $<br />
|-<br />
|}<br />
<br />
<HR><br />
<BR/><br />
<br />
== Printed Circuit Board ==<br />
<Picture and information, including links to your PCB><br />
<br><br />
<br />
<HR><br />
<BR/><br />
== CAN Communication ==<br />
<Talk about your message IDs or communication strategy, such as periodic transmission, MIA management etc.><br />
<br />
=== Hardware Design ===<br />
<Show your CAN bus hardware design><br />
<br />
=== DBC File ===<br />
<Gitlab link to your DBC file><br />
<You can optionally use an inline image><br />
<br />
<br />
<HR><br />
<BR/><br />
== Sensor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== <font color="0000FF">Technical Challenges </font>===<br />
<br />
==== Neighboring Sensor Interference: ====<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Motor ECU ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Geographical Controller ==<br />
<br />
''[https://gitlab.com/nimit.patel/roadster/-/merge_requests/5 Repository link for Geo Controller]''<br />
<br />
=== Hardware Design ===<br />
<br />
[[File:GPS.jpg|400px|thumb|left|GPS Module]]<br />
[[File:compass_roadster.jpg|400px|thumb|right|3 Axis Magnetometer (eCompass)]]<br />
[[File:Votlage Divider.jpg|400px|thumb|center|Battery Monitoring]]<br />
[[File:Hc05.jpeg|400px|thumb|left|Bluetooth Trans-receiver]]<br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
<BR/><br />
The SJ2 board communicates with:<br />
* Bluettoth transreceiver over UART<br />
* LSM303DLHC over I2C<br />
* GPS model over UART<br />
**Battery monitoring <br />
<br />
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.<br />
<br />
=== Software Design ===<br />
[[File:Geo logic.png|800px|thumb|center|Heading computation from geographical (Geo) controller]]<br />
<br />
The GEO controller is divided into 5 parts.<br />
<br />
*The current location of the car is determined using the GPS.<br />
<br />
*The current magnetic heading of car is determined using the on board compass.<br />
<br />
*The way point calculation determines the nearest way point continuously by computing the distance using Haversine formula and current location using GPS.<br />
<br />
*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.<br />
<br />
*Alternatively, once the car is within the threshold distance, next way point is selected and the car heads to the next way point.<br />
<br />
=== Technical Challenges ===<br />
<br />
* 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.<br />
* 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.<br />
*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.<br />
<br />
<HR><br />
<br />
== Communication Bridge Controller & LCD ==<br />
<Picture and link to Gitlab><br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
== Driver Node ==<br />
<Picture and link to Gitlab><br />
<br />
<br />
=== Hardware Design ===<br />
<br />
=== Software Design ===<br />
*Flow Chart<br />
[[File:Drivernode flowchart.png|1000px|thumb|center|Driver Node Flow Chart]]<br />
<br />
<br />
*Obstacle Avoidance Logic<br />
[[File:Obstacle avoidance fsm2.png]]<br />
<br />
*1 Hz Loop:<br />
**Transmit debug messages over the CAN bus<br />
*20 Hz Loop:<br />
**Receive Sensor Data<br />
**Receive Geo Data<br />
**Process and Transmit Data(Motor Direction and Speed) to Motor Node<br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<HR><br />
<BR/><br />
<br />
== Mobile Application ==<br />
<Picture and link to Gitlab><br />
We created a lightweight mobile app to control 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.<br />
<br />
=== Software Design ===<br />
This app has mainly two activities, The main activity and maps activity.<br />
<br />
===Maps Activity===<br />
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.<br />
<br />
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. Bluetooth socket module provides read() and write() API used to communicate. Below is the code snippet that parses the incoming stream with location and debug data sent by the bridge node. <br />
<br />
if(readMessage.indexOf("\n")>0) {<br />
message = new StringTokenizer(readMessage, "\n");<br />
StringTokenizer st;<br />
while (message.hasMoreTokens()) {<br />
st = null;<br />
received_line = message.nextToken();<br />
st = new StringTokenizer(received_line, ",");<br />
try {<br />
read = st.nextToken();<br />
} catch (Exception e) {<br />
continue;<br />
}<br />
if (read.compareTo("GPS") == 0) {<br />
try {<br />
LatLng current_location = new LatLng(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));<br />
waypoint.setText(st.nextToken("\n").replace(",", ""));<br />
prev.remove();<br />
prev = mMap.addMarker(new <br />
MarkerOptions().position(current_location).anchor(0.5f,0.5f).rotation(compass_value).title("Roadster")<br />
.icon(BitmapFromVector(getApplicationContext(), R.drawable.ic_baseline_directions_car_filled_24)));<br />
if (state || init) {<br />
mMap.moveCamera(CameraUpdateFactory.newLatLng(current_location));<br />
if (current_location.latitude != 0) init = false;<br />
}<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("speed") == 0) {<br />
try {<br />
speed.setText(st.nextToken("\n").replace(",", "") + "m/s");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("sens") == 0) {<br />
try {<br />
left.setText(st.nextToken() + "cm");<br />
right.setText(st.nextToken() + "cm");<br />
center.setText(st.nextToken() + "cm");<br />
back.setText(st.nextToken("\n").replace(",", "") + "cm");<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("comp") == 0) {<br />
try {<br />
compass.setText(st.nextToken());<br />
String compass_s=st.nextToken("\n").replace(",", "");<br />
compass_raw.setText(compass_s);<br />
compass_value =Integer.parseInt(compass_s);<br />
prev.setAnchor(0.5f,0.5f);<br />
prev.setRotation(compass_value);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("dist") == 0) {<br />
try {<br />
String dis=st.nextToken("\n").replace(",", "");<br />
distance.setText(dis+"m");<br />
//int prog=(int)Float.parseFloat(dis)%200;<br />
//progress.setProgress(prog);<br />
} catch (Exception e) {<br />
}<br />
} else if (read.compareTo("mot") == 0) {<br />
try {<br />
rps.setText(st.nextToken());<br />
pwm.setText(st.nextToken("\n").replace(",", ""));<br />
} catch (Exception e) {<br />
}<br />
}<br />
else if(read.compareTo("bat")==0){<br />
try{<br />
battery.setText(st.nextToken("\n").replace(",", "")+"%");<br />
}catch (Exception e){<br />
}<br />
}<br />
}<br />
readMessage="";<br />
<br />
=== Hardware Design ===<br />
<br />
<br />
<List the code modules that are being called periodically.><br />
<br />
=== Technical Challenges ===<br />
<br />
< List of problems and their detailed resolutions><br />
<br />
<br />
<BR/><br />
<HR><br />
<HR><br />
<BR/><br />
<br />
== Conclusion ==<br />
<Organized summary of the project><br />
<br />
<What did you learn?><br />
<br />
=== Project Video ===<br />
<br />
=== Project Source Code ===<br />
''[https://gitlab.com/nimit.patel/roadster Repository link for Autonomous RC Car]''<br />
<br />
=== Advise for Future Students ===<br />
* 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.<br />
*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.<br />
* 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.<br />
<br />
=== Acknowledgement ===<br />
<br />
=== References ===</div>Proj user3