Forum: Mikrocontroller und Digitale Elektronik [C-Code Optimierung] RDM responder


von Henne (Gast)


Lesenswert?

Hallo zusammen,

Da mein DMX-Krempel auf mehr Interesse als erwartet stieß, habe ich vor 
kurzem auf RDM (s.u.) aufgerüstet.
Leider schluckt der Code beinahe 2kB, was ein Viertel vom 
Programmspeicher eines mega8 oder mega8515 ist.
Da etliche Geräte sogar nur den TINY2313 verwenden, ist dies wohl 
letztlich einfach zu viel...

Ich habe bereits ziemlich in die Trickkiste gegriffen und am Code 
gefeilt - hoffe aber, dass Ihr noch ein paar Einfälle habt.
(Als angehender Maschi habe ich programmiertechnisch ja auch nicht die 
Weisheit mit Löffeln gefressen...)

Die ISRs sollten neben der geringen Codegröße natürlich auch möglichst 
flott sein.
Bei den anderen Funktionen spielt Geschwindigkeit keine derart 
wesentliche Rolle.

Erläuterungen zu dem Code: 
http://www.hoelscher-hi.de/hendrik/light/ressources/AN017.pdf
Der Code selbst: 
http://www.hoelscher-hi.de/hendrik/light/ressources/rdm_in.zip
(Ansich ist nur die lib_rdm_in.c und der Header interessant...)

Tausend Dank im Voraus!
Hendrik


Hier noch etwas Hintergrund, was aber nicht unmittelbar wichtig ist:

RDM (remote device management) ist eine Erweiterung des DMX512 
Lichtsteuerprotokolls und durch die ANSI E1.20 spezifiziert.
(Ich darf sie aber wohl aus Copyright-Gründen nicht hochladen...)
Durch RDM können angeschlossene Geräte konfiguriert werden und auch 
Status- und Fehlerinformationen können ausgelesen werden.

RDM ist paketbasiert: Der Controller sendet ein Paket via RS485 an einen 
Responder und der antwortet.

Der Ablauf geschieht folgendermaßen:
Der Controller ermittelt die angeschlossenen Geräte über eine 
Discovery-Prozedur, bei der an alle Geräte eine Nachricht mit einem 
MAC-Adressbereich (Untergrenze, Obergrenze) gebroadcastet wird.
Liegt die MAC eines Empfängers im Bereich antwortet er mit seiner 
encodierten Mac. (Da mehrere Empfänger antworten, bekommt der Controller 
also einen üblen Datensalat...)
Nun engt er den Adressbereich immer weiter ein, bis nur noch ein 
Empfänger antwortet, der dann gemuted wird. (Treesearch)

Sind alle Empfänger identifiziert, kann der Controller ein Paket gezielt 
verschicken:
RDM start code (0xCC)
RDM sub start code (0x01)
Paketlänge
Zieladresse
Quelladresse
Typ des Paketes (Discovery, Ändern eines Parameters, Auslesen eines 
Parameters)
ID des Parameters
Länge der Daten des Parameters
Datenfeld
additive Checksumme

Es gilt dabei MSB first.

Leute, die mir bei der Optimierung helfen, werde ich gern mit als Autor 
aufführen (wenn gewünscht).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Viel Kleinkram...

Um zu beurteilen, wo Potential liegt, ist eigentlich ein Blick in den 
erzeugten Assembler notwendig. Weil die Software auf unterschiedlichen 
µC und auch verschiedenen Compiler-Versionen laufen soll (auch ältere 
gcc-Versionen sowie kommende), die Teilweise anderes Verhalten zeigen 
werden, sind allgemeint Tipps sehr schwer zu geben.

Immerhin will man ja in C proggen, weil das halbwegs unabhängig ist von 
der Hardware, anstatt C als portierbaren Assembler zu verwenden.

Ok, genug Prosa.

-- Winz-Funktionen wie swapInt fühlen sich sehr warscheinlich wohler als 
static inline, bzw. der Aufrufer hat ne deutlich bequemere 
RegisterlAllokierung.

-- isHigher ist als isLower doppelt vorhanden. Eine Vergleichs-Func, die 
je nach Gemengelage -1, 0 oder 1 liefert, ist evtl. praktikabler.

-- getMsgP gibt's als memcpy_P, was wehlt ist nur Rumgecaste

-- RxState ist volatile und Du machst 1000 Zugriffe, zB in einer ISR. 
Das ist sau teuer! --> Auf lokaler, temporärer Kopie arbeiten! Dito 
für den Mini-Zoo an anderen Globals -- dazu gehören evtl. auch 
Komposit-Elemente von Globals.

Siehe auch

Beitrag "Bitte um Hilfe bei Code-Optimierung"

-- Indirekter Zugriff in C wird nicht unbedingt zu (möglicherweise 
platzsparenderem als direktem Zugriff) indirektem Zugriff in Assembler. 
Erkläuterungen dazu gibt's ebenfalls hinter obigem Link.

Zum Code:

Die ISRs sollen flott sein? delay-Zeug hat nix in einer ISR zu suchen, 
zumindest nicht bei deaktivierten IRQs und wenns schnell sein soll. In 
einer ISR IRQs zuzulassen und damit eine Prioritäts-Zwischenschicht 
einzuziehen ist möglich (hab ich in fast all meinen AVR-Anwendungen), 
das will aber genau überlegt sein.

Es soll ja vermutlich noch ne Anwendung laufen, die Dein Zeug benutzt. 
Wenn die härtere Echtzeit-Anforderungen hat, kann sie diese wegen der 
erhöhten IRQ-Latenz uU nicht erfüllen.

von Henne (Gast)


Lesenswert?

Zunächst einmal Vielen Dank, Johann!

Die Tipps der static inline Deklaration und memcpy_P werde ich später 
mal einbauen.

Die Vergleichsfunktionen könnten etwas frickelig werden. Ich hatte dies 
schon mal versucht und wahrscheinlich einen Denkfehler bei den 
Abbruchbedingungen...

Bei der Verwendung von RxState hast Du Dich wahrscheinlich verguckt:
Bei jedem Durchlauf lese ich ein Mal den Wert ein und schreibe ein Mal 
einen Wert zurück. Der Compiler lädt dazu direkt den Wert in ein gerade 
freies Register und kopiert es direkt ins RAM. Der Compiler arbeitet da, 
meine ich, optimal...
In allen anderen Fällen (echte Mehrfachzugriffe) hast Du vollkommen 
Recht und ich lege lokale Kopieen an. (Falls nicht, ist das ein Fehler 
von mir.)

Zum indirekten Zugriff:
Ich hatte zuvor mit Pointern gearbeitet, der GCC scheint den jetzigen 
Zugriff aber lieber zu mögen... (Es sei denn, ich habe Denkfehler 
gemacht und dadurch Overhead verzapft.)

