Arduino Asksin library

Begonnen von trilu, 06 August 2013, 10:02:17

Vorheriges Thema - Nächstes Thema

papa

Da hast Du Recht. Es ist nicht ohne weiteres möglich rauszufinden, warum man aus dem Power down zurückgekehrt ist. Vor allem ist es (zumindest mir) nicht bekannt, wie man rauskriegt, wieviel Zeit inzwischen vergangen ist. Das geht sicherlich nur über eine externen Uhr.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

Dietmar63

...  Oder man macht es wie ich dem Beispiel oben : man startet den Watchdog nur dann neu, wenn wdt und wdtold sich unterscheiden. Dann ist sichergestellt, dass der Watchdog timer abgelaufen ist.

Die Zeit wird dann auf Basis des 128k wdt timers berechnet
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

papa

Trotzdem weisst Du nicht, wie lange der Sleep gedauert hat und wieviel millis Du korregieren musst.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

Dietmar63

Doch ich bin schon der Meinung, dass man die Zeit einigermaßen gut messen kann, weil sie nur in
ISR(WDT_vect) aufsummiert wird.

NewAskSin startet bei einem Interrupt  den timer nur jedesmal neu und dadurch kommt es zu Fehlern.
Das weitere Problem ist, dass Watchdog timer mit 128khz bestimmt ungenauer ist als der 16Mhz Timer.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Linef

#1174
Ja, der WD-Timer ist z.T. katastrophal ungenau (5-8% daneben).
Ich habe mir deshalb eine automatische Kalibrierung dazu gebaut.
Die ermittelt mit Hilfe des normalen (RC-genauen) 1ms-Timers die wirkliche Laufzeit zwischen dem Start und dem Ablauf des WD-Timers. Und dann wird eben im WDT-ISR nicht z.B. 256ms dazu addiert, sondern 278...

Und den RC-Oszillator kalibriere ich über ein eigenes Register. Damit bekomme ich genügend Genauigkeit hin, um die Empfangsfenster eines HM-CC-RT-DN zu treffen.

Ich hätte auch gerne den Quarz als Timer verwendet, aber dann kann ich mit dem Power-Down-Modus nicht so weit runter fahren - der Quarz-Oszillator muß weiter laufen und der braucht einiges mehr an Strom als nur der WDT.

Bei Batteriebetrieb versucht man halt, alles Mögliche einzusparen.
Auch eine Lösung mit dem separaten Uhrenquartz geht nicht - zumindest hatte ich keine verwertbare Idee...

Martin
fhem auf cubietruck, HM-USB-CFG-2, CUL-V3, 6x HM-CC-RT-DN, 5x HM-SEC-SD, 2x HM-SEC-SCo, 5x HM Eigenbausensoren, AVR-Heizungsgateway

Dietmar63

Danke, dass bestätigt meine Vermutung.
Kannst du auch die von mir beschriebene Problematik mit den Interrupts bestätigen?

Dass ein Interrupt mit laufenden Watchdog timer nicht nur den ISR ausführt, sondern auch die
Hauptschleife loop() weiterführt. Eigentlich dürfte in ihr der Arduino nur sofort wieder schlafen gelegt werden.

In den meisten Fällen wird aber der Watchdog timer neu gestartet. In diesen Fällen kann man dann nicht sagen wieviel Zeit vergangen ist. 
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Dietmar63

#1176
In NewAskSin kann man debugging per
dbg << xxx << yyy << zzz <<  aaa;
Über den seriellen Anschluss durchgeführen.
Ich finde einfach nicht den Code, um dies in eigenen Projekten zu nutzen.

Kann mir jemand auf die Sprünge helfen.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Linef

Hallo Dietmar,

wenn der Atmel schlafen gelegt wurde, kann er über verschiedene Ereignisse aufgeweckt werden, z.B. WD-Interrupt oder PC-Interrupt.
Das bedeutet aber nicht, daß er nur die ISR abarbeitet und sich dann wieder schlafen legt.

...er wird aufgeweckt...und läuft dann komplett, bis er irgendwo per sleep-Kommando wieder zur Ruhe geschickt wird.

