Difference between revisions of "F15: Smart Car"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Parts List & Cost)
(Conclusion)
 
(97 intermediate revisions by the same user not shown)
Line 1: Line 1:
=== Grading Criteria ===
+
== Smart Car ==
<font color="green">
 
*  How well is Software & Hardware Design described?
 
*  How well can this report be used to reproduce this project?
 
*  Code Quality
 
*  Overall Report Quality:
 
**  Software Block Diagrams
 
**  Hardware Block Diagrams
 
**:  Schematic Quality
 
**  Quality of technical challenges and solutions adopted.
 
</font>
 
 
 
== Project Title ==
 
Smart Car
 
  
 
== Abstract ==
 
== Abstract ==
A smart car with three wheels will be designed to have the capability of following high contrast lines. Options for the lines include using black Sharpie, black duct tape, and white duct tape. Afterwards, it will send back a CSV file format with 0s and 1s. 1s denote that the car was traveling in the area of the map. Using a peripheral compass, the car will also be able to draw a map of the route that it took.
+
A smart car with three wheels will be designed to have the capability of following high contrast lines. Options for the lines include using black Sharpie, black duct tape, and white duct tape. Afterwards, it will send back an X and Y coordinate which will be used to plot a visual representation of where the car has traveled onto the LED matrix. The controller board is in charge of plotting the LED matrix while the car's board is in charge of sending X and Y coordinates.
  
 
== Objectives & Introduction ==
 
== Objectives & Introduction ==
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.
+
Our objectives include the following:
 +
* Self-driving car that is able to follow a line
 +
* LED matrix that can draw out the path the car is taking
  
 
=== Team Members & Responsibilities ===
 
=== Team Members & Responsibilities ===
Line 27: Line 16:
  
 
== Schedule ==
 
== Schedule ==
Show a simple table or figures that show your scheduled as planned before you started working on the project.  Then in another table column, write down the actual schedule so that readers can see the planned vs. actual goals.  The point of the schedule is for readers to assess how to pace themselves if they are doing a similar project.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 44: Line 32:
 
| 10/30
 
| 10/30
 
| Gather parts
 
| Gather parts
| Incomplete
+
| Complete
 
|-
 
|-
 
! scope="row"| 3
 
! scope="row"| 3
 
| 11/06
 
| 11/06
| Complete project abstract
+
| Program compass
 
| Complete
 
| Complete
 
|-
 
|-
 
! scope="row"| 4
 
! scope="row"| 4
 
| 11/13
 
| 11/13
| Complete project abstract
+
| Program LED matrix
 
| Complete
 
| Complete
 
|-
 
|-
 
! scope="row"| 5
 
! scope="row"| 5
 
| 11/20
 
| 11/20
| Complete project abstract
+
| Program wireless functionality
 
| Complete
 
| Complete
 
|-
 
|-
 
! scope="row"| 6
 
! scope="row"| 6
 
| 11/27
 
| 11/27
| Complete project abstract
+
| Build car
 
| Complete
 
| Complete
 
|-
 
|-
 
! scope="row"| 7
 
! scope="row"| 7
 
| 12/04
 
| 12/04
| Complete project abstract
+
| Put all the pieces together
 
| Complete
 
| Complete
 
|-
 
|-
 
! scope="row"| 8
 
! scope="row"| 8
 
| 12/11
 
| 12/11
| Complete project abstract
+
| Testing
| Complete
+
| Incomplete
 
|}
 
|}
  
== Parts List & Cost ==
 
 
- Servos (2)
 
 
- Motors (2)
 
 
- LED matrix array $24.95
 
 
- Array of sensors
 
 
== Parts List & Cost ==
 
== Parts List & Cost ==
  
Line 96: Line 75:
 
|-
 
|-
 
! scope="row"| 2
 
! scope="row"| 2
| SJ-One development board
+
| SJ-One board
 
| $80 ea
 
| $80 ea
 
|-
 
|-
Line 108: Line 87:
 
|-
 
|-
 
! scope="row"| 1
 
! scope="row"| 1
| Omniwheel
+
| Electric tape
| $4.47
+
| $1.99 ea
 