Deinen Link habe ich vor meinem Thread schon durchgearbeitet - er war 
eigentlich der Anlass, so einen Thread auch einmal zu versuchen...

Zur TxISR:
Ich bin eigentlich über Delays (besonders in ISRs) genauso verärgert wie 
Du. Der Hintergrund hier ist:
Ich muss den Bus noch 20us IDLE halten, damit der Controller keine EMV 
als weitere Daten interpretiert. Warte ich kürzer, bekommt der 
Controller evtl Probleme - warte ich deutlich länger, verpasse ich evtl. 
ein folgendes Paket, falls der Controller zu schnell sendet.
Ich kann also nicht einfach sofort wieder auf Empfang schalten.
Ich kann auch nicht einen Counter für das Hauptprogramm starten, da ich 
dort keinen wirklichen Einfluss auf das Zeitverhalten habe.
Ich möchte eigentlich auch keinen Timer opfern.
Was bleibt mir dann noch??
(Als Entschuldigung sei gesagt, dass das Delay nur ein Mal pro zu 
beantwortendem Paket stört - also fast nie...)

Nochmals Danke!
Hendrik

von Henne (Gast)


Lesenswert?

Das ursprüngliche Projekt brauchte 1712 Bytes.
Die Deklaration der Winz-Funktionen als static inline führte zu 1630 
Bytes.
Die Nutzung von memcpy_P anstatt meine eigenen Funktion führte zu 1628 
Bytes.

Das ist jetzt noch kein gewaltiger Sprung - aber doch ganz nett :-)

Viele Grüße,
Hendrik

von Henne (Gast)


Lesenswert?

Eine einzelne Vergleichsfunktion mit Übergabe des Leseoffsets 
vergrößerte den Code auf 1634 Bytes.

von chris (Gast)


Lesenswert?

Mach einen byte Vergleich z.B.

compare(char*a,char*b) { // sollte man ueberpruefen wegen flash pointer.
uint16 res; char i=6; // compare 6 bytes
 while(i--) {
  res=*a++;
  res-=*b++;
  if (!res) return continue;
 }
  if (res<0) return 2;
  return res>0;
}

von Henne (Gast)


Lesenswert?

Der Compare-Vergleich nach chris führt zu 1628 Bytes (identische Größe).
(Entweder gibt es automatisches Inlining oder die Funktion ist 
aufwendiger als mein Konstrukt - müsste ich mir noch einmal im 
Disassembler anschauen.)

Ich befürchte langsam, dass ich an genau der Stelle wohl nicht Hunderte 
von Bytes einsparen kann...

Oder kennt jemand eine Alternative zu den delays in den ISRs für 
konstante inter byte gaps und den Senderichtungswechsel?

Vielen Dank für Eure Mühe bislang,
Hendrik

von Henne (Gast)


Lesenswert?

Hier der Disassembler-Code von "compare":
1
@0000009C: compare
2
161:      uint8_t compare(uint8_t*a,const uint8_t*b) { // sollte man ueberpruefen wegen flash pointer.
3
+0000009C:   01DC        MOVW    R26,R24          Copy register pair
4
+0000009D:   01FB        MOVW    R30,R22          Copy register pair
5
+0000009E:   E096        LDI     R25,0x06         Load immediate
6
+0000009F:   C00B        RJMP    PC+0x000C        Relative jump
7
164:        res=*a++;
8
+000000A0:   918C        LD      R24,X            Load indirect
9
+000000A1:   2F28        MOV     R18,R24          Copy register
10
+000000A2:   E030        LDI     R19,0x00         Load immediate
11
165:        res-=*b++;
12
+000000A3:   8180        LDD     R24,Z+0          Load indirect with displacement
13
+000000A4:   1B28        SUB     R18,R24          Subtract without carry
14
+000000A5:   0931        SBC     R19,R1           Subtract with carry
15
166:        if (res !=0) break;
16
+000000A6:   1521        CP      R18,R1           Compare
17
+000000A7:   0531        CPC     R19,R1           Compare with carry
18
+000000A8:   F421        BRNE    PC+0x05          Branch if not equal
19
+000000A9:   9611        ADIW    R26,0x01         Add immediate to word
20
+000000AA:   9631        ADIW    R30,0x01         Add immediate to word
21
163:       while(i--) {
22
+000000AB:   5091        SUBI    R25,0x01         Subtract immediate
23
+000000AC:   F798        BRCC    PC-0x0C          Branch if carry cleared
24
+000000AD:   01C9        MOVW    R24,R18          Copy register pair
25
+000000AE:   2B23        OR      R18,R19          Logical OR
26
+000000AF:   F011        BREQ    PC+0x03          Branch if equal
27
+000000B0:   E081        LDI     R24,0x01         Load immediate
28
+000000B1:   E090        LDI     R25,0x00         Load immediate
29
170:      }
30
+000000B2:   9508        RET                      Subroutine return

Hier der Aufruf:
1
if((compare(&(rdm->Data[0]), DevID) != 1) && (compare(&(rdm->Data[6]), DevID) != 2))
2
+00000229:   E660        LDI     R22,0x60         Load immediate
3
+0000022A:   E070        LDI     R23,0x00         Load immediate
4
+0000022B:   E889        LDI     R24,0x89         Load immediate
5
+0000022C:   E090        LDI     R25,0x00         Load immediate
6
+0000022D:   DE6E        RCALL   PC-0x0191        Relative call subroutine
7
+0000022E:   3081        CPI     R24,0x01         Compare with immediate
8
+0000022F:   F409        BRNE    PC+0x02          Branch if not equal
9
+00000230:   C082        RJMP    PC+0x0083        Relative jump
10
+00000231:   E660        LDI     R22,0x60         Load immediate
11
+00000232:   E070        LDI     R23,0x00         Load immediate
12
+00000233:   E88F        LDI     R24,0x8F         Load immediate
13
+00000234:   E090        LDI     R25,0x00         Load immediate
14
+00000235:   DE66        RCALL   PC-0x0199        Relative call subroutine
15
+00000236:   3082        CPI     R24,0x02         Compare with immediate
16
+00000237:   F409        BRNE    PC+0x02          Branch if not equal
17
+00000238:   C07A        RJMP    PC+0x007B        Relative jump

=========================================================
mein Geraffel:
1
176:      rdm = (struct RDM_Packet *)&RdmField;
2
+00000216:   E7A1        LDI     R26,0x71         Load immediate
3
+00000217:   E0B0        LDI     R27,0x00         Load immediate
4
+00000218:   E6E0        LDI     R30,0x60         Load immediate
5
+00000219:   E0F0        LDI     R31,0x00         Load immediate
6
180:        buf= rdm->Data[i]; 
7
+0000021A:   01ED        MOVW    R28,R26          Copy register pair
8
+0000021B:   8D98        LDD     R25,Y+24         Load indirect with displacement
9
181:        if      (buf < DevID[i]) return (0);
10
+0000021C:   8180        LDD     R24,Z+0          Load indirect with displacement
11
+0000021D:   1798        CP      R25,R24          Compare
12
+0000021E:   F048        BRCS    PC+0x0A          Branch if carry set
13
182:        else if (buf > DevID[i]) return (1);
14
+0000021F:   1789        CP      R24,R25          Compare
15
+00000220:   F408        BRCC    PC+0x02          Branch if carry cleared
16
+00000221:   C091        RJMP    PC+0x0092        Relative jump
17
+00000222:   9611        ADIW    R26,0x01         Add immediate to word
18
+00000223:   9631        ADIW    R30,0x01         Add immediate to word
19
178:      for (i=0; i<6; i++)
20
+00000224:   E080        LDI     R24,0x00         Load immediate
21
+00000225:   36E6        CPI     R30,0x66         Compare with immediate
22
+00000226:   07F8        CPC     R31,R24          Compare with carry
23
+00000227:   F791        BRNE    PC-0x0D          Branch if not equal
24
192:      rdm = (struct RDM_Packet *)&RdmField;
25
+00000228:   E7E1        LDI     R30,0x71         Load immediate
26
+00000229:   E0F0        LDI     R31,0x00         Load immediate
27
196:        buf= rdm->Data[i +6]; 
28
+0000022A:   8D96        LDD     R25,Z+30         Load indirect with displacement
29
197:        if      (buf > DevID[i]) return (0);
30
+0000022B:   01DB        MOVW    R26,R22          Copy register pair
31
+0000022C:   918C        LD      R24,X            Load indirect
32
+0000022D:   1789        CP      R24,R25          Compare
33
+0000022E:   F050        BRCS    PC+0x0B          Branch if carry set
34
198:        else if (buf < DevID[i]) return (1);
35
+0000022F:   1798        CP      R25,R24          Compare
36
+00000230:   F408        BRCC    PC+0x02          Branch if carry cleared
37
+00000231:   C081        RJMP    PC+0x0082        Relative jump
38
+00000232:   9631        ADIW    R30,0x01         Add immediate to word
39
+00000233:   5F6F        SUBI    R22,0xFF         Subtract immediate
40
+00000234:   4F7F        SBCI    R23,0xFF         Subtract immediate with carry
41
194:      for (i=0; i<6; i++)
42
+00000235:   E0B0        LDI     R27,0x00         Load immediate
43
+00000236:   3666        CPI     R22,0x66         Compare with immediate
44
+00000237:   077B        CPC     R23,R27          Compare with carry
45
+00000238:   F789        BRNE    PC-0x0E          Branch if not equal

von chris (Gast)


Lesenswert?

Bin ich richtig in der Annahme, daß dein Code ge-Inlined wird, und 
compare nicht. Bei den Switch Anweisungen lassen sich ca 100-200 bytes 
einsparen, aber das ist zu wenig.

von Henne (Gast)


Lesenswert?

@chris:

so ist es. Deinen Code brauche ich zwei Mal; bei mir jeden Vergleich ein 
Mal. Deshalb wird compare wohl nicht ge-inlined...

Der Ersatz von switch (Sprungtabelle) durch einzelne Bedingungen machte 
die RxISR ein Stück langsamer und der switch in der Auswertung wird in 
einzelne Bedingungen aufgelöst.

von chris (Gast)


Lesenswert?

@Henne
Habe gerade bemerkt, daß du compare nur 2x aufrufst, wobei es 3x sein 
sollte, ich glaube forUs fehlt dir. Weiters könnte man die Konstante in
compare laden, so spart man sich ein paar bytes. Auch eventuell 
mitgeben,
 auf was getestet werden muß, muß man sich anschauen, ob das was bringt, 
aber du hast recht, es bringt weniger als ich vermutete.
Achso, habe einen fehler drin, res muß signed und nicht unsigned sein.

von Henne (Gast)


Lesenswert?

@chris:

In "forUs" teste ich gleichzeitig auf einen broadcast - Da würde ich 
nicht viel raus holen können...
Mit der Konstanten hast Du natürlich Recht - verbessert aber nichts, wie 
ich gerade gesehen habe.

Viele Grüße,
Hendrik

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

--swapInt ist überflüssig, weil nur gegen Compilezeit-Konstanten 
verglichen wird. Man kann den swap also vom Compiler auf den Konstanten 
machen lassen.

-- isLower und isHigher werden nur 1x verwendet. Wenn die auserhalb 
nicht gebraucht werden, reicht ne Deklaration als static zum Inlinen.

-- RxCount_16 in der einen ISR fühlt sich wohler als lokale Auto.

von Henne (Gast)


Lesenswert?

Moin Johann,

swapInt wertet die Bedeutung eines eintreffenden Paketes (also die PID) 
aus. Ich kenne die einzelnen Pakete, die später bei meinem Gerät 
eintreffen, nicht zur Compilezeit...
Man könnte allerdings die PID-Definitionen im Header umdrehen. 
Allerdings würde ich dann gegen die Norm verstoßen, weil ich für mich 
die PIDs geswappt haben möchte. Das dürfte dann bei PID-Erweiterungen 
von Dritten für ordentlich Verwirrung sorgen, oder?

In RxCount_16 werden im DMX-Betrieb die eintreffenden Bytes bis zum 
Erreichen der Startadresse runtergezählt. Im RDM-Betrieb wird darin die 
additive Checksumme gebildet. Sie muss also im RAM gehalten werden.
Bislang dachte ich, es mache keinen Unterschied, ob ich solche Variablen 
global in der Datei angebe oder innerhalb der Funktion als statisch 
markiere. Da werde ich noch einmal schauen...

Vielen Dank,
Hendrik

von Henne (Gast)


Lesenswert?

Der Unterschied zwischen den Deklarationen ist, dass ich bei lokal und 
static nicht außerhalb der Funktion auf die Variable zugreifen kann. Ich 
meine, dies wäre im Sinne der Data Encapsulation - ich seh da allerdings 
keinen Vorteil für mich. Bei größeren Dateien sieht das bestimmt anders 
aus...

von Michael Wilhelm (Gast)


Lesenswert?

uint8_t isLower(void)
{
struct RDM_Packet *rdm;
rdm = (struct RDM_Packet *)&RdmField;
uint8_t i ,buf;
for (i=0; i<6; i++)
  {
  buf= rdm->Data[i];
//  if      (buf < DevID[i]) return (0);
//  else
          if (buf > DevID[i]) return (1);
  }
return (0);
}



uint8_t isHigher(void)
{
struct RDM_Packet *rdm;
rdm = (struct RDM_Packet *)&RdmField;
uint8_t i ,buf;
for (i=0; i<6; i++)
  {
  buf= rdm->Data[i +6];
//  if      (buf > DevID[i]) return (0);
//  else
         if (buf < DevID[i]) return (1);
  }
return (0);


Das ist mir aufgefallen. Könnte das nicht so gehen?

MW
}

von Henne (Gast)


Lesenswert?

@Michael:
Stimmt - die andere Abbruchbedingung spart nur Zeit, auf die es hier 
aber eigentlich nicht ankommt...

von Gast (Gast)


Lesenswert?

@Michael,@Henne:

Ich kenne jetzt nicht die gesamte Anwendung aber durch das 
Auskommentieren verändert sich das Verhalten der Funktion und unter 
Umständen das Ergebnis.

DevID[] = {0,1,1}
buf[] = {1,0,1}

isHiger()_original liefert 0
isHigher()_modifiziert liefert 1

Falls ich mich jetzt nicht gerade vertue...

von chris (Gast)


Lesenswert?

Hallo,
einiges scheinen Manchestercodiert zu sein, andere nicht.
ev. schick mir die RDM pdf auf scoxo3511514@yahoo.com, wobei
 die o und der 5 wegzulassen sind, vor dem domain.
Habe ein paar optimierungideen bez. Messages, aber ohne Hintergrundinfo,
ist es ein heikles thema.

von Johann L. (gjlayde) Benutzerseite


Angehängte Dateien:

Lesenswert?

Henne wrote:

> swapInt wertet die Bedeutung eines eintreffenden Paketes (also die PID)
> aus. Ich kenne die einzelnen Pakete, die später bei meinem Gerät
> eintreffen, nicht zur Compilezeit...

Brauchst auch nicht.

Anstatt
1
switch (SWAP(var))
2
   case A:
3
   case B:

geht doch
1
switch (var)
2
   case SWAP(A):
3
   case SWAP(B):

wobei in der zweiten Skizze SWAP zur Compilezeit auswertbar sein muss 
und dann auch zur CZ ausgewertet wird. Das spart also Laufzeit und 
Platz.

> Man könnte allerdings die PID-Definitionen im Header umdrehen.

Könnte man muss man aber nicht wie eben skizziert.

> In RxCount_16 werden im DMX-Betrieb die eintreffenden Bytes bis zum
> Erreichen der Startadresse runtergezählt. Im RDM-Betrieb wird darin die
> additive Checksumme gebildet. Sie muss also im RAM gehalten werden.
> Bislang dachte ich, es mache keinen Unterschied, ob ich solche Variablen
> global in der Datei angebe oder innerhalb der Funktion als statisch
> markiere. Da werde ich noch einmal schauen...

Das macht auch keinen Unterschied. Zumindest, was Resourcen-Verbrauch 
angeht.

Gemeint ist's so wie im Anhang in der einen ISR: Man operiert auf einer 
lokalen auto Variablen (nicht auf einem Static!). Gelesen und 
Geschrieben wird nur 1x, am Anfang und am Ende. Das typeof() ist 
Faulheit, würd ich in der Endversion nicht verwenden.

Bei vielen Zugriffen auf das gleiche Ding spart man so Zugriffe, die der 
Compiler nicht immer wegoptimiert (oder nicht wegoptimieren darf wenn 
das Ding volatile ist). Um abzuwägen, ob sich das lohnt, schaut man das 
Listfile durch. "Nester" mit den 4-Byte-Zugriffen ins RAM sind beim 
Drüberscrollen schnell zu erkennen, weil sie aus den normalen 
2-Byte-Zugriffen vorstechen. Wird in einer Funktion oft auf die selbe 
Adresse gegriffen, ist's ein potentieller Kandidat.

Kosten für die lokale Variante sind die Regs, in denen man das Datum 
halten muss. In einer ISR muss das Reg zudem immer gesichert werden im 
Gegensatz zu einer normalen Funktion, wo nicht alle Regs gesichert 
werden mussen, und ein Umbau sich eigentlich immer lohnt, wenn noch 
call-used-Regs frei sind und die Funktion ein Blatt im Call-Baum ist.

Johann

von Henne (Gast)


Lesenswert?

@chris:
Es gibt nirgendwo eine Manchestercodierung...

@Gast:
Das Original ist richtig. Ich brauche die Abbruchbedingung, da ich 
andernfalls die Vergleichsergebnisse der höher wertigen Bytes nicht 
berücksichtige.

@Johann:
Die Idee mit der Swapumstellung ist vielversprechend. Mal schaun...
Die "Nester" räucher ich eigentlich immer wie du es beschrieben hast aus 
- von daher wird es mich wundern, wenn ich da viel hohle.

Was mir derzeit keine Ruhe lässt sind die delays:
Mit 5us könnte ich noch leben - aber die 20 sind wirklich etwas viel.
Wäre ein Sperren des TxC-IRQs, danach ein sei und dann die Schleife 
vertretbar?
- halbwegs definierte Umschaltzeit des Ports
- keine ungewollten rekursiven Aufrufe der TxISR
- andere Interrupts freigegeben

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Henne schrieb:
> Was mir derzeit keine Ruhe lässt sind die delays:
> Mit 5us könnte ich noch leben - aber die 20 sind wirklich etwas viel.
> Wäre ein Sperren des TxC-IRQs, danach ein sei und dann die Schleife
> vertretbar?

Seh ich kein Problem. Vor Verlassen der ISR muss der IRQ aber wieder 
aktiviert werden, davor ein CLI.

Auch möglich, ist am Ende der ISR abzudesten, ob das IRQ-Flag schon 
wieder gesetzt ist. Gegebenenfalls wird das Flag gelöscht in der ISR 
geschleift. Weil bei gesetztem IRQ-Flag die ISR eh nach Verlassen wieder 
angesprungen würde, spart diese Technik Zeit, nämlich einen ISR-Epilog 
und -Prolog.

In Deinem Fall braucht man diese Technik aber kaum. CLI und 
IRQ-reaktivieren sollte vollauf genügen.

Bei der Methode steigt die ISR-Tiefe um Eins, was bei der ISR, um die es 
geht, aber kaum was ausmacht. Die braucht ja nur ne handvoll Bytes aufm 
Stack, das sollte auch bei 128 Bytes RAM unkritisch sein.

von Christian T. (Gast)


Lesenswert?

Hallo Henne,

ich greif das Thema nach langer Zeit mal wieder auf. Bin auch grad dabei 
eine RDM Implementation für einen Mega 162 controller zu schreiben. 
Deswegen habe ich mir deinen Code mal angesehen. Hab das auch soweit 
umgeschrieben bekommen das ich es auf dem Mega 162 ans laufen bekomme. 
DMX empfang läuft. RDM geht leider noch nicht.

Kann es sein das du die Checksumme für die "discover unique branch" 
respond Message nicht richtig berechnet wird. Laut Ansi 1.20 steht da 
drin "Checksum is the sum of the previous 12 EUID slots. The checksum is 
an unsigned additive sum of the 8-bit fields into a 16-bit response 
value."
In deinem code adierst du aber den preamble auch mit hinzu. und jede 
EUID auch nur einmal.
Hast du das ganze schon mal mit einer echten RDM Anwendung getestet?
Ich habe im Moment das Enttec RDM USB Pro Interface zum probieren hier.

Mein controller Empfängt die RDM Pakete und sendet auch was zurück. Aber 
der Enttec RDM Controller findet das Device nicht.

Und beim DMX Empfang würde ich auch noch nen kleinen schönheitsfehler 
ausbügeln. In Zeile 427 würde ich >= schreiben weil es sonst seihen kann 
das wenn du den letzten DMX Kanal abgreifen kannst der Status nicht 
gewechselt wird.

case STARTADR_DMX:
    DmxField[RxCount_8++]= DmxByte;            //get channel
    if (RxCount_8 > sizeof(DmxField))
      {
       Flags |= (1<<EVAL_DMX);              //reception finished
       RxState  = IDLE;                //all ch received -> wait for 
break
      }
    break;

von henne (Gast)


Lesenswert?

Mit dem ersten Punkt liegst Du falsch. (Rechne nach ;-))

