Hi,
For a project I’m building I was wondering if it is possible to let a bar graph with origin in the center of the LCD row to move from the center to the right or center to the left?
I’m building a Center of Gravity meter to determine my balance of my RC planes. I’m using some strain gauge with HX711 to get the weights. Not only do I want to measure the balance from tail to nose as well the balance from the left wing to the right wing.
When the weight on the left main gear and the weight on the right main gear are equal the plane is in balance. When one side is heavier than the other side I want the bar graph to increase to the heavier side.
In case 4 I display the weight from the left and right main gear. I was thinking by subtracting both weights from each other to use that value to increase the bar graph. The problem is I don’t know how to write it down. I once did something for a fuel gauge but it took a lot of writing. Maybe there’s a much easier way?
#include <LiquidCrystal_I2C.h>
#include <menuLCDs.h>
#include <Wire.h>
#include <menuFields.h>
#include <quadEncoder.h>//quadrature encoder driver and fake stream
#include <keyStream.h>//keyboard driver and fake stream (for the encoder button)
#include <chainStream.h>// concatenate multiple input streams (this allows adding a button to the encoder)
#include <HX711.h>
//LiquidCrystal lcd1(7, 6, 5, 4, 3, 2);
LiquidCrystal_I2C lcd1(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the lcd1 I2C address
const float calibration_factor_LA = 218.25;//This value is obtained using the SparkFun_HX711_Calibration sketch
const float calibration_factor_RA = 219.5; //This value is obtained using the SparkFun_HX711_Calibration sketch
const float calibration_factor_Nose = 219.75; //This value is obtained using the SparkFun_HX711_Calibration sketch
const float Zwaartekracht =9.81;
#define DOUT_RA 40
#define CLK_RA 41
#define DOUT_LA 36
#define CLK_LA 37
#define DOUT_Nose 38
#define CLK_Nose 39
HX711 scale_RA(DOUT_RA, CLK_RA);
HX711 scale_LA(DOUT_LA, CLK_LA);
HX711 scale_Nose(DOUT_Nose, CLK_Nose);
////////////////////////////////////////////
// ENCODER (aka rotary switch) PINS
// rotary
#define encA 10
#define encB 12
//this encoder has a button here
#define encBtn 13
byte CGL[8] = {B00011,B00100,B01000,B01000,B01111,B01111,B00111,B00011};
byte CGR[8] = {B11000,B11100,B11110,B11110,B00010,B00010,B00100,B11000};
static unsigned long NextTrigger = 0;
int opdracht = 0;
int plotDelay = 200;
bool pollmenu = true;
//aux function
void nothing() {}
void Afzonderlijke_Gewichten(){opdracht = 1; pollmenu = false; lcd1.clear();} // Hier zijn alle afzonderlijke gewichten te zien
void Totaal_Gewicht(){opdracht = 2; pollmenu = false; lcd1.clear();} // totaal gewicht toestel
void CGmeten(){opdracht = 3; pollmenu = false; lcd1.clear();} // Hier wordt het toe te voegen of af te trekken gewicht weergegeven op het corectiepunt CP
void Balance(){opdracht = 4; pollmenu = false; lcd1.clear();} // Balance AC L/R
int MainToNose = 0;
int MainToCG = 0;
int CoGToCP = 0;
/////////////////////////////////////////////////////////////////////////
// MENU DEFINITION
// here we define the menu structure and wire actions functions to it
// empty options are just for scroll testing
MENU(Instellingen,"Instellingen", // Hier zijn de afstanden aan te passen van de onderlinge punten
FIELD(MainToNose,"Main to Nose","mm",-2000,2000,10,1,nothing),
FIELD(MainToCG,"Main to CG","mm",-2000,2000,10,1,nothing),
FIELD(CoGToCP,"CoG to CP","mm",-2000,2000,10,1,nothing)
);
MENU(Gewichten,"Gewichten",
OP("Gewichten",Afzonderlijke_Gewichten),
OP("Totaal Gewicht",Totaal_Gewicht)
);
MENU(mainMenu,"Main menu",
OP("CG Meten",CGmeten),
OP("Balance", Balance),
SUBMENU(Gewichten),
SUBMENU(Instellingen)
);
//the quadEncoder
quadEncoder quadEncoder1(encA,encB);//simple quad encoder driver
quadEncoderStream enc(quadEncoder1,5);// simple quad encoder fake Stream
//a keyboard with only one key :D, this is the encoder button
keyMap encBtn_map[]={{-encBtn,menu::enterCode}};//negative pin numbers means we have a pull-up, this is on when low
keyLook<1> encButton(encBtn_map);
//multiple inputs allow conjugation of the quadEncoder with a single key keyboard that is the quadEncoder button
Stream* in[]={&enc,&encButton};
chainStream<2> quadEncoder_button(in);
//describing a menu output, alternatives so far are Serial or LiquidCrystal lcd1
menuLCD lcd(lcd1,20,4);
/////////////////////////////////////////////////////////////////////////
void setup() {
quadEncoder1.begin();
pinMode(encBtn, INPUT);
digitalWrite(encBtn,1);
Serial.begin(9600);
lcd1.begin(20,4);
lcd1.clear();
lcd1.setCursor(0,1);
lcd1.print(" CoG Calculator ");
lcd1.setCursor(0,3);
lcd1.print(" By Benovitch ");
lcd1.createChar(1,CGL);
lcd1.createChar(2,CGR);
long zero_factor_LA = scale_LA.read_average(5);
long zero_factor_RA = scale_RA.read_average(5);
long zero_factor_Nose = scale_Nose.read_average(5);
delay(1500);
scale_RA.set_scale(calibration_factor_RA); //This value is obtained by using the SparkFun_HX711_Calibration sketch
scale_RA.set_offset(zero_factor_RA); //Zero out the scale using a previously known zero_factor
scale_LA.set_scale(calibration_factor_LA); //This value is obtained by using the SparkFun_HX711_Calibration sketch
scale_LA.set_offset(zero_factor_LA); //Zero out the scale using a previously known zero_factor
scale_Nose.set_scale(calibration_factor_Nose); //This value is obtained by using the SparkFun_HX711_Calibration sketch
scale_Nose.set_offset(zero_factor_Nose); //Zero out the scale using a previously known zero_factor
scale_LA.tare();
scale_RA.tare();
scale_Nose.tare();
delay(10);
}
void loop() {
if (millis() > NextTrigger){
int Gewicht_RA = 900 + scale_RA.get_units() ;
int Gewicht_LA = 900 + scale_LA.get_units() ;
int Gewicht_Nose =1000 + scale_Nose.get_units() ;
float Totaal_Gewicht_AC = (Gewicht_RA + Gewicht_LA + Gewicht_Nose); //Totaal_Gewicht = functie --> naam variable gewijzigd
float Gewicht_MainGear = (Gewicht_RA + Gewicht_LA);
float Afstand_CGtoNose = (MainToNose - MainToCG); //CG ligt dus tussen Main gear en Nose gear? --> Moment voor de CG = negatief, Moment achter de CG = positief?
float Moment_CGtoMG = abs(Gewicht_MainGear * MainToCG);
float Moment_CGtoNG = abs(Gewicht_Nose * Afstand_CGtoNose);
//float Total_Moment = (Moment_CGtoMG - Moment_CGtoNG) ;
float Gewicht_CP = ((Moment_CGtoMG - Moment_CGtoNG)/CoGToCP) ; // Hiermee wordt het eigenlijke gewicht op het CP berekend --> CP???
//float Gewicht_CP = ((5000*9.81*4.5)-(1500*9.81*12))/(12*9.81);
switch (opdracht){
.....
case 4:
lcd1.setCursor(6,0);
lcd1.print("Balance");
lcd1.setCursor(0,1);
lcd1.print(Gewicht_LA);
lcd1.print(" gr");
lcd1.print(" ");
lcd1.setCursor(13,1);
lcd1.print(Gewicht_RA);
lcd1.print(" gr");
lcd1.print(" ");
lcd1.setCursor(9,2);
lcd1.write (byte(1));
lcd1.setCursor(10,2);
lcd1.write (byte(2));
break;
default:
pollmenu = true;
break;
}
if (opdracht != 0) { // om vanuit de berekeningen terug naar het menu te gaan
int stateButton = digitalRead(encBtn);
if(stateButton == 0) {
opdracht = 0;
pollmenu = true;
lcd.clear();
lcd.drawn=NULL;
delay(500);
}
}
NextTrigger = (long)(millis() + plotDelay);
}
if (pollmenu) {mainMenu.poll(lcd, quadEncoder_button);};
}
A part of the code from the fuel gauge:
if (fuel >= 10) {
lcd.setCursor(0,3);
lcd.write(byte(4));
}
else {
lcd.setCursor(0,3);
lcd.print(" ");
}
if (fuel >= 20) {
lcd.setCursor(1,3);
lcd.write(byte(4));
}
else {
lcd.setCursor(1,3);
lcd.print(" ");
}
if (fuel >= 30) {
lcd.setCursor(2,3);
lcd.write(byte(4));
}
else {
lcd.setCursor(2,3);
lcd.print(" ");
}
...
}
if (fuel >= 190) {
lcd.setCursor(18,3);
lcd.write(byte(4));
}
else {
lcd.setCursor(18,3);
lcd.print(" ");
}
if (fuel >= 200) {
lcd.setCursor(19,3);
lcd.write(byte(4));
}
else {
lcd.setCursor(19,3);
lcd.print(" ");
}