// simple project using Arduino UNO and 16x2 character display to display smooth gauge,
// created by upir, 2022
// modified by herma, 02/2024 legge potenziometro
// youtube channel: https://www.youtube.com/upir_upir
// FULL TUTORIAL: https://youtu.be/ZzIGHiHObYw
// GAUGE IN 11 MINUTES TUTORIAL: https://youtu.be/upE17NHrdPc
// Links
// character creator - https://maxpromer.github.io/LCD-Character-Creator/
// sprintf explanation - https://www.programmingelectronics.com/sprintf-arduino/
// custom characters simplest project - https://wokwi.com/projects/294395602645549578
// Arduino I2C scanner - https://playground.arduino.cc/Main/I2cScanner/
// 16x2 available characters - https://docs.wokwi.com/parts/wokwi-lcd1602#font
#include <LiquidCrystal_I2C.h>
#include "H_BarGraph.h"
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
//LiquidCrystal_I2C lcd(0x3f,16,2); // set the LCD address to 0x3f for a 16 chars and 2 line display
int val_trimmer=0;
void setup()
{ lcdSetup();
}
void loop()
{
val_gauge = map(analogRead(A0), 0, 1023, 0, 100);
drawGraph();
delay(500); // wait for a while
}
void lcdSetup(void) {
lcd.init(); // initialize the 16x2 lcd module
lcd.createChar(7, gauge_empty); // middle empty gauge
lcd.createChar(1, gauge_fill_1); // filled gauge - 1 column
lcd.createChar(2, gauge_fill_2); // filled gauge - 2 columns
lcd.createChar(3, gauge_fill_3); // filled gauge - 3 columns
lcd.createChar(4, gauge_fill_4); // filled gauge - 4 columns
lcd.createChar(0, warning_icon); // warning icon - just because we have one more custom character that we could use
lcd.backlight(); // enable backlight for the LCD module
}
void drawGraph (void) {
float units_per_pixel = (gauge_size_chars*5.0)/100.0; // every character is 5px wide, we want to count from 0-100
int value_in_pixels = round(val_gauge * units_per_pixel); // cpu_gauge value converted to pixel width
int tip_position = 0; // 0= not set, 1=tip in first char, 2=tip in middle, 3=tip in last char
if (value_in_pixels < 5) {tip_position = 1;} // tip is inside the first character
else if (value_in_pixels > gauge_size_chars*5.0-5) {tip_position = 3;} // tip is inside the last character
else {tip_position = 2;} // tip is somewhere in the middle
move_offset = 4 - ((value_in_pixels-1) % 5); // value for offseting the pixels for the smooth filling
for (int i=0; i<8; i++) { // dynamically create left part of the gauge
if (tip_position == 1) {gauge_left_dynamic[i] = (gauge_fill_5[i] << move_offset) | gauge_left[i];} // tip on the first character
else {gauge_left_dynamic[i] = gauge_fill_5[i];} // tip not on the first character
gauge_left_dynamic[i] = gauge_left_dynamic[i] & gauge_mask_left[i]; // apply mask for rounded corners
}
for (int i=0; i<8; i++) { // dynamically create right part of the gauge
if (tip_position == 3) {gauge_right_dynamic[i] = (gauge_fill_5[i] << move_offset) | gauge_right[i];} // tip on the last character
else {gauge_right_dynamic[i] = gauge_right[i];} // tip not on the last character
gauge_right_dynamic[i] = gauge_right_dynamic[i] & gauge_mask_right[i]; // apply mask for rounded corners
}
lcd.createChar(5, gauge_left_dynamic); // create custom character for the left part of the gauge
lcd.createChar(6, gauge_right_dynamic); // create custom character for the right part of the gauge
for (int i=0; i<gauge_size_chars; i++) { // set all the characters for the gauge
if (i==0) {gauge_string[i] = byte(5);} // first character = custom left piece
else if (i==gauge_size_chars-1) {gauge_string[i] = byte(6);} // last character = custom right piece
else { // character in the middle, could be empty, tip or fill
if (value_in_pixels <= i*5) {gauge_string[i] = byte(7);} // empty character
else if (value_in_pixels > i*5 && value_in_pixels < (i+1)*5) {gauge_string[i] = byte(5-move_offset);} // tip
else {gauge_string[i] = byte(255);} // filled character
}
}
// gauge drawing
lcd.setCursor(0,0); // move cursor to top left
sprintf(buffer, "val:%3d%% ", val_gauge); // set a string as val: XX%, with the number always taking at least 3 character
lcd.print(buffer); // print the string on the display
lcd.setCursor(14,0);
lcd.write(byte(0)); // print warning character
lcd.setCursor(0,1); // move the cursor to the next line
lcd.print(gauge_string); // display the gauge
}