Beim zweiten liegst Du richtig.

VG,
Hendrik

von henne (Gast)


Lesenswert?

Wenn Du die Lib mit dem Enttec-Controller zum Laufen gebracht hast, 
würden mich die Änderungen interessieren.

Die Discovery und die Adressvergabe hatten bei mir damals funktioniert - 
das Auslesen der Device-Eigenschaften wollte jedoch nicht.

von Christian T. (Gast)


Lesenswert?

Also ich schau mir das mit der Checksumme noch mal an. Habs gestern dann 
auch noch soweit geschafft das mein RDM Device schon mal erkannt wird. 
Die ID wird im Enntec Tool angezeigt. Und dann meldet er die meiste Zeit 
"Selected Device did not respond to the DEVICE_INFO, No Information to 
display, Refer to the Manual for more info"

Aber ich habs auch schon gehapt das er alle Parameter richtig ausgelesen 
hat. Ist aber mehr sporadisch. Das blöde ist ich kann nicht gleichzeitig 
RDM senden und mit dem Interface den Datenstrom mitsniffen. Aber 
irgendwie wird das wohl auch noch zum laufen zu bringen sein. :-)

Wenn ich was rausfinde sag ich auf jeden Fall bescheid. Muss den Code 
dann auch noch etwas aufräumen. Wollte das eigentlich auch dann noch so 
machen das man das ganze noch etwas leichter für andere Prozessoren der 
AVR Reihe anpassen kann.

von Henne (Gast)


Lesenswert?

@Christian:
Jetzt sind wir mit dem Enttec-Teil genau auf demselben Stand.

Ich hatte deswegen auch schon bei rdmprotocol.org gepostet, wo mir 
empfohlen wurde, die Daten mit einem Oszi anzuschauen und die Pakete 
nachzurechnen.
(Was anderes ist ja auch schlecht möglich...)

Selbstverständlich habe ich auch als erstes die Response-Pakete nochmal 
durchgesehen (Oszi bringt mir dabei nicht viel): Es wird gesendet, was 
ich nach meiner Interpretation der E1.20 glaube, senden zu müssen. 
Abgesehen davon, sollte sonst nie irgendein Paket korrekt behandelt 
werden...

Evtl. ist es sinnvoll, mit einem zweiten Rechner und meinem 
"OpenRDM"-Dongle den Bus mal abzuhorchen und vielleicht doch mal mit 
einem Oszi nachprüfen, wie sich der Bus während der Port-Turn-Arounds 
verhält. (Eigentlich müsste er über einen Pullup im ENTTEC-IF auf IDLE - 
also HI - gehalten werden.)


Ich bin auf jeden Fall für alles dankbar - ich kann zwar mit meinen 
eigenen Systemen RDM fahren, möchte aber natürlich zum offiziellen 
Standard kompatibel sein.


VG,
Hendrik

von Henne (Gast)


Lesenswert?

zur CS:

Präambel wird nicht berücksichtigt.

Additive 16bit cs über:
UID[0] |0xAA
UID[0] |0x55
UID[1] |0xAA
UID[1] |0x55
UID[2] |0xAA
UID[2] |0x55
UID[3] |0xAA
UID[3] |0x55
UID[4] |0xAA
UID[4] |0x55
UID[5] |0xAA
UID[5] |0x55

Dies entspricht mMn. 6*0xFF +UID[0] +UID[1] +UID[2] +UID[3] +UID[4] 
+UID[5]

VG,
Hendrik

von Christian T. (Gast)


Lesenswert?

Ich hab auch noch mal deine Paketreihenfolge mit dem Protokoll 
verglichen. Sieht eigentlich gut aus was du da rauschickst. Hab auch 
schon nen bißchen mit dem AVR simulator rumprobiert. Aber ich denke auch 
mal das es nen Timing Problem oder sowas ist. Weil er mir halt auch 
gestern zeitweise auch schon mal sämtliche Daten im enttec Programm 
dargestellt hat.

Aber ich werd mir jetzt wohl erstmal noch dein OpenRDM-Dongel bauen 
damit ich das vernüftig Sniffen kann. Ich kann mit dem Enntec Interface 
ja leider nicht gleichzeitg RDM senden und die Pakete Analysieren. Aber 
werd dann mal mit deiner Software RDM Daten schicken und schauen was der 
Enttec RDM Sniffer dazu sagt. Ozzi hab ich auch da. Muss ich mal auf den 
Pin triggern der die Sendeumschaltung macht und gleichzeitig die Daten 
anschauen. Vielleicht krieg ich dann auch schon was raus.

Meistens ist es ja immer nur ne Kleinigkeit die einem Kopfschmerzen 
bereitet.

Gruß
Christian

von Henne (Gast)


Lesenswert?

@Christian:

Ich glaube, ich habe noch ein fertiges Modul bei mir liegen. Wenn Du mir 
Deine Adresse mailst, kann ich es Dir für die nächsten Monate gegen 
Erstattung der Versandkosten leihen.

Meine eMail-Adresse findest Du auf meiner Seite.

VG,
Hendrik

von henne (Gast)


Lesenswert?

Ich habe das Modul gerade gefunden.

Es ist dies hier:
http://www.nodna.com/xtc/product_info.php?info=p850_Devantech-USB-zu-RS485-Interface-Modul.html

VG,
Hendrik

von Christian T. (Gast)


Lesenswert?

@ Hendrik
Danke für das Angebot und fürs rausuchen des Moduls. Aber ich denk mal 
ich werd mir das heute mal Anhand deines Schaltplans zusammen basteln. 
Der Materialwert liegt ja doch etwas unter 33 Euro. Und so hab ich noch 
nen bißchen was zu löten. Hab mir schon die passenden ICs besorgt. Von 
daher muss ich mir nur noch die Platine basteln. Aber Layout hab ich 
gestern schon gemacht.
Hab gestern auch noch mal vorm Ozilloskop gesessen und gemessen. Aber so 
richtig nen Fehler erkennen konnte ich bisher nocht. Ist halt auch nicht 
so einfach damit nen Datenstrom zu analysieren. Aber ich denk mal wenn 
ich den RS485 umsetzer fertig hab sieht man weiter. Hab zwar hier 
haufenweise normale DMX Interfaces zum Testen. Aber das hilft einem bei 
RDM leider auch nicht wiklich weiter. (Arbeite für meine Lichtsteurungen 
unter anderem mit Martin Lightjockey, Ecue und seit neustem Cuelux. Ecue 
hat zwar angekündigt im laufe des Jahres auch RDM zu unterstüzen. Aber 
bisher ist mir da noch keine Version bekannt die das unterstüzt.

von Henne (Gast)


Lesenswert?

Meinen Schaltplan würde ich mittlerweile etwas erweitern:

In der E1.20 ist in einem Anhang die Bus-Termination dargestellt, so 
dass er während der Port Turn-Arounds hochohmig auf IDLE hängt. Diese 
Widerstandsanordnung sollte übernommen werden.

Tx und Rx LEDs würde ich auch noch spendieren.

Falls es hakeln sollte: mein Angebot steht noch.

VG,
Hendrik

von Henne (Gast)


Lesenswert?

zum Oszi:

Was geschieht in der Zeit zwischen dem Ende der Anfrage und dem Beginn 
der Antwort? Wenn der Bus da floatet haben wir die Antwort...

von Christian T. (Gast)


Lesenswert?

So, USB --> RS485 Umsetzer hab ich aufgebaut und fertig am Laufen. Inkl. 
LEDs und Widerstandskette.
Hab dann also den neuen Dongel mit deiner Software zum discovern und 
Datenabfragen verwendet. Funktioniert soweit auch wunderbar. Dann hab 
ich das Enttec interface als Sniffer geflasht und die Daten mit der 
Enntec Sniffer Software mitgelockt.
Die gute Nachricht ist, die Daten die übertragen werden sind soweit ok. 
Also die Pakete passen von den Anzahl und Cheksumme.
Aber er meckert bei mir jedes Paket mit nem Timing fehler an. (Sowohl 
die gesendeeten vom PC wie auch die Response Nachrichten)

Jetzt muss ich der Sache mal noch weiter auf den Grund gehen. Die 
Leitung floatet auf jeden Fall nicht. Haben jetzt immer nen definierten 
Zustand drauf.
Ich werd mal noch nen bißchen experementieren. Sollte wohl in den Griff 
zu bekommen sein.
MfG
Christian

von Henne (Gast)


Lesenswert?

Auf der FTDI-Seite wirst Du nicht viel machen können:
Der Port Turn-Around erfolgt automatisch.
Interbyte Gaps sind nicht möglich.
Der Break dauert mind. 1,X ms, da die Frequenz, mit der die USB-Pakete 
verschickt werden, wohl nicht mehr hergibt.

Laut E1.20 dürfte ich aber eigentlich keine Grenzwerte verletzen.
Auf der AVR-Seite haben wir freie Hand.


Danke schonmal für das bisherige Feedback!

Hendrik

von Henne (Gast)


Lesenswert?

schon irgendwelche neuen Erkenntnisse?

VG,
Hendrik

von Christian T. (Gast)


Lesenswert?

So, komme jetzt auch langsam mit den ganzen Features der Enttec Sniffer 
Software klar. Also auf der FTDI Senderseite macht er folgende 
Fehlermeldung:
RDM Paket: Timing Error
Recorded Breakt Time: 2973 usek
Allowed Break Time: Controller (176 usek --- 352 usek)
Refer: Page 8, Table 3-1, Line 1&2 (RMD Spec)

 Timestamp(us)    Count    Event      Data
 0                                -    Start Break    -
 2973                             -    End Of Break     -
 5061                           1    Data     CC
 5105                           2    Data     01
 5149                           3    Data     18
 5193                           4    Data     FF
 5237                           5    Data     FF
 5281                           6    Data     FF
 5325                           7    Data     FF
 5369                           8    Data     FF
 5413                           9    Data     FF
 5457                          10    Data     41
 5501                          11    Data     64
 5545                          12    Data     FF
 5589                          13    Data     00
 5633                          14    Data     00
 5677                          15    Data     01
 5721                          16    Data     01
 5765                          17    Data     01
 5809                          18    Data     00
 5853                          19    Data     00
 5897                          20    Data     00
 5941                          21    Data     10
 5985                          22    Data     00
 6029                          23    Data     03
 6074                          24    Data     00
 6116                          25    Data     08
 6160                          26    Data     99

Wobei die Zeit über nen ganzen Datensatz auf Senderseite zwischen 2000 
und 3000 usek liegt.

Wenn du sagst der Break liegt da immer bei mindestens 1,xx ms. Dann 
überschreitet man natürlich immer die Zeit. (Die Angabe aus der Ansi 
1.20 stimmen) Aber ist ja auch erstmal nicht so tragisch. Zu Testzwecken 
reicht einem das natürlich erstmal.

Auf AVR Seite habe ich derzeit erstmal die Delayzeiten rausgenommen die 
du eingepglegt hast. Dann hab ich mal mit der Baudrate für den Break 
gespielt. (90,9k)

Mit deiner Einstellung produziert er folgenden Fehler:
RDM Paket: Timing Error
Recorded Breakt Time: 110 usek
Allowed Break Time: Controller (176 usek --- 352 usek)
Refer: Page 10, Table 3-3, Line 1&2 (RMD Spec)

Hab das dann mal angepasst auf z.B. (voher UBRR0L  = 0x05;) auf UBRR0L = 
0x11;

Dann meldet er keine Fehler auf AVR Seite im Sniffer:

 Timestamp(us)    Count    Event      Data
 0                                -    Start Break    -
 326                              -    End Of Break     -
 402                               -      Start Code   CC
 452                            1    Data     01
 501                            2    Data     1A
 551                            3    Data     41
 601                            4    Data     64
 651                            5    Data     FF
 703                            6    Data     00
 752                            7    Data     00
 801                            8    Data     01
 851                            9    Data     12
 901                           10    Data     34
 951                           11    Data     56
 1005                          12    Data     78
 1054                          13    Data     9A
 1103                          14    Data     BC
 1151                          15    Data     A8
 1201                          16    Data     00
 1251                          17    Data     00
 1301                          18    Data     00
 1351                          19    Data     00
 1405                          20    Data     11
 1453                          21    Data     00
 1502                          22    Data     03
 1551                          23    Data     02
 1601                          24    Data     00
 1651                          25    Data     00
 1701                          26    Data     05
 1755                          27    Data     B4

Dann hab ich mit der Firmware im AVR mal wieder den RDM Controller 
gestartet und nen Discovery gemacht. Immer noch Fehler:
"Selected Device did not respond to the DEVICE_INFO, No Information to
display, Refer to the Manual for more info"

Das ist dann allerdings merkwürdig. Wenn der Sniffer sagt das jetzt das 
Timing im grünen Bereich liegt, sollte es ja eigentlich sauber laufen. 
Muss ich wohl noch etwas weiter tüffteln.

von Henne (Gast)


Lesenswert?

Erst einmal vielen Dank für das Timing des Response Break! Das werde ich 
heute anpassen.

Mögliche Fehlerquelle bei device info request:
Wenn ich nach der Discovery gemuted werde, antworte ich nicht auf eine 
Device Info Request (oder irgendetwas anderes)

Darf ich also zum Zeitpunkt der Anfrage überhaupt antworten oder bin ich 
gemuted?


VG,
Hendrik


(Es gibt zum Muting die Interpretationen, dass es sich nur auf die 
Discovery oder auf alles außer Mute/Umute bezieht. Ich schließe mich der 
letzteren an, um sicherzustellen, dass meine Geräte nie aus Versehen 
dazwischenquaken...)

von Christian T. (Gast)


Lesenswert?

Also das Muting bezieht sich meiner Meinung nach nur auf Discovery 
Messages. Der Trick an der Sache ist ja das ein Device normal nur 
Antwortet wenn es angesprochen wird.

Wenn man aber nicht die IDs der Geräte kennt werden alle Geräte unmuted 
per Broadcast. Dann spricht man einen bestimmten Adressbereich an und 
schaut ob jemand Antwortet. Wenn man ein vernüftiges Paket bekommt mit 
gültiger Checksumme dann hat man auch eine gültige ID. Man spricht also 
das erkannte Device an und schickt ihm eine Mute Message. Wenn das 
Device dieser erhält, reagiert es ab sofort nicht mehr auf Discovery 
Messages und sendet eine Respond das es den Mute Befehl verstanden hat.
Jetzt ist dieses Device in dem Adressbereich Still wenn man ihn noch mal 
anspricht. Sollten jetzt noch andere Devices in dem Bereich seihen 
werden diese Antworten.
Bekommt man bei der Abfrage keine gültige Nachricht zurück weil zwei 
Geräte gleichzeitig Antworten, muss man den Adressraum einschränken. 
Solange bis man ein gültiges Paket bekommt. Wenn niemand antwortet geht 
man davon aus das der Adressbereich in dem man sucht frei ist.

Generell muss jedes Device immer Auf eine geziehlte Anfrage mit der 
passenden ID reagieren. Damit man testen kann ob es noch da ist. Das 
Muten gibts meiner meinung nach nur damit man halt bei der Erkennung 
erkannte Geräte ausblenden kann. Aber man möchte natürlich nach der 
Erkennung der "Seriennummern" anschliessend die Gerätedaten auslesen. 
Von daher macht es ja keinen Sinn Geräte dann auszuschalten.

Generell Antwortet ein RDM Gerät ja nur dann wenn es danach gefragt 
wird. Somit besteht im Normalbetrieb eigentlich keine Gefahr das zwei 
Geräte durcheinader funken. (Außer der Hersteller pennt und liefert zwei 
Geräte mit der gleichen ID aus)
Ich werd mir das gleich noch mal anschauen in deinem Code. Aber so wie 
ich das sehe ist es dann natürlich klar das sich das Device auf die Info 
Message nicht mehr meldet.

von Christian T. (Gast)


Lesenswert?

Jau, daran lags, hab grad deine IF Abfrage der Mute Flags bei der

void respondMsg(void)

rausgenommen. Jetzt funktioniert das wie es soll. Erklärung siehe oben 
:-)