D.h. nach einem PC-Int wird zwar die ISR abgearbeitet, aber er ist danach wach und damit kommt er auch im Power-Modul ans Ende der Routine, kehrt von dort zurück und ist in der Main-Loop des AS-Moduls...
Also ganz normales Verhalten.

"dbg" ist ein Alias für "Serial" - definiert in macros.h.
Serial kommt aus den Arduino-Files HardwareSerial*

Viele Grüße,
Martin

fhem auf cubietruck, HM-USB-CFG-2, CUL-V3, 6x HM-CC-RT-DN, 5x HM-SEC-SD, 2x HM-SEC-SCo, 5x HM Eigenbausensoren, AVR-Heizungsgateway

Dietmar63

Ok, versuche ich dort mein Glück
Danke Dietmar
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Linef

Zum Thema WDT und PCINT nochmal:
Im Normalfall wird der PCINT in der NewAskSin nur durch den Config-Taster ausgelöst - und das ist recht selten der Fall.
Damit tritt das "falsche Weiterzählen" vergleichsweise selten auf.

Grundsätzlich ist die Problematik m.E. schwer lösbar. Wenn der Atmel wach ist, soll ja der 1ms-Timer verwendet werden.

Wenn beispielsweise durch einen PCINT der Atmel schon früher aufgeweckt wird, müßte man den WDT noch zu Ende laufen lassen um festzustellen, wieviel ms nach dem PCINT der WD-INT kommt. Nur so wüßte man, wieviele ms nach dem Start des WDT der PCINT auftrat.

Anschließend müßte man den normalen 1ms-Timer "nachkorrigieren". Das beeinflußt dann aber wieder bereits gestartete Timer aus der Timer-Klasse, so daß diese Timings dann nicht mehr stimmen...

Martin
fhem auf cubietruck, HM-USB-CFG-2, CUL-V3, 6x HM-CC-RT-DN, 5x HM-SEC-SD, 2x HM-SEC-SCo, 5x HM Eigenbausensoren, AVR-Heizungsgateway

Dietmar63

#1180
ja, so in etwa habe ich mir das gedacht.
daran erkennt man, dass der Atmel dafür nicht designt wurde.

Zitat
Wenn beispielsweise durch einen PCINT der Atmel schon früher aufgeweckt wird, müßte man den WDT noch zu Ende laufen lassen um festzustellen, wieviel ms nach dem PCINT der WD-INT kommt. Nur so wüßte man, wieviele ms nach dem Start des WDT der PCINT auftrat.
genau so habe ich es im Beispielscetch gemacht. Ich habe ihn einfach weiterlaufen lassen und in der ISR 8192ms addiert. Das passt einigermaßen.

Mein Problem ist, dass ich die Blinks einer Fotodiode zählen will(500Hz/KWH). Alle 5 Mintuen sollen dann Meldungen über den Stromverbrauch an die FHEM-Zentrale gehen. Es soll im Prinzip ein Nachbau des HM-ES-TX-WM werden. Der liefert fertige Leistungswerte, die kann man nur mit  vernünftigen Zeitbezug errechnen. Ich könnte die Logik in die Zentrale verlagern, dann müsste ich aber dort HM-ES-TX-WM verändern.

Im Moment hat sich allerdings herausgestellt, dass meine LED am Stromzähler nicht hell genug ist deshalb baue ich einem LM4250 dazwischen. Mal sehen ob es damit klappt. Die Schaltung und der Scetch funktionieren schon. Habe es mit einer LED probiert, die der A. selbst in sehr kurzen Abständen schaltet. 5 Blinks pro Sekunde waren kein Problem.

Wie hast du die Kalibrierung des WDT timers gebaut?

Für
Serial << "xxx" << "yyy" << "zzz\n"
ist folgende Zeile erforderlich:
template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
Damit klappt es.

Danke Dietmar
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Linef

Eigentlich ganz einfach:


void calibrateWatchdog() { // initMillis() must have been called yet
uint8_t sreg = SREG; // remember interrupt state (sei / cli)
wdt_cal_ms = 0;
startWDG250ms();

uint16_t startMillis = getMillis();
wdt_int = 0;
wdt_reset();
sei();

while(!wdt_int) // wait for watchdog interrupt
;
SREG = sreg; // restore previous interrupt state
wdt_cal_ms = getMillis() - startMillis; // wdt_cal_ms now has "real" length of 250ms wdt_interrupt
stopWDG();
dbg << F("wdt_cal: ") << wdt_cal_ms << F("\n");
}

ISR(WDT_vect) {
// nothing to do, only for waking up
addMillis(wdtSleep_TIME);
wdt_int = 1;
}

void    startWDG250ms(void) {
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDIE) | (1<<WDP2);
wdtSleep_TIME = wdt_cal_ms;
}

void    startWDG8000ms(void) {
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDIE) | (1<<WDP3) | (1<<WDP0);
wdtSleep_TIME = wdt_cal_ms * 32;
}


In der Kalibrierungsroutine Flag (das wird in der WD-ISR gesetzt) zurücksetzen, WDT auf 0 setzen, aktuellen 1ms-Counter merken, Interrupts freigeben und auf gesetztes Flag warten. Dann kann die wirkliche WD-Laufzeit anhand des 1ms-Counters berechnet werden.
Diesen Wert dann für die künftigen Korrekturen in der WD-ISR merken.

Martin
fhem auf cubietruck, HM-USB-CFG-2, CUL-V3, 6x HM-CC-RT-DN, 5x HM-SEC-SD, 2x HM-SEC-SCo, 5x HM Eigenbausensoren, AVR-Heizungsgateway

Dietmar63

Danke für den Code!

Damit werde ich mal testen - kann man ja fest im setup() einbauen.
Dann wird automatisch auf neuer Hardware kalibriert.

Gruß Dietmar
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Tom71

Zitat von: kadettilac89 am 18 September 2016, 09:44:14
Hi Tom71,

hast du das OTA hinbekommen? Wenn ja, welchen Boatloader und nach welcher Anleitung hast du ihn geflasht?

Ja, hier ist mein Flash-Workflow:

  • Kompilieren des Bootloaders mit der Änderung der Serial und HM-ID in devices/HB-UW-Sen-THPL.h
  • make clean HB_UW_Sen_THPL -> Bootloader-AskSin-OTA-HB_UW_Sen_THPL.hex
  • Dann flashen des OTA-Bootloaders mit meinem Raspi:
    sudo bin/avrdude -Cbin/avrdude.conf -p m328p -P gpio -c gpio -U lfuse:w:0xE2:m -U hfuse:w:0xD0:m -U efuse:w:0x06:m -U lock:w:0x2F:m -e -Uflash:w:Bootloader-AskSin-OTA-HB_UW_Sen_THPL.hex:i
  • Dann mit Arduino-IDE die Software übersetzt und per OTA geflashed:
    ./flash_ota.sh HM-Sensor-UWS7475130.hex UWS7475130

    #!/bin/bash
    FILE_NAME=$1
    php hex2eq3.php --inFile $FILE_NAME --outFile $FILE_NAME.eq3  --spmPageSize 128 --outFormat eq3 --withCrcCheck --pathTo-srec_cat /usr/local/bin/srec_cat
    sudo flash-ota -c /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AI03VVGB-if00-port0 -f $FILE_NAME.eq3 -s $2

Hier nochmal etwas ausführlicher der erste Teil: https://tom71blog.wordpress.com/2016/05/13/universalsensor-fuer-homematic/

Zum flashen über OTA muss man das hex-File in ein eq3-File umwandeln, daher der Weg über hex2eq3.php und srec_cat
Homematic | RaspberryMatic

Dietmar63

Zitat von: Dietmar63 am 26 September 2016, 11:19:54
Danke für den Code!

Damit werde ich mal testen - kann man ja fest im setup() einbauen.
Dann wird automatisch auf neuer Hardware kalibriert.

Gruß Dietmar

Danke nochmals für den Code.
Habe ihn als Grundlage für ein eigenes kleines Testprogramm genutzt, und beim normalen Arduino eine Abweichungen von 11.34% ermittelt. Mal sehen wie es mit dem Mini aussieht.

Danke dir!
Gruß Dietmar
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm