ECE 3400 Wiki - Eli Zhang (ekz5)

ECE 3400 Wiki

View on GitHub

ECE 3400 Wiki

This is the wiki page for Eli Zhang (ekz5).

Lab 1

In Lab 1, we constructed the basic photoresistor voltage divider circuits and connected them to the Arduino Nano Every. These photoresistors will be used in Lab 2 to navigate the robot based on different lighting conditions.

By calling analogRead on the proper pins and measuring how the analog readings changed for the left and right photoresistors, I was able to determine the lighter and darker portions of the room (comparing left and right).

The photoresistors were placed in the breadboard and turned to either side to get proper light readings, as shown in the picture below.

To determine the number of incident photons per second, I used the millimeter measurements listed in the datasheet for the photoresistor and calculated the approximate square meters.

The only additions made to the code were defining new analog pins to read values related to the photoresistors, calculating the relative left and right values related to brightness, and printing out the measurements.

Lab 2

In Lab 2, we added the H-bridge controller to the Arduino, calibrated the wheels to travel at the same speed, and tested moving towards light sources.

The first part of the lab was just reading datasheets to find the clock frequency, which wasn't actually used later in the lab.

Then we had to implement moving the wheels forward and backward independently. This was difficult at first because I forgot to connect the grounds of the Arduino and the AA battery holder, so they didn't move at all initially. I also had to connect all the relevant H-bridge controller pins to the Arduino with a series resistor, which helped limit the H-bridge current draw and prevent back-EMF. We also added decoupling capacitors between power and ground.

Programming the motors to move was relatively straightforward: I just found the numbers of the connected Arduino pins (ensuring the enA and enB were PWM-compatible), set them as outputs, and then changed the analogWrite value to set the speed. Reversing the high and low values for each motor's input pins reversed the direction. Then I set up code to rotate the required direction for each stage and kept track of the stage with a counter that I incremented. Instead of using delay(), I kept a value tracking previousMillis and compared it to the current millis() reading to figure out when to proceed to the next stage.

For the next portion of the lab, we had to calibrate the motors to have the car drive forward at a consistent speed. Since the wheels touched the ground unevenly, in order to the get the car moving forward consistently I had to set the motor speed for one motor to be 30 higher than the other. Afterwards it worked relatively well.

At this point I realized that my Vin wasn't working properly: either the 9V had discharged somehow or the pin was fried, since connecting the battery directly to Vin and GND didn't end up turning the Arduino on. For the rest of the lab I had to do all my tests while plugged in from USB.

To get the LED blinking, I used a similar timing mechanism to my earlier implementation to increment the stage number. I determined the different light thresholds and values by printing the sensor values to the Serial console. To determine when the light was on the left or right side, I compared the normalized values and checked when the difference was sufficiently high and it wasn't too bright. If the conditions were met, I turned on one motor to orient in the correct direction and if both values were high enough and the difference wasn't significant, I turned on both motors to drive the car forward. Otherwise, I flashed the LED normally and turned on only one motor to "search" for a light source.

Lab 3

The primary purpose of lab 3 was to test how well we could capture frequency information with the help of the Fast Fourier Transform and different filters. The first part of the lab was testing how these filters would ideally perform and setting up the microphone circuit. Using both LTSpice and Cadence, I was able to generate graphs for the low pass and high pass filters that matched the expected behavior, with the corner frequency at 1/RC radians.

The microphone circuit, pictured below, could then be used to test whether experimental behavior resembled ideal behavior.

Before setting up the microphone with the filters, I first had to set up the ADC to run freely and to read from the analog pin connected to the microphone. Using the data on the analog pin (which is originally taken in as an unsigned positive value), I then normalized it by finding the middle value by looking at the analog reading when there was little to no noise. This middle value was subtracted from all analog readings. Then I scaled the new value up by a constant, which was determined by finding the maximum possible value the ADC variable could hold and dividing by the maximum possible adjusted reading.

With the new normalized values, I was able to read them over a serial port over a period of time while a tone at a given frequency was playing. This allowed me to graph the waveform and also run a Fast Fourier Transform on the output to measure relevant frequencies in the incoming signal to the microphone. These graphs are pictured below:

In the next part of the lab, I actually built the filters to test their behavior compared to the original graphs. However, to read the output better, I added an amplifier circuit using an op amp. Getting the correct behavior was pretty challenging, despite properly placing the resistors and capacitors on the output of the amplifier circuit. Below is an example of what the amplified circuit waveform looked like:

However, when adding the low pass and high pass circuits and sweeping the frequencies, although the behavior of the circuit vaguely resembled the ideal behavior, it behaved much more inconsistently at different frequencies than expected. LPF Behavior (ideal vs. experimental):

HPF Behavior (ideal vs. experimental):

As seen in the comparison graphs, although there were dips in the LPF for higher frequencies as expected and the HPF generally followed the expected behavior and the transfer function increased for higher frequencies, there were still weird jumps that did not reflect the desired behavior.

For the Butterworth bandpass filter, behavior was similarly inconsistent in some ways. Although there was a range where the transfer function was larger and it falls off on either sides, the range did not exactly match the target frequencies.

All these inconsistencies could have been caused by many things, such as component inconsistencies, not being able to sample properly at all frequencies, and poor microphone behavior. However, we can see that in general the experimental behavior vaguely resembled ideal behavior.

For the third part of the lab, we performed the FFT directly on the Arduino at different frequencies. The behavior here was much more consistent, as shown below: 500 Hz:

700 Hz:

900 Hz:

First, I removed the BPF since it was performing inconsistently. This caused the FFT to be noisier than expected, but there are still three clearly longer stems in bins that correspond to the tone that was being played for each frequency. Getting the FFT to work involved installing the FFT library, enabling the interrupt, and sampling ADC values, normalizing them and storing them in an array to process with the FFT library. This was similar to all the ADC reading we did earlier in the class. The FFT values could then be copied into MATLAB and graphed with relative ease.

Lab 4

In the final lab, we set up two demos: one to demonstrate the FFT capabilities on the Arduino and to configure the ultrasonic sensor, and the other to show the light-following abilities combined with the ultrasonic sensor.

For the first part of the lab, we had to set up the ultrasonic sensor and configure the FFT library to run continuously. This required dividing the code into two sections: one where the Arduino continuously ran the FFT code from the previous lab, writing over the array and checking to see if any of the bins of the relevant target frequency were beyond a certain threshold. If they were, the robot would transition into its second stage, where the TCA period would change to instead interrupt every microsecond.

Since our code wasn't supposed to be blocking, I needed the TCA interrupt to track microseconds since I couldn't use delayMicros(). The ultrasonic sensor tracks distance by sending out and receiving sound pulses, so by configuring the interrupt to count microsecond intervals, I was able to recreate the earlier ultrasonic code example we had without using any blocking delays.

In the second section of the code, I continuously monitored the ultrasonic readings and updated the onboard LED accordingly to indicate whether an obstacle was detected. It was easy to differentiate between the two sections of the demo with a simple switch statement and a variable to track the current stage.

For the second demo of the final lab, I had to reconfigure the Arduino to take in light readings and direct the car with the light, similar to how we did in lab 1 and 2. This just involved copying code from the earlier labs and modifying certain light thresholds. Since in the earlier labs we had the robot spin in place if there was too much light or not enough light, I had to also remove some code to make sure it remained immobile when there wasn't the right amount of light detected.

The rest of the second demo was just figuring out how each step of the demonstration would be programmed. Every step was some variant of the earlier code we've done: following the light until an obstacle a certain distance was detected, or waiting for the light to come from one direction before proceeding to the next step. With a variable to track the step number, it was easy to divide the logic up for the demonstration into clear conditions to proceed in the switch statement.

One problem that kept occurring was the light in the room kept changing throughout the day. This made the thresholds I coded in work inconsistently, so I had to tape a large curtain over the window to prevent any light from entering the room (the curtain kept falling down because the tape was from 7-11). I also had a lot of trouble getting the car to drive on the carpet, partially because one of the wheels may have been slightly off the ground at some points because the floor wasn't level. I fixed this by taping small dense objects to the back of my car to weigh down the wheels.

I was also finally able to run my Arduino with the 9V battery after replacing the Arduino Nano Every with a different one.

The car is pictured below:

A video of the demo can be found here: https://streamable.com/s/suf7vj