Dann kann ich jetzt mich ja dran machen die anderen RDM Funktionen ans 
laufen zu bekommen.
MfG
Christian

von Christian T. (Gast)


Lesenswert?

So, zu den verbessungen die noch gmacht werden sollten:

SOFTWARE_VERSION_LABEL ist laut Norm auch ein Pflichtfeld, sollte also 
bei dir auch noch eingebaut werden:

//*********** Deklaration als Beispiel

const unsigned char Software_V_Label_Msg[] =
{   //Software Version Label msg (ASCII text up to 32 character)
'A','B'
};


Dann musste deine Switch Case Funktion noch um nen Punkt erweitern:


case SOFTWARE_VERSION_LABEL:
  getMsgP(Software_V_Label_Msg,    sizeof(Software_V_Label_Msg));
  rdm->PDLen= sizeof(Software_V_Label_Msg);
  rdm->PortID= RESPONSE_TYPE_ACK;  //Acknolege
  respondMsg();
  break;


Und was mir in deinem Code auch noch aufgefallen ist. Es sind einige 
Variablen sind mitten in den Funktionen deklariert. Normal gehören die 
Deklarationen an den Anfang der Funktion. Hab das bei mir bereits 
geändert. Der WinAVR Compiler stört das scheinabr nicht. Aber andere 
Compiler meckern das schon an.

von Christian T. (Gast)


Lesenswert?

ParamMsg[] muss natürlich auch noch angepasst werden...

von Henne (Gast)


Lesenswert?

Ich werde das Muting und Break-Timing ändern.

Zu dem SW-Version Label:
Ist Pflicht, ich sehe darin keinen Nutzen, es raubt mir Flash (der mir 
an allen Ecken und Enden fehlt).

-> Ich lass es weg.

Zu Parametern in Funktionen:
Meine WinAVR-Version ist nicht so schlau sich anzugucken, wann ich 
welche Variable in der Funktion brauche. Dadurch gibt es mehr 
SRAM-Zugriffe zum Puffern lok. Variablen als notwendig und der Code wird 
größer.

Grundsätzlich hast Du natürlich Recht.

Vielen Dank,
Hendrik

von Christian T. (Gast)


Lesenswert?

Ok, ich geize halt normal nichzt so mit den Recourcen. Man kann sich ja 
aussuchen welchen Controller man nimmt. Und in nen Mega 128 passt schon 
ne Menge Code. Die kleinen Controller haben meistens auch zu wenig 
Hardware PWS mit 16 Bit. Da nutzt man dann doch eher das Teil ne Numer 
größer. Werd das ganze in nen LED Netzteil einbauen. Und da möchte ich 
dann schon alles was von der Norm vorgegebn wird auch drin zu haben. 
Dann kann man das Teil auch für drausen vergießen und alels schön übern 
Bus steuern.

