Week 9
Output Devices
Overview
This week I attempted to build a simplified acoustic levitator, using the SAMD21E18A breakout board I built last week. Unfortunately, the levitator is still a work-in-progress, but I pivoted to using an Adafruit_SSD1306 OLED display as my output device for the assignment this week. This page documents my successes and failures throughout the week.
Microcontroller (Recap of Week 8)
Just as a quick recap, in Week 8 I designed and fabricated a PCB for programming a SAMD21E18A microcontroller. This is the board I will be using this week to control my acoustic levitator. The images below illustrate the process of taking a schematic built in KiCad to physical circuit board. For a more detailed explanation of this process, check out my post from Week 8.
Acoustic Levitator - Background
Acoustic levitation is a key component of my final project, so I thought I'd use this week to work on building a deeper understanding of how it works. I've found several resources around the web on acoustic levitation using ultrasonic arrays, the full list can be found on my final project page. This project is what I used as inspiration and as a reference for this week's assignment. The project distills the acoustic levitation output device to the simplest form I've found - two opposing transmitters from HC-SR04 ultrasonic sensors. I wanted my first step in exploration to align closely with the documented work, so I ordered a couple L239N gate driver breakout boards. These are currently sold on Amazon in packs of 8 for ~$10.
Acoustic Levitator - Setup
To build the output device, I started by detaching the transmitting sensors from two pairs of HC-SR04 ultrasonic sensors. I stripped a couple jumpers wires to use as... jumper wires. With the multimeter I identified the positive and negative leads on each transducer. I did this by setting the multimeter to a constant voltage, then touching the negative multimeter lead to one leg and then the positive lead to the other leg. If the voltage read negative on the multimeter, I marked the first transducer leg I touched (with the negative multimeter lead) as negative. If the voltage read positive, I marked the first transducer leg I touched (with the negative multimeter lead) as positive. Soldered the jumper wires together in parallel, considering the +/- information. Finally, I stripped the screen of an unused receiving transducer to build a little scoop for the foam particles I planned to levitate.
Acoustic Levitator - Programming
TLDR: I overlooked the instruction differences between AVR and ARM...
The code (below) provided in the Makezine link above (and in the several replications of this project around the internet) is for an ATMEAG328P (Arduino Uno). I assumed the coding portion of this setup was taken care of and (incorrectly) budgeted time accordingly. As a workaround, I started digging into the datasheet of the SAMD21 to see if I could deconstruct the AVR code and rewrite it for the SAMD21. However, during this experimentation my laptop stopped reliably recognizing my board. At first, I could simply remove and/or reset the board and the computer would again recognize it, but I could find no repeatable pattern. Eventually, the laptop would more often not recognize the board than recognize it, until it stopped recognizing it completely. I visually inspected, probed with the multimeter for continuity, but didn't find any issues. Without any other ideas, I removed the SAMD21 chip and swapped it for a new one. I was able to program it fine, but could not get my computer to recognize it. This time, I think the issues was because the data line from the USB port to the chip had become very burned from all the soldering, that the copper was lifting off the board. I decided to make a fresh board in the morning and fix some issues with my previous board.
byte TP = 0b10101010; // Every other port receives the inverted signal
void setup() {
DDRC = 0b11111111; // Set all analog ports to be outputs
// Initialize Timer1
noInterrupts(); // Disable interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 200; // Set compare register (16MHz / 200 = 80kHz square wave -> 40kHz full wave)
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS10); // Set prescaler to 1 ==> no prescaling
TIMSK1 |= (1 << OCIE1A); // Enable compare timer interrupt
interrupts(); // Enable interrupts
}
ISR(TIMER1_COMPA_vect) {
PORTC = TP; // Send the value of TP to the outputs
TP = ~TP; // Invert TP for the next run
}
void loop() {
// Nothing left to do here :)
}
New Board Intermission
On the bright side, this process feels like it's getting quicker for me. I cleaned up the board design in Adobe Illustrator, removed all the pine names (which didn't mill well and caused connectivity issues), added a pinout for 5V, and exported as 1000ppi PNGs. I imported the board into mods and milled it without any issues. After I removed it from the SRM-20, I spent a bit more time cleaning the board. I removed all the non-trace copper with a razor blade and tweezers, rinsed the board of all debris and dried it. Soldered all the components went fairly quickly. Finally, I bootloaded the board and my computer was recognizing it.
Pivot to OLED Output
Given the timing and mindset, I wanted to get an output device working (and a win for morale) prior to attempting to rewrite the acoustic levitation code. I found a Adafruit_SSD1306 OLED display in the lab I decided to use. I downloaded the library for the display from within the Arduino IDE. Details of this process can be found on the GitHub repo for the Adafruit_SSD1306. Tried one of the examples, OLED_featherwing (which is also a SAMD board), but ran into issues with the library. However, I found Lingdong's extremely helpful GitLab issue write-up, which noted a bug in the library and included a fixed version of the C++ file. With the fixed added to the library, I was able to successfully push the OLED_featherwing example I was trying to push. After, I had to try Lingong's other test script, which also worked smoothly and added to the morale boost I was looking for.
Acoustic Levitator - ATTINY1614 Breakoutboard
I did a cursory look of readily stocked AVR microcontrollers in the fab with similar timer/counter abilities as the ATMEGA238P, and found that the ATTINY1614 might work. I also found a fab academy student who had previously built a breakout board for the ATTINY1614. So I milled this board to experiment and see if I could easily get it to drive the ultrasonic sensors via the L298N driver board. Unfortunately, I ran into address issues between the Makezine code above and the corresponding components within the ATTINY1614. The rough cut of the board was also giving me concerns on the reliability of connections between components. A couple of days ago I had ordered an ATMEGA2560 for this very purpose and had received a message that it arrived. Instead of going further with this ATTINY board, I decided to test the setup with a known working 2560.
Acoustic Levitator - ATMEGA2560 Setup
I set up the acoustic levitator with the L239N board and ATMEGA2560, pictured below, so that it mimics the setup of the Makezine article. After reconfiguring the Arduino IDE with the ATMEGA2560 board, I was able to push the code to the board without an issue. However, I was not getting any signal from the ultrasonic sensors. I began through the datasheet of the ATMEGA2560 and ATMEGA328P, comparing the addresses in each line of the code. On the initial pass everything looked the same, it wasn't until I started getting into the weeds of each address that I noticed a difference. On the 328P, the Analog Input pins are on Port C, whereas on the 2560 the Analog Input pins are on Port F and Port K. Changing "DDRC" to "DDRF" (line 3) and "PORTC" to "PORTF" (line 16) fixed the issue. I could hear the faintest sound of oscillating pulses coming from the transducers, which gave me the feeling of my first hello world blinking LED. I spent an hour or so in the middle of the night playing with spacing between the transducers to levitate a small foam particle, but had no success. I think I am very close though, to be continued...
Update 11/20:
We have levitation! Looks like input voltage seemed to be the remaining issue. I was providing 5V to the ultrasonic sensors previously, straight from the USB. However, using two 9V batteries in series, for a total of 18V, was enough to provide the necessary amplitude of waves. Check out the video below to see the results. Note - the sound IRL is inaudible, but can be quite annoying in the video.