Go Down

Topic: Projekt: LCDMenuLib - LCD Menü mit mehreren Ebenen (4Bit/I2C/ShiftReg/...) (Read 59 times) previous topic - next topic

Jomelo

@m6m7m9
Ich habs gerade mal ausprobiert, das klappt so nicht, da das Menü nur neu aufgebaut wird, wenn Enter gedrückt wird oder der Kursor aus den sichtbaren Bereich heraus bewegt wird. Bei der Scrollbewegung wird nur der Kursor bewegt, ansonsten ändert sicht erstmal nichts in der Lib. Die Änderung wäre somit nur mit einem größerem umschreiben der Lib möglich und zudem belegt das noch mehr Speicher, da Variablen zwischengespeichert werden müssen.

Wozu brauchst du das denn genau ? Eigentlich weißt du doch in welcher Funktion sich das Menü gerade befindet und kannst eine Variable passend beschreiben, das geht deutlich schneller als alles umzuschrieben.


m6m7m9

..ich versuche mal, das Ganze zu beschreiben.

Das Menü soll an einem Phono Vorverstärker über eine Relaissteuerung die Eingänge verwalten (Input 1-5) und über eine weitere Relaissteuerung den kapazitiven bzw. Abschlusswiderstand steuern (8 Relais, die in verschiedenen Kombinationen angesteuert werden..)

Die Eingangswahl ist realisiert, ebenso die Wahl der verschiedenen Widerstandskombinationen samt grafischer Anzeige. Was nicht bisher klappt, ist die individuelle - interaktive - Zusammenstellung von 5 Eingangsmenükonstellationen.

Dazu sollen für jeden Eingang Folgendes voreinstellbar sein:
- Name des Spielers
- Name des Systems
- Grösse es Widerstandes
- Abschluss (MM oder MC)

Über die Menüsteuerung (drücken des rechten Drehencoders) sollen dem benutzer die Möglichkeit gegeben werden, aus einer Gruppe von Bezeichnungen jedem Input die o.g. Parameter "voreingestellt"´zuzuordnen - also quasi eine Menüvorauswahl.

Dazu wird im Menü als Item der 1. Ebene der Eingang gewählt, in der 2. Ebene o.g. Parameter, und jetzt kommt es:

der jeweilige Paramter der letzten Ebene soll dann als Textstring gespeichert werden (Druck des rechten Encoders >1sek und nach Übernahme Meldung "done")

Eingang1 -> Name1 + System1 + Widerstand 1 + Abschluss 1
oder in Textform als Beispiel:
Eingang1 ->  "TD126" - "MC10MK2" - "100 Ohm" - "MC"
Eingang2 -> "Cello" - "Valencia" - "120 Ohm" - MC
Eingang 3 -> "TD320" - "VM-red" - "47k" - MM
........

Wird nun der Eingang verändert (linker Drehencoder), sollen die voreingestellten Parameter direkt angewählt und angezeigt werden und über die 2. relaissteuerung die Widerstandskombination geschaltet werden.

Soweit das Ganze in Kurzform. Es fehlt eine Funktion, über den Menüstring "Text" der letzten Ebene zu übernehmen.

Jomelo

@AndiBar

Ich hab mir deinen Code mal angeschaut, dort gibt es noch einiges an Optimierungspotenzial. Zudem hast du dir die Beispiele des Menüs nicht richtig angeschaut, da dort schon ein Timer mit millis verwendet wird, der fast genau das macht was du vor hast.

Dein Code angepasst zum lernen:  WICHTIG: schau dir das genau an
Code: [Select]

// Konstanten kannst du auch mit #define schreiben. Die Bezeichnung #define wird beim übersetzen der Software
// vom Preprozessor im Programmcode ersetzt. Sieh es einfach als Platzhalter an, die du zu Laufzeit des Programms
// nicht verändern kannst
const int kompressorMax = 405;
const int kompressorMin = 610;

void setup() {
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
 lcd.begin(16,2);
 // das auslesen des Sensors macht hier keinen sinn, da die Variable sensorValue in dieser Funktion angelegt wird
 // Normale Variablen in Funktionen sind nur solange gesetzt, wie die funktion geöffnet ist.
 int sensorValue = analogRead(A1);
 int vari;
 // Den LED Pin kannst du auch per #define anlegen, da dieser ja Fest ist bzw sich die angeschlossene Hardware in den
 // seltensten Fällen ohne neue Softwareanpassung einfach ändert
 int led = 2;
 pinMode(led, OUTPUT);

}

