Zitat von manu241
Beitrag anzeigen
Ankündigung
Einklappen
Keine Ankündigung bisher.
ESP8266 KNX mit ETS
Einklappen
X
-
Geht mir genau so! Finde das Thema extrem spannend, Arduinos habe ich auch schon des öfteren programmiert, aber hier steige ich irgendwie nicht durch.Zuletzt geändert von MasterOfPuppets; 10.10.2019, 13:27.
-
Hallo,
wäre eventuell jemand so nett und erstellt ein DemoIO-Projekt wie man die I/Os eines Arduino nutzen kann um KNX Befehle per Arduino sendet und auch empfängt?
Ich verstehe aktuell nicht, wie es funktioniert und könnte so eventuell einen besseren Einstieg finden.
Gruß und danke Manuel
- Likes 1
Einen Kommentar schreiben:
-
thesing da hat sich glaub was überschnitten, aber deine erklärte Vorgehensweise entspricht nahezu 1:1 wie ich es angegangen bin, zum Problem mit den wechselnden Table Größen hab ich eben ein kleines dynamisches memory management für den Flash implementiert. Das wiederfinden passiert über eine eindeutige "memoryID" welche in addSaveRestore() vergeben wird.
Zu den 4,5k, gute Frage, eigentlich sollten es ca. 3k weniger sein (2k Emulation +1k ETS Daten), kann ich mir grad auch nicht erklären aber vielleicht ist da bei meiner Messung was schief gegangen (Ram usage zu untersuchen ist ja gar nicht sooo leicht
)
Die Werte der KOs bleiben natürlich im RAM die müssen ja nicht über einen Device neustart hinaus gerettet werden....
Firmware-Update mache ich über den Debugger (Jlink) und der löscht nur den Flashbereich für den es auch neue Daten gibt (überschreibt quasi die alten), mehr zu löschen ist ganz einfach nicht notwendig. Ich vermute mal der Arduino Bootloader macht das auch so aber ich weiß es eben nicht. Der Grund warum bei der FlashStorage lib die ETS Daten nach jedem Update verlorgen gehen ist, das die Lib Flash Speicher über ein const Array reserviert und das landet natürlich irgendwo inmitten des text segements welches jedes mal vor dem schreiben der neuen daten gelöscht werden muss. Deshalb bin ich ja einen anderen Weg gegangen und mach es ähnlich wie Stack/Heap mit dem Ram, damit kommen sich die Bereiche so lange nicht in die Quere solange die Summe unter ~99% bleibt.
Nachdem das alles rel. grobe Änderungen mit sich brachte sind ausführliche Tests hier sehr wilkommen
thesing , was hälst du von einem stable/develop branch?
Einen Kommentar schreiben:
-
Hi,
das ist jetzt echt strange - ich mach mir ein paar Gedanken und Du hast gleich eine Lösung! Und auch noch eine wesentlich bessere als ich es mir hätte ausdenken können!
Noch ein paar Fragen eines technisch interessierten (hab mir Dein Coding noch nicht angeschaut, kommt am Wochenende):- internalRam spart die Duplizierung bei den TableObject-Daten, hab ich verstanden -> Also hast Du hier die gleiche Idee wie ich gehabt, die Klassen arbeiten nur mit einem Pointer, deswegen auch 1,1k weniger RAM-Verbrauch, verstehe ich.
- external ist das, was ich eigentlich für meinen i2c-EEPROM-Implementierung gebraucht hätte, wenn ich vorher richtig drüber nachgedacht hätte... auch verstanden.
- internalFlash hört sich vom Speicherverbrauch am interessantesten an, aber hier verstehe ich nicht, wo Du die ca. 4,5k gespart hast? Und was passiert mit den Werten der KO (also die GroupObject-Klasse)? Werden deren Änderungen auch im Flash gespeichert? Das würde ja endlos viele Seiten-Updates erfordern, da man ja häufig KO wegschreibt (zumindest mach ich das, viele davon mit valueNoSend, damit sie für den nächsten ReadRequest verfügbar sind). Macht das den Flash nicht zu schnell kaputt?
- Wie machst Du denn den Firmware-Update, wenn Du sagst, dass bei Dir nicht der ganze Flash gelöscht wird? Ich hab nämlich keine Ahnung, wer den Flash löscht, bisher dachte ich immer, das "gehört" so
.
Ich habe mit der bisherigen Plattform eine EEPROM_EMULATION_SIZE von 6144 hin bekommen, bei ca. 5500 bytes an ETS-Daten. Das sind entweder 50 meiner Logikkanäle oder der BME280 (mit seiner Lib) mit Temperatur, Luftfeuchte, Luftdruck, Taupunkt, Wohlfühlbereich und 40 Logikkanälen. Oder ein SCD30 mit Temperatur, Luftfeuchte, Co2, Taupunkt, Wohlfühlbereich und 40 Logikkanälen. Ich wollte mich demnächst mal am BME680 versuchen, aber da scheint dessen Lib recht viel Speicher zu verbrauchen. Insofern wäre mehr RAM sehr interessant, dann könnte ich einheitliche Firmware für verschiedene Sensoren haben.
Auf jeden Fall super, dass Du das gemacht hast, ich versuche mich durch Tests zu bedanken...
Gruß, Waldemar
Einen Kommentar schreiben:
-
Hallo Waldemar,
ich finde dein Vorhaben sehr löblich
Ich würde bei der SaveRestore-Klasse und der Memory-Klasse anfangen, da Flash blockweise geschrieben werden muss, und möglichste jedes InterfaceObjekt getrennt voneinander geschrieben werden muss. Daher musst du ggf. Padding einführen. Da weiterhin partielle Programmierung möglich sein sollte, musst du dann damit klar kommen, dass sie die Größe von einzelnen InterfaceObjekten verändern könnte wenn z.B. neue GAs zu den KOs hinzugefügt werden.
Passt soweit.Zitat von mumpf Beitrag anzeigen- TableObject wird so umgebaut, dass es nur mit einer Speicherreferenz auf den Anfang eines Speicherblocks arbeiten kann und kein einziger Wert ins RAM kopiert wird.
- Damit könnte man für die Parameter und die GA-Zuordnungen direkt auf den Flash referenzieren, da sich diese Tabellen ja zur Laufzeit nicht ändern (nur beim Programmieren -> kommt noch). Damit könnte man für diese Tabellen auf ein malloc verzichten.
- Nach dem Programmieren werden die Daten ins Flash geschrieben und dann der SAMD neu gestartet, dann bekommt die Firmware ja ihr RAM wieder.
Hier muss nichts geändert werden, da die GroupObjekt-Objekte eh in der GroupObjektTable erzeugt werden.Zitat von mumpf Beitrag anzeigen- KO und deren Werte werden weiterhin im RAM belassen. Dazu muss hier ein malloc passieren, das müsste dann "außerhalb" der TableObject-Klasse passieren (oder über einen alternativen Konstruktor, das kann man ja noch sehen)
Da solltest du ein zusätzliches Callback an der Facade oder der Bau-Klasse vorsehen. Durch dieses Callback kann die eigentliche Anwendung dann vor der Programmierung Speicher freigeben.Zitat von mumpf Beitrag anzeigen- Beim Programmieren gehe ich davon aus, dass die eigentliche Firmware (also das, was den Stack nutzt) gestoppt ist. Sollte diese RAM brauchen, dann wird dieser während der Programmierung nicht gebraucht und kann "missbraucht" werden - für die zu programmierenden TableObject (Parameter, KO und GA).
Das Hauptproblem bei der partiellen Programmierung besteht, ist dass du dann damit klar kommen musst, dass sich die Größe von einzelnen InterfaceObjekten verändern könnte wenn z.B. neue GAs zu den KOs hinzugefügt werden.Zitat von mumpf Beitrag anzeigen- Ich muss nochmal untersuchen, was beim partiellen Programmieren abgeht, das blicke ich noch nicht ganz, obiges würde nur (falls überhaupt) für das Programmieren der gesamten Applikation funktionieren.
Bsp.:
Ist AdressTable 100 Byte startet an Offset 0, AssoziationTable 100 Byte startet and Offset 100, GoT 100 Byte startet an Offset 200, Paramter 100 Byte startet an Offset 300.
Nun soll nur die AssoziationTable geändert werden. (da eine GA auch an ein anderes KO zugewiesen wurde). Diese wird jetzt größer. Also ändern sich die Offsets von Got und Parameter. Du kannst dann entweder für die einzelnen InterfaceObjekte feste Größen vorsehen, oder du schreibst die abwechselnd auf zwei Bereiche im Flash, oder du lädst alle in den Ram und schreibst sie neu in den Flash. (ggf. pro Block prüfen ob man neu schreiben muss). Oder dir fällt noch etwas neues ein.
Die Hauptarbeit wird am Zusammenspiel der Klassen Memory, SaveRestore und TableObject sein. Die Platform muss wahrscheinlich auch mehr Operationen für das blockweise Speichern bekommen. Das ist insgesamt sicher keine ganze einfache Aufgabe.
Ich würde wahrscheinlich damit anfangen, dass die Memory-Klasse die Platform fragt wie groß die Blockgröße zum Speichern sein soll. Dann fragt die MemoryKlasse der Reihe nach alle registrierten SaveRestore Objekte nach den Blöcken und speichert diese. Den letzen Block sollte man am besten auffüllen damit ein neues SaveRestore immer an einem Block beginnt. Zusätzlich muss du dir irgendwo merken wie viele Blöcke jedes SaveRestore hat (vielleicht in den ersten zwei Blöcken?)
Dies nur als schnell heruntergeschriebene Idee.
Ich wünsche jedenfalls viel Spaß
VG
Thomas
Einen Kommentar schreiben:
-
lustig das du das genau jetzt schreibst, ich habe vor genau dazu einen pull request zu machen
habe den Stack nämlich folgendermaßen erweitert damit es möglich ist 3 unterschiedliche NV Memory "Typen" zu handeln:- internalRam = externe Library welche die Daten eines externen Speichers selbst in den Ram kopiert (wie zb. die aktuell verwendeteFlashStorage lib). Hier wird den saveRestore Objekten dann aber nur der Pointer auf diese Daten übergeben und nicht nochmal dupliziert
- internalFlash = hier wird direkt (kleinere Buffer im Ram sind nötig) alles in den Flash geschrieben und gelesen, dazu braucht es ein memory management welches malloc/free etc. auf den Flash ermöglicht (hab ich für den sam in samd_flash.h gemacht). Beim Programmieren fordert allocTable() dann Speicher der jeweiligen Größe von der Platform an. Die Daten selbst kommen dann später häppchenweise über memoryWriteIndication()
- external = hier wird im memory Objekt ein Ram buffer für jedes saveRestore Objekt erzeugt mit welchem der Stack dann arbeitet, die Daten für den buffer können byteweise aus dem externen Speicher gelesen/geschrieben werden. Hier könnte man noch ansetzen und die selten/langsam benötigten Daten vom z.b. Application Table (Parameter) nicht im Ram zu buffern sondern byteweise direkt in den externen Speicher zu schreiben/lesen (hab ich aber noch nicht implementiert)
In samd_platform.cpp findet man Beispiele (meine Tests) für die Implementierung der 3 Varianten.....
Für den Samd sollte das bereits alles funktionieren, bei den anderen Plattformen hab ich versucht die "internalRam" Variante zu implementieren (wie vorher nur ohne die zusätzliche Ram Kopie in den Stack Objekten) aber das ist alles ungetestet. Hier könntest du Waldemar evtl. aushelfen und zumindest die Linux Variante mal anschaun, ich hab dazu nämlich nicht wirklich was am Start
Auch interessant wäre wie weit du beim SamD mit deiner Kanalduplizierung kommst, ich hab mit meinem Testprojekt mal grob die max Ram usage angeschaut, absolut natürlich wenig aussagekräftig aber relativ zueinander schon plausibel: (ETS Daten sind hier ca. 1,1k)
original Stack 12,8k EEPROM_EMULATION_SIZE = 2048k internalRam 11,7k EEPROM_EMULATION_SIZE = 2048k external 12,8k EEPROM_EMULATION_SIZE = 2048k, hier werden die Daten dupliziert weil ich den externen EEPROM nur emuliere, sonst wären es 2k weniger also ca. 10,8k internalFlash 8,3k
thesing vielleicht findest du auch die Zeit und schaust dir das mal an, evtl. hast du noch div. Anregungen
PS: mein flash memory management arbeitet von oben herab bis zur nächsten Row der text+data Adresse, bleibt somit also auch beim neu Flashen des MC erhalten wenn man nicht vorher den ganzen Flash löscht (macht das der Arduino Bootloader?) und somit muss man auch nicht immer neu programmieren über die ETS
Einen Kommentar schreiben:
-
Hi Thomas ( thesing ) et all,
ich wollte hier mal ein paar Fragen zur Speicherverwaltung los werden und hoffe auf Tipps...
Ausgangssituation: Ich habe mal auf dem SAMD ein Speichern und Lesen der ETS-Daten auf einem I2C-EEPROM statt im Flash implementiert, in der Hoffnung, damit RAM zu sparen (das war zugegebenermaßen blauäugig und ohne es zu Ende zu überlegen). Die Daten werden ja immer erstmal ins RAM geladen, egal ob aus dem Flash oder aus dem EEPROM... Immerhin kann ich jetzt nach einem Flash der Firmware sofort testen, da die Parametrisierung der ETS nicht mehr verloren geht.
Dann habe ich mir den Startup vom knx-Stack weiter angesehen und festgestellt, dass die jeweiligen TableObject die Daten nochmal ins eigene Objektmodell deserialisieren, also wird der Inhalt nochmal ins RAM gepackt. Und wenn man so programmiert wie ich, dann packt man die Parameter- und KO-Werte in Variablen und hat dann so die Daten ein drittes mal im Speicher
. Das "3. mal im Speicher" habe ich inzwischen behoben, aber ich hätte gerne noch mehr RAM frei
.
Ich würde gerne folgendes probieren (aber vorher mit euch diskutieren, um nicht wieder komplett falsch zu liegen):- TableObject wird so umgebaut, dass es nur mit einer Speicherreferenz auf den Anfang eines Speicherblocks arbeiten kann und kein einziger Wert ins RAM kopiert wird.
- Damit könnte man für die Parameter und die GA-Zuordnungen direkt auf den Flash referenzieren, da sich diese Tabellen ja zur Laufzeit nicht ändern (nur beim Programmieren -> kommt noch). Damit könnte man für diese Tabellen auf ein malloc verzichten.
- KO und deren Werte werden weiterhin im RAM belassen. Dazu muss hier ein malloc passieren, das müsste dann "außerhalb" der TableObject-Klasse passieren (oder über einen alternativen Konstruktor, das kann man ja noch sehen)
- Beim Programmieren gehe ich davon aus, dass die eigentliche Firmware (also das, was den Stack nutzt) gestoppt ist. Sollte diese RAM brauchen, dann wird dieser während der Programmierung nicht gebraucht und kann "missbraucht" werden - für die zu programmierenden TableObject (Parameter, KO und GA).
- Nach dem Programmieren werden die Daten ins Flash geschrieben und dann der SAMD neu gestartet, dann bekommt die Firmware ja ihr RAM wieder.
- Ich muss nochmal untersuchen, was beim partiellen Programmieren abgeht, das blicke ich noch nicht ganz, obiges würde nur (falls überhaupt) für das Programmieren der gesamten Applikation funktionieren.
- alle Parameter im Flash (bei mir ca. 5k, gerne mehr)
- alle GA-Zurodnungen im Flash (das können auch viele werden, wenn man viele KO hat)
- alle KO im RAM
- Es gibt noch eine 4. Tabelle, von der weiß ich nicht, was drin steht, aber die ist nie groß, könnte also auch ins RAM...
Ich sage jetzt nicht, dass ich wirklich in der Lage bin, das zu programmieren - ich bin noch recht neu dabei, aber ich würde es gerne versuchen. Die Frage ist, was ich nicht bedacht habe oder ob ich etwas falsch verstanden habe...
Gruß, Waldemar
Einen Kommentar schreiben:
-
Hi Manuel,
leider kann ich dir hier nicht helfen, ich bin auf der SAMD Plattform unterwegs. Ich hab mir zum Spielen einen ESP 32 besorgt, aber noch nichts damit gemacht.
Mir hat es aber sehr geholfen, die ersten Schritte unter Linux zu machen, und dann erst auf die Zielhardware zu wechseln.
Gruß, Waldemar
Einen Kommentar schreiben:
-
Hallo mumpf,
Auf dem NodeMCU Wifi-Chip steht ESP8266MOD. Ich hoffe, dann sollte es passen, oder ? Geladen habe ich die KNX-Demo und Lade es via Arduino 1.8.10 in den NodeMCU. Jedoch wie geschrieben, bekomme ich diese Meldung:
Gruß ManuelCode:ets Jan 8 2013,rst cause:2, boot mode:(3,7) load 0x4010f000, len 1384, room 16 tail 8 chksum 0x2d csum 0x2d v8b899c12 ~ld ISR not in IRAM!
Einen Kommentar schreiben:
-
Hi Thomas,
ich habe nach längeren Tests jetzt den Pull-Request fürs "Restart Device" gestellt. Es funktioniert mit allen Geräten, dich ich im Haus habe (wobei ich nicht jedes Gerät, sondern nur Gerätekategorie/Hersteller-Kombis getestet habe). Wäre schön, wenn das in den Haupt-Stack mit rein könnte.
manu241: Ich hab mit dem ESP noch nichts gemacht, aber so wie ich das verstanden habe, ist derzeit nur der ESP8266 und der ESP32 unterstützt. Und zum CreateKnxProd: Ich habe gerade mal Version 2.0 runtergeladen, das hat ohne Probleme geklappt und das config-File ist in dem Zip drin.
Gruß, Waldemar
Einen Kommentar schreiben:
-
Moin,
Ich habe nun auch mal versucht das Demo-Projekt in ein Nodemcu 1.0 ESP-12E zu laden. Jedoch steht im Seriellen Monitor : ISR not in IRAM! Was hat das zu bedeuten und was müsste ich anders machen ?
Gruß Manuel
Einen Kommentar schreiben:
-
Hallo,
ich wollte mich morgen mal an diesem Projekt versuchen. Dazu habe ich mir das Demo-Projekt geladen, sowie das CreateKNXProd.
Dort steht:Jedoch finde ich im Downloadverzeichnis dieses file :Code:Configuration: Change the path in CreateKnxProd.exe.config to your ETS4 Path. If you have ETS5 use the path to the ETS4 dlls of ETS5. For example: C:\Program Files (x86)\ETS5\CV\4.0.1997.50261 You can also change UICulture and Culture from 'de' to 'en' there.
nicht. Verstehe ich da etwas falsch?Code:CreateKnxProd.exe.config
Sorry für die Anfängerfragen.
Gruß Manuel
Einen Kommentar schreiben:
-
Hi Manuel,
ja, mit der ESP-Plattform kannst Du über das eingebaute WLAN-Modul und über Deinen KNX-Router Daten auf den Bus senden/empfangen. Das Projekt selbst kann noch viel mehr
Gruß, Waldemar
Einen Kommentar schreiben:
-
Hallo,
verstehe ich dieses Projekt richtig, dass der Arduino ein "KNX-Gerät" ist, dass eigenständig ohne KNX-Kabel über ein KNX-Router Daten auf mein Bussystem schreiben kann, je nachdem welcher Sensor etc angeschlossen ist.
Ich finde es sehr intressant, da ich damit gerne einen Regenmesser realisieren würde (wie in diesem Projekt https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/diy-do-it-yourself/36798-arudino-knx-regenmesser nur ohne TPUART)
Gruß Manuel
Einen Kommentar schreiben:


Einen Kommentar schreiben: