Forum: Mikrocontroller und Digitale Elektronik tlc5947 spi programmieren, lauflicht


von michael (Gast)


Lesenswert?

hallo Leute,

ich würde gerne ein simples Lauflicht programmieren, das gestaltet sich 
nicht so simpel wie ich erhoffte. SPI übermittelt 8 bit, der Chip hat 24 
Ausgänge und erwartet sich 12Bit pro Ausgang. also 488 Bit.
##################

#include <SPI.h>

int i = 0;

int channel[24] = { 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0,
                  };

byte muster [36] = {
  channel[0] >> 4, (channel[0] << 4) | (channel[1] >> 8), channel[1],
  channel[2] >> 4, (channel[2] << 4) | (channel[3] >> 8), channel[3],
  channel[4] >> 4, (channel[4] << 4) | (channel[5] >> 8), channel[5],
  channel[6] >> 4, (channel[6] << 4) | (channel[7] >> 8),  channel[7],
  channel[8] >> 4, (channel[8] << 4) | (channel[9] >> 8),  channel[9],
  channel[10] >> 4, (channel[10] << 4) | (channel[11] >> 8), 
channel[11],
  channel[12] >> 4,  (channel[12] << 4) | (channel[13] >> 8), 
channel[13],
  channel[14] >> 4, (channel[14] << 4) | (channel[15] >> 8), 
channel[15],
  channel[16] >> 4,  (channel[16] << 4) | (channel[17] >> 8), 
channel[17],
  channel[18] >> 4,  (channel[18] << 4) | (channel[19] >> 8), 
channel[19],
  channel[20] >> 4,  (channel[20] << 4) | (channel[21] >> 8), 
channel[21],
  channel[22] >> 4,  (channel[22] << 4) | (channel[23] >> 8), 
channel[23]
};

byte buffer [36];

void setup() {
  pinMode(9, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(LSBFIRST);
  Serial.begin(9600);
}

void loop() {
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
  digitalWrite(9, 0);
  memcpy(buffer, muster, sizeof(muster));

  channel[i] = 4095;
  SPI.transfer(buffer, 36);
  digitalWrite(9, 1);
  SPI.endTransaction();
  delay(3000);
  i++;
}
##############

kann mir hier jemand helfen und sagen warum das Lauflicht nicht läuft? 
laut meinem Verständnis gebe ich auf jeden channel 4096 pro loop, also 
sollte dadurch auch das muster dementsprechend angepasst werden.

Mike

von Max D. (max_d)


Lesenswert?

Ich kenn mich mit der Arduino SPI-Implementierung nicht so gut aus, kann 
sein dass da auch was faul ist.
Was ich allerdings sehen kann:
Du füllst dein "muster" mit einem Haufen Nullen (die Zuweisung errechnet 
der Compiler noch vor dem Upload und das "channel" array ist da voll mit 
Nullen) und kopierst das dann in irgendwelche Puffer rein.
Das ganze Bit-Geschiebe und Verknüpfen musst du explizit dynamisch in 
der loop machen.
Was das geplante finale Muster ist erschließt sich auch nicht auf den 
ersten Blick, aber so kann es nicht funktionieren.

Ich würde mich vlt. erstmal rantasten:
1. LED (PIN13 afaik) blinken, dann ist der Upload geglückt
2. Festes Muster aus dem SPI rausschieben (testet die Hardware)
3. Dann anfangen dynamische Muster zu erzeugen (wenn da was nicht geht, 
dann ist nicht die Hardware schuld, sonder nur der neue Code)

von Falk B. (falk)


Lesenswert?

michael schrieb:
> hallo Leute,
>
> ich würde gerne ein simples Lauflicht programmieren, das gestaltet sich
> nicht so simpel wie ich erhoffte. SPI übermittelt 8 bit, der Chip hat 24
> Ausgänge und erwartet sich 12Bit pro Ausgang. also 488 Bit.

Na dann mal los. Wie immer sollte bzw. muss man das Problem in 
Teilprobleme zerlegen und einzeln lösen. Das 1. Problem ist das Senden 
der Daten an den IC. Das 2. ist die Umrechnung von RGB Farbwerten in das 
Sendeformat für den IC. Das 3. isd das eigentliche Lauflicht, sprich, 
das Verschieben des Farbmusters.

Löse alle drei Probleme getrennt und du wirst weniger Stress haben.

>kann mir hier jemand helfen und sagen warum das Lauflicht nicht läuft?

Was tut es denn?

>laut meinem Verständnis gebe ich auf jeden channel 4096 pro loop, also
>sollte dadurch auch das muster dementsprechend angepasst werden.

Erstmal muss deine LED-Ansteuerung rein statisch funktionieren. D.h. 
jede LED muss einzeln steuerbar sein. Sprich, erstmal muss dein Buffer 
immer komplett leer sein und nur eine einzelne LED mit RGB=0xFFF geladen 
werden. Wenn das läuft sehen wir weiter.

von Falk B. (falk)


Lesenswert?

>int channel[24] = { 0, 0, 0, 0, 0, 0, 0, 0,
>                    0, 0, 0, 0, 0, 0, 0, 0,
>                    0, 0, 0, 0, 0, 0, 0, 0,
>                  };

Das ist schon mal gut, ein Array mit 24 Elementen für 24 LEDs.

>byte muster [36] = {
>  channel[0] >> 4, (channel[0] << 4) | (channel[1] >> 8), channel[1],
>  channel[2] >> 4, (channel[2] << 4) | (channel[3] >> 8), channel[3],

Das ist Käse. Da sieht keiner durch. Vergiss es. Wenn du ein Muster 
definieren willst, tu das genau so wie für channel. Ein int/LED! Das ist 
DEUTLICH einfacher lesbar! Die Kompression der 12 Bit/LED auf die 8Bit 
der einzelnen Bytes macht man hier NICHT! Das macht entweder eine 
separate Funktion (einfacher Ansatz) oder man macht es während der 
SPI-Ausgabe live (etwas komplexer).
1
int muster[24] = {0xF0F, 0xFFF, 0xF00 . . . . .};

>byte buffer [36];

Schreib erstmal eine Funktion, welche das einfache Muster in muster in 
die komprimierte Form hier rein schreibt.

[Wink mit dem Zaunspfahl]
Das hat was mit Bitmanipulation zu tun.
[/Wink mit dem Zaunspfahl]

>void setup() {
>  pinMode(9, OUTPUT);
>  SPI.begin();
>  SPI.setBitOrder(LSBFIRST);
>  Serial.begin(9600);
>}

OK

>void loop() {
>  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
>  digitalWrite(9, 0);

Hier kommt die Umwandlung von muster in buffer rein, kein einfaches 
kopieren.

>  memcpy(buffer, muster, sizeof(muster));

Das fliegt raus.

>  channel[i] = 4095;
>  SPI.transfer(buffer, 36);


>  digitalWrite(9, 1);
>  SPI.endTransaction();

Ich glaube die beiden Zeilen müssen vertauscht werden, damit sicher erst 
alle Daten rausgeschoben werden, ehe das Chip Select bzw. LATCH-Signal 
auf HIGH geht.

>  delay(3000);
>  i++;

Hier fehlt wenigstens ein Abfangen des Überlaufs, denn dein Array hat 
nur 24 Elemente, nicht unbegrenzt.

if (i>23) i=0;

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.