LCD displays 0-1023 instead of 30 to 350?

I expected my liquid crystal display to have a range of 30 to 350. When I turn the 5K potentiometer the LCD display's range is 0 to 1023. I thought my code would scale the range down, but it does not. Code is below

#include<LiquidCrystal.h> // Library for the Liquid Crystal Display
LiquidCrystal lcd(12,11,5,4,3,2);  //  Digital pins for the Liquid Crystal Display

const int duration = 50; // Duration of LED staying on during bpm
int potPin = 0;
int potValue;  //Potentiometer pin


unsigned int beats_per_minute = 60; // Variables to track tempo and time delay
unsigned int MS_per_beat = 0;
void setup()
{
  lcd.begin(16,2); // Begin LCD
  lcd.clear();  // Clear LCD screen
  unsigned int milliseconds_per_minute = 1000 * 60;  //Calculate MS_per_beat based on tempo in bpm
  MS_per_beat = milliseconds_per_minute/beats_per_minute;
 }
void loop()
{
int value = analogRead(potPin); //Check the status of the potentiometer
  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
  beats_per_minute = map(potValue, 0, 1023, 30, 350); // Map the value to a reasonable metronome range of 30 to 350 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  potValue = value; //Update potvalue
}
  lcd.setCursor(0,0);
  lcd.print("Beat Per Minute");
  lcd.setCursor(0,1);
  lcd.print(value); //Output to the LCD
  delay(MS_per_beat); //Delay loop for specified amount of time
  lcd.clear(); //Clear LCD screen
  }

try lcd.print(beats_per_minute); instead of lcd.print(value);

shouldn't your main loop be like this ?

void loop()
{
int value = analogRead(potPin); //Check the status of the potentiometer
  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
  beats_per_minute = map(potValue, 0, 1023, 30, 350); // Map the value to a reasonable metronome range of 30 to 350 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  potValue = value; //Update potvalue

  lcd.setCursor(0,0);
  lcd.print("Beat Per Minute");
  lcd.setCursor(0,1);
  lcd.print(beats_per_minute); //Output to the LCD
//  delay(MS_per_beat); //Delay loop for specified amount of time
//  lcd.clear(); //Clear LCD screen
}
  }

It is bed time, will check it out and report back in the morning. Thanks!

Congrats [KeithHilton]on a perfectly posted code, big step up ,,,,,onwards and etc :laughing:

Not sure what the intent is but that code seems to be calculating and displaying the previous beats per minute not the current one.
i.e. if you change the pot, it calculates and displays things based on the pot reading prior to changing it.

  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
  beats_per_minute = map(potValue, 0, 1023, 30, 350); // Map the value to a reasonable metronome range of 30 to 350 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  potValue = value; //Update potvalue

I would think it should be this if you want to see the beats per minute based on the current pot reading:

  if (value != potValue) //Recalculate the tempo if the value has changed. 
  {
    potValue = value; //Update potvalue
    beats_per_minute = map(potValue, 0, 1023, 30, 350); // Map the latest potValue to a reasonable metronome range of 30 to 350 bpm
    unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
    MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time

Thanks to Kassimsamjl and bperrybap! With the addition of their suggestions to the code, the LCD started printing from 30 to 350 as I turned the 5K control potentiometer.
I wanted to add a red led to blink at the beats per minute rate also. I hooked up a red led, anode to pin 8 of the digital, and 1K resistor cathode to ground. I included the constants as const int ledPin = 8 I tried adding code 6 lines up from the bottom to make the led come on. Nothing I wrote in code on that line would work. Things like ledPin(beats_per_minute); What do I need to write in that space to make the led blink at the beats per minute rate? The following code ran, but did not light the led, because I can't come up with the correct command.

#include<LiquidCrystal.h> // Library for the Liquid Crystal Display
LiquidCrystal lcd(12,11,5,4,3,2);  //  Digital pins for the Liquid Crystal Display

const int duration = 50; // Duration of LED staying on during bpm
const int ledPin = 8;
const int potPin = 0;
int potValue;  //Potentiometer pin
unsigned int beats_per_minute = 60; // Variables to track tempo and time delay
unsigned int MS_per_beat = 0;
void setup()
{
  lcd.begin(16,2); // Begin LCD
  lcd.clear();  // Clear LCD screen
  unsigned int milliseconds_per_minute = 1000 * 60;  //Calculate MS_per_beat based on tempo in bpm
  MS_per_beat = milliseconds_per_minute/beats_per_minute;
 }
void loop()
{
int value = analogRead(potPin); //Check the status of the potentiometer
  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
  potValue-value;
  beats_per_minute = map(potValue, 0, 1023, 30, 350); // Map the value to a reasonable metronome range of 30 to 350 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  potValue = value; //Update potvalue
}
  lcd.setCursor(0,0);
  lcd.print("Beats Per Minute");
  lcd.setCursor(0,1);
  lcd.print(beats_per_minute); //Output to the LCD
  delay(MS_per_beat); //Delay loop for specified amount of time
  lcd.clear(); //Clear LCD screen
  }

