Hallo ihr Byteschubser!
Per (BASCOM) I2C sollen Farbwerte an einen angebundenen Slave gesendet
werden, an dem eine RGB LED mit Chip hängt.
Folgende -funktionierende- Lib läuft auf dem Slave:
https://github.com/usedbytes/neopixel_i2c
INFO:
1
'The slave address is currently hardcoded to 0x40 in the firmware
2
'
3
'Writes look like this:
4
'Start Slave Address Register Address Data Stop
5
'The register address will auto-increment after every byte, so you can write data in bursts.
6
'The LED values are only updated after a STOP is received.
7
'
8
'*** Register Map:
9
'The register map consists of a number of global control registers - address 0x00-0x03 - followed by an array of registers which hold the individual value for each LED in normal mode.
10
'
11
'Address Name Description Access Reset
12
'0x00 CTRL Control Register R/W 0
13
'0x01 GLB_G Global Green Value R/W 0
14
'0x02 GLB_R Global Red Value R/W 0
15
'0x03 GLB_B Global Blue Value R/W 0
16
'*** Register Descriptions:
17
'CTRL
18
'The control register sets the operating mode.
19
'Name: RSVD RSVD RSVD RSVD RSVD RSVD GLB RST
20
'Bit: 7 6 5 4 3 2 1 0
21
'Access: r r r r r r rw rw
22
'
23
'RST
24
'Writing a 1 to this bit will reset the LED controler, setting all LEDs to OFF. This bit will be automatically cleared once the reset has completed.
25
'
26
'GLB
27
'Writing a one to this bit causes the global color value to be displayed on all LEDs at the end of the transaction.
28
'Normally you would set the GLB_R, GLB_G, and GLB_B values in the same transaction as setting the GLB bit, so that the new colour is immediately applied.
29
'Writing a zero to this bit will disable the global colour override and return to normal operation.
30
'
31
'*** GLB_R, GLB_G, GLB_B:
32
'These registers hold the global colour value. When the GLB bit in the CTRL register is set, all LEDs will display this colour.
33
'
34
'*** LED Value Array:
35
'Everything after the global registers is an array of data for each LED. When the GLB bit is not set, each LED will display whatever value is programmed in its corresponding register set.
36
37
38
'Info aus der I2C Lib des Slaves:
39
'Here's an example of I2C Communication to start a SRF08 ranging in cm:
40
'i2c_start(); // send start sequence
41
'i2c_tx(0xE0); // SRF08 I2C address with R/W bit clear
42
'i2c_tx(0x00); // SRF08 command register address
43
'i2c_tx(0x51); // command to start ranging in cm
44
'i2c_stop(); // send stop sequence
##############################################
BASCOM:
Die Prints kommen in der finales Version natürlich weg!
1
$regfile "m328pdef.dat"
2
$crystal = 8000000
3
4
$framesize = 32
5
$swstack = 32
6
$hwstack = 64
7
8
$baud = 4800
9
$lib "i2c_twi.lbx"
10
Config Twi = 100000 ' Init TWBR und TWSR - wanted clock frequency - 100kHz Standard , 400kHz Fast , 3.4MHz High speed
11
12
' TWI gleich einschalten, das macht Bascom ansonsten erst beim I2CStart:
If Err = 0 Then Print "i2c start ok" ' In der Systemvariablen err wird das Ack-Bit hinterlegt
39
40
I2csend I2c_slave_adress_write ' Slave ansprechen 'I2CSEND combines the i2cstart,i2cwbyte and i2cstop statements.
41
If Err = 0 Then Print "i2c slave adresse ok"
42
43
I2cwbyte I2c_slave_ctrl_reg ' Slave Control Register auswählen
44
If Err = 0 Then Print "i2c CTRL register ok"
45
46
I2cwbyte &H01 ' GLB_G Register auswählen
47
I2cwbyte Greenvalue ' Farbwerte ins Register schreiben
48
If Err = 0 Then Print "i2c farbbyte uebertragen"
49
50
I2cwbyte &H02 ' GLB_R Register auswählen
51
I2cwbyte Redvalue ' Farbwerte ins Register schreiben
52
If Err = 0 Then Print "i2c farbbyte uebertragen"
53
54
I2cwbyte &H03 ' GLB_B Register auswählen
55
I2cwbyte Bluevalue ' Farbwerte ins Register schreiben
56
If Err = 0 Then Print "i2c farbbyte uebertragen"
57
58
I2cstop ' The LED values are only updated after a STOP is received
59
If Err = 0 Then Print "i2c stop - LED values updated"
60
61
62
63
Print Err ' Err = 0 -> kein Fehler ! Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).
64
Print
65
66
Wait 5
67
68
' NÄCHSTE FARBE
69
70
Loop
71
72
End
Ich schaffe es einfach nicht das RGB Bytearray bzw. die Einzelwerte
korrekt an den Slave zu schicken.
Muss ich nach dem Control-Register-Aufruf die 3 GLB_ Register einzeln
aufrufen, gefolgt von Farbbytes oder schicke ich sofort 3 Farbbytes nach
dem Aufruf des Control Registers?
Muss ich in das Control Register vor den Farbbytes irgendwas bestimmtes
reinschreiben?
Wie könnte ich die 3 RGB Bytes "eleganter" übergeben, als alles einzelne
Programmzeilen zu erstellen?
Interessant zu wissen ist folgendes:
"I2CSEND combines the i2cstart,i2cwbyte and i2cstop statements."
Wenn ich "I2c_slave_adress_write" mit I2c*wbyte* aufrufe, erhalte ich
kein ACK und die restlichen I2C Kommandos werden übersprungen. Wenn ich
es mit dem Kombinationsbefehl I2c*send* mache, dann bekomme ich das ACK
und alle weiteren Prints werden ausgegeben. Vom Prinzip her müsste es
aber mit I2c*wbyte* funktioneren.
Hat jemand eine Ahnung warum das nicht mit I2c*wbyte* funktioniert?
Hallo Alfred,
wenn Du die aktuelle Bascom Version (ab 2.0.7.9) verwendest, dann musst
Du eigentlich nur die so genannte Rainbow Library verwenden - und
fertig. Die Hilfe (F1) hält dazu auch ganz ordentliche Beispiele parat.
Du sparst Zeit und hast schneller Erfolg...
monkye
Danke für den Hinweis Uwe. Ich möchte aber lieber flexibel bleiben und
das Prozedere auch für andere Projekte einsetzen. Die Rainbow-lib kommt
nicht in Frage ;)
Alfred S. schrieb:> Hello? Nur C und Assembler Fans hier? =)
Hat nichts mit der Sprache zu tun. Du must erst mal verstehen wie
das Ganze funktioniert (auch I2C).
Also, so wie ich das oben rausgelesen habe, funktioniert es
folgendermassen:
a) Alle LEDs selbe Farbe z.B. RED
1
i2cstart
2
i2cwbyte(SlaveAdress*2)/* Weiss allerdings nicht, wie die Adressierung beim Bascom ist... */
3
i2cwbyte1/* Wenn es stimmt was du oben geschrieben hast, gehen alle LEDs aus */
4
i2cstop/* Ende, alle LEDs sollten jetzt Aus sein */
5
waitms50/* Bisschen warten... */
6
i2cstart
7
i2cwbyte(SlaveAdress*2)/* Weiss allerdings nicht, wie die Adressierung beim Bascom ist... */
8
i2cwbyte2/* Global Value (in deinem Fall RED) wird angezeigt */
9
i2cwbyte0/* GLB_G (GREEN) ist OFF */
10
i2cwbyte255/* GLB_R (RED) ist ON */
11
i2cwbyte0/* GLB_B (BLUE) ist OFF */
12
i2cstop/* Ende, alle LEDs sollten jetzt Rot leuchten */
b) Die ersten 5 LEDs leuchten in verschiedenen Farben:
1
DimNrOfLeds,lWertAsByte
2
3
i2cstart
4
i2cwbyte(SlaveAdress*2)
5
ForNrOfLeds=1To4
6
i2cwbyte0/* CTRL + GLB_X sind OFF */
7
Next
8
RestoreledRGB
9
ForNrOfLeds=1To15
10
ReadlWert
11
i2cwbytelWert
12
Next
13
i2cstop/* Ende, alle LEDs sollten jetzt in verschiedenen Farben leuchten */
14
End
15
16
ledRGB:
17
Data255,0,0,0,255,0,0,0,255,150,150,0,0,150,150
Sollte funktionieren - ausprobieren, Resultat posten...
Das geht einfach nicht mit "wbyte" an der Slaveadresse. Musste es durch
"send" ersetzen. Ich musste den Slave insgesamt nur 1x an seiner
Slaveadresse ansprechen. Habe es hinbekommen! Allerdings besteht noch
Klärungbedarf:
If Err = 0 Then Print "was soll das hier - ohne gehts nicht"
57
'*******
58
I2cwbyte Greenvalue
59
I2cwbyte Redvalue
60
I2cwbyte Bluevalue
61
I2cstop
62
Print Err
63
64
Wait 2
65
66
'weitere Farben
67
68
Loop
Bei "was soll das hier - ohne gehts nicht" musste ich ein Byte
übertragen, sonst wären die Farbwerte nicht übertragen worden. Es war
dabei quasi egal welchen Wert es enthielt. Hätte auch &HFF / 255 sein
können.
Läuft so seit Stunden mit 10 verschiedenen Farben durch und funktioniert
wohl einwandfrei.
Frage: Warum musste ich ein Byte rüberschicken, wo der Wert quasi egal
ist? Das CTRL Register hatte ich doch bereits ausgerufen und einen Wert
reingeschrieben...
Auch komisch: bei der Übertragung von &B00000001 ins CTRL Register wurde
das RESET Bit auf 1 gesetzt... und die LEDs blieben an (allerdings mit
falscher Farbdarstellung). Gibt es dazu eine Erklärung? Habe
verschiedene CTRL Registerwerte ausprobiert und die nicht
funktionierenden auskommentiert.
Alfred S. schrieb:> Auch komisch: bei der Übertragung von &B00000001 ins CTRL Register wurde> das RESET Bit auf 1 gesetzt... und die LEDs blieben an (allerdings mit> falscher Farbdarstellung). Gibt es dazu eine Erklärung? Habe
Ja.
Das ist alles so falsch, dass du diesen armen LED-Treiber (was ist das
überhaupt für ein Ding ?) wahrscheinlich total durcheinandergebracht
hast.
Also, ohne durch deinen (Horror) Program ganz durchzugehen:
Nein, nicht Control Register auswählen.
Das, was du oben (zufällig) gemacht hast, nennt sich General Call,
und nur deswegen geht es überhaupt weiter...
Und von da an hatte ich keine Lust mehr.
Entweder hörst du auf rumzuspielen, machst ganz einfach ein copy &
paste mit von mir gepostetem Program und sagst ob es geht/nicht geht
oder es wird nie etwas.
Wenn es mit von dir oben gepostetem Program geht (wenn auch falsch),
dann muss es mit meinem Program erst recht gehen .
Das einzige, was bei mir ev. geändert werden müsste, ist die Adresse
für Slave, also einfach 0x40 als Adresse reinschreiben, mit dem Rest
nicht rumspielen, nicht ändern.
So:
Ich habe dein Programm getestet. Es lief nicht durch. Von daher habe ich
die Änderungen eingebaut.
Hier der Test mit deinem Programm:
1
Do
2
3
Print "es geht los:"
4
5
i2cstart
6
If Err = 0 Then Print "i2c start ok"
7
I2cwbyte &H40 'Slaveadressierung
8
If Err = 0 Then Print "i2c slave ok"
9
I2cwbyte 1 '/* Wenn es stimmt was du oben geschrieben hast, gehen alle LEDs aus */
10
If Err = 0 Then Print "i2c byte ok"
11
I2cstop '/* Ende, alle LEDs sollten jetzt Aus sein */
12
If Err = 0 Then Print "i2c stop ok"
13
Waitms 50 '/* Bisschen warten... */
14
I2cstart
15
If Err = 0 Then Print "i2c start ok"
16
I2cwbyte &H40 'Slaveadressierung
17
If Err = 0 Then Print "i2c slave ok"
18
I2cwbyte 2 '/* Global Value (in deinem Fall RED) wird angezeigt */
19
If Err = 0 Then Print "i2c global value ok"
20
I2cwbyte 0 '/* GLB_G (GREEN) ist OFF */
21
If Err = 0 Then Print "i2c GLB_G ok"
22
I2cwbyte 255 '/* GLB_R (RED) ist ON */
23
If Err = 0 Then Print "i2c GLB_R ok"
24
I2cwbyte 0 '/* GLB_B (BLUE) ist OFF */
25
If Err = 0 Then Print "i2c GLB_B ok"
26
I2cstop '/* Ende, alle LEDs sollten jetzt Rot leuchten */
27
If Err = 0 Then Print "i2c stop ok"
28
29
Print Err
30
31
Wait 2
32
33
'nächste Farbe
34
Loop
Ausgabe im Terminal:
1
es geht los:
2
i2c start ok
3
i2c start ok
4
1
Gemäß der Anleitung und gemäß deines Codes müsste es funktionieren wie
von dir beschrieben. Tut es leider nicht.
Der Slave wird korrekt adressiert und da geht es nicht weiter. Hast du
einen Verdacht was es sein könnte? Adresse ist korrekt!
Alfred S. schrieb:> Der Slave wird korrekt adressiert und da geht es nicht weiter. Hast du> einen Verdacht was es sein könnte? Adresse ist korrekt!
Nein.
Aber da du 2 Mal hintereinander "i2c start ok" kriegst und danach
eine 1 (wahrscheinlich für Err), nehme ich an, dass dieses Ding
die Adresse nicht bestätigt, also die Adresse falsch ist.
Probiere es mal mit General Call Adresse 0x00, so:
1
I2cwbyte&H0'Slaveadressierung
Wenn es durchgeht, dann ist das Ding in Ordnung, nur die Adresse
stimmt eben nicht - danach kannst du die Adresse 0x80 probieren, wenn
das aber nicht klappt, musst du die Adressen eine nach der anderen
abklappern...
Und zum zweiten Mal: Was ist das überhaupt für ein Ding ?
Mit der geänderten Adresse auf &H80 funktioniert dein Programm (es
musste nur noch das CTRL Register eingefügt werden.)
Mit Dezimal 1 gehen die LEDs aus und mit 2 gehen die an.
Ich muss das CTRL Register und das CTRL Byte aber bei JEDEM Farbwechsel
mitschicken, sonst ändert sich nichts.
Const I2c_slave_hello = &H80
Const I2c_slave_ctrl_reg = &H00
I2cstart
I2cwbyte I2c_slave_hello
I2cwbyte I2c_slave_ctrl_reg
I2cwbyte &B00000010 'Dezimal 2
I2cwbyte Greenvalue
I2cwbyte Redvalue
I2cwbyte Bluevalue
I2cstop
Was ist das überhaupt für ein Ding ? Siehe 1. Post:
https://github.com/usedbytes/neopixel_i2c
Das mit dem General Call funktioniert übrigens auch. Danke für den
Hinweis, dass es sowas gibt!
Insgesamt mal wieder was dazu gelernt.