Für mein Projekt - eine Steuerung für einen Pilzzuchtkasten - verwende ich die sehr großartige LCDML2.
Leider habe ich ein Problem, wenn ich (per Rotary Encoder) ein Untermenü aufrufe, welches den eingebauten Lüfter für eine vorgegebene Zeit manuell starten (bzw. falls er gerade läuft, stoppen) soll. Das tut es zwar, und während dessen laufen soweit ich das erkennen kann auch die weiteren Funktionen (Temperatur-, Luftfeuchtigkeits-, CO2-Sensoren, Logging, serielle Ausgabe, ... ) normal und der Lüfter stoppt auch nach Ablauf des Countdown. Allerdings hängt sich der Mega in diesem Moment auf. Manchmal startet er auch einfach neu. Da es keine Fehlermeldung gibt, bin ich ziemlich ratlos.
Hier ist der Code der entsprechenden Funktion. Wenn ich das Programm nur mit Menüfunktionen, also ohne die anderen Loop-Funktionen laufen lasse, funktioniert alles einfandfrei. In Loop sind ansonsten die oben genannten Funktionen, die meisten davon in einer 5000 ms - Schleife.
// *********************************************************************
void mFunc_fan_manOnOff()
// *********************************************************************
{
// mFunc_fan_state =1; // habe ich als Statusvariable ausprobiert, um nicht mit dem dem automatischen Lüfteranlauf
// in die Quere zu kommen, hat aber leider nichts gebracht
uint32_t fan_remaintime;
char fan_countdown[21];
if(LCDML.FUNC_setup()) // ****** SETUP *********
{
// setup
// is called only if it is started
// starts a trigger event for the loop function every 100 milliseconds
LCDML.FUNC_setLoopInterval(100);
if(fan_state == 0){
fan_state = 1;
fan_starttime_temp=millis();
}
else{
fan_state = 0;
LCDML.FUNC_goBackToMenu();
}
digitalWrite(fan_pinA, fan_state);
digitalWrite(fan_pinB, fan_state);
LCDML.FUNC_disableScreensaver();
}
if(LCDML.FUNC_loop()) // ****** LOOP *********
{
// loop
// is called when it is triggered
// - with LCDML_DISP_triggerMenu( milliseconds )
// - with every button status change
fan_remaintime = (fan_starttime_temp+fan_duration_manuell-millis())/1000.0;
sprintf(fan_countdown, "remaining: %d s ", fan_remaintime);
if( millis() - fan_starttime_temp >= fan_duration_manuell ){
fan_state = 0;
LCDML.FUNC_goBackToMenu();
}
lcd.setCursor(0, 0);
lcd.print(F("CO2: "));
lcd.setCursor(13, 0);
lcd.print(CO2_av);
lcd.print(F(" ppm"));
lcd.setCursor(0, 2);
lcd.print(fan_countdown);
lcd.setCursor(0, 2);
if(LCDML.BT_checkAny()) {
// LCDML.FUNC_goBackToMenu();
}
digitalWrite(fan_pinA, fan_state);
digitalWrite(fan_pinB, fan_state);
}
if(LCDML.FUNC_close()) // ****** STABLE END *********
{
//LCDML.FUNC_goBackToMenu();
// loop end
// you can here reset some global vars or delete it
}
}
Wie steuerst Du das LOG Shield an?
Der Arduino MEGA hat die SPI Schnittstelle an anderen Pins als 11-13. Laut Bilder fehlen die Pins an der ISP-Schnittstelle über die der Arduino Mega mit der SD Karte sprechen könnte.
Grüße Uwe
statte deinen Sketch mit Serial.print / Debug Ausgaben aus und verfolge wo dein Programm aussteigt.
Wenn du den Fehler einkreisen konntest, gib dir alles an Variablen aus, was in den nächsten Schritten benötigt wird.
Teil-Programme machen selten Sinn, weil öfter das Problem doch in ganz anderen Bereichen liegt als vom TO vermutet.
das könnte knapp werden:
char fan_countdown[21];
wenn ich das sehe:
sprintf(fan_countdown, "remaining: %d s ", fan_remaintime);
15 Zeichen Fixtext + 10 Zeichen für etwas was bis zu 4294967295 sein kann + \0 ist mehr als 21
Kann das
LCDML.FUNC_goBackToMenu();
so im Sketch frei verwendet werden, oder ist Das der Menü-Struktur vorenthalten?
Wenn Letzteres, könnte ich mir vorstellen, daß auf dem Stack nicht die richtige Rücksprung-Adresse gefunden wird, weil diese Funktion nicht sauber verlassen wurde?!?
uwefed:
Wie steuerst Du das LOG Shield an?
Der Arduino MEGA hat die SPI Schnittstelle an anderen Pins als 11-13. Laut Bilder fehlen die Pins an der ISP-Schnittstelle über die der Arduino Mega mit der SD Karte sprechen könnte.
Grüße Uwe
Ja, das stimmt. War etwas hakelig, da auch noch die Library angepasst werden muss. Aber ich hab das Logging Shield auf chipSelect(10,11,12,13), so wie es der Downloadlink von Velleman verlangt. Das läuft auch.
noiasca:
statte deinen Sketch mit Serial.print / Debug Ausgaben aus und verfolge wo dein Programm aussteigt.
Wenn du den Fehler einkreisen konntest, gib dir alles an Variablen aus, was in den nächsten Schritten benötigt wird.
Teil-Programme machen selten Sinn, weil öfter das Problem doch in ganz anderen Bereichen liegt als vom TO vermutet.
Stimmt, so mache ich das normalerweise auch. Hier ist es halt sehr umfangreich, es ist mein erster Kontakt mit der LCDML. Vorher habe ich mich nur in einem einzigen Tab bewegt ... Aber ich werde es mal so versuchen.
das könnte knapp werden:
char fan_countdown[21];
wenn ich das sehe:
sprintf(fan_countdown, "remaining: %d s ", fan_remaintime);
15 Zeichen Fixtext + 10 Zeichen für etwas was bis zu 4294967295 sein kann + \0 ist mehr als 21
Das habe ich von hier, wobei ich den Gebrauch von sprintf() auch noch nicht wirklich verstanden habe (wie an den Leerzeichen nach dem 's' zu erkennen ist...). Dass dies den Fehler verursachen könnte kann ich nicht ausschließen. Allerdings ist die Funktion an sich ja wie gesagt in Ordnung, wenn nichts anderes läuft.
Kann das
LCDML.FUNC_goBackToMenu();
so im Sketch frei verwendet werden, oder ist Das der Menü-Struktur vorenthalten?
Wenn Letzteres, könnte ich mir vorstellen, daß auf dem Stack nicht die richtige Rücksprung-Adresse gefunden wird, weil diese Funktion nicht sauber verlassen wurde?!?
MfG
Du meinst allgemein? Oder ein bestimmtes?
Ich habe einfach das passende Beispiel (I2C 20x4) aus der Library genommen, und daraus die mFunc_timer_info() umgebastelt:
// *********************************************************************
uint8_t g_func_timer_info = 0; // time counter (global variable)
unsigned long g_timer_1 = 0; // timer variable (global variable)
void mFunc_timer_info(uint8_t param)
// *********************************************************************
{
if(LCDML.FUNC_setup()) // ****** SETUP *********
{
lcd.print(F("20 sec wait")); // print some content on first row
g_func_timer_info = 20; // reset and set timer
LCDML.FUNC_setLoopInterval(100); // starts a trigger event for the loop function every 100 milliseconds
LCDML.TIMER_msReset(g_timer_1);
}
if(LCDML.FUNC_loop()) // ****** LOOP *********
{
// loop function, can be run in a loop when LCDML_DISP_triggerMenu(xx) is set
// the quit button works in every DISP function without any checks; it starts the loop_end function
// reset screensaver timer
LCDML.SCREEN_resetTimer();
// this function is called every 100 milliseconds
// this method checks every 1000 milliseconds if it is called
if(LCDML.TIMER_ms(g_timer_1, 1000)) {
g_func_timer_info--; // increment the value every second
lcd.setCursor(0, 0); // set cursor pos
lcd.print(F(" "));
lcd.setCursor(0, 0); // set cursor pos
lcd.print(g_func_timer_info); // print the time counter value
}
// this function can only be ended when quit button is pressed or the time is over
// check if the function ends normally
if (g_func_timer_info <= 0)
{
// leave this function
LCDML.FUNC_goBackToMenu();
}
}
if(LCDML.FUNC_close()) // ****** STABLE END *********
{
// you can here reset some global vars or do nothing
}
}
Das einzige was mir aufgefallen ist, ist das bei deiner Funktion der Übergabeparameter nicht definiert ist. Es kann sein das dies zu Problemen führen kann.
// deins:
void mFunc_fan_manOnOff()
// sollte eigentlich so sein:
void mFunc_fan_manOnOff(uint8_t param)
Ich habe die Funktion gerade getestet (ohne Hardware). Der Zähler läuft runter und das Menü wird wieder angezeigt.
Das einzige was mir aufgefallen ist, ist das bei deiner Funktion der Übergabeparameter nicht definiert ist. Es kann sein das dies zu Problemen führen kann.
// deins:
void mFunc_fan_manOnOff()
// sollte eigentlich so sein:
void mFunc_fan_manOnOff(uint8_t param)
Ich habe die Funktion gerade getestet (ohne Hardware). Der Zähler läuft runter und das Menü wird wieder angezeigt.
Hey,
vielen Dank! Es scheint, als könnte das die Ursache gewesen sein! Ich mache noch ein paar Tests mit unterschiedlichen Konstellationen, aber es sieht sehr gut aus!
Auch danke für die Library, die Beschäftigung damit bringt mich gerade in einigen Punkten wirklich weiter!
Vll. ist's nur eine Warnung?
Die muß explizit aktiviert werden (warum auch immer Das nicht die Standardeinstellung ist).
mfG
Hmm, ich habe sie mal angeschaltet, kann aber wenig damit anfangen.
_LCDML.ino:683:3: note: in expansion of macro 'LCDML_add'
LCDML_add (1 , LCDML_0_1 , 1 , "Fan on/off" , mFunc_fan_manOnOff); // this menu function can be found on "LCDML_display_menuFunction" tab
Moin,
das sind nicht direkt Warnings sondern nur Hinweise den Code zu optimieren. Das was ich zu vor meinte ist hiermit nicht gemeint. Mach dir da keinen Kopf drum.