This is exactly where all your timing is done.

It is inaccurate to the extent that all the other work in the loop take some time of its own.

But probably close enough…

So here is also where you can blink your LED.

   digitalWrite(theLEDPin, HIGH);

   delay(MS_per_beat - MS_per_beat / 2);

   digitalWrite(theLEDPin, LOW);

   delay(MS_per_beat / 2);

Replace the one line full delay with the four line half delays and turn on and off the LED.

This is until the whole thing gets redone, but if the timing accuracy and general behaviour are OK, so too should this.

You'll need to

const byte theLEDPin = 8;    // put an LED on pin 8

up top and place

pinMode(theLEDPin, OUTPUT);

in your setup().

Oh, I see you already in your code those little dets.

Edit: I tweaked the maths a bit to improve accuracy.

HTH

a7

Thanks alto777, it worked, my LED is blinking in what ever beats per minute the LCD is showing. The code I wrote was slightly different than what you typed, but I got the general idea, from your basic examples. alto777 Thank You! Below is the code that makes it work!

#include<LiquidCrystal.h> // Library for the Liquid Crystal Display
LiquidCrystal lcd(12,11,5,4,3,2);  //  Digital pins for the Liquid Crystal Display

const int duration = 50; // Duration of LED staying on during bpm
const byte ledPin = 8; //put a LED on pin 8
const int potPin = 0;
int potValue;  //Potentiometer pin
unsigned int beats_per_minute = 60; // Variables to track tempo and time delay
unsigned int MS_per_beat = 0;
void setup()
{
  pinMode(ledPin,OUTPUT);
  lcd.begin(16,2); // Begin LCD
  lcd.clear();  // Clear LCD screen
  unsigned int milliseconds_per_minute = 1000 * 60;  //Calculate MS_per_beat based on tempo in bpm
  MS_per_beat = milliseconds_per_minute/beats_per_minute;
 }
void loop()
{
int value = analogRead(potPin); //Check the status of the potentiometer
  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
  potValue-value;
  beats_per_minute = map(potValue, 0, 1023, 30, 350); // Map the value to a reasonable metronome range of 30 to 350 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  potValue = value; //Update potvalue
}
  lcd.setCursor(0,0);
  lcd.print("Beats Per Minute");
  lcd.setCursor(0,1);
  lcd.print(beats_per_minute); //Output to the LCD
  digitalWrite(ledPin, HIGH);
  delay(MS_per_beat / 2);
  digitalWrite(ledPin, LOW);
  delay(MS_per_beat / 2);
  lcd.clear(); //Clear LCD screen
  }

Nice. If you happy, me too.

But the slight edit that came to me while I was doing the dishes is worth noticing, if not that important

In integer arithmetic odd numbers make for a tiny problem.

Take 51 ms per beat.

51 ms per beat as

51 / 2 and 51 / 2 is

25 + 25

only 50 milliseconds total.

If we instead do

51 / 2 and 51 - 51 / 2 or

25 and 51 - 25 (26)

then the total is 25 + 26 or 51.

So one delay is MS_per_beat / 2, and the other MS_per_beat - MS_per_beat / 2.

Like I said, no one gonna notice. But something to keep in mind if it ever became. Critical.

Another little trick you could do is to have a fixed LED ON period like this

   digitalWrite(theLEDPin, HIGH);

   delay(30);    // 30 ms STAB of light, fixed

   digitalWrite(theLEDPin, LOW);

   delay(MS_per_beat - 30);   // off for the rest of the beat period

Play on!

a7

alto 777 thanks, I understand concerning the time difference. I will try what you suggest.

I put your code into some instrumentation.

Everything but the delay part takes around 1/10 of a millisecond. We can ignore that.

In the timing section, the writing to the LCD takes around 5 milliseconds. Accuracy can be improved by subtracting 5 from the calculated MS_per_beat figure.

  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  MS_per_beat -= 5;  // compensate for slow LCD writing