|-
 
|-
 
! scope="row"| 1
 
! scope="row"| 1
 
| Compass
 
| Compass
| $
+
| $14.95
 
|-
 
|-
 
! scope="row"| 2
 
! scope="row"| 2
 
| Motors
 
| Motors
| $80~
+
| $0 (reused)
 
|-
 
|-
! scope="row"| 2
+
! scope="row"| 1
 
| LED matrix
 
| LED matrix
 
| $24.95 ea
 
| $24.95 ea
 +
|-
 +
! scope="row"| 2
 +
| Photoresistors
 +
| $1.20 ea
 +
|-
 +
! scope="row"| 3
 +
| Jumper cables
 +
| $3.99 ea
 +
|-
 +
! scope="row"| 1
 +
| Super glue
 +
| $3.99 ea
 +
|-
 +
! scope="row"| 1
 +
| Breadboard
 +
| $6.49 ea
 +
|-
 +
! scope="row"| 2
 +
| NPN transistors
 +
| $3.29 ea
 +
|-
 +
! scope="row"| 1
 +
| 5k potentiometer
 +
| $2.29 ea
 +
|-
 +
! scope="row"| 1
 +
| Switch
 +
| $2.99 ea
 
|-
 
|-
 
! scope="row"|  
 
! scope="row"|  
Line 129: Line 136:
 
! scope="row"|  
 
! scope="row"|  
 
| Estimated total
 
| Estimated total
| $
+
| $243.12
 
|-
 
|-
  
Line 135: Line 142:
  
 
== Design & Implementation ==
 
== Design & Implementation ==
 +
[[File:Cmpe146_F15_smartcar_car.jpg|700px]]
  
 
=== Hardware Design ===
 
=== Hardware Design ===
Discuss your hardware design here. Show detailed schematics, and the interface here.
+
[[File:Cmpe146_F15_smartcar_system.png]]
 +
 
 +
=== Compass ===
 +
 
 +
The compass uses I2C as the communication protocol. The x, y, and z coordinates were able to be read from the compass depending on its orientation. After one of the SJSUOne boards reads the x, y, and z values from the compass, it wirelessly sends the values to the other board to determine which LEDs to light up. The compass' purpose was to determine the car's location so that the path the car was taking could be drawn on the LED matrix.
 +
 
 +
[[File:cmpe146_F15_smartcar_compassInterface.png]][[File:Cmpe146_F15_smartcar_compass.jpg|300px|right|HMC5883L Compass]]
 +
 
 +
=== LED Matrix ===
 +
The purpose of the LED matrix was to display the path that the car is traveling. It uses SPI as its communication protocol. The LED matrix consists of 2 x 3 blocks of 8x8 LEDs. It has a few ports that must be utilized for LED programming. The first port is the WR port which is listed as active low. This is actually the serial clock which captures data in its DATA port on rising edges. While the datasheet recommends using an idle LOW serial clock, this is not a must. With the LPC1758, changing the active level of the serial clock is not the solution to this and will cause problems for data transmission to the LED matrix as it will be transmitting data on the falling edge instead and data corruption will occur.
 +
 
 +
[[File:Cmpe146_F15_smartcar_ledmatrix.jpg|500px|LED Matrix]]
 +
 
 +
=== Motors ===
 +
NPN transistors were used to control the power source to the motors. There was very little documentation for the motors used so initial tests with varying input voltages yielded that these motors seemed to operate successfully at 5V. This method should not be used on documented motors. Instead make sure to adhere to the specifications provided. In addition, if the input voltage is negated, the motor had the ability to rotate in the opposite direction. For the application, only the positive voltage was utilized since the car did not need to go backwards. For turning purposes, one motor moved slower than the other.
 +
 
 +
=== Photoresistor ===
 +
Photoresistors are resistors that have a special characteristic of having different resistances when exposed to differing intensities of light. If high intensity light is absorbed, the photoresistor will have a low resistance. If low intensity light is absorbed, the photoresistor will have a high resistance.
 +
 
 +
