For a school project I'm currently working on a metronome with LEDs; the beats per minute (the tempo) being controlled by a potentiometer. I'm making the circuit in Tinkercad before I'm physically making everything, because I want to make sure it's gonna work properly.
This is the code I wrote:
#include <LiquidCrystal.h>
#include <math.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Setting up the LCD which displays the BPM.
int sensorPin = A0; // Potentiometer
int led1 = 13;
int led2 = 12;
int led3 = 11;
int led4 = 10; // Yes I'm using 4 LEDs instead of one, I just like the looks of having 4 LEDs.
int sensorValue;
int outputValue;
float bpm_ms;
int counter = 0;
String bpm_str; // To display the BPM onto the lcd display.
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print("BPM");
Serial.begin(9600);
}
void loop() {
// Reading the potentiometer
sensorValue = analogRead(sensorPin);
// Mapping to be able to choose a BPM between 60 and 170.
outputValue = map(sensorValue, 0, 1023, 60, 170);
// To display the BPM with LEDs there has to be a certain amount of time between ticks, thus 60s (60000ms) / BPM.
bpm_ms = float(60000.0/outputValue);
// Displaying the BPM on the lcd is basically converting the mapped sensorValue to a string.
bpm_str = String(outputValue);
lcd.setCursor(6,0);
lcd.print(bpm_str);
// This metronome is only used for 4/4 beats; when the counter hits 1 I want the 1st LED to blink and so on.
counter += 1;
if(counter==1) {
digitalWrite(led1,HIGH);
delay(bpm_ms);
digitalWrite(led1,LOW);
}
if(counter==2) {
digitalWrite(led2,HIGH);
delay(bpm_ms);
digitalWrite(led2,LOW);
}
if(counter==3) {
digitalWrite(led3,HIGH);
delay(bpm_ms);
digitalWrite(led3,LOW);
}
if(counter==4) {
digitalWrite(led4,HIGH);
delay(bpm_ms);
digitalWrite(led4,LOW);
counter = 0;
}
}
I know it looks amateurish, please just keep in mind this is my first Arduino project
The issue is that delay() only takes integers as parameters, but because that ignores all the decimals my metronome isn't 100% accurate (I tested it with online BPM tap tools). Using something more precise like delayMicroseconds() doesn't work with my code: delayMicroseconds() doesn't take large numbers as parameters:
For delays longer than a few thousand microseconds, you should use delay() instead.
bpm_ms = float(60000.0/outputValue) calculates the amount of milliseconds between ticks, so
bpm_ms = float(60000000.0/outputValue) would calculate the amount of microseconds.
This would result in bpm_ms to be 631579 (rounded) for a BPM of 95, a large number delayMicroseconds() doesn't work with.
This is why I was wondering if anyone knows a way to make the calculations I use in my code more precise. If you happen to know a way where my code didn't need to be completely altered, it would be amazing but I'm also okay with changing my code if it's to a point that I still understand what's happening