Generally the original was about 1 % slow. The adjustment makes it closer to 99.9 % accurate.

Inaccuracy will also come from the Arduino clock, which depends on the type. Resonators are 0.5% to 1%, crystal oscillators much better.

Not too bad for a tiny amount of code and near literal simplicity of function. Of course there are other ways of doing this, but this is success with which I cannot argue.

a7

alto777, thanks for checking the timing accuracy! Looks like all that is needed is to add the MS_per_beat - =5; right before the void loop()
If you will look at the last complete code I posted above, I failed to do what you suggested. The code ran. I went back yesterday, and put the code in you suggested and it ran. I assume the time was better. With the addition of what you suggested today the timing will be 99.9% accurate. The the delay code part that is listed above was changed to this code yesterday.

  digitalWrite(ledPin, HIGH);
  delay(MS_per_beat - MS_per_beat / 2);
  digitalWrite(ledPin, LOW);
  delay(MS_per_beat / 2);
  lcd.clear(); //Clear LCD screen

Just to be complete and sure you've done the -5 adjustment, and for anyone copying your project, please post the last version.

The three lines in my adjustment are meant to be three lines in a row right there where the other two lines were... so when you say it is

right before the void loop()

makes me think it went in the wrong place.

On these mission critical matters it is important to strive for perfection. :wink:

a7

alto777 Below is the code you requested, my last version of the code. Is everything in it's correct place?

#include<LiquidCrystal.h> // Library for the Liquid Crystal Display
LiquidCrystal lcd(12,11,5,4,3,2);  //  Digital pins for the Liquid Crystal Display

const int duration = 50; // Duration of LED staying on during bpm
const byte ledPin = 8; //put a LED on pin 8
const int potPin = 0;
int potValue;  //Potentiometer pin
unsigned int beats_per_minute = 60; // Variables to track tempo and time delay
unsigned int MS_per_beat = 0;
void setup()
{
  pinMode(ledPin,OUTPUT);
  lcd.begin(16,2); // Begin LCD
  lcd.clear();  // Clear LCD screen
  unsigned int milliseconds_per_minute = 1000 * 60;  //Calculate MS_per_beat based on tempo in bpm
  MS_per_beat = milliseconds_per_minute/beats_per_minute;
  MS_per_beat -= 5;
 }
void loop()
{
int value = analogRead(potPin); //Check the status of the potentiometer
  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
  potValue-value;
  beats_per_minute = map(potValue, 0, 1023, 30, 225); // Map the value to a reasonable metronome range of 30 to 350 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  potValue = value; //Update potvalue
}
  lcd.setCursor(0,0);
  lcd.print("Beats Per Minute");
  lcd.setCursor(0,1);
  lcd.print(beats_per_minute); //Output to the LCD
  digitalWrite(ledPin, HIGH);
  delay(MS_per_beat - MS_per_beat / 2);
  digitalWrite(ledPin, LOW);
  delay(MS_per_beat / 2);
  lcd.clear(); //Clear LCD screen
  }

alto777 Notice I changed the 30, 350 in my previous code, to 30, 225 in the code above. I thought 350 was to fast for a song tempo.

Oh, no! My bad.

Sry sry sry, there are two places where those lines appear. I may have been vaguely aware at one time that you do the calculation in setup() as well as loop().

I noticed your original range and had to google-remind myself, 40 to 208 was used quite a bit. There is no hard standard, but your high number did seem a bit prestissimo.

Prestississimo, haha.

So here’s the code for what I hope will be near the last time for version 1. I moved one thing out because it is a constant, no large deal. I added the -5 correction where it wasn’t.

I removed this line

    potValue - value;

which is a perfectly fine way of doing… nothing.

I used the IDE autoformat tool to make it one kind of pretty.

# include <LiquidCrystal.h> // Library for the Liquid Crystal Display
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //  Digital pins for the Liquid Crystal Display

const int duration = 50; // Duration of LED staying on during bpm
const byte ledPin = 8; //put a LED on pin 8
const int potPin = A0;

const unsigned int milliseconds_per_minute = 1000 * 60;

int potValue;  //Potentiometer pin
unsigned int beats_per_minute = 60; // Variables to track tempo and time delay
unsigned int MS_per_beat = 0;

void setup()
{
//  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);
  lcd.begin(16, 2); // Begin LCD
  lcd.clear();  // Clear LCD screen

  //calculate milliseconds per beat
  MS_per_beat = milliseconds_per_minute / beats_per_minute;
  MS_per_beat -= 5;  // allow for LCD writing time
}

