Hi Max,
ja, den zweiten Schritt (GA-Index auf KO-Nummer) habe ich auch nicht. Bei angenommen 256 GAs und KOs kommt man zwar mit 2-Byte-Einträgen hin - aber wozu?
Schätze die Idee war es, dass eine GA nur einmal abgelegt wird und dann eben über den Association Table mit MEHREREN KOs verknüpft werden kann. Ändert sich die GA muss nur ein Eintrag (im Addresstable) geändert werden.
Meine Beobachtung ist aber, das man an einem Gerät eher selten mehreren KOs dieselbe GA zuweist (außer vielleicht Zentraladressen). Daher fand ich eben auch zwei Tabellen wie oben dargestellt ausreichend:
Addresstable mit Mapping: GA-Idx: <GA> -> <KO-Idx>
KO-Table: KO-Idx: Flags, Options
Ja, bei den Properties der BCU kann man nur die Speicheradresse der Tables auslesen.
ABER:
Bei neueren Typen wird das auch per Property gemacht, eben weil das "memwrite" zu limitiert war. Daher sollten wir das auch nicht mehr machen, da man sonst immer wissen muss, wie die Firmware die Adressen und vor allem die weiteren Daten intern ablegt. Das ging bei einer BCU2 vielleicht, aber bei komplexeren Busunits führt das in die Irre. Beim Zugriff über Properties kann die Firmware Prüfen, Umsortieren oder sogar sich weigern.
Irgendwann hatte ich auch schon mal die Specs neuerer Typen gesehen - kann es aber grad nicht finden.
Also: Alles gut. Einzig könnten wir uns vielleicht noch mal auf eine (Bit-)Reihenfolge für die Kommunikationsflags einigen damit man da nicht umdenken muss. Da bin ich aber schmerzfrei.
Grüße
Robert
Ankündigung
Einklappen
Keine Ankündigung bisher.
KNX-Multisensor
Einklappen
X
-
Ah, danke! Dort hatte ich nicht nachgesehen.Zitat von Robert Beitrag anzeigenDas BCU2-Helpfile findest du unter BCU manuals
Meine Implementation weicht hier vom Standard ab. Dort ist ein doppeltes Mapping, einmal von GA auf cr_id, dann von cr_id auf SAP vorgesehen. Den zweiten Teil habe ich mir gespart, weil ich den Sinn dahinter nicht verstanden habe. Vermutlich hängt es mit der Trennung BCU/Applikation zusammen.
Entsprechend scheint es auch in der BCU2 umgesetzt zu sein. Ich bin eher unmotiviert, meine Implementierung anzupassen, werde mich dem de-facto-Standard aber wohl fügen.
Sehe ich es richtig, dass bei der BCU2 die Property zu Address Table und Association Table nur in den Speicher verweisen? Da steht jeweils "pointer to ... table", Typ unsigned int. Das wollte ich so nicht implementieren. Dein ursprünglicher Input war ja auch gewesen "PropertyWrite statt MemoryWrite" verwenden. Und PropertyWrite/Read funktioniert auch in der Praxis zuverlässig und schnell.
Alternativ müsste ich das Verhalten emulieren. Also: auf die Frage nach der Address Table und der Association Table je eine Dummy-Adresse zurückliefern, eben diese bei MemoryWrite abfangen, die Daten extrahieren und das Ergebnis wieder abspeichern. Bäh.
Vielleicht implementiere ich auch einfach beide Mechanismen parallel. Als ersten Schritt werde ich wohl die Objects ändern:
0 -> Device
1...3 -> reserved
0xFE -> Debugging
0xFF -> GA Association Table à la Max
Gruß,
Max
Einen Kommentar schreiben:
-
Das BCU2-Helpfile findest du unter BCU manualsZitat von l0wside Beitrag anzeigenHallo Robert,
Kompatibilität ist immer gut. Ich habe mit der BCU keine Erfahrung, stelle aber gerne entsprechend um. Woher hast du die Bezeichnungen und Werte für PID_ORDER_INFO und PID_MANUFACTURER_ID?
Dort dann "Interface Objects" -> "System Interface Objects"
"Device Object" = 0
"Addr-.." = 1
"Assoc..." = 2
"Application Program Object" = 3
Die werden halt auch bei einer Geräteinfo gelesen.
Dort ist auch der generelle Aufbau der GA-KO erkennbar: Liste der GAs, Liste von Mappings GA-Index zu KO-Nummer, KO-Liste mit Data pointer (zum KO-eigenen Configbereich!), Config byte mit Flags, Type-byte mit DPT.
Welches Object-Nummer wär mir (außer 0-3) egal. Die müsste ja nicht mal gleich sein - ich bräuchte aber eine danach für meine KOs. Gern also "5".Zitat von l0wside Beitrag anzeigenMeinetwegen verfrachten wir die GAs auf Object 0xFF. Allerdings bin ich mit deinem Aufbau nicht einverstanden: die GA sind zwei Octets, und ich würde sie auch im Speicher und auf dem Bus so handhaben. Die Abbildung auf ein lesbares Format ist Aufgabe des PC-seitigen Frontends, nicht der Konfiguration im Gerät.
Die PA werden nicht über die Properties eingestellt, deswegen würde ich sie hier rauslassen. Dafür gibt es die zugehörigen Broadcast-Funktionen.
Was die GA und Octets angeht: Hab ich auch so gemeint - high-byte, dann low-byte, dann KO-Zuordnung. Aber die müssen halt getrennt geschrieben werden!?
PA wird mit Verweis auf die BCU2 Doc als erster Addresseintrag im Address Table dargestellt (siehe "Address Table Object").
Denke das sollte kein Beinbruch sein. Eben weil die KOs Firmwarespezifisch war dachte ich evtl. die Parameter die zu einer KO führen in die KO zu schieben. Aber insgesamt wäre ja immer das Mapping Parameter -> "irgendwo-in-einem-KO-Prop-Offset" möglich.Zitat von l0wside Beitrag anzeigenDie KOs selbst sind firmware-spezifisch und nicht per Konfiguration veränderbar - jedenfalls in den Geräten, die ich bisher per ETS parametriert habe. Du gehst implizit davon aus, dass eine bestimmte Funktion immer 1:1 mit einem KO korrespondiert. Das sehe ich eher nicht so. Beispielsweise kann die Senderate für Temperatur und Feuchte identisch sein, beide haben aber verschiedene KOs.
Ich nehme aber als Anregung mit, die Object-Nummer der Konfiguration möglichst passend zum KO zu wählen. KO 10 (bei mir Temperatur) würde dann über Object 10 konfiguriert. Ist das für dich ein akzeptabler Kompromiss?
Grüße
Robert
Einen Kommentar schreiben:
-
Hallo Robert,Zitat von Robert Beitrag anzeigenIch "emuliere" nach außen eine BCU2, damit die PA geschrieben werden kann und ich "Geräteinfo" nutzen kann. "Geräteinfo" fragt aber BCU2-konform die Objekte 0-3 ab (u.A. Seriennummer, Herstellerkennung, Run-/Load-State (was ja nicht schlecht ist wenn das ohne Extra-Programm aus der ETS abgefragt werden kann)
Kompatibilität ist immer gut. Ich habe mit der BCU keine Erfahrung, stelle aber gerne entsprechend um. Woher hast du die Bezeichnungen und Werte für PID_ORDER_INFO und PID_MANUFACTURER_ID?
Meinetwegen verfrachten wir die GAs auf Object 0xFF. Allerdings bin ich mit deinem Aufbau nicht einverstanden: die GA sind zwei Octets, und ich würde sie auch im Speicher und auf dem Bus so handhaben. Die Abbildung auf ein lesbares Format ist Aufgabe des PC-seitigen Frontends, nicht der Konfiguration im Gerät.Zitat von Robert Beitrag anzeigenIch würde dann irgendein OBJECT für die GA-Liste hernehmen. Property 0 ist PA, Prop1 ist erste GA, Prop2 ist zweite GA...
Aufbau dann xpropwrite local:/tmp/eib 1.1.240 <GA-OBJ> <GA> 1 3 <GA-HIGHBYTE> <GA-LOWBYTE> <GA-KO-MAPPING>
Die PA werden nicht über die Properties eingestellt, deswegen würde ich sie hier rauslassen. Dafür gibt es die zugehörigen Broadcast-Funktionen.
Die KOs selbst sind firmware-spezifisch und nicht per Konfiguration veränderbar - jedenfalls in den Geräten, die ich bisher per ETS parametriert habe. Du gehst implizit davon aus, dass eine bestimmte Funktion immer 1:1 mit einem KO korrespondiert. Das sehe ich eher nicht so. Beispielsweise kann die Senderate für Temperatur und Feuchte identisch sein, beide haben aber verschiedene KOs.Zitat von Robert Beitrag anzeigenDann ein Object, was die KOs hält:
Aufbau dann xpropwrite local:/tmp/eib 1.1.240 <KO-OBJ> <KO> 1 1+n <FLAGS> <n-weitere Bytes für spezifische Konfig des KO>
Da würde dann bei deinem Temperatur-KO auch die Senderate etc drin stecken. Vorteil: das logische KO als Kommunikationsendpunkt würde dann die eigene Konfiguration direkt mitbekommen und könnte diese entsprechend ablegen. Jedes KO hätte so einen gewisse Autarkie.
Ich nehme aber als Anregung mit, die Object-Nummer der Konfiguration möglichst passend zum KO zu wählen. KO 10 (bei mir Temperatur) würde dann über Object 10 konfiguriert. Ist das für dich ein akzeptabler Kompromiss?
Mangel an verfügbaren Objekten war bisher eine meiner kleinsten Sorgen.Zitat von Robert Beitrag anzeigenEs würden nur schlanke 2 Objekte belegt.
Grüße,
Max
Einen Kommentar schreiben:
-
War bei meinem eibd dabei. Notfalls aus der Source selbst kompilieren, ist relativ unkompliziert. xpropread gibt es auch.Zitat von JuMi2006 Beitrag anzeigenIch bin auch an dem Punkt damit spielen, allerdings scheitere ich schon an xpropwrite. Wo gibt's das? Ich habe lediglich mpropwrite gefunden, aber auch keine doku dazu.
Es müsste ja auch sowas wie xpropread geben.
Max
Einen Kommentar schreiben:
-
Ich bin auch an dem Punkt damit spielen, allerdings scheitere ich schon an xpropwrite. Wo gibt's das? Ich habe lediglich mpropwrite gefunden, aber auch keine doku dazu.
Es müsste ja auch sowas wie xpropread geben.
Einen Kommentar schreiben:
-
Hi Max,Zitat von l0wside Beitrag anzeigenDas ganze ist so zu interpretieren:- Objekt 0: GA-Mapping (Vorschlag: immer fix auf Objekt 0)
- Objekt 1: Temperatur
- Property 0: Sendeintervall (16 bit)
- Property 1: Temperatur-Offset (16 bit)
- Objekt 2: Feuchte
- Property 0: Sendeintervall (16 bit)
Die GA-Liste ist wie folgt:
16 bit GA (im gleichen Format wie auf dem Bus, also kein Unterschied zwischen little und big endian)
8 bit KO
8 bit Flags (siehe #defines)
Auf Objekt 0xFF gibt es noch Debuginfos zum Lesen, das ist aber unsupported.
Verwendung auf PC-Seite
Verwendet wird xpropwrite:
xpropwrite url eibaddr obj prop start nr_of_elem [xx xx ..]
Das Sendeintervall für die Temperatur wird wie folgt auf 60 gesetzt:
Interpretation: Obj=1, Prop=0, Start=0, NoElem=1, Wert=3C00Code:xpropwrite local:/tmp/eib 1.2.34 1 0 0 1 3C 00
Der Wert sieht deswegen so seltsam aus, weil Little Endian geschrieben wird, also der niedrigwertige Anteil zuerst.
ich hatte heute mal Gelegenheit die xpropwwrite-Geschichte auch bei meinem Stack näher zu betrachten:
Problem: Ich "emuliere" nach außen eine BCU2, damit die PA geschrieben werden kann und ich "Geräteinfo" nutzen kann. "Geräteinfo" fragt aber BCU2-konform die Objekte 0-3 ab (u.A. Seriennummer, Herstellerkennung, Run-/Load-State (was ja nicht schlecht ist wenn das ohne Extra-Programm aus der ETS abgefragt werden kann)
Ich würde mich freuen, wenn man da so etwas wie "BCU2"-Kompatiblität vereinbaren könnte. Damit könnte man dann auch sicher selbstgebastelte Sachen erst erkennen und dann erst parametrieren (also PID_MANUFACTURER_ID auf 0x00 0x00 prüfen, dann per PID_ORDER_INFO gucken ob es das eigene Gerät ist, dann sogar per Seriennummer unterscheiden.
Ich würde dann irgendein OBJECT für die GA-Liste hernehmen. Property 0 ist PA, Prop1 ist erste GA, Prop2 ist zweite GA...
Aufbau dann xpropwrite local:/tmp/eib 1.1.240 <GA-OBJ> <GA> 1 3 <GA-HIGHBYTE> <GA-LOWBYTE> <GA-KO-MAPPING>
Dann ein Object, was die KOs hält:
Aufbau dann xpropwrite local:/tmp/eib 1.1.240 <KO-OBJ> <KO> 1 1+n <FLAGS> <n-weitere Bytes für spezifische Konfig des KO>
Da würde dann bei deinem Temperatur-KO auch die Senderate etc drin stecken. Vorteil: das logische KO als Kommunikationsendpunkt würde dann die eigene Konfiguration direkt mitbekommen und könnte diese entsprechend ablegen. Jedes KO hätte so einen gewisse Autarkie.
Wenn du dann nur die Senderate, nicht aber die Flags ändern wolltest, sähe es so aus:
xpropwrite local:/tmp/eib 1.1.240 <KO-OBJ> <TEMPERATUR-KO> 2 n <n Bytes für spezifische Konfig des KO>
So könnten 256 GAs und 256 KOs unterstützt werden. Ein KO könnte dabei bis zu 65535 Byte Konfig-Daten (+1 Byte Flags) enthalten.
Es würden nur schlanke 2 Objekte belegt.
Wäre das so wie du dir das auch vorstellen kannst?
Grüße
Robert
Einen Kommentar schreiben:
-
Hallo Ease,Zitat von ease Beitrag anzeigenAlso die MSP430 Serie programmiere ich mit Code Composer Studio. Die 16kB Lizenz ist kostenlos. Mit dem MSP430 Launchpad kann man mit Vcc, GND und den beiden SBW Pins direkt von den Jumperbrücken an ein externen MSP (der SBW unterstützt). Wenn man >16kB benötigt muss man um kostenfrei zu programmieren auf Linux schwenken.
die Diskussion will ich hier eigentlich nicht führen. Deswegen eine abschließende Antwort dazu (wir können ggf. bei mikrocontroller.net weiter diskutieren):
Der ez430 funktioniert mit CCS5 nicht unter Linux und auch nicht mit dem MS430F5310 (ein etwas größeres Modell). Launchpad habe ich nicht getestet.
Ich setze den FET-UIF ein. Für mich war die Investition ok, der FET-UIF kostet rund 100 EUR. Über JTAG ist die Verbindung recht zuverlässig, über SBW in einem früheren Projekt war sie immer ziemlich hakelig. SBW wird auf der momentanen PCB-Revision nicht unterstützt und ist auch nicht geplant.
> 16kB gehen auch unter Windows, wenn man Teile des Codes in eine Library auslagert.
Max
Einen Kommentar schreiben:
-
Also die MSP430 Serie programmiere ich mit Code Composer Studio. Die 16kB Lizenz ist kostenlos. Mit dem MSP430 Launchpad kann man mit Vcc, GND und den beiden SBW Pins direkt von den Jumperbrücken an ein externen MSP (der SBW unterstützt). Wenn man >16kB benötigt muss man um kostenfrei zu programmieren auf Linux schwenken.
Programmiert wird üblicherwise in C. Assembler für die Hartgesottenen!
Einen Kommentar schreiben:
-
@Robert und Max:
Ja die Kombination macht Sinn, das war ja eher nur eine grobe Skizze.
Auch dialog und tkperl machen Sinn. Dazu muss man den Prozess einfach mal real durchlaufen. XML als config können wir ja schonmal als gesetzt annehmen ... macht es für Konsolen-Jünger schneller
. Es darf später ja auch ruhig mehrere Wege nach Rom geben.
An den Webserver hatte ich mit cgi/perl gedacht, aber nicht jedermanns Sache aber SSH und Konsole würde ich für bastelwütigen Heimautomatisierer mal Grundlage ansehen - diese Meinung ist ganz privat.
Grüße
P.S.: Womit wird der µC programmiert? Dieses Projekt hat einen hohen Stellenwert für mich und eine Vertiefung in die Welt der µC war eh geplant.
Einen Kommentar schreiben:
-
Bin zufällig hier gelandet.
Nur als Tipp von mir: Warum nicht Spy-By-Wire nutzen? Dann kann man mit dem 5$ Launchpad programmieren. Bis 16kb in Windows und open end unter linux.
Einen Kommentar schreiben:
-
@Robert: ich habe gerade keinen Standard und keine ETS zur Hand. Ich kann ja aber einem KO mehrere GA zuordnen, aber nur einer dieser GA ist dann das Ü-Flag zugeordnet. Es kann also Unterschiede geben.
Ansonsten ist es an der Konfigurationssoftware, größeren Blödsinn zu verhindern.
Ich bin mir zwar nicht sicher, es scheint mir aber, dass auch kommerzielle Geräte sich darauf verlassen, dass die ETS keinen Unfug schickt. Den Punkt würde ich also eher in der Konfigurations-SW abfangen. Im Prinzip ist mir´s aber egal, das ist schnell geändert.
@JuMi: dass du auf der Konsole bleiben willst, kann ich nachvollziehen.
Implementiere doch für den Anfang nur das Parsen der XML-Datei, Parameterübergabe dann per Kommandozeile (z.B. knxconfig local:/tmp/eib 1.2.34 knxms.xml --temp_interval=60 --ga_add=temp,4/3/21,kls) oder wie in deinem Dialog.
Ich würde lokal keine Konfigurationsdaten speichern. xpropread ist so schnell, dass man es problemlos beim Starten des Programms aufrufen kann, um die aktuellen Werte auszulesen. Diese kann man dann ja im Dialog als Defaultwerte vorgeben.
Ansonsten: schau dir doch mal dialog(1) an. Oder tkperl.
Max
Einen Kommentar schreiben:
-
Das stelle ich mir sehr schmerzhaft vor, wenn ich 20+ GAs (neu) eintippen muss nur weil ich die Zeit zum automatischen Schließen des Garagentors ändern wollte.Zitat von JuMi2006 Beitrag anzeigenAlso ich würde das sicherlich auf bash oder perl/cgi machen.
Am Ende muss es eine Textdatei geben, die pro Eintrag folgendes enthält:
Um bei Max Beispiel zu bleiben (Pseudo!!):Code:<Klartext> <Mapping auf Property, Object, Element... - im Zweifelsfall sogar einen expliziten Befehl> <Datentyp bzw. Grenzwerte> <den vom Benutzer setzbaren Wert>
Nun gibt es zwei Möglichkeiten:Code:<Sendeinterval Temperatursensor [s]> <Obj=1, Prop=0, Start=0> <uint16_t, min=0, max=3600> <0>
Ein Programm liest das und stellt eine einfache listenartige Eingabemaske bereit (könnte sogar ein Webserver sein!?):
"PA: ___________"
"Sendeinterval Temperatursensor [s]: ________"
[Schreiben] [Lesen]
oder eben ein Konsolen-Programm parst die Textdatei, checkt die Wertebereiche und schreibt es direkt per xpropwrite raus.
Grüße
Robert
Einen Kommentar schreiben:
-
Also ich würde das sicherlich auf bash oder perl/cgi machen.
Das ganze interaktiv (hier mal ne grobe Skizze):
< ./config
>set physical adress ? (y/n)
< y
>adress in format x.y.z:
< 1.2.3
>group adress for humidity in format 1/2/3:
< 1/3/0
>cycle in seconds (0=no cycle):
< 300
>flags (klsüai):
< kls
>group adress for temperature in format 1/2/3:
< 1/3/1
>cycle in seconds (0=no cycle):
< 300
>flags (klsüai):
< kls
>would you like to write following data to rom ?
PA: 1.2.3
humidity-ga: 1/3/0
cycle: 300
temperature-ga: 1/3/0
cycle: 300
>press "program-button" on device and accept (y/n)
< y
>Writing Rom!
Also mal so ganz grob....
Einen Kommentar schreiben:
-
Hi Max,Zitat von l0wside Beitrag anzeigenDie GA-Liste ist wie folgt:
16 bit GA (im gleichen Format wie auf dem Bus, also kein Unterschied zwischen little und big endian)
8 bit KO
8 bit Flags
das mag generell so gehen, allerdings widerspricht das in meinen Augen der GA-KO-Struktur im Standard und auch der ETS (und meiner Implementierung):
- die Flags gehören dem KO
- eine GA gehört zu einem KO und "erbt" die Flags
Generell gibt es kein hartes Argument, dass gegen eine Flags-für-GA-Struktur spricht, aber ich denke es ist nicht "gängig" (ich sage bewusst nicht "nicht standardkonform"!).Code:#ifndef __STACK_H #define __STACK_H #include "frame.h" #define FLAG_COMMUNICATE (1<<0) #define FLAG_READ (1<<1) #define FLAG_WRITE (1<<2) #define FLAG_TRANSMIT (1<<3) #define FLAG_UPDATE (1<<5) #define FLAG_READ_ON_INIT (1<<6) #define FLAGS(c,r,w,t,u,roi) ((c?FLAG_COMMUNICATE:0) | \ (r?FLAG_READ:0) | \ (w?FLAG_WRITE:0) | \ (t?FLAG_TRANSMIT:0) | \ (u?FLAG_UPDATE:0) | \ (roi?FLAG_READ_ON_INIT:0)) #define PA(hg,mg,ug) ((hg&0x0f)<<12|(mg&0x0f)<<8|(ug&0xff)) #define GA2(hg,ug) ((hg&0x1f)<<11|(ug&0x07ff)) #define GA3(hg,mg,ug) ((hg&0x1f)<<11|(mg&0x07)<<8|(ug&0xff)) #define RTD_ACCESSED 0x01 #define RTD_CHANGED 0x02 typedef struct obj_entry { uint8_t flags; uint8_t dpt; uint8_t options; uint32_t value; uint8_t runtime_data; } obj_entry; typedef struct addr_entry { uint16_t value; uint8_t object_num; } addr_entry; typedef struct tsap_entry { uint16_t addr; uint8_t seqno; } tsap_entry; uint8_t Stack_Process_P2P_APDU(Frame* rx_frame, Frame* response); int8_t Stack_Write_Object_To_Frame(Frame* frame, obj_entry* object); uint8_t Stack_Process_Object(uint8_t object_num, uint32_t value); uint8_t Stack_Process_Multicast_APDU(Frame* rx_frame, uint8_t object_num, Frame* response); uint8_t Stack_Process_LPDU(Frame* rx_frame, Frame* response); addr_entry* Stack_Get_Addr_Table(void); uint8_t Stack_Is_Object_Runtime(uint8_t object_num, uint32_t mask); void Stack_Clear_Object_Runtime(uint8_t object_num, uint32_t mask); uint32_t Stack_Get_Object_Value(uint8_t object_num); void Stack_Task(void); void Stack_Init(void); uint8_t Stack_Can_Sleep(void); #endif /* __STACK_H */
Ansonsten lese ich hier nach wie vor sehr interessiert mit, nur bin ich momentan beruflich so im Stress (Ende Uni, Anfang Job), dass ich mich erst mal raus halte. Von mir wird es aber definitiv auch noch einen Beitrag zu dem Thema geben (auf ARM-Basis...).
Grüße
Robert
Einen Kommentar schreiben:

Einen Kommentar schreiben: