Hi,
ich nutze eine Wägezelle (LoadCell) welche mir das aktuelle Gewicht in Kg (KG) einen Max-Wert (MAX) und einen fortlaufenden Durchschnitt (AVG) auf einem LCD anzeigt. Soweit funktioniert das auch.
Ich möchte jetzt per Tastendruck zwischen einem Menü I (KG, MAX, AVG) und Menü II (KG und MAX) hin und her schalten. Das funktioniert nur bedingt.
Die Menü Struktur funktioniert, jedoch aktualisieren sich die Sensor-Daten nur beim Umschalten(!) zwischen den zwei Menüs. Verweilt man in einem Menü aktualisieren sich die Sensor Daten nichtmehr.
Die Frage ist jetzt: Wie kann ich den Sensor (LoadCell) fortlaufend innerhalb des Menüs lesen und auf dem LCD anzeigen?
#include <LiquidCrystal.h>
#include <HX711_ADC.h> // LoadCell Libary
LiquidCrystal lcd(12,11,5,4,3,2);
HX711_ADC LoadCell(8, 9); // LoadCell
#include <EEPROM.h> // LoadCell
#define SAMPLES 1 // Defines Sampling rate from LoadCell libary
#define IGN_HIGH_SAMPLE 0
#define IGN_LOW_SAMPLE 0
#define SCK_DISABLE_INTERRUPTS 1 //default value: 0
float max1 = 0; // max
int LedPin = 7; // LED Pin lights up after the 1min Interval is over
unsigned long total; // this block is used to calculate the average
float count; //
unsigned long whenStarted; //
const unsigned long INTERVAL = 500; // 5sec
int MenuButton = 10; // MENU Button
boolean ButtonPressed = false;
void setup() {
LoadCell.begin(); // start connection to HX711
LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
LoadCell.setCalFactor(4390.0);
lcd.begin(16,2);
pinMode(MenuButton, INPUT_PULLUP);
lcd.setCursor(0,0);
whenStarted = millis ();
}
void loop() {
LoadCell.update();
float i = LoadCell.getData(); // get output value from LoadCell
if (digitalRead(MenuButton) == LOW) {
delay(10);
if (digitalRead(MenuButton) == LOW) {
reverseLED();
while (digitalRead(MenuButton) == LOW); // else menue
delay (10);
}
}
}
void reverseLED() {
if(ButtonPressed) { // MENUE 1
LoadCell.update();
float i = LoadCell.getData(); // get output value
lcd.clear();
lcd.setCursor(0, 0); // set cursor to first row
lcd.print("Kg:"); // print out to LCD
lcd.print(i/10,1); // print out the retrieved value to the second row
if (i/10 > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
max1 = i/10;
}
lcd.setCursor(0,1);
lcd.print ("MAX:");
lcd.print (max1,1);
lcd.print(" Avg:"); // Place holder for the Average over 1min.
total += i/10; // calculate average in Volts
count++;
lcd.print(total/count,1); // displays the averageValue
ButtonPressed = false;
}
else { //MENUE II
LoadCell.update();
float i = LoadCell.getData(); // get output value
lcd.clear();
if (i/10 > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
max1 = i/10;
}
lcd.setCursor(0,1);
lcd.print ("MAX:");
lcd.print (max1,1);
ButtonPressed = true;
}
}
Deine Menue-Ausgabe wird ja auch nur bei jedem Drücken deines Menue-Buttons 1x aufgerufen und das wars. Da kann sich nichts aktualisieren.
Du musst das Flag (bei dir das 'ButtonPressed' ) für das aktuelle Menue unabhängig von der Ausgabe umschalten, und dann Die LCD-Ausgabe regelmäßig aufrufen. Je nachdem wie das Flag steht, wird dann die eine oder andere Anzeige ausgegeben.
Und Du solltest deine Variablennamen etwas sinnvoller wählen. Bei 'ButtonPressed' erschließt sich nicht gleich, dass damit der Menuestatus gemeint ist.
Die Abfrage deines MenuButton ist auch nicht gerade optimal. Solange Du den drückst, macht der Arduino garnichts.
Danke für deine Antwort! Das macht natürlich Sinn, warum sich mein LCD nicht aktualisiert. Wie würdest du das Flag denn setzen? Kannst du mir evtl ein/zwei Zeilen Code schreiben dass ich mir besser vorstellen kann wie du das Problem angehen würdest?
Danke!
Hallo,
mal ein ungetesteter Vorschlag:
....
const byte MenuButton = 10; // MENU Button
boolean menueButtonState = HIGH;
boolean ButtonPressed = false;
....
....
void loop() {
LoadCell.update();
float i = LoadCell.getData(); // get output value from LoadCell <-- überflüssig, da Du das in der Funktion machst
if (digitalRead(MenuButton) != menueButtonState) {
// Taste wurde betätigt ( gedrückt oder losgelassen )
// Tasterstatus aktualisieren
menueButtonState != menueButtonState;
if (menueButtonState == LOW) {
ButtonPressed = !ButtonPressed; // <-- Der Name passt nicht zur Funktionalität
lcd.clear();
}
}
reverseLED(); // <--- der Funktionsname passt auch nicht zur Funktion
delay(200);
}
...
...
Das delay am Ende ist natürlich nicht optimal, aber die LCD-Ausgabe sollte schon etwas 'gebremst' werden. Ausserdem musst Du in 'reverseLED' noch die beiden Anweisungen, in denen 'ButtonPressed' verändert wird rausschmeißen. Ausserdem ist das lcd.clear() in der Funktion schlecht. Da wird das LCD recht heftig flackern. Deshalb auch rausschmeißen. Gelöscht wird das LCD nur, wenn das Menue wechselt.
Hallo,
du könntest mit dem Button und der pos. Flanke zunächst mal einen Zähler aufbauen. Der zählt immer von 0 bis 2 . Wenn er bei 2 angekommen ist wird er sofort wieder auf 0 gesetzt. Die Zähler variable nennst Du z.B Seite. Dann wechset die jetzt immer von 0 auf 1 usw.
Anschliessend machst Du mit mehreren if oder select case Abfragen von "Seite" die ausgabe auf dem Display.
Vorteil das lässt sich bei Bedarf auch leicht auf mehrere Seiten erweitern.
Heinz
@MicroBahner
Ich hab das jetzt mal eingebaut. So wie der Code jetzt ist zeigt er mir nur Menü II an und der Button ist außer Funktion.
Wenn ich in der Funktion (habe sie umbenannt in "GoToMenu") die Bedingungen für die Änderung des ButtonState (ButtonPressed = true, ButtonPressed=false) drinnen behalte, bekomme ich nur Menü I angezeigt. Auch hier ist der Button ohne Funktion.
#include <LiquidCrystal.h>
#include <HX711_ADC.h> // LoadCell Libary
LiquidCrystal lcd(12,11,5,4,3,2);
HX711_ADC LoadCell(8, 9); // LoadCell
#include <EEPROM.h> // LoadCell
#define SAMPLES 1 // Defines Sampling rate from LoadCell libary
#define IGN_HIGH_SAMPLE 0
#define IGN_LOW_SAMPLE 0
#define SCK_DISABLE_INTERRUPTS 1 //default value: 0
float max1 = 0; // max
int LedPin = 7; // LED Pin lights up after the 1min Interval is over
unsigned long total; // this block is used to calculate the average
float count; //
unsigned long whenStarted; //
const unsigned long INTERVAL = 500; // 5sec
const byte MenuButton = 10; // MENU Button
boolean menueButtonState = HIGH;
boolean ButtonPressed = false;
void setup() {
LoadCell.begin(); // start connection to HX711
LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
LoadCell.setCalFactor(4390.0);
lcd.begin(16,2);
pinMode(MenuButton, INPUT_PULLUP);
lcd.setCursor(0,0);
whenStarted = millis ();
}
void loop() {
LoadCell.update();
float i = LoadCell.getData(); // get output value from LoadCell
if (digitalRead(MenuButton) != menueButtonState) {
// Taste wurde betätigt ( gedrückt oder losgelassen )
// Tasterstatus aktualisieren
menueButtonState != menueButtonState;
if (menueButtonState == LOW) {
ButtonPressed = !ButtonPressed; // <-- Der Name passt nicht zur Funktionalität
lcd.clear();
}
}
GoToMenu();
delay(200);
}
void GoToMenu() {
if(ButtonPressed) { // MENUE 1
LoadCell.update();
float i = LoadCell.getData(); // get output value
lcd.setCursor(0, 0); // set cursor to first row
lcd.print("Kg:"); // print out to LCD
lcd.print(i/10,1); // print out the retrieved value to the second row
if (i/10 > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
max1 = i/10;
}
lcd.setCursor(0,1);
lcd.print ("MAX:");
lcd.print (max1,1);
lcd.print(" Avg:"); // Place holder for the Average over 1min.
total += i/10; // calculate average in Volts
count++;
lcd.print(total/count,1); // displays the averageValue
//ButtonPressed = false;
}
else { //MENUE II
LoadCell.update();
float i = LoadCell.getData(); // get output value
if (i/10 > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
max1 = i/10;
}
lcd.setCursor(0,1);
lcd.print ("MAX:");
lcd.print (max1,1);
//ButtonPressed = true;
}
}
@Rentner
Vielen Dank für deine Hilfestellung. Ich beschäftige mich erst seit einem Monat mit dem Arduino, deswegen tu ich mir schwer mit deiner Erklärung. Kannst du mir das in Form eines Code beschreiben, dann verstehe ich evtl besser was du meinst. Danke!
Sorry, da war ein Tippfehler drin ( war ja ungetestet
).
So ist es richtig:
menueButtonState = !menueButtonState;
An der Stelle soll menueButtonState einfach auf den jeweils anderen Wert ( true/false ) umgeschaltet werden.
Mit dem Tippfehler:
menueButtonState != menueButtonState;
war es einfach ein Vergleich, dessen Ergebnis weggeschmissen wurde.
Schalt mal die Warnungen an, dann macht dich der Compiler auf solchen Unsinn aufmerksam.
P.S. Es wäre auch gut, wenn Du versuchst zu verstehen was Du da abtippst. Dann wäre Dir der Vertipper vielleicht aufgefallen
.
Danke! Jetzt funktioniert es! Ich bin noch total am Anfang mit dem Arduino. Mir fällt es noch schwer flags zu verstehen und wie man die am besten einsetzt. Wenn ich dann einen fertigen Code sehe, leuchtet es aber in der Regel ein.
Jeder hat mal angefangen - das wird schon noch 
Super, dass es jetzt funktioniert.
Hallo,
schön das es jetzt klappt. Hier noch ein Gerüst wie ich das gemeint hatte, ohne jetzt auf den Inhalt der einzelnen Seiten einzugehen. Um es einfach zu machen hab ich den Taster mit delay() entprellt und alles hintereinander geschrieben. Eigendlich würde man die Umschaltung besser in eine eigene Function mit Parameter und Rückgabewert bauen bauen, aber daran kannst Du ja dann selbst noch mal üben, wenn Du Dich mit dem Thema "Funktionen schreiben" beschäftigen willst.
Heinz
/* Taster schaltet gegen 0 Volt
Hardware UNO
*/
const byte btnpin = 2; // Pin für den Taster
byte seite = 1; // Voreinstellung der Seite
byte maxseite = 3; // max Anzahl
bool button; // Zustand des Eingangs
bool buttonflag; // Hilfsflag für den Taster
void setup() {
pinMode(btnpin, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
button = !digitalRead(btnpin); // Taster einlesen un invertieren
// Seitenumschaltung
if (button == true && buttonflag == false) { // Pos. Flanke erkennen
delay(10); // Taster entprellen
buttonflag = true;// Status setzen
seite++;
if (seite > maxseite) seite = 1; // auf Anfang
}
// Wenn der Taster nicht gedrückt ist dann das Hiflsflag zurück
if (button == false) buttonflag = false;
// Auswertung der aktuellen Seite
if (seite == 1) {
Serial.println("Seite 1 angewählt");
// Hier ausgabe auf das Display für Seite 1
}
else if (seite == 2) {
Serial.println("Seite 2 angewählt");
// Hier ausgabe auf das Display für Seite 2
}
else if (seite == 3) {
Serial.println("Seite 3 angewählt");
// Hier ausgabe auf das Display für Seite 3
}
}
@Rentner
Danke für die viele Hilfe! Ich bin ehrlich gesagt ein bisschen verblüfft wie viel Unterstützung man hier bekommt. Finde ich super!