Ankündigung

Einklappen
Keine Ankündigung bisher.

ARDUINO am KNX

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Meine Hardware lässt immer noch auf sich warten. In der Zwischenzeit hab ich mal mit Fritzing ein 7ch LED Controller Shield für den Leonardo gebastelt.

    Fehlt noch ein Taster, eine LED, sowie ein paar herausgeführte Pins für Relais (zum Abschalten der Netzteile bei Bedarf) und Siemens BCU. Dürfte gerade so noch drauf passen ohne die Platine größer als den Arduino werden zu lassen.

    Werde aber erst mal testen wieviel Wärme da tatsächlich entsteht bevor drüber nachdenke die Platine tatsächlich fertigen zu lassen.
    Angehängte Dateien

    Kommentar


      Gehört zwar nicht unbedingt zum Thema KNX, aber bezüglich der Größe des Codes bin ich zufällig auf das hier gestoßen:

      HaikuVM - A Java VM for ARDUINO and other micros using the leJOS runtime.

      "Angeblich" soll der damit produzierte binary code kleiner sein als mit klassischem C?!

      Vielleicht kanns ja jemand gebrauchen.

      btw: Mein China Arduino Leonardo ist da. Macht einen guten Eindruck und hat nach dem installieren der Treiber auch gleich geklappt. Wenn jetzt noch die MOSFETs kommen kann ich loslegen.

      Gruß
      Alex

      Kommentar


        Zitat von tuxedo Beitrag anzeigen
        Werde aber erst mal testen wieviel Wärme da tatsächlich entsteht bevor drüber nachdenke die Platine tatsächlich fertigen zu lassen.
        Das hab ich mich auch grad gefragt
        Was fuer LEDs steuerst du denn damit an? Ich habe hier fuer die meisten Anwendungen (ok, das sind auch alles nur max 5W pro Kanal) den/die "Arduino-typischen" TLC-5940 und daran dann P-Channel LogL SMD-FETs im SOT-32 Gehaeuse - da wird dann auch nix wirklich warm.
        Ich hab den Abfall am FET nicht gemessen, aber da muesste noch einiges mehr durchgehen bevor das grenzwertig wird...


        gruesse :: Michael

        Kommentar


          Bei gewünschten 4..5A/Kanal (bis zu 7m LED Stripe) wird laut Datenblatt wohl verdammt wenig abfallen. Wohl irgendwas <=1W.
          Warte noch auf die MOSFETs... Hab mir jetzt auch noch einen kleinen Satz Lochrasterplatinen geordert (in Deutschland ;-) ). Damit werde ich den ersten Prototypen basteln. Platz hab ich ja genug auf dem Dachboden ;-)

          Kommentar


            Hardware ist da. Erster PWM Dimmer-Test war erfolgreich:

            https://www.youtube.com/watch?v=F8a99YWbdA4

            Jetzt kommt der Busankoppler an die Reihe ...

            Bis jetzt: sehr sehr geil ... ;-)

            [update]
            Sehr sehr geil. KNX geht auch auf anhieb. Ein/Auschalten per Glastaster funktioniert. Dimmen will noch nicht.

            Hat jemand nen Tipp wie man möglichst einfach Variablen auf die Console schreiben kann (zum debuggen)? oder muss ich wirklich alles erst in char konvertieren?!

            [update]
            So, dimmen geht nun auch:

            https://www.youtube.com/watch?v=ajvleXMCRoI

            Im Video ist das Dimmverhalten nur nicht gut zu sehen, weil gegen das Licht filmen mal wieder nicht der Knüller ist. Dimm-zeit noch auf 4-sek eingestellt und schon lässt sich das ganze super bedienen.

            Prototyp Nr. 1 ist somit fertig. Jetzt fehlt nur noch der saubere Aufbau auf Lochraster (lasse die fertige Platine erstmal außen vor) sowie die Programmierung des ganzen Rests: 7 Kanäle statt nur eineem, Soft an/aus. Speichern der Werte im Eeprom, Sonnenaufgang/-untergang-Modus, ..., Parametrisierung via property-write, ... Mal schauen ob das alles in den Speicher passt.


            Finde die API aber an der einen Stelle seltsam: Der Taster sendet DPT 3.007

            An der Lib dachte ich, ich kann get1ByteIntValue() benutzen um das ganze anzufragen. Pustekuchen. Ich muss getFirstDataByte() benutzen.

            Warum wird da ein Unterschied gemacht? Intern geht ersteres auf byte[8] und letzteres auf ein paar bits von byte[7] ... *Bahnhof*

            Kommentar


              Welchen Schaltplan hast Du dazu als Vorlage verwendet ?

              Grüße
              Umgezogen? Ja! ... Fertig? Nein!
              Baustelle 2.0 !

              Kommentar


                Den hier: https://www.sparkfun.com/products/10618

                hab allerdings einen anderen Mosfet verwendet. Der in China bestellte kam ohne "L" am Ende der Bezeichnung und war für die Logik-Beschaltung mit dem Arduino nicht geeignet. Auf die weiteren 30 tage für die Korrekturlieferung wollte ich nicht warten und hab dann den hier verwendet:

                IRLIZ 44N nur 0,79 €: Leistungs-MOSFET N-LogL TO-220-FU 55V 30A bei reichelt elektronik

                Der hat gleich den Vorteil dass er voll isoliert ist, sprich: ich kann alle Mosfets gemeinsam ohne weitere Schutzisolation an einen Kühlkörper hängen. Von der Leistung her ist er ähnlich zu dem von Sparkfun (welcher bei uns nur schwer oder teuer zu bekommen ist).

                Kommentar


                  Kann mir jemand erklären warum in der KNX TPUart Lib für den Arduino sogut wie alle Werte (Float, 14byte Text, ...) erst ab buffer[8] im Telegram liegen, aber ich für DPT 3.007 (für's dimmen) in buffer[7] nachschauen muss?

                  Wieso wird zwischen "first data byte" (buffer[7]) und anderen [buffer[8] und weiter hinten) unterschieden?

                  Ist nur die API in der Wahl der methodennamen unglücklich gewählt, oder hat das einen tieferen Sinn? In der Spec (EIBA) hab ich dazu (noch) nix gefunden.

                  Noch ein Wort zur Größe der KNX TpUart Lib für den Arduino:

                  So wirklich gut aufteilen lässt sich die Lib nicht. Da wo am meisten "Sparpotential" drin steckt ist doch KnxTelegram.cpp ... Hier könnte man doch auch mit "if defined..." diverse Bereiche (getter&setter für diverse Datentypen) ausklammern wenn man sie nicht braucht.

                  Wäre u.U. übersichtlicher ein Einsteigerfreundlicher. Per default ist alles drin. Und der Experte der Platz braucht klammert sich mit einem "#define xyz" die ungenutzen Bereiche aus und spart so Platz.


                  [update]
                  Wieder einmal kann ich mir meine Frage wohl selbst beantworten:

                  Volume 3, Part 3, Chapter 7, Fig. 3/3/7-7 zeigt es:
                  Werte mit 6 oder weniger bit sind in Octet7 an Bit 1-6 (in der Doku wird bei 1 angefangen, also Bit 1-8, statt 0-7) die Werte platziert.

                  Da es sich beim Dimmen um DPT 3.007 handelt (3bit gesteuert, laut ETS), fällt dieser Wert in genau diese Definition.

                  [update2]
                  Das Lexikon erklärt es sogar noch besser: http://redaktion.knx-user-forum.de/lexikon/datentypen/ Im dort verlinkten Dokument steht's Haarklein beschrieben.

                  [update3]
                  Jetzt zeigt es sich dass ich von Java und modernen CPUs verwöhnt bin:
                  Mein Dimmer soll 7 PWM Kanäle haben. Wenn ich einen Kanal in 4 sek von 0 auf 100% dimmen will, dann brauch ich bei 255 Dimm-Schritten ca. 15ms pause zwischen jedem Schritt.
                  Wenn ich jetzt parallel einen einzelnen Kanal mit einem 1sec-SoftStart an oder ausschalten will, dann hab ich hier ein anderes Delay. Nämlich knapp 4ms zwischen jedem Schritt.

                  In Java würden jetzt zwei Threads laufen. Mit dem Arduino hab ich aber nur einen. Also muss ich den ganzen Krempel auf Zyklen mit Zeitauswertung (wie lange ist seit dem letzten Zyklus vergangen) umstellen. Bin gespannt wie gut das mit 7 Kanälen funktioniert.

                  Kommentar


                    Zitat von tuxedo Beitrag anzeigen
                    Bin gespannt wie gut das mit 7 Kanälen funktioniert.
                    Hast du dir mal nen TLC5940 angeschaut? Den gibts evtl bei TI als Gratisprobe, zumindest hab ich meine damals daher bekommen. Mit der entsprechenden Lib nehmen die Dir die Arbeit komplett ab und koennen zudem PWM deutlich besser als der Arduino nativ.
                    Allerdings musste dann mit anderen FETs arbeiten wenn du "echte" Lasten dranhaengen willst weil der TLC eine PWM-Senke ist. Dafuer bekommste AFAIR 16 Kanaele pro Chip und chainen lassen die sich auch noch (ich glaub bis hin zu 4096 Kanaelen).


                    gruesse :: Michael

                    Kommentar


                      Nein, hatte ich noch nicht angeschaut.

                      Meine Bedenken galten der Geschwindigkeit der Ansteuerung der einzelnen Ausgänge wenn alle Ausgänge gleichzeitig verändert werden. Denn jeder Ausgang kann (in meinem Fall) wie bei einem käuflich zu erwerbenden Controller seine eigene Einschalt/Ausschalt Geschwindigkeit haben. Und falls noch Platz im Speicher ist sein eigenes Ein/Ausschalt-Delay.

                      Sehe noch nicht wie dieser IC beim Zeit-Management der Ansteuerung helfen sollte?

                      ---------------------

                      Hab mir jetzt eine Klasse zusammengeschustert die einen PWM Kanal mit all seinen Funktionen abbildet. Darin auch eine "cycleCheck" Methodik.

                      Die Haut-Loop-Schleife ruft nacheinander bei jedem Kanal dessen "loopCycle" Methode auf. Darin schaut dann jeder Kanal was es für ihn in diesem Schleifendurchlauf zu tun gibt und tut das dann.

                      Ein kleines "delay()" kommt nur noch dann zum Einsatz, wenn die Haupt-Loop-Schleife schneller als xxx ms durchgelaufen ist (es also nix zu tun gibt) --> spart wohl ein klein wenig Strom.

                      Hab bisher "trocken" Programmiert. Muss das Ergebnis dann mal noch testen. Denke aber das das so klappt.

                      -------------------------

                      Vom Speicher her bin ich aktuell bei:

                      Binäre Sketchgröße: 20.238 Bytes (von einem Maximum von 28.672 Bytes)

                      Es fehlen noch ein paar Methoden zum Speichern und Lesen des Eeprom-Inhalts, das setzen der Parameter mittels property-write Telegramm, sowie das programmieren der PA.

                      Bereits implementierte (aber noch nicht getestete) Feature sind:

                      * An/Aus
                      * Dimmen heller/dunkler mit festlegbarem Min/Max-Wert
                      * Soft an/aus, unter Berücksichtigung des Min/Max-Werts
                      * Sonnenaufgang/Untergang-Modus: Extrem langsames an/aus dimmen
                      * Steuerung mit aktuell 8 GAs pro Kanal

                      Hoffe der Platz reicht für den fehlenden Rest.

                      Unter Umständen werden ich die KNX-Lib mit den Settern/Gettern für die verschiedenen Datentypen ein wenig aufbrechen oder mit "#if defined(...)" nicht benötigte Methoden ausklammern.

                      Wenn alle Stricke reissen muss halt ein Mega her... Platz hab ich dafür.


                      [update]
                      ...nicht benötigte Methoden ausklammern.
                      Eigentlich sollte ich es besser wissen. Methoden die gar nicht verwendet werden vergrößern den Sketch nicht, da der Compiler die schon wegoptimiert.
                      Zum Platzsparen hilft es also nur: Platzsparend implementieren :-(

                      Kommentar


                        Zitat von tuxedo Beitrag anzeigen
                        Sehe noch nicht wie dieser IC beim Zeit-Management der Ansteuerung helfen sollte? (
                        Steht in der Doku zur zugehoerigen Arduino-Library, zB hier: Arduino Tlc5940 Library: Tlc_Fade Struct Reference


                        Du sagst im Prinzip: dieser Kanal soll um diese Zeit mit der Helligkeit anfangen und um jene Zeit mit der Helligkeit enden - um alles weitere kuemmert sich der TLC5940.
                        Ausserdem hat der TLC nicht nur quasi beliebig viele Kanaele, er hat auch 12 bit Aufloesung (4096 Helligkeitswerte), der Arduino kann sich in der Zwischenzeit um andere Dinge kuemmern und die PWM ist per default bereits doppelt so hoch (IIRC).


                        gruesse :: Michael

                        Kommentar


                          ok, soo genau hab ich dann wohl nicht gelesen :-)

                          4k Helligkeitswerte... Luxus, aber unnötig. Schon bei 256 Werten siehst du keine Dimm-Schritte und die Helligkeit lässt sich prima einstellen.

                          Hab das mit dem cycleCheck verfahren nun ausprobiert: Wenn ich nicht noch tonnenweise Logoutput habe der parallel dazu verläuft, dann reicht die Arduino-Power gut aus. Hab keine Einbußen feststellen können.

                          ----


                          Was mich aber gerade tierisch auf den Zeiger geht: Mir scheinen unterwegs Daten im Flöten zu gehen.

                          Wie gesagt habe ich die Funktionalität eines Dimm-Kanals in einer Klasse gebündelt.

                          In dieser Klasse gibt es ein "init()", das ich vom setup() des Sketches ausrufen lasse. also in etwa so:

                          Code:
                          void setup() {
                          
                          ....
                          
                          channelA.init();
                          channelB.init();
                          channelC.init();
                          channelD.init();
                          ....
                          
                          }
                          Die Init-Methode macht intern folgendes:

                          Code:
                          ....
                          // ----------------------------
                          	// -  FIXME for testing only  -
                          	// ----------------------------
                          	_gaDimm = "1/1/2"; // dimm relative	
                          	_gaDimmAbs = "1/1/3"; // dimm absolute
                          	_gaSwitch = "1/1/1"; // switch on/off
                          	
                          	_maxDimmValue = 255;
                          	_minDimmValue = 0;
                          
                          	_currentDimmValue = _maxDimmValue;
                          	
                          	_dimmSpeed = 3000;
                          	_onSpeed = 350;
                          	_offSpeed = 350;
                          	
                          	_onDelay = 0;
                          	_offDelay = 0;
                          	
                          	_switchOnState = SwitchOnState_LAST;
                          	_switchOnValue = 255;
                          
                          	if (_gaDimm.length()>0) {
                          		Serial.println("Setup listen for dimm ...");
                          		Serial.println(_gaDimm);
                          		_knx->addListenGroupAddress(_gaDimm);
                          		Serial.println("*done*");
                          	} 
                          	if (_gaSwitch.length()>0) {
                          		Serial.println("Setup listen for switch ...");
                          		Serial.println(_gaSwitch);
                          		_knx->addListenGroupAddress(_gaSwitch);
                          		Serial.println("*done*");
                          	}
                          	if (_gaDimmAbs.length()>0) {
                          		Serial.println("Setup listen for dimm abs ...");
                          		Serial.println(_gaDimmAbs);
                          		_knx->addListenGroupAddress(_gaDimmAbs);
                          		Serial.println("*done*");
                          	}
                          ....
                          ich weiß, ist alles nicht nicht optimal, aber ich bin ja auch noch nicht fertig.

                          Jedenfalls geht's hier um das registrieren der verschiedenen GAs für die verschiedenen Funktionen des Dimm-Kanals.

                          Die addListengroupAddress()-methode sieht wie folgt aus:


                          Code:
                          void KnxTpUart::addListenGroupAddress(String address) {
                          	if (_listen_group_address_count >= MAX_LISTEN_GROUP_ADDRESSES) {
                          #if defined(TPUART_DEBUG)
                          		TPUART_DEBUG_PORT.println("Already listening to MAX_LISTEN_GROUP_ADDRESSES, cannot listen to another");
                          #endif
                          		return;
                          	}
                          
                          #if defined(TPUART_DEBUG)
                          	TPUART_DEBUG_PORT.print("Adding {");
                          	TPUART_DEBUG_PORT.print(address);
                          	TPUART_DEBUG_PORT.print("} to [");
                          	TPUART_DEBUG_PORT.print(_listen_group_address_count);
                          	TPUART_DEBUG_PORT.print("]: ");
                          	TPUART_DEBUG_PORT.print(address.substring(0, address.indexOf('/')).toInt());
                          	TPUART_DEBUG_PORT.print("/");	
                          	TPUART_DEBUG_PORT.print(address.substring(address.indexOf('/')+1, address.lastIndexOf('/')).toInt());
                          	TPUART_DEBUG_PORT.print("/");
                          	TPUART_DEBUG_PORT.println(address.substring(address.lastIndexOf('/')+1,address.length()).toInt());
                          #endif
                          
                          	_listen_group_addresses[_listen_group_address_count][0] = address.substring(0, address.indexOf('/')).toInt();
                          	_listen_group_addresses[_listen_group_address_count][1] = address.substring(address.indexOf('/')+1, address.lastIndexOf('/')).toInt();
                          	_listen_group_addresses[_listen_group_address_count][2] = address.substring(address.lastIndexOf('/')+1,address.length()).toInt(); 
                          
                          	_listen_group_address_count++;
                          
                          #if defined(TPUART_DEBUG)
                          
                          	for (int i = 0; i < _listen_group_address_count; i++) {
                          
                          		TPUART_DEBUG_PORT.print("Listen for: [");
                          		TPUART_DEBUG_PORT.print(i);
                          		TPUART_DEBUG_PORT.print("] -> ");
                          		TPUART_DEBUG_PORT.print(_listen_group_addresses[i][0]);
                          		TPUART_DEBUG_PORT.print("/");
                          		TPUART_DEBUG_PORT.print(_listen_group_addresses[i][1]);
                          		TPUART_DEBUG_PORT.print("/");
                          		TPUART_DEBUG_PORT.print(_listen_group_addresses[i][2]);
                          		TPUART_DEBUG_PORT.println("");
                          	}
                          
                          #endif
                          
                          }
                          Ich hab hier schon extra Debug-Output eingebaut.

                          Was ich nun auf der Console sehe:


                          Code:
                          Setup listen for dimm abs ...
                          1/1/3
                          Adding {} to [0]: 0/0/0
                          Listen for: [0] -> 0/0/0
                          
                          Setup listen for switch ...
                          1/1/1
                          Adding {} to [1]: 0/0/0
                          Listen for: [0] -> 0/0/0
                          Listen for: [1] -> 0/0/0
                          Das macht mich noch wahnsinnig.

                          1) Warum sehe ich nur 2 Registriervorgänge? Es sollten doch in meinem Fall (test mit 2 Kanälen mit je 3 GAs) 6 Vorgänge sein?

                          2) Und warum fängt er mit "dimm abs" an statt mit "dimm"?

                          3) Und wieso hab ich VOR dem Aufruf von "addListenGroupAddress()" noch eine Adresse und innerhalb des Aufrufs auf einmal nichts mehr?! Wo sind die Daten geblieben?!

                          Reduziere ich den Code auf nur noch Kanal-A, dann klappts auf einmal...?!

                          Riecht nach einem hochohmigen Kurzschluss :-(



                          [update]
                          Hmm, kratze ich viellicht schon am Limit des 2,5kbyte großen RAMs?! Wie seh ich das ob ich da schon am Limit laufe? Mal Tante Google fragen...

                          Kommentar


                            Also laut Doku auf arduino.cc ist der RAM eine heikle Sache. Bricht man das Limit, so kann die Anwendung gar nicht, oder komplett seltsam laufen.

                            Und das tut es ja bei mir.

                            Hab dann geschaut ob man irgendwie an die RAM Auslastung ran kommt und bin dann auf das hier gestoßen:


                            Code:
                            void freeRam() {
                              extern int __heap_start, *__brkval; 
                              int v; 
                              Serial.print((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
                              Serial.println(" bytes free RAM");
                              //return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
                            }
                            Hab ich eingebaut. Wenn ich nur einen Kanal-Instanz erzeuge und sonst nur noch den KNX Stack, dann hab ich direkt beim Start noch ca. 700bytes von rund 2500 frei.

                            Und da hab ich schon den KNX Stack in Sachen GA-Speicher optimiert (byte statt int verwendet).

                            Mal schauen ob ich weiter optimieren kann. Notfalls muss ich auf einen Mega mit 8k RAM umsteigen oder mir nix im RAM halten sondern immer aus dem EEPROM holen (kostet halt Zeit...)

                            Also Vorsicht bei dem RAM Verwendung ...


                            [update]

                            Tatsache. Hatte bisher die GAs als String im Speicher gehalten. Bei 7 Kanälen mit je 8 GAs summiert sich da einiges auf. Hole die GAs jetzt bei Bedarf aus dem EEPROM und spare dadurch. den KNX Stack hab ich auch von int auf byte beim Speichern der Listen-GAs umgebaut. Spart dort auch nochmal 50%.

                            Werde dann mal testen wie sich das ständige aus dem EEPROM Lesen auswirkt. Mein Debug-Output sagt mir 3ms für 8x GA (in 2 byte gepresst) aus dem Eeprom lesen (8x2bytes = 16 bytes in 3ms). Bei 6 Kanälen wären das 18ms nur für das holen der GAs bei jedem KNX Kommando das eingeht und verarbeitet werden muss....

                            Vllt. ändere ich den Stack ein wenig damit er nicht String- sondern Byte-Basiert mit dem GAs arbeitet. Dann könnte ich die GAs vllt. doch im Speicher halten und so Zeit sparen.

                            Kommentar


                              Zitat von tuxedo Beitrag anzeigen
                              Eigentlich sollte ich es besser wissen. Methoden die gar nicht verwendet werden vergrößern den Sketch nicht, da der Compiler die schon wegoptimiert.
                              Zum Platzsparen hilft es also nur: Platzsparend implementieren :-(
                              Gut zu wissen :-)

                              Zitat von tuxedo
                              erst ab buffer[8] im Telegram liegen, aber ich für DPT 3.007 (für's dimmen) in buffer[7] nachschauen muss?
                              Gut das du das selbst gefunden hast. Ich hatte das schonmal gewusst - konnte das aber nicht aus dem Kopf zitieren... sowas verdränge ich gerne wieder nachdem ich es nicht mehr brauche...

                              Zitat von tuxedo
                              Vllt. ändere ich den Stack ein wenig damit er nicht String- sondern Byte-Basiert mit dem GAs arbeitet. Dann könnte ich die GAs vllt. doch im Speicher halten und so Zeit sparen.
                              Hm - so ganz verstehe ich nicht was du da vorhast... kannst Du mir das nochmal genauer erklären?
                              Damit meinst du eine Änderung der Library, oder?

                              Gruß
                              Thorsten

                              Kommentar


                                Byte statt String... Bis jetzt arbeitet die Lib mit Strings wenn es um Gruppenadressen etc geht. Strings belegen deutlich mehr Speicher als wenn man die Adressen in zwei Bytes packt. Vor allem macht sich das dann auch bei der internen Liste mit GA auf die die Lib hört. Dort ist eine GA aktuell in einem Integer-Array untergebracht.
                                Pro GA werden so 3x 2bytes benötigt. Im ersten schritt hab ich das auf byte umgestellt. Jetzt eines nur noch 3x 1 byte. Im nächsten schritt reduziere ich es von diesen 3 bytes auf nur noch 2 bytes.
                                Brauche für meinen led controller mindestens 48 GAs. Da macht sich das schnell bemerkbar.

                                Wenn ich das in einem brauchbaren zustand habe präsentiert ichs hier...

                                Kommentar

                                Lädt...
                                X