/*
Arduino based VU meter by mircemk.
Developed by ThomAce (Tamas Kamocsai) based on siemenwauters, theredstonelabz and michiel H's VU meter.
GNU GPL License v3
Developer: ThomAce (Tamas Kamocsai)
Mail: thomacepcg@gmail.com
Version: 1.0
Last modification date: 2019.09.24
Original version:
https://www.instructables.com/id/ARDUINO-VU-METER/
Original description:
VU meter by siemenwauters, theredstonelabz and michiel H don't forget to like and subscribe to support my work. tnx
Modified by "mircemk" date: 2021.07.13
*/
#include <LiquidCrystal.h>
byte Bar[8] = {
B11111,
B00000,
B00000,
B11111,
B11111,
B00000,
B00000,
B11111
};
byte L[8] = {
B00111,
B01000,
B10100,
B10100,
B10100,
B10111,
B01000,
B00111
};
byte R[8] = {
B00111,
B01000,
B10110,
B10101,
B10110,
B10101,
B01000,
B00111
};
byte EndMark[8] = {
B10000,
B01000,
B00100,
B00100,
B00100,
B00100,
B01000,
B10000
};
byte EmptyBar[8] = {
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B11111
};
byte peakHoldChar[8] = {
B11111,
B00000,
B00011,
B00011,
B00011,
B00011,
B00000,
B11111
};
String main_version = "1.1";
int left, right; //Variables to store and calculate the channel levels
const int numReadings = 1; //Refresh rate. Lower value = higher rate. 5 is the defaul
int indexL = 0; //Actual channel index
int totalL = 0; //Total channel data
int maxL = 0; //Maximal level
int indexR = 0;
int totalR = 0;
int maxR = 0;
int inputPinL = A1; //Input pin Analog 1 for LEFT channel
int inputPinR = A0; //Input pin Analog 0 for RIGHT channel
int volL = 0;
int volR = 0;
int rightAvg = 0;
int leftAvg = 0;
long peakHoldTime = 1500; //peak hold time in miliseconds
long peakHold = 0;
int rightPeak = 0;
int leftPeak = 0;
long decayTime = 0;
long actualMillis = 0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //lcd configuration
void setup()
{
lcd.begin(40, 2); //Setting up LCD. 40 chars and 2 rows
lcd.createChar(1, Bar);
lcd.createChar(2, L);
lcd.createChar(3, R);
lcd.createChar(4, EmptyBar);
lcd.createChar(5, EndMark);
lcd.createChar(6, peakHoldChar);
//Showing loading message and loading bar
String mircemk = "* mircemk *";
for (int i = 0; i <= 40; i++)
{
lcd.setCursor(15, 0);
lcd.print(mircemk.substring(0, i));
delay(50);
}
mircemk = " VU meter " + main_version;
for (int i = 0; i <= mircemk.length(); i++)
{
lcd.setCursor(0, 1);
lcd.print(mircemk.substring(0, i));
delay(50);
}
delay(500);
lcd.clear();
lcd.setCursor(15, 0);
lcd.print("Loading...");
for (int i = 0; i < 40; i++)
{
lcd.setCursor(i, 1);
lcd.write(4);
}
for (int i = 0; i < 40; i++)
{
lcd.setCursor(i, 1);
lcd.write(1);
delay(50);
}
delay(5);
lcd.clear();
decayTime = millis();
}
void loop()
{
actualMillis = millis();
lcd.setCursor(0, 0); //L channel index
lcd.write(2); //L symbol
lcd.setCursor(0, 1); //R channel index
lcd.write(3); //R symbol
lcd.setCursor(39, 0); //closing tag / end mark index 1
lcd.write(5); //closing tag / end mark
lcd.setCursor(39, 1); //closing tag / end mark index 2
lcd.write(5); //closing tag / end mark
totalL = analogRead(inputPinL) / 4 - 128; //reducing the detected hum and noise
if(totalL > maxL)
{
maxL = totalL;
}
indexL++;
if (indexL >= numReadings)
{
indexL = 0;
left = maxL;
maxL = 0;
}
totalR = analogRead(inputPinR) / 4 - 128; //reducing the detected hum and noise
if(totalR > maxR)
{
maxR = totalR;
}
indexR++;
if (indexR >= numReadings)
{
indexR = 0;
right = maxR;
maxR = 0;
}
volR = right / 3;
if(volR > 38)
{
volR = 38;
}
if (volR < (rightAvg - 2))
{
if (decayTime < actualMillis)
rightAvg--;
volR = rightAvg;
}
else if (volR > (rightAvg + 2))
{
volR = (rightAvg + 2);
rightAvg = volR;
}
else
{
rightAvg = volR;
}
if (volR > rightPeak)
{
rightPeak = volR;
}
drawBar(volR, rightPeak, 1);
volL = left / 3;
if(volL > 38)
{
volL = 38;
}
if (volL < (leftAvg - 2))
{
if (decayTime < actualMillis)
leftAvg--;
volL = leftAvg;
}
else if (volL > (leftAvg + 2))
{
volL = (leftAvg + 2);
leftAvg = volL;
}
else
{
leftAvg = volL;
}
if (volL > leftPeak)
{
leftPeak = volL;
}
drawBar(volL, leftPeak, 0);
if (decayTime < actualMillis)
decayTime = (millis() + 50);
if (peakHold < actualMillis)
{
peakHold = (millis() + peakHoldTime);
rightPeak = -1;
leftPeak = -1;
}
}
void drawBar(int data, int peakData, int row)
{
//If the previous peak data is 1 or 0, then not taking care of the value.
if (peakData < 2)
{
peakData = -1;
}
//First char (idx 0) = R or L
//Last (16th) char (idx 15) is the closing mark of the bar.
//We have 14 chars to write.
for (int col = 1; col < 39; col++)
{
lcd.setCursor(col, row);
if (col < data)
{
lcd.write(1); //write bar element
}
else if (peakData == col)
{
lcd.write(6); //write the peak marker
}
else
{
lcd.write(4); //write "empty"
}
}
}
Comments