74HC595 vs PCF8574

Ich will 6 von diesen LEDs ansteuern, womit wäre ich besser bedient, SPI oder i2C?
Sollen paar Stunden leuchten und beim Taster betätigen kurz aufleuchten.
Was den Code angeht, was wäre einfacher oder Platzsparender?
Shiftregister hab ich hier auf Breadboard schon getestet mit der ShiftPWM Lib. Allerdings blink ich beim schieben der Bits nicht durch. Das Prinzip mit den Wire.send(B00000001); gefällt mir besser.
Hab wohl ein i2C LCD1602 Adapter Board hab aber noch nicht getestet obs damit geht.

Würde eher zu den Shiftregistern tendieren. Die maximalen Transferraten liegen deutlich ausserhalb dessen, was 8Bit AVR MCUs schaffen.

Wenn dir die Lib von elco nicht zusagt, was spricht gegen die eigene Lib?
http://arduino.cc/en/pmwiki.php?n=Reference/ShiftOut

oder direkt in avr gcc

Hab jetzt keine fertige Lib bereit, aber das sollte sehr einfach zu machen sein.

Da alle Lösungen eine Ansteuerung der LED über 100Hz ermöglichen sind alle Lösungen im Bezug auf die optische Wahrnehmung gleich.

I2C braucht weniger Pins.
Schieberegister können über pins oder auch über SPI angesteuert werden.

Das einzige ist daß Schieberegister billiger als PCF8574 sind aber zur Ansteuerung aller LED gleichzeitig zuwenig Strom liefern. Bei Schieberegistern braucht es darum noch Treiber (zb ULN2803) oder Schieberegister mit Treiberausgängen (zB TPIC6B595N). Beides macht es wieder teurer und somit sind die Lösungen gleichwertig bzw im Falle der Verwendung vom ULN2803 mehr Hardware aufwand.

Wenn Du die LED in der Helligkeit regeln willst ist ein LED-Treiber nützlich. Ein TLC5940 ist aber überdimensoniert da er 16 Ausgänge hat oder der TLC5947 hat 24 Ausgänge

Grüße Uwe

Wie bereits erwähnt, hab ich von bitschieberei keine Ahnung, das Konzept ist mir klar aber dies umzusetzen macht mir schwer, sehe es nicht in naher Zukunft in meinen Projekten, daher kein Anreiz dies zu lernen.
Dies hab ich gefunden:
http://www.ledhilfe.de/viewtopic.php?f=35&t=14820

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister#Acht_LEDs_mit_je_20mA_pro_Schieberegister

Wenn ich also VCC mit Anode verbinde, kann ich alle 8 Ausgänge vom Shiftregister mit 20mA Leds betreiben.
i2C und SPI brauchen beide 3 Pins zur Ansteuerung.
ULN fällt schon mal weg. Platz und Kostenersparnis.
PCF kann aber auch nur 20mA pro Pin liefern.

Könnt ihr noch was wegen Code sagen, gibts da Schwierigkeiten zu überwinden etc?

Man muss das ja nicht per Hand machen. Wenn du Wire.send() machen kannst, kannst du genauso SPI.transfer() machen. Oder shiftOut() wenn langsameres Bit-bangig ausreicht.

Wenn ich also VCC mit Anode verbinde, kann ich alle 8 Ausgänge vom Shiftregister mit 20mA Leds betreiben.

Die Hälfte der LEDs verwenden so betrieben. Bei der anderen Hälfte fließt der Strom aus dem IC heraus.

Deshalb muss man vor dem versenden das eine Halbbyte (auch Nibble oder Nybble genannt) mit ^ 0x0F (oder 0xF0) invertieren.

Warum die Hälfte und nicht alle?

Weil die 70mA nicht für das gesamte IC gelten sondern einmal für den Strom über Vcc und einmal den Strom über GND. Dann kann man 70mA über GND fließen lassen (in das IC hinein) und 70mA über Vcc (aus dem IC heraus).

Dass die SR aber auch normal beschaltet in der Praxis mehr als 70mA vertragen wird auch auf der shiftPWM Seite mal irgendwo erwähnt.

74HC595 bekommst du um die 30 Cent, den I2C IC bekommst du erst für knapp 1,20€
Schieberegister kannst du (fast unbegrenzt) kaskadieren. Maximal brauchst du da ein paar Gatter als Bustreiber wenn’s über 10 werden sollen. Beim 595 kannst du über Output Enable und PWM noch dimmen. Das kann der PCF 8574 so nicht. Bei I2C bekommst du über 8 ein Problem mit der Adressierung, da nur 3 Bit zum Adresse jumpern da sind. Ok, es gibt beim PCF 8574 noch die A Version mit einer anderen Adresse, so das dann in Kombination mit beiden Versionen 16 IC’s mit 8 Ausgängen möglich sind. I2C ermöglicht einen längeren Bus. Ich habe ohne weiteres (mit einem IC) 2m hinbekommen. Mit einem Umsetzer auf 12V Bus wäre auch wesentlich mehr möglich. Bei SPI wird es vermutlich über 30 cm schwierig werden.
Eine pauschale Aussage ist somit unmöglich. Such dir was aus, was für dich am besten passt :wink:

Gruß Gerald

mehr als 10cm wird nicht und mehr als 6 Leds werdens auch nicht.
Was mir nicht gefällt ist, wie man die LEDs anschließt.
Entweder alle auf GND oder alle auf VCC, wäre einfacher beim programmieren und löten.

Mit dem Sketch wäre nur eine LED am leuchten (jenachdem wie angeschlossen, wären 5 am leuchten)

