ASSIGNMENT
Add an output device to a microcontroller board you've designed, and program it to do something
After the class, and due to the inability of being in the lab to choose from different output devices, i decided i would look around the house to see if i could scavenge something. I found 2 old PCs, a pentium2 and a pentium4 and opened them to start looking for things.
After much unscrewing, forcing and vacuum-cleaning, i got all of this out:
- A bunch of cables with headers.
- 2 floppy disk drives: 4 motors out of them.
- 3 optical drives: 3 laser diodes, 9 motors.
- 5 fans. All rated a 12v DC.
- 2 speakers of different sizes.
To start with, i went with the speakers since it seemed like the easiest thing to play with. They just have two cables, ground and VCC, no mistery.
From Neil's class i knew, through the C example seen on class, that you had to pass both frequency and amplitude
I started looking on how to do PWM with the ESP32, and found this really nice guide that explains every step. The guide is focused on cycling through the brightness of an LED, but in the end it's all the same. The functions used belong to Espressif's arduino-esp32 library, and are all meant to deal with LEDs if you look at the function names: ledcWrite, ledcAttachPin, ledcSetup...
but again, it's all the same. What matters is the library allows you to output PWM passing in frequency and amplitude.
As a first test, i just the code from that website as is. Here it is, changing the comments to remove the LED references. What this does is just ramp up the volume from 0 to 255, and then ramp it down at a fixed frequency of 5000Hz (annoyingly high by the way).
The most interesting part is in the setup part, where you configure the PWM mode from the 3 parameters.
#define PIN 12
// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;
void setup() {
// configure PWM functionalitites
ledcSetup(ledChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(PIN, ledChannel);
}
void loop() {
// increase the amplitude
for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
// decrease the amplitude
for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
}
Once i saw that it was working and how annoying it was to listen to, i rushed to make some changes. I figure that if i called the setup functions inside the loop while changing the frequency values, i could create something more melodic. So i chose to try to change frequencies. The fastest thing i could think of, was to use the for loops to increment and decrement the frequency inside the loop cycle. So i just needed to add a call to setup the PWM parameters by using the iteration to change the frequency:
void loop() {
// increase the amplitude
for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){
ledcSetup(ledChannel, dutyCycle*20, resolution);
ledcWrite(ledChannel, 255);
delay(15);
}
// decrease the amplitude
for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
ledcSetup(ledChannel, dutyCycle*20, resolution);
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
}
And here's the result:
Next, i decided to create random noises that follow the chromatic scale ( C-D-E-F-G-A-B ). To do so i had to lookup a table that matched notes to frequencies, and found this one. I created a frequencies array from C4 to B4 like so: int freqs[] = {261.63, 293.66, 329.63, 349.23, 392, 440, 493.88};
and then on the loop function i would just pick a random number from 0 to 6 and play that frequency for a certain amount of time:
void loop() {
int rnd = random(7);
ledcSetup(ledChannel, freqs[rnd], resolution);
ledcAttachPin(PIN, ledChannel);
ledcWrite(ledChannel, 150);
delay(100);
}
Now this sounds a bit like the soundtrack of an old video game! I also plugged in the second speaker i had found inside the PCs, just for fun.
Lastly, The 8-bit 1980s video game soundtrack generator !. With just a couple of changes, we could get this to create a somewhat listenable thing that could well be the endless soundtrack of a 1980s 8-bit video game.
1) Add some silences in between notes, so that it doesn't feel like an eternal stream of sounds:
// Create some variety on notes vs. silences.
int note = random(6);
if (note > 4)
{
ledcWrite(ledChannel, 0);
}
else
{
ledcWrite(ledChannel, 255);
}
2) Add some variety in the length of notes and silences. To do so, i just generate another random number from 1 to 4 and delay by multiples of 100ms times that number
// create some variety on length of notes
rnd = random(4);
delay(100*rnd);
The files