Analog output
1.LED dimmer controlled with analog output
Code:
// connect resistor and LED from PWM pin 5 to ground
int brightness; void setup() { pinMode(5, OUTPUT); }
void loop() { for (int brightness = 0; brightness < 256; brightness++) { analogWrite(5, brightness); delay(30); }
for (int brightness = 255; brightness >= 0; brightness--) { analogWrite(5, brightness); delay(30); } delay(1000); }
2.Servo Motor with FSR
Code:
#include <Servo.h> //attach FSR to analog input A0 //attach servo to pin 5 Servo myServo;
void setup() { myServo.attach(5); Serial.begin(9600); }
void loop() { int analogVal = analogRead(A0); Serial.println(analogVal); int angle=map(analogVal,0,1023,0,179); myServo.write(angle); delay(20); }
Troubleshoot:
First time when I ran the code, it didn't work, and I didn't see any analogVal being printed in serial monitor. So I double checked my circuit connections with the schematic diagram, and I found out that my analog read skipped over the FSR, instead, I was supposed to measure the analog input voltage from +5V across the FSR to analog pin A0. so I moved the yellow wire up a grid to connect the other side of FSR and it worked.
3. Speaker controlled by photocell to generate tone
Code:
int frequency; int analogVal;
void setup() { pinMode(9,OUTPUT); Serial.begin(9600); }
void loop() { analogVal = analogRead(A0); Serial.println(analogVal); frequency = map(analogVal,0,100 ,100,1000); tone(9,frequency); delay(30); }
Application
To apply all the topics we covered in the past two weeks, I came up with a 4/4 servo metronome which applies the concepts of digital output, analog input and analog output(PWM), tone() and servo.
The metronome is in 4/4 meter, with a BPM range of 60-160 controlled by a potentiometer. Each measure has 4 quarter-note beats generated by a piezo speaker. (1st beat is accented with higher note E3 and the rest three notes are C3). 4 LEDs correspond to which beat we are at in each measure, red LED is the 1st(accent) beat, green LEDs are the rest 3 beats. Each servo movement in one direction indicates one beat, just like how a real mechanical metronome works.
Code:
#include "pitches.h"
#include <Servo.h> int BPM; //beats per minute
int potValue;
int angle[]= {20, 160, 20, 160}; //servo pulsing between 20 -160 degrees
int melody[] = {NOTE_E3, NOTE_C3, NOTE_C3, NOTE_C3}; //notes E(accent)-C-C-C Servo myServo;
void setup() {
pinMode(2, OUTPUT); //red LED (1st beat)
pinMode(3, OUTPUT); //green LED (2nd beat)
pinMode(4, OUTPUT); //green LED (3rd beat)
pinMode(5, OUTPUT); //green LED (4th beat)
myServo.attach(9); //servo attached to pin 9 Serial.begin(9600); }
void loop() {
potValue = analogRead(A0); //analog input reading from potentiometer
BPM = map (potValue, 0, 1023, 60, 160); //map potValue to 60-160 BPM range
Serial.println("potValue:");
Serial.println(potValue);
Serial.println("BPM");
Serial.println(BPM);
//note duration converted from BPM (60000ms/min)/(number of beats/min)
int noteDuration = 60000 / BPM;
for (int thisNote = 0; thisNote < 4; thisNote++) {
//play tone E3 or C3 from speaker (pin 6) tone(6, melody[thisNote]);
//move servo by alternating direction at angle 20 and 160 each cycle through loop/each //beat is played
myServo.write(angle[thisNote]);
if (thisNote == 0) { //At 1st beat, red LED on
digitalWrite(2, HIGH);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
} else if (thisNote == 1) { //At 2nd beat, 1 st green LED on
digitalWrite(2, LOW);
digitalWrite(3, HIGH);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
} else if (thisNote == 2) { //At 3rd beat, 2nd green LED on
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
} else if (thisNote == 3) { //At 4th beat, 3rd green LED on
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, HIGH); }
//stops the program for noteDuration ms before next beat plays
delay(noteDuration);
}
}
Challenge:
I had two major problems I couldn't figure out to get the program running, so I reached out to resident Mithru and he was extremely smart and helpful. I was so impressed by how fast he identified my problems. Huge thanks to Mithru here.
One of the challenges was the note duration. As I know with tone() I can pass in 3 parameters: pin, frequency, duration. So I calculated noteDuration from BPM value converted from potentiometer reading, and passed in that noteDuration value into tone(). However, no matter how I changed the potentiometer's reading, it wouldn't affect the noteDuration at all. When I first ran it, the servo would jitter really fast in really small angles and I can barely tell the beats from each other. It just sounded like a consecutive C note. Then I changed the delay(20) after tone() and myServo.write() to delay(100) and to delay (500), and to delay(1000), I noticed the milliseconds in delay() is what actually affecting the speed of the beats. So I passed noteDuration into delay() and it worked, and the speaker was playing beats accurately at the BPM printed on serial monitor. Though I still do no know why passing in noteDuration doesn't change anything. If I can just add a delay() to pulse the notes, what does the duration in tone(pin, frequency, duration) do?
Another problem I encountered was that although the LEDs were lit in synch with the beats, the order of the color being lit did not match the order of the beats being played. The order of lighting is lagging 1 beat behind the notes. As opposed to notes E-C-C-C corresponding to LED R-G-G-G. It was behaving as notes E-C-C-C corresponding to LED G-R-G-G. Then I noticed it was because I had delay(noteDuration) placed ahead of the codes for LED, therefore resulting in LEDs lagging one beat behind the corresponding notes. I fixed the problem by placing delay after LED code at the end of for loop.