int taktPin = 8;      // SH_CP 
int speicherPin = 9;  // ST_CP
int datenPin = 10;    // DS
void setup(){
  pinMode(taktPin, OUTPUT);
  pinMode(speicherPin, OUTPUT);
  pinMode(datenPin, OUTPUT);
}

void loop(){
  sendeBytes(0B00000001);
}

// Funktion zum Übertragen der Informationen
void sendeBytes(int wert){
    digitalWrite(speicherPin, LOW);
    shiftOut(datenPin, taktPin, MSBFIRST, wert >> 8); 
    digitalWrite(speicherPin, HIGH);
}

Deshalb muss man vor dem versenden das eine Halbbyte (auch Nibble oder Nybble genannt) mit ^ 0x0F (oder 0xF0) invertieren.

Wie macht man es denn hier?

Sowie ich es geschrieben habe

Aber wenn du nur 6 LEDs willst, wieso übergibst du dann einen int an die Funktion? Das >> 8 braucht man wenn man einen 16 Bit Integer auf 2 Byte aufteilt. Dann muss man aber auch zweimal shiftOut() machen.

Für ein Byte reicht das:

void sendeByte(byte wert)
{
    digitalWrite(speicherPin, LOW);
    shiftOut(datenPin, taktPin, MSBFIRST, wert ^ 0x0F); 
    digitalWrite(speicherPin, HIGH);
}

Hier wird das untere Halb-Byte invertiert, d.h. low-aktiv angesteuert.

Und woran hängt es ab ob das ^ oder & sein soll? Was bewirkt das &, in welchem Fall wirds angewendet?

Wieso ein &?? ^ ist ein XOR. Ein XOR invertiert alle Bits bei denen die Maske 1 ist und belässt die Bits bei denen die Maske 0 ist.

& ist ein Und. Das verwendet man u.a. um Bits auf 0 zu setzten, z.B. um einzelne Bits zu löschen oder bestimmte Bits zu Ignorieren (z.B. wenn man 8 Bits auf einmal von einem Port einliest und nur ein paar davon braucht).

Hab den Code so von Erik Bartmann übernommen und nur das zweite shiftout() gelöscht. Daher das int.
Das & daher, weil ich in einem anderem Post von dir gelesen hatte.

void loop(){
  sendeBytes(0B00001111);
}

void sendeByte(byte wert)
{
    digitalWrite(speicherPin, LOW);
    shiftOut(datenPin, taktPin, MSBFIRST, wert ^ 0x0F); 
    shiftOut(datenPin, taktPin, MSBFIRST, wert); 
    digitalWrite(speicherPin, HIGH);
}

Somit wären alle Leds eingeschaltet, versteh ichs richtig?

Der Sinn von ^ 0x0F ist doch, dass du dein Bit-Muster ganz normal High-aktiv betrachtest und dich nicht darum kümmern musst dass das nochmal invertiert werden soll. Deshalb ist das vom Programm her auch gar nicht komplizierter, da das nur einmal am Ende geändert werden muss.

void loop(){
  sendeBytes(0B11111111);   //alle LEDs an = 8 mal 1
}

void sendeByte(byte wert)
{
    digitalWrite(speicherPin, LOW);
    shiftOut(datenPin, taktPin, MSBFIRST, wert ^ 0x0F);   //hier werden dann die unteren 4 Bits invertiert
    digitalWrite(speicherPin, HIGH);
}

Das & daher, weil ich in einem anderem Post von dir gelesen hatte.

Da geht es darum nicht benötigte Eingänge auszumaskieren. Das ist was ganz anderes.

Wollt grad schon fragen, welche 4 Bits nun invertiert werden…
Das kann man ja mit MSBFIRST und LSBFIRST regeln.

Dann muss ich also beim verdrahten dies auch berücksichtigen, gefällt mir erstmal nicht.
Muss mal schauen obs so klapppt.

Du machst es dir komplizierter als es sein müsste. Beim Verdrahten musst du eigentlich nichts berücksichtigen. Eine Hälfte so, die andere anders. Egal wie es ist, man kann es dann in Software so hinbiegen wie man es braucht.

Du kannst auch einfach mit ^0xF0 das obere Nibble invertieren, falls die anderen 4 LEDs low-aktiv angesteuert werden müssen.

Ich versteh es so:
Erste 4 Leds mit 0xF0 invert.
letzte 4 Leds mit 0x0F invert.

Was wenn ich erste 3 normal und nächste 3 invert haben muss? Dann funktioniert dieser Code so nicht.

Und beim verrahten muss ich eigentlich nix beachten, stimmt, kann man im Code ändern.
Nur da ich von Bitschieberei null Ahnung habe, muss man sich zu helfen finden.

skorpi08:
Was wenn ich erste 3 normal und nächste 3 invert haben muss? Dann funktioniert dieser Code so nicht.

Das tritt nicht auf, da du das SR halb/halb verdrahtest. Bei 6 LEDs dann halt 4/2 statt 4/4. Der Code ist der gleiche wie bei 8 LEDs.

Ansonsten müsste man lediglich die Bitmaske anpassen. Überall wo eine 1 steht wird invertiert.

Dann kann man ja auf die 2 Leds pfeifen und gleich alle auf VCC schalten :smiley:

4/2 würd besser passen, mach ich dann halt so.

Laut abgebildete Platine: Du kannst keine LED einfach paralellschalten. Da braucht jede LED ihren eigenen Vorwiderstand.
Außerdem brauchen sie dann den doppelten Strom. Du brauchst Treiber oder die ShiftRegister Version mit integriertem Treiber.
Grüße Uwe