Initial tests of the photoresistors yielded a magnitude of several hundred ohms when shone by a very bright phone LED and several mega-ohms in a very dark setting. A voltage divider circuit was used to read the intensity of light with a 10kOhm resistor.
 +
 
 +
By using a resistor that had a magnitude logarithmically near the center of the two values, a decent range of voltage readings was able to be provided in many different environments in the voltage divider circuit. This would prove useful for light-sensitive applications.
 +
 
 +
ADC channels were used to record the voltage across the 10kOhm resistor. There were only two configurations to record the voltage from: across photoresistor or across 10kOhm resistor. Measuring across the constant resistance was chosen because when the photoresistor became exposed to light, the resistance would drop, and the voltage drop across the photoresistor would decrease in the voltage divider circuit. Therefore, the voltage divider circuit provided an analog voltage between the two resistors with a positive correlation to brightness instead of darkness.
 +
 
 +
[[File:Cmpe146_F15_smartcar_voltagedivider.png]]
 +
 
 +
=== SJOne ===
 +
The SJOne was the microprocessor used for this project. The USB port from the PC was used to power the board. The 3.3V output was used to power the compass and the LED matrix. The compass and LED matrix were interfaced with the SJOne board. The compass used I2C while the LED matrix used SPI. The wireless functionality of the board was also utilized to in order to send information from one board to another.
  
 
=== Hardware Interface ===
 
=== Hardware Interface ===
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.
+
Communication protocols used:
 +
 
 +
#'''I2C''' - HMC5883L Compass
 +
#'''SPI''' - LED matrix
 +
#'''PWM''' - Motors
  
 
=== Software Design ===
 
=== Software Design ===
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.
+
The software design utilizes drivers such as SPI and I2C. In addition to the drivers, Nordic wireless functionality was programmed.
 +
 
 +
'''Reading Position'''
 +
 
 +
The X, Y, and Z coordinates were able to be read from the compass depending on its orientation. After one of the SJSUOne boards reads the X, Y, and Z values from the compass, it wirelessly sends the values to the other board to determine which LEDs to light up. The compass' purpose was to determine the car's direction. Once the direction is interpreted, it is combined with the speed of the car to calculate position.
 +
 
 +
 
 +
'''Displaying position'''
 +
 
 +
The position of the car will be centered around the center point of the LED matrix which we will map to coordinates (1,1), (1,-1), (-1, -1) and (-1,1). The first digit is the position we are at West vs East while the second digit represents how far we went North or South. Positive corresponds to traveling East and North for the first and second digit respectively.
 +
 
 +
 
 +
'''Handling Start/Stop and Compass readings'''
 +
 
 +
The wireless transceiver task for the controller (with the LED matrix) is in charge of sending start and stop commands to the vehicle. In addition, the car’s board will be sending map coordinates for its X and Y coordinates. The controller will be in charge of turning that X and Y mapping into a format such that the LED matrix can properly display the data.
 +
 
 +
The format for the wireless transmission will be:
 +
 
 +
Byte 0,,,,,,,Byte 1,,,,,,,,,,,,,,,,,Byte 2
 +
 
 +
0x00,,,,,,,,,Start(1)/Stop(0)
 +
 
 +
0x01,,,,,,,,,X position,,,,,,,,,,,,,Y position
  
 
=== Implementation ===
 
=== Implementation ===
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.
+
'''Obtaining Compass Readings'''
 +
 
 +
In order to do read values from the compass, the compass must be in continuous read mode. Continuous read mode is enabled by writing a 0 to register 2. After continuous read mode is enabled, the values could be read by writing a 0 to register 3 and register 4 for x, a 0 to register 5 and register 6 for z, and a 0 to register 7 and 8 for y.
 +
 
 +
 
 +
'''Mapping Received Coordinates to LED Matrix'''
 +
 
 +
There were only a few SPI ports and SPI0 was used for the original LED driver. Unfortunately, this was the same SPI port used for our wireless transceiver. As a result, the SPI port is shared between the two tasks. Currently there is no thread-safe protection with the SPI port and therefore some wireless communication may be dropped as a result. In order to share the SPI driver, the clock speed of the driver must be changed before/after each transmission to the LED matrix.
 +
 
 +