// the loop routine runs over and over again forever:
void loop() {
 // siehe oben
 int led = 2;


 int sensorValue = analogRead(A1);
 int vari;
 
// Die Abfrage lässt sich wesentlich kürzer darstellen, wenn du die ersten beiden Abfragen mit einem "ODER" verknüpfst
if (sensorValue < kompressorMax) {
  digitalWrite(led, LOW);
}
else if (sensorValue > kompressorMin) {
  digitalWrite(led, LOW);
 
}
else {
  digitalWrite(led, HIGH);
}
 // print out the value you read:
vari = (100 - ((100 / 1023.0) * sensorValue));

// Jegliche Speicherung von Strings,  z.b. "Poti" wird im Ram des Kontrollers abgelegt. Da der Ram sehr sehr klein ist, solltest
// du darauf achten, nicht zu viel mit unnützen Strings zu verschwenden. Eine Alternative ist das F Makro. Mit diesem werden
// Strings im Flashspeicher abgelegt, davon ist meistens genug vorhanden.     F("Poti")
Serial.print("Poti ");
Serial.print(vari);
Serial.print( "%");
Serial.println("...");
Serial.print(sensorValue);

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Poti");
lcd.setCursor(5,1);
lcd.print(vari);
lcd.print("%");

// Verwende niemals delay in deinen Programmen, außer du weißt 110% was du machst, wieso du das machst und
// das es keine andere Lösung gibt
delay(1000);
}


So nun zu der Funktion im Menü. Diese ist nun nicht mehr erklärt, da die Erklärungen oben im Code stehen
Code: [Select]

#define LED  2
#define KOMPRESSOR_MAX 405
#define KOMPRESSOR_MIN 610

uint8_t g_func_timer_DEIN_NAME = 0;  /* time counter */
unsigned long g_timer_DEIN_NAME = 0;    /* timer variable */

/* callback function - FUNC_information */
void FUNC_DEIN_NAME(void)
{
  /* setup function */       
  if(!LCDML.FuncInit())
  {
    /* clear the display and init the time counter value */         
    lcd.clear();
    lcd.print(F("x sec warten"));     
         
  }
     
  if(LCDML.Timer(g_timer_1, 1000)) {      /* init a timer with 1000ms */
   
    unsigned int sensorValue = analogRead(A1);
   
 
    if (sensorValue < KOMPRESSOR_MAX || sensorValue > KOMPRESSOR_MIN) {
      digitalWrite(LED, LOW);   
    } else {
      digitalWrite(LED, HIGH);
    }
   
    // print out the value you read:
    unsigned char vari = (100 - ((100 / 1023.0) * sensorValue));
   
    Serial.print(F("Poti "));
    Serial.print(vari);
    Serial.print(F("%"));
    Serial.println(F("..."));
    Serial.print(sensorValue);
   
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(F("Poti"));
    lcd.setCursor(5,1);
    lcd.print(vari);
    lcd.print(F("%"));
  }   
 

  /* end function for callback */
  if(LCDML.FuncEnd(0, 1, 0, 0, 0, 0)) /* (direct, enter, up, down, left, right) */ 
  {
    /* do something bevor this function is closed */     
  } 
   
 
}




Jomelo

@m6m7m9

Dann ist das schon eher möglich. Also mit diesem code kann ich die letzte Ebene Auslesen, insofern es nicht die Rootebene ist. Ich denke wenn du damit etwas "rumspielst" bekommst du damit deine Lösung umgesetzt. Der "Back" Button wird auch noch nicht utnerstützt, aber die Werte kann man auch wohl so irgendwie zurücksetzen.

Code: [Select]

//....
uint8_t g_last = _LCDMenuLib_NO_FUNC;

void loop()
{  
// hier noch so anpassen, das es bei dir läuft
 //LCDMenuLib_control_analog();      /* lcd menu control - config in tab "LCDML_control" */
 //LCDMenuLib_control_digital();     /* lcd menu control - config in tab "LCDML_control" */
 LCDMenuLib_control_serial();        /* lcd menu control */  
 LCDMenuLib_loop();                  /* lcd function call */


 
 uint8_t num = LCDML.getFunction();
 
 
 if(num != _LCDMenuLib_NO_FUNC) {    
   if(g_last != num) {
     if(g_last != _LCDMenuLib_NO_FUNC) {
       // Auslesen
       char name[20];
       strcpy_P(name, (char*)pgm_read_word(&(g_LCDMenuLib_lang_table[g_last])));
       Serial.println(name);
     }
     g_last = num;
   }
 }
}


m6m7m9

...es scheint meinem Anliegen deutlich näher zu kommen! Danke!

Der Textstring wird tatsächlich ausgegeben, nun muss ich herausarbeiten, dass ein kurzes Drücken des Encoderknopfes einen Itemwechsel in die nächste Ebene bedeutet

und ein langes Drücken (>1 sek)

- eine Übernahme des Textes macht
- eine Bestätigungsmeldung "done" macht
- wieder eine Item-Ebene zurückgeht.

Aber der grundsätzliche Weg ist gebahnt, und das ist SUPER!!! Danke!

Go Up