void loop()
{
  int value = analogRead(potPin); //Check the status of the potentiometer
//  Serial.println(value);

  if (value != potValue) //Recalculate the tempo if the value has changed.
  {
    beats_per_minute = map(value, 0, 1023, 30, 225); // Map the value to a reasonable metronome range of 30 to 350 bpm

    MS_per_beat = milliseconds_per_minute / beats_per_minute; //Recalculate milliseconds per beat
    MS_per_beat -= 5;  // allow for LCD writing time

    potValue = value; //Update potValue
  }
  lcd.setCursor(0, 0);
  lcd.print("Beats Per Minute");
  lcd.setCursor(0, 1);
  lcd.print(beats_per_minute); //Output to the LCD
  digitalWrite(ledPin, HIGH);
  delay(MS_per_beat - MS_per_beat / 2);
  digitalWrite(ledPin, LOW);
  delay(MS_per_beat / 2);
  lcd.clear(); //Clear LCD screen
}

YIKES. Best for last. I noticed the slide fader had a bit of a challenge setting the tempo. I traced it to a little thinko no one noticed. You may have noticed it's a bit fiddly - you can get it to work, but it is not perfect. The code above has that corrected.

   beats_per_minute = map(potValue, 0, 1023, 30, 225); // Map the value to a reasonable metronome range of 30 to 350 bpm

should use value, the reading from the potentiometer.

Lastly, into a wokwi to test for damages. As far as I can tell it is functioning to specification.

I'm never sure of anything anymore, but I think we can stamp this with the old "MARK VII".

доверяй, но проверяй.

a7

OK there remains the tiniest of flaws, Imma let you discover (or not!) what that might be and fix it yourself (or not!).

Not a show stopper or anything, just one of those things one tends to see after programming lotsa little devices with pots and LEDs and stuff.

Tiny. Little. Flaw.

a7

alto777 I will study what you wrote and let you know my opinion soon.

alto777 I made some corrections. Don't know if the corrections are the tiny flaws you mentioned? My corrected code is below. I have always wondered about this line in the code const int duration = 50; //Duration of the LED staying on during bpm. Why is that even needed? 50 mili-seconds is a very short duration. At what speed is the human eye no longer able to perceive the off and on anyway?
Also, I am using a 5K potentiometer. A larger value potentiometer might be needed. The larger the potentiometer the smaller the jumps in beats per minute, as your move the potentiometer. The potentiometer value being bigger should make the LCD read out more stable as the potentiometer was moved.

#include<LiquidCrystal.h> // Library for the Liquid Crystal Display
LiquidCrystal lcd(12,11,5,4,3,2);  //  Digital pins for the Liquid Crystal Display

const int duration = 50; // Duration of LED staying on during bpm
const byte ledPin = 8; //put a LED on pin 8
const int potPin = 0;
int potValue;  //Potentiometer pin
unsigned int beats_per_minute = 60; // Variables to track tempo and time delay
unsigned int MS_per_beat = 0;
void setup()
{
  pinMode(ledPin,OUTPUT);
  lcd.begin(16,2); // Begin LCD
  lcd.clear();  // Clear LCD screen
  unsigned int milliseconds_per_minute = 1000 * 60;  //Calculate MS_per_beat based on tempo in bpm
  MS_per_beat = milliseconds_per_minute/beats_per_minute;
  MS_per_beat -= 5;  //allow for LCD writing time
 }
void loop()
{
int value = analogRead(potPin); //Check the status of the potentiometer
  if (value != potValue) //Recalculate the tempo if the value has changed. 
{
 beats_per_minute = map(potValue, 0, 1023, 30, 225); // Map the value to a reasonable metronome range of 30 to 225 bpm
  unsigned int milliseconds_per_minute = 1000 * 60; //Recalculate the delay time
  MS_per_beat = milliseconds_per_minute/beats_per_minute;  //Recalculate the delay time
  MS_per_beat -= 5;  //allow for LCD writing time
  potValue = value; //Update potvalue
}
  lcd.setCursor(0,0);
  lcd.print("Beats Per Minute");
  lcd.setCursor(0,1);
  lcd.print(beats_per_minute); //Output to the LCD
  digitalWrite(ledPin, HIGH);
  delay(MS_per_beat - MS_per_beat / 2);
  digitalWrite(ledPin, LOW);
  delay(MS_per_beat / 2);
  lcd.clear(); //Clear LCD screen
  }