The controller on the car is in charge of reading the compass heading and translating that into a x and y vector where the combined vector would always yield the same magnitude. This would give us a more accurate reading for the car’s position at all times. This would be multiplied with the speed at which the car is moving and generate an X and Y position. On startup, the car will be placed at location 0,0. Since the LED matrix’ center cannot be represented on an even-dimension display (no true center), we will be setting the mapping of row 0 and column 0 to 1’s instead. Therefore the starting point will actually be displayed as 1,1 offset from the true center of the LED display.
 +
 
 +
The software to generate the correct register address/data is provided in the mapping.h header file. The addressing is quite complicated so when providing the user interface, we decided to organize the user’s API to only have to worry about putting an X and Y coordinate. In one layer, the X and Y coordinate are converted into a format of row, block and data. There are 16 rows, and each block consists of 8 columns. Therefore there are 16 rows and 3 blocks with each data being 8 bits (8 LEDs) wide. In the next layer, we convert from the 2D array of rows and blocks of data into the actual register mapping on the LED matrix.
 +
 
 +
 
 +
'''Brightness'''
 +
 
 +
Since we decided to make our ADC channel have a positive correlation to the intensity of light, we can interpret the mV reading as a starting point for measuring the brightness of the environment of the photoresistor. This raw data can be used in more advanced ways such as passing it through a filter or for a calibration step but that is a possible option that we did not explore too deeply.
 +
 
 +
 
 +
'''Motor Control'''
 +
 
 +
In order to control a DC motor without an analog high-power source coming from the SJ One Board, we utilize a PWM channel to control the gate to an npn transistor. By putting the motor in series with the transistor and the power source, we can use a lower voltage/power source from our microcontroller to control the source of the motor. At a high enough frequency, the circuit acts similarly to a high-powered analog source controlled by the microcontroller.
 +
 
 +
The software for the motor control is premature as it receives limited information from the photoresistors and converts that into an error term that is handled only by a proportional and integral control. There needs to be more thought involved in calibrating the movement code. The logic for the motor control is merely, if the left photoresistors is brighter than the right photoresistors , then that means we are veering off course too far to the right of the tape. Therefore, we increase the command to the right motor and decrease the command to the left motor, attempting to return the motor back on track. Since we did not have reversing capabilities on our motors, there was no way to stop in place and return back on track before continuing. This was an adaptation that was inadequately handled and required more thought.
  
 
== Testing & Technical Challenges ==
 
== Testing & Technical Challenges ==
Describe the challenges of your project.  What advise would you give yourself or someone else if your project can be started from scratch again?
+
'''Plotting coordinates on the LED'''
Make a smooth transition to testing section and described what it took to test your project.
 
  
Include sub-sections that list out a problem and solution, such as:
+
To test plotting the coordinates on the LED, we put the mapping code on the controller and transmitted X and Y coordinates through the terminal. This was before we had issues with our SPI drivers when the LED task was running in conjunction with the wireless task. This test would make sure that each step from X and Y position code to LED display work correctly. We tested the corners of each block of LEDs on our display to make sure the mapping software was setting the appropriate registers on the LED matrix.
 +
 
 +
 
 +
'''Running the LED matrix mapping'''
 +
 
 +
For the LED matrix mapping, we wrote tests to print out the result of turning a 2D array mapping of bytes into messages over SPI. Each bit that is set in the 2D array represents an LED. To test that each LED was addressed properly, we light up each LED in order until the entire LED matrix is lit up. In fact, due to this test being useful for many applications. We kept this in the code base running parallel to our X and Y plotter. Since the memory used to store the LED mappings was not completely volatile (existed a few minutes after loss of power), we had code to erase the LED matrix using a preprocessor compilation variable called ERASE. If ERASE is set, then the LED matrix will be erased. Otherwise, the LED matrix will be filled up. By compiling with ERASE being set, we guarantee that each time we restart the processor, the LED matrix will be reinitialized.
 +
 
 +
 
 +
'''Testing the Smart Car'''
 +
 
 +