Das mit dem SOFTWARE_VERSION_LABEL hat aber schon nen Sinn. Weil es 
viele Geräte am Markt gibt die im laufe der Zeit neue Versionen 
bekommen. Und da die sich dann nicht gleich verhalten macht es auch Sinn 
das ganze zu Kennzeichnen. Damit man dann auch sehen kann wenn man 
unterschiedliche Geräte im Strang hat.

IDENTYFY_DEVICE ist übrigens auch noch ein Pflichtfeld. Wenn du willst 
kannst du ja zumindest nen Komentar im Quelltext hinterlegen. Damit dann 
andere Leute das bei Bedarf mit aufnehmen können.

Ist ja durch die Struktur sehr schön nen Befehl dazu zu bauen.

Ansonsten muss man mal schauen ob sich RDM in der Lichtechnik weiter 
durchsetzt. Die neuen Robe Scheinwerfer habens zumindest auch mit drin. 
Ansonsten kommen die anderen großen Hersteller ja auch auf den Trichter 
ihre Geräte damit auszurüsten. Würd mich freuen wenn ich demnächt keine 
Dippschalter mehr adressieren muss g

von henne (Gast)


Lesenswert?

Identify haben meine fertigen Geräte. Ist haber gerätespezifisch - 
deswegen habe ich es aus meiner GPL-Lib erst einmal rausgelassen.

Zu den Kosten:
Wenn die FW für eine Funzel ist, von der 10k Stäck/a gefertigt werden, 
bekommst Du ziemlich klare Kostenvorgaben. Und schon wird die jedes Byte 
lieb und teuer ;-)

zur Durchsetzung:
In einigen FWs läuft es versteckt schon mit, wenn der Platz da ist. Ich 
bin in einigen Mailverteilern zu dem Thema und konnte mal eine halbwegs 
akteuelle UID-Liste der ESTA sehen: RDM wird kommen.

von henne (Gast)


Lesenswert?

Die neue Version der Lib ist oben.

Viel Spaß,
Hendrik

von Christian T. (Gast)


Lesenswert?

Identify ist schon Gerätespezifisch, gibt sicherlich auch Geräte wo mans 
nicht so toll einbauen kann. Bei Lampen ist das ja nicht das Problem... 
lass es leuchten oder blinken.

Also die Geräte die ich bisher gebaut habe gehen normal nie in 10k 
Stückzahlen. Von daher hat man den Vorteil das man nicht um jeden Cent 
sparen muss. Wenn man in Deutschland was produziert ist das Material 
meistens auch eher ein kleiner Faktor. Da versauen dann eher die 
Personal und Handlingskosten den Schnitt. Genrell kann man aber wenns 
wiklich mal was in größeren Stückzahlen läuft man bei fast jedem 
Hersteller auch was am preis drehen.

Offtopic an
Bei mir ist es halt so, ich toure schon seit 10 jahren als DJ und LJ 
durch die gegend. Habe Radio und Fernsehtechniker gelernt. Und nach der 
Ausbildung bei meiner jetzigen Firma in der Produktion angefangen. Dann 
nebenbei meinen Techniker gemacht. Technikerarbeit war dann ne 
Metallkernleiterplatte mit 4 stromgeregelten Luxeon 1 LEDs und DMX 
Eingang drauf. Nach dem Techniker bin ich dann in die Entwicklung 
gewechselt. Die Firma macht aber normal halt Motoren und Steuerungen für 
RWA (Rauch- und Wärmeabzug). Wir produzieren aber im Elektronikbereich 
auch viel OEM als Bestückung. Seit nen paar Jahren bestücken wir halt 
auch viel Hochleistungsleds für diverse Kunden (Lampenhersteller und 
Industriekunden). Dadurch kommen dann halt auch mal Anfragen für 
Kundenspezifische Lösungen. Das LED Netzteil ist halt auch ne 
Entwicklung für nen Lampenhersteller. Der bekommt das aber nur mit 1-10V 
Eingang. Da das aber Modular aufgebaut ist hab ich mir jetzt halt mal ne 
Controllerplatine gebaut mit RS485 Schnittstelle. DMX drauf ist ja kein 
Thema... Aber wollte mich jetzt halt auch mal mit RDM beschäftigen. Hat 
man halt schon ne Menge möglichkeiten auch wenns leider im Moment noch 
nicht so toll unterstüzt wird. Aber ich denk auch das es kommen wird. 
Weil der mehraufwand an der Hardware halt sehr gering ist.

Die Aktuellen Hersteller IDs sind übrigens online veröffentlich:
http://www.esta.org/tsp/working_groups/CP/mfctrIDs.php

Sind eigentlich alle Namenhaften Hersteller dabei. Da die Registrierung 
auch nichts kostet steht der Sache auch nichts entgegen.

Muss jetzt mal schauen ob ich für mich privat jetzt mal nen Satz 
Controllerplatine für die Netzteile bauen lasse. Das dumme ist halt das 
die Firma halt immer nur Zulieferteile herstellt und man leider nie ne 
komplette Leuchte hat. Muss man sich dann schon selbst was basteln.

Bis jetzt hat auch bei uns noch niemand nach RDM gefragt. Aber wird 
vielleicht dann auch mal kommen das es ein Lampenhersteller haben will. 
aktuell baue ich grad erstmal an ner Motorsteuerung. Von daher ist 
nichts mit hell und bunt.

Deine Libary werd ich dann auch noch mal ausprobieren. Hab mir 
spasseshalber auch mal eine von deinen Controllerplatinen bestellt. Dann 
kann ichs auch mal auf deiner Hardwarebasis den Code für dich testen. 
Ich selbst baue ja fast nur noch SMD. Obwohl ich auch schon ne DMX 
Platine mit nem Solid State Relais in bedratet gebaut habe. War auch für 
nen Kundenprojekt. Die brauchten da einmal 100 Stück von. Da lohnt das 
dann nicht extra nen Bestückungsautomat für anzuwerfen.

Wenn du noch was wissen willst schreib einfach an dj AT turnthetable DOT 
de

Vielleicht kannst mir dann auch mal nen paar Infos geben was du noch so 
treibst und was du so mit Lichtechnik zu tun hast. Würd mich auch mal 
intressieren.

Und wenn du mal was produzieren lassen willst kann ich da vielleicht 
auch mal was für dich tun. Ist zwar mehr Aufgabe unseres Vertriebs. Aber 
die sitzen ja im Büro um die Ecke.

Ansonsten hab ich halt ganz gute Kontakte im Bereich Hochleistungs LEDs. 
Wenn du da Infos brauchst oder Material brauchst kannst dich auch gerne 
melden.

Offtopic aus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.