We ran several tests for this design and went through several tuning methods but each method we attempted would force the car to go off track very often. We would place the car to go onto the center of the tape but detect that the phototransistor readings were actually quite different from each other due to the lighting and shadows made from the car. After each iteration, the correction algorithms would be changed but to no luck. At one point we managed to keep the robot on track by having very small error correction but the moment it hit a turn, it would not be capable of adjusting quickly enough.
 +
 
 +
== Issues Faced ==
 +
'''Wireless communication and LED Matrix'''
  
== Issue 1 ==
 
Wireless communication and LED Matrix
 
 
The LED matrix that was used was programmed using SPI0. However, it turns out that SPI0 is shared with the wireless communication API. To fix the issue, the LED matrix was reprogrammed on SPI1.
 
The LED matrix that was used was programmed using SPI0. However, it turns out that SPI0 is shared with the wireless communication API. To fix the issue, the LED matrix was reprogrammed on SPI1.
 +
 +
 +
'''Varied lighting conditions'''
 +
 +
The car was tested in various conditions, which affected our ability to calibrate the photoresistors properly. Additionally, the lighting in the environment often cast a shadow on one of the photoresistors, giving them very different values even though the car was centered on the white line. This drastically affected the car's ability to successfully follow the line.
 +
 +
 +
'''Voltage drops'''
 +
 +
A 9V battery was used to power the motors and the LED strip. However, the LED strip required a vast amount of current that the battery was not able to fully supply. As a result, the voltage of the batteries dropped drastically. This caused the LED strip to dim and the motors to move extremely slowly. Due to those two problems, consistent calibration of the car was not successful.
  
 
== Conclusion ==
 
== Conclusion ==
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?
+
The goal of the project was to create a car that would be able to follow a line and to display the car's path on an LED matrix. The LED matrix mapped the car's path, but the car was not able to successfully follow a line. This is due to the lack of time that was spent testing. The light of the environment that the car is vital to proper calibration. Because of how varied the environment the car was tested in was, its ability to follow the line was compromised. In addition, the light also cast a shadow underneath the car which affected the photoresistors. Ultimately, the project reinforced the concepts learned in CMPE146, particularly through the use of SPI and I2C drivers for communication between external hardware modules and the microprocessor.  
  
=== Project Video ===
+
We learned that more time should be spent on the car's line-following capabilities as it was the largest functional requirement we promised. The compass to LED mapping was only a nice to have. Tracking a line is very difficult and we should have spent more time researching alternatives to phototransistors such as IR sensors. We also should have investigated more configurations of the sensor locations such that we can create better car movement controls.
Upload a video of your project and post the link here.
 
  
 
=== Project Source Code ===
 
=== Project Source Code ===
Line 169: Line 273:
 
== References ==
 
== References ==
 
=== Acknowledgement ===
 
=== Acknowledgement ===
Any acknowledgement that you may wish to provide can be included here.
+
We would like to acknowledge Haluk Ozemek and Preetpal Kang for providing us with the knowledge for this project.
  
 
=== References Used ===
 
=== References Used ===
List any references used in project.
+
LED Matrix HT1632C datasheet: https://www.adafruit.com/datasheets/ht1632cv120.pdf
 +
 
 +
3-Axis Digital Compass IC HMC5883L datasheet: https://www.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf
  
 
=== Appendix ===
 
=== Appendix ===
 
You can list the references you used.
 
You can list the references you used.

Latest revision as of 16:29, 19 December 2015

Smart Car

Abstract

A smart car with three wheels will be designed to have the capability of following high contrast lines. Options for the lines include using black Sharpie, black duct tape, and white duct tape. Afterwards, it will send back an X and Y coordinate which will be used to plot a visual representation of where the car has traveled onto the LED matrix. The controller board is in charge of plotting the LED matrix while the car's board is in charge of sending X and Y coordinates.

Objectives & Introduction

Our objectives include the following:

  • Self-driving car that is able to follow a line
  • LED matrix that can draw out the path the car is taking

Team Members & Responsibilities

  • Steven Hwu
    • B.S. Computer Engineering
  • Helen Tsui
    • B.S. Computer Engineering

Schedule

Week# Date Task Actual
1 10/23 Complete project abstract Complete
2 10/30 Gather parts Complete
3 11/06 Program compass Complete
4 11/13 Program LED matrix Complete
5 11/20 Program wireless functionality Complete
6 11/27 Build car Complete
7 12/04 Put all the pieces together Complete
8 12/11 Testing Incomplete

Parts List & Cost

Quantity Description Price
2 SJ-One board $80 ea
1 Cardboard $0 ea
1 White duct tape $4.52 ea
1 Electric tape $1.99 ea
1 Compass $14.95
2 Motors $0 (reused)
1 LED matrix $24.95 ea
2 Photoresistors $1.20 ea
3 Jumper cables $3.99 ea
1 Super glue $3.99 ea
1 Breadboard $6.49 ea
2 NPN transistors $3.29 ea
1 5k potentiometer $2.29 ea
1 Switch $2.99 ea
_______
Estimated total $243.12

Design & Implementation

Cmpe146 F15 smartcar car.jpg

Hardware Design

Cmpe146 F15 smartcar system.png

Compass

The compass uses I2C as the communication protocol. The x, y, and z coordinates were able to be read from the compass depending on its orientation. After one of the SJSUOne boards reads the x, y, and z values from the compass, it wirelessly sends the values to the other board to determine which LEDs to light up. The compass' purpose was to determine the car's location so that the path the car was taking could be drawn on the LED matrix.

Cmpe146 F15 smartcar compassInterface.png
HMC5883L Compass

LED Matrix

The purpose of the LED matrix was to display the path that the car is traveling. It uses SPI as its communication protocol. The LED matrix consists of 2 x 3 blocks of 8x8 LEDs. It has a few ports that must be utilized for LED programming. The first port is the WR port which is listed as active low. This is actually the serial clock which captures data in its DATA port on rising edges. While the datasheet recommends using an idle LOW serial clock, this is not a must. With the LPC1758, changing the active level of the serial clock is not the solution to this and will cause problems for data transmission to the LED matrix as it will be transmitting data on the falling edge instead and data corruption will occur.

LED Matrix

Motors

NPN transistors were used to control the power source to the motors. There was very little documentation for the motors used so initial tests with varying input voltages yielded that these motors seemed to operate successfully at 5V. This method should not be used on documented motors. Instead make sure to adhere to the specifications provided. In addition, if the input voltage is negated, the motor had the ability to rotate in the opposite direction. For the application, only the positive voltage was utilized since the car did not need to go backwards. For turning purposes, one motor moved slower than the other.

Photoresistor

Photoresistors are resistors that have a special characteristic of having different resistances when exposed to differing intensities of light. If high intensity light is absorbed, the photoresistor will have a low resistance. If low intensity light is absorbed, the photoresistor will have a high resistance.

Initial tests of the photoresistors yielded a magnitude of several hundred ohms when shone by a very bright phone LED and several mega-ohms in a very dark setting. A voltage divider circuit was used to read the intensity of light with a 10kOhm resistor.

By using a resistor that had a magnitude logarithmically near the center of the two values, a decent range of voltage readings was able to be provided in many different environments in the voltage divider circuit. This would prove useful for light-sensitive applications.

ADC channels were used to record the voltage across the 10kOhm resistor. There were only two configurations to record the voltage from: across photoresistor or across 10kOhm resistor. Measuring across the constant resistance was chosen because when the photoresistor became exposed to light, the resistance would drop, and the voltage drop across the photoresistor would decrease in the voltage divider circuit. Therefore, the voltage divider circuit provided an analog voltage between the two resistors with a positive correlation to brightness instead of darkness.

Cmpe146 F15 smartcar voltagedivider.png

SJOne

The SJOne was the microprocessor used for this project. The USB port from the PC was used to power the board. The 3.3V output was used to power the compass and the LED matrix. The compass and LED matrix were interfaced with the SJOne board. The compass used I2C while the LED matrix used SPI. The wireless functionality of the board was also utilized to in order to send information from one board to another.

Hardware Interface

Communication protocols used:

  1. I2C - HMC5883L Compass
  2. SPI - LED matrix
  3. PWM - Motors

Software Design

The software design utilizes drivers such as SPI and I2C. In addition to the drivers, Nordic wireless functionality was programmed.

Reading Position

The X, Y, and Z coordinates were able to be read from the compass depending on its orientation. After one of the SJSUOne boards reads the X, Y, and Z values from the compass, it wirelessly sends the values to the other board to determine which LEDs to light up. The compass' purpose was to determine the car's direction. Once the direction is interpreted, it is combined with the speed of the car to calculate position.


Displaying position

The position of the car will be centered around the center point of the LED matrix which we will map to coordinates (1,1), (1,-1), (-1, -1) and (-1,1). The first digit is the position we are at West vs East while the second digit represents how far we went North or South. Positive corresponds to traveling East and North for the first and second digit respectively.


Handling Start/Stop and Compass readings

The wireless transceiver task for the controller (with the LED matrix) is in charge of sending start and stop commands to the vehicle. In addition, the car’s board will be sending map coordinates for its X and Y coordinates. The controller will be in charge of turning that X and Y mapping into a format such that the LED matrix can properly display the data.

The format for the wireless transmission will be:

Byte 0,,,,,,,Byte 1,,,,,,,,,,,,,,,,,Byte 2

0x00,,,,,,,,,Start(1)/Stop(0)

0x01,,,,,,,,,X position,,,,,,,,,,,,,Y position

Implementation

Obtaining Compass Readings

In order to do read values from the compass, the compass must be in continuous read mode. Continuous read mode is enabled by writing a 0 to register 2. After continuous read mode is enabled, the values could be read by writing a 0 to register 3 and register 4 for x, a 0 to register 5 and register 6 for z, and a 0 to register 7 and 8 for y.


Mapping Received Coordinates to LED Matrix

There were only a few SPI ports and SPI0 was used for the original LED driver. Unfortunately, this was the same SPI port used for our wireless transceiver. As a result, the SPI port is shared between the two tasks. Currently there is no thread-safe protection with the SPI port and therefore some wireless communication may be dropped as a result. In order to share the SPI driver, the clock speed of the driver must be changed before/after each transmission to the LED matrix.

The controller on the car is in charge of reading the compass heading and translating that into a x and y vector where the combined vector would always yield the same magnitude. This would give us a more accurate reading for the car’s position at all times. This would be multiplied with the speed at which the car is moving and generate an X and Y position. On startup, the car will be placed at location 0,0. Since the LED matrix’ center cannot be represented on an even-dimension display (no true center), we will be setting the mapping of row 0 and column 0 to 1’s instead. Therefore the starting point will actually be displayed as 1,1 offset from the true center of the LED display.

The software to generate the correct register address/data is provided in the mapping.h header file. The addressing is quite complicated so when providing the user interface, we decided to organize the user’s API to only have to worry about putting an X and Y coordinate. In one layer, the X and Y coordinate are converted into a format of row, block and data. There are 16 rows, and each block consists of 8 columns. Therefore there are 16 rows and 3 blocks with each data being 8 bits (8 LEDs) wide. In the next layer, we convert from the 2D array of rows and blocks of data into the actual register mapping on the LED matrix.


Brightness

Since we decided to make our ADC channel have a positive correlation to the intensity of light, we can interpret the mV reading as a starting point for measuring the brightness of the environment of the photoresistor. This raw data can be used in more advanced ways such as passing it through a filter or for a calibration step but that is a possible option that we did not explore too deeply.


Motor Control

In order to control a DC motor without an analog high-power source coming from the SJ One Board, we utilize a PWM channel to control the gate to an npn transistor. By putting the motor in series with the transistor and the power source, we can use a lower voltage/power source from our microcontroller to control the source of the motor. At a high enough frequency, the circuit acts similarly to a high-powered analog source controlled by the microcontroller.

The software for the motor control is premature as it receives limited information from the photoresistors and converts that into an error term that is handled only by a proportional and integral control. There needs to be more thought involved in calibrating the movement code. The logic for the motor control is merely, if the left photoresistors is brighter than the right photoresistors , then that means we are veering off course too far to the right of the tape. Therefore, we increase the command to the right motor and decrease the command to the left motor, attempting to return the motor back on track. Since we did not have reversing capabilities on our motors, there was no way to stop in place and return back on track before continuing. This was an adaptation that was inadequately handled and required more thought.

Testing & Technical Challenges

Plotting coordinates on the LED

To test plotting the coordinates on the LED, we put the mapping code on the controller and transmitted X and Y coordinates through the terminal. This was before we had issues with our SPI drivers when the LED task was running in conjunction with the wireless task. This test would make sure that each step from X and Y position code to LED display work correctly. We tested the corners of each block of LEDs on our display to make sure the mapping software was setting the appropriate registers on the LED matrix.


Running the LED matrix mapping

For the LED matrix mapping, we wrote tests to print out the result of turning a 2D array mapping of bytes into messages over SPI. Each bit that is set in the 2D array represents an LED. To test that each LED was addressed properly, we light up each LED in order until the entire LED matrix is lit up. In fact, due to this test being useful for many applications. We kept this in the code base running parallel to our X and Y plotter. Since the memory used to store the LED mappings was not completely volatile (existed a few minutes after loss of power), we had code to erase the LED matrix using a preprocessor compilation variable called ERASE. If ERASE is set, then the LED matrix will be erased. Otherwise, the LED matrix will be filled up. By compiling with ERASE being set, we guarantee that each time we restart the processor, the LED matrix will be reinitialized.


Testing the Smart Car

We ran several tests for this design and went through several tuning methods but each method we attempted would force the car to go off track very often. We would place the car to go onto the center of the tape but detect that the phototransistor readings were actually quite different from each other due to the lighting and shadows made from the car. After each iteration, the correction algorithms would be changed but to no luck. At one point we managed to keep the robot on track by having very small error correction but the moment it hit a turn, it would not be capable of adjusting quickly enough.

Issues Faced

Wireless communication and LED Matrix

The LED matrix that was used was programmed using SPI0. However, it turns out that SPI0 is shared with the wireless communication API. To fix the issue, the LED matrix was reprogrammed on SPI1.


Varied lighting conditions

The car was tested in various conditions, which affected our ability to calibrate the photoresistors properly. Additionally, the lighting in the environment often cast a shadow on one of the photoresistors, giving them very different values even though the car was centered on the white line. This drastically affected the car's ability to successfully follow the line.


Voltage drops

A 9V battery was used to power the motors and the LED strip. However, the LED strip required a vast amount of current that the battery was not able to fully supply. As a result, the voltage of the batteries dropped drastically. This caused the LED strip to dim and the motors to move extremely slowly. Due to those two problems, consistent calibration of the car was not successful.

Conclusion

The goal of the project was to create a car that would be able to follow a line and to display the car's path on an LED matrix. The LED matrix mapped the car's path, but the car was not able to successfully follow a line. This is due to the lack of time that was spent testing. The light of the environment that the car is vital to proper calibration. Because of how varied the environment the car was tested in was, its ability to follow the line was compromised. In addition, the light also cast a shadow underneath the car which affected the photoresistors. Ultimately, the project reinforced the concepts learned in CMPE146, particularly through the use of SPI and I2C drivers for communication between external hardware modules and the microprocessor.

We learned that more time should be spent on the car's line-following capabilities as it was the largest functional requirement we promised. The compass to LED mapping was only a nice to have. Tracking a line is very difficult and we should have spent more time researching alternatives to phototransistors such as IR sensors. We also should have investigated more configurations of the sensor locations such that we can create better car movement controls.

Project Source Code

References

Acknowledgement

We would like to acknowledge Haluk Ozemek and Preetpal Kang for providing us with the knowledge for this project.

References Used

LED Matrix HT1632C datasheet: https://www.adafruit.com/datasheets/ht1632cv120.pdf

3-Axis Digital Compass IC HMC5883L datasheet: https://www.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf

Appendix

You can list the references you used.