Hallo zusammen,
das Jahr des Mad Max 2021 geht langsam zu Ende und bald fahren wir in
die Donnerkuppel ein; zumindest Einige...
.. und ich bekomme den I2C Slave nicht hin.
Ich suchte nach einer extrem kostengünstigen Alternative einen I2C Slave
zu bauen. Auf der Suche nach einem Bauteil blieb ich beim AtTiny85 und
der TinyWireS Lib hängen. Soweit so gut.
Die Wire.h Lib vom Arduino funktioniert mit dem AtTiny85 nicht. Aus dem
Grund verwendete ich die TinyWireS Lib. Von dieser Lib existieren einige
Versionen. Es gibt die Version die arbeiten mit Events/Interrupt Handler
und welche die arbeiten ohne diesen Mechanismus im Hauptprogram. Also
OnRequest/ OnResponse usw. meine ich damit. Ich habe wohl die
ursprüngliche Version erwischt die ohne Interrupt im Hauptprogramm
arbeitet.
Das Senden zum Slave funktioniert soweit. Alledings muss ich beim
Response vom Slave zum Master immer 0x00 zurückgeben! Das sieht aus wenn
der Wert wie ein Rückgabecode behandelt würde.
Ich bin den Code unter der Arduino "IDE" über die TinyWireS bis zur
usiTwiSlave Library gefolgt. (TinyWireS.send(byteRcvd);)
In der usiTwiSlave werden die Daten in der ISR gesendet:
1
ISR(USI_OVERFLOW_VECTOR)
2
{
3
4
switch(overflowState)
5
{
6
7
// Address mode: check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK,
8
// else reset USI
9
caseUSI_SLAVE_CHECK_ADDRESS:
10
if((USIDR==0)||((USIDR>>1)==slaveAddress))
11
{
12
if(USIDR&0x01)
13
{
14
overflowState=USI_SLAVE_SEND_DATA;
15
}
16
else
17
{
18
overflowState=USI_SLAVE_REQUEST_DATA;
19
}// end if
20
TxLock();
21
SET_USI_TO_SEND_ACK();
22
TxUnLock();
23
}
24
else
25
{
26
SET_USI_TO_TWI_START_CONDITION_MODE();
27
}
28
break;
29
30
// Master write data mode: check reply and goto USI_SLAVE_SEND_DATA if OK,
31
// else reset USI
32
caseUSI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
33
if(USIDR)
34
{
35
// if NACK, the master does not want more data
36
SET_USI_TO_TWI_START_CONDITION_MODE();
37
return;
38
}
39
// from here we just drop straight into USI_SLAVE_SEND_DATA if the
40
// master sent an ACK
41
42
// copy data from buffer to USIDR and set USI to shift byte
// Master read data mode: set USI to sample data from master, next
79
// USI_SLAVE_GET_DATA_AND_SEND_ACK
80
caseUSI_SLAVE_REQUEST_DATA:
81
overflowState=USI_SLAVE_GET_DATA_AND_SEND_ACK;
82
SET_USI_TO_READ_DATA();
83
break;
84
85
// copy data from USIDR and send ACK
86
// next USI_SLAVE_REQUEST_DATA
87
caseUSI_SLAVE_GET_DATA_AND_SEND_ACK:
88
// put data into buffer
89
// Not necessary, but prevents warnings
90
rxHead=(rxHead+1)&TWI_RX_BUFFER_MASK;
91
rxBuf[rxHead]=USIDR;
92
// next USI_SLAVE_REQUEST_DATA
93
overflowState=USI_SLAVE_REQUEST_DATA;
94
SET_USI_TO_SEND_ACK();
95
break;
96
97
}// end switch
98
99
}// end ISR( USI_OVERFLOW_VECTOR )
Vor "<<<=================hier" (case USI_SLAVE_SEND_DATA:) steht die
Stelle wo das Register gesetzt wird. An der Stelle muß die Lib falsch
sein.
Es gibt wohl laut Datenblatt eine Möglichkeit mit der man an der Stelle
Adresswerte auf Register übergeben kann; - aber das funktioniert
logischerweise mit uint_8 nicht.
Jetzt die Frage:
Was habe ich da nicht verstanden?
Schreiben macht nur bei Ausgaben und Steuerungen Sinn. Das Lesen (von
Nullwerten) sieht bei mir wie auf dem Bild aus. Wobei das Terminal am
Ende scheinbar nicht antwortet...
Hans schrieb:> Hat der Attiny85 einen I2C Slave bzw. nutzbar dafür?
Eigentlich hat der gar kein I2C. Der hat eine USI, mit der man so etwas
ähnlich hinbasteln kann.
Andreas V. schrieb:> Es gibt wohl laut Datenblatt eine Möglichkeit mit der man an der Stelle> Adresswerte auf Register übergeben kann; - aber das funktioniert> logischerweise mit uint_8 nicht.
Nun ja, diese Aussage ist irgendwie … gewagt, und zeigt ein gewisses
Unverständnis über die Funktion der USI und I2C an sich.
Es wird dir nichts anderes übrig bleiben, als das Datenblatt zu
verstehen, und dann die fragwürdige Libs aus dem Netz auf Fehler hin zu
überprüfen.
Wenn’s ohne Arduino auch geht, würde ich mir das hier anschauen:
http://www.jtronics.de/avr-tutorial/avr-library-i2c-twi-slave-usi/
Oliver
Nachtrag:
Andreas V. schrieb:> //txBuf[txTail] = 0;> //USIDR = txBuf[ txTail ]; //txBuffer;> USIDR = 0x00; // <<<=================hier> //USI_SET_SDA_OUTPUT();> //DDR_USI |= (1 << PORT_USI_SDA);> //PORT_USI |= (1 << PORT_USI_SDA);
Stammen die USIDR-Zeile und die Auskommentierungen von dir?
Wenn ja, warum?
Was passiert, wenn du den Original-Code laufen lässt?
Du hast deine zu sendenden Daten auch vor der eigentlichen
I2C-Kommuniaktion in den txBuf-Buffer geschrieben, unter benutzung der
dafür vorgesehenen Funktionen, die die Indizies richtig setzen, oder?
Oliver
Oliver S. schrieb:> Stammen die USIDR-Zeile und die Auskommentierungen von dir?
Die direkte Zuweisung ist von mir. Der Rest nicht.
> Wenn ja, warum?
Mit dem originalen Code lief der Client in Fehler!
> Was passiert, wenn du den Original-Code laufen lässt?
Fehler!
> Du hast deine zu sendenden Daten auch vor der eigentlichen> I2C-Kommuniaktion in den txBuf-Buffer geschrieben, unter benutzung der> dafür vorgesehenen Funktionen, die die Indizies richtig setzen, oder?
Geht so nicht. Es kann aber sein daß man dafür ein spezielles Terminal
braucht!
Andreas V. schrieb:>> Wenn ja, warum?> Mit dem originalen Code lief der Client in Fehler!
Geht das etwas genauer?
Wie sieht dann das Diagramm aus?
Oliver
Nachtrag:
Andreas V. schrieb:> 1314void loop() {> 15byte byteRcvd = 0;> 16 while (TinyWireS.available()){ // got I2C input!> 17 byteRcvd = TinyWireS.receive(); // get the byte from master> 18 // master must wait for this to finish before calling> Wire.requestFrom> 19 byteRcvd += 1; // add 10 to what's received> 20 //Blink(LED1_PIN, sendBack);> 21 byteRcvd = 0x42;> 22 TinyWireS.send(byteRcvd); // send it back to master> 23 }> 24}
Hast du gelesen und verstanden, was das Programm tut?
Oliver
> Hast du gelesen und verstanden, was das Programm tut?>> Oliver
Wenn man das immer so genau wüßte!
Ich gehe mal davon aus ein normaler Master hält sich nicht an den
Kommentar:
>> 18 // master must wait for this to finish before calling
Andreas V. schrieb im Beitrag #6898896
> Wenn man das immer so genau wüßte!
Das solltest du aber. Das, was da in loop steht, definiert, was der
Slave macht. Das solltest du schon wissen, und der Master auch.
Oliver
Ich bin jetzt von den Tiefen in die tiefsten Tiefen der Library
abgetaucht. Ehrlich gesagt wundere ich mich in letzter Zeit immer mehr.
Die Aussage daß der ATTiny nur mit 8MHz läuft gab mir zu denken!!! Was
mir auffiel waren Acks die zu früh geschickt wurden und kollidierten.
Die Stelle beim Senden zum Master wo die Bits verschoben werden konnten
auch nicht funktionieren. An der Stelle kam immer 0x00 oder 0xFF zurück.
1
#define SET_USI_TO_SEND_DATA( ) \
2
{ \
3
/* set SDA as output */ \
4
DDR_USI |= ( 1 << PORT_USI_SDA ); \
5
/* clear all interrupt flags, except Start Cond */ \
6
USISR= \
7
(0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)| \
8
(1<<USIDC)| \
9
/* set USI to shift out 8 bits */ \
10
(1<<USICNT0); \
11
}
"( 0 << USICNT0 );" setzte ich auf "( 1 << USICNT0 );" was mir
logischer erschien. Und schon kann ich auch Werte schicken.
Jetzt kann man auch Werte unterschiedlich von 0x00 und 0xff senden.
Grundsätzlich kann der Code mit speziellen ATTiny's funktionieren.
Allerdings scheint mein ATTiny85 aus der Rolle zu fallen, weil sich die
technischen Werte geringfügig unterscheiden.
Was mir auffiel war daß man versucht Daten unsynchronisiert in einen
Puffer(Array) zu schreiben und dann zu senden. Dadurch entstehen
Synchronisierubngsfehler und der Slave crasht.
Ich habe angefangen die Library zu synchronisieren. Ich nutze momentan
nur das erste Arrayelement im Puffer. Und schon fallen viele Fehler weg.
ALLERDINGS IST DAS NICHT DAS GELBE VOM EI, WEIL ICH KEINE SEMAPHOREN FÜR
DIE ARDUINO IDE GEFUNDEN HABE!!!
Die meisten Übertragungen laufen jetzt wie im Bild!
FYI: Ich habe zwei Bytes zum Master gesendet! 0x34 und 0x08.
Die Rückgabe auf dem Terminal sieht dann wie folgt aus:
> I2C Read, Address = 44, Read 2 bytes, Delay = 0
OK
< 34 08
Andreas V. schrieb:> Grundsätzlich kann der Code mit speziellen ATTiny's funktionieren.> Allerdings scheint mein ATTiny85 aus der Rolle zu fallen, weil sich die> technischen Werte geringfügig unterscheiden.
Unsinn. Ein USI ist wie das andere. Die einzige Ausnahme von dieser
Regel ist die Verfügbarkeit eines in Leserichtung gebufferten
Datenregisters, das gibt's nicht für jedes USI.
Aber so lange der Code dieses sowieso nicht benutzt, sollte er (so er
denn korrekt ist) auf jedem USI laufen, ganz egal welcher Tiny den nun
enthält. Und im Bezug auf einen Tiny85 sogar dann, wenn der Code dieses
Bufferregister benutzt, denn der hat den!
Das Problem ist möglicherweise das Timing. Dieser Slave funktioniert nur
dann zuverlässig, wenn der I2C-Master Clock-Stretching beherrscht. Nur
bei hohem Systemtakt des Slaves und cleverer Benutzung könnte er u.U.
auch ohne diese Vorraussetzung funktionieren.
Das Problem könnte also z.B. der Master sein. Laß mich raten: Raspi?
> ALLERDINGS IST DAS NICHT DAS GELBE VOM EI, WEIL ICH KEINE SEMAPHOREN FÜR> DIE ARDUINO IDE GEFUNDEN HABE!!!
Kann es auch nicht geben. Es gibt beim Arduino kein preemptives
Multitasking, sondern nur Main und Interrupts. Interrupts sind
(zumindest auf den Arduino-AVR8) systemweit blockierend und können
deshalb nicht warten, weil sie unweigerlich bis in alle Ewigkeit warten
würden. Damit sind alle in MT-Systemen üblichen Sync-Mechanismen
praktisch nicht sinnvoll umsetzbar. Das einzige, was geht, sind
"critical sections", hier typisch ausgedrückt durch atomic blocks im
Kontext von Main, denn die ISRs sind von Natur aus "critical sections".
In Main kann man halt solche Blocks verwenden, wenn man verhindern muss,
dass irgendwelche ISRs reingrätschen. Letztlich wird aber einfach die
Notwendigkeit zum Warten dadurch verhindert, dass der Code, der
eventuell warten müsste, erst garnicht zur Ausführung gelangt.
Oder anders ausgedrückt: du hast rein garnix von der Programmierung
außerhalb einer MT-OS-Umgebung verstanden, nix von der Funktionsweise
eines AVR8 und dem USI und außerdem nichts von der Logik von
I2C-Transfers und benutzt deshalb diesen Slave vollkommen falsch
und/oder an einem ungeeigneten Master...
Sprich: bevor du anfängst, an dem Code rumzufrickeln, solltest du
erstmal all diese Wissenslücken schließen.
@c-hater:
Danke! Du hast das was ich schrieb bzw. meinte auf andere Weise
ausgedrückt. Der Hinweis mit den "critical sections" war echt hilfreich.
Danach werde ich suchen! Ich kenne den Arduino Compiler nicht so gut.
Ich verwende die Arduino IDE auch nur weil ich ein "billiges" und weit
verbreitetes Bauteil als Alternative verwenden wollte.
Die Lib ist so wie sie ist. Allerdings möchte ich die TinyWireS Lib so
nicht verwenden. Das ist mir zu unsicher. Die Read Error Meldungen beim
Terminal kommen nicht umsonst. Auch der Absturz des Slave kommt davon!
Mit den Interrupts hast Du natürlich vollkommen Recht!
Ich greife mit dem MCP2221 auf i2c zu!
Andreas V. schrieb:> Ich verwende die Arduino IDE auch nur weil ich ein "billiges" und weit> verbreitetes Bauteil als Alternative verwenden wollte.
Es zwingt dich überhaupt niemand, die Arduino-IDE und deren libs zu
benutzen. Der Harware ist es völlig egal, womit du die programmierst.
Oliver
Andreas V. schrieb:> Der Hinweis mit den "critical sections" war echt hilfreich.> Danach werde ich suchen! Ich kenne den Arduino Compiler nicht so gut.
Das hat nichts mit Arduino zu tun.
util/atomic.h
Wird beim Compiler, dem AVR gcc, mitgeliefert.
Merkwürdig an der Sache mit dem Synch ist:
rxBuf ist so definiert:
1
volatileuint8_trxBuf[TWI_RX_BUFFER_SIZE];
Außerhalb des ISR wird so zugegriffen (in usiTwiReceiveByte):
1
uint8_treturnValue=rxBuf[rxTail];
innerhalb des ISR wird :
1
rxBuf[rxHead]=USIDR;
bzw. ich habe es mal hardcodiert um das Register auszuschließen ->
1
rxBuf[rxHead]=123;
Dadurch daß die Variable "volatile" definiert ist hätte ich jetzt
erwartet daß der Compiler den Variablezugriff für mich regelt. Das hat
wohl der Autor auch so gedacht. Allerdings crasht es bei mir an den
Stellen.
Gibt es da eine Compilereinstellung?
Heinrich schrieb:> Hast du dir mal den Attiny 841 angesehen?
Der Mikrocontroller ist nicht schlecht. Er zeichnet sich durch sehr
niedrigen Stromverbarauch aus! Eventuell kann ich die Slave-Lib dafür
auch verwenden!
Hallo zusammen,
ich habe jetzt viele Fehler in der Slave-Lib eliminiert. Nur Eines kann
ich mir nicht erklären.
Warum bekomme ich einen Schreibfehler wenn ich dem Datenregister einen
Wert ungleich 0 zuweise?
1
ISR(USI_OVERFLOW_VECTOR)
2
{
3
4
switch(overflowState)
5
{
6
....
7
caseUSI_SLAVE_SEND_DATA:
8
// Get data from Buffer
9
if(txBufCounter>0)
10
{
11
volatileuint8_ttmpData=TxBufferRemoveByte();
12
13
USIDR=0x02;//tmpData; <== hier knallt es egal was ich mache ausser bei Wert 0
Andreas V. schrieb:> Dadurch daß die Variable "volatile" definiert ist hätte ich jetzt> erwartet daß der Compiler den Variablezugriff für mich regelt. Das hat> wohl der Autor auch so gedacht. Allerdings crasht es bei mir an den> Stellen.Andreas V. schrieb:> Warum bekomme ich einen Schreibfehler wenn ich dem Datenregister einen> Wert ungleich 0 zuweise?> …> 13 USIDR = 0x02; //tmpData; <== hier knallt es egal was ich mache> ausser bei Wert 0
Der Prozessor knallt nicht (oder wenn, dann nur mit viel Rauch), der
crasht auch nicht, und bringt auch keine Schreibfehler.
Die Problembeschreibungen sind Murks.
Wie soll man dir da helfen?
Oliver
Ich weiß ja auch nicht wie ich es noch genauer beschreiben soll. Der
Prozesser kommt nach der Zeile in einen instabilen Zustand bzw. geht
ganz außer Betrieb. ...
1
USIDR=0x02;
Nach meinem Verständnis dürte daß nicht passieren, außer der Master
zieht den Pin nach unten und es gibt einen Schluß....
Andreas V. schrieb:> Der> Prozesser kommt nach der Zeile in einen instabilen Zustand bzw. geht> ganz außer Betrieb. ...1USIDR = 0x02;
Beides ist mit an Sicherheit grenzender Wahrscheinlichkeit nicht der
Fall.
Wie diagnostizierst du das denn?
Oliver
Der Slave antwortet dann nicht mehr. Wenn ich die Zeile auskommentiere
bekomme ich im Terminal zwar immer 0 zurück, aber es antwortet
wenigstens immer.
Andreas V. schrieb:> Ich greife mit dem MCP2221 auf i2c zu!
Dann sollte der ATtin85 kein Problem sein, da der MCP2221 Clock
Stretching kann (Datenblatt, S.21), was die Voraussetzung für Slaves mit
einem MC ist.
Ein I2C-Slave muß auf einem MC grundsätzlich als Interrupt laufen, damit
der Master nicht ewig warten muß, wenn die Mainloop des Slave mal etwas
beschäftigt ist.
Zur Qualität der Arduino-Libs kann ich nichts sagen.
Andreas V. schrieb:> Was> mir auffiel waren Acks die zu früh geschickt wurden und kollidierten.
Die ACK/NACK sehen völlig o.k. aus, sie müssen während SCL = 1 stabil
sein.
Aber der jeweils 8. SCL-Puls ist eindeutig zu kurz.
Andreas V. schrieb:> So sieht die Terminalausgabe im Fehlerfall aus:>I2C Write, Address = 44,> Data: EE Delay = 370> OK>> I2C Read, Address = 44, Read 1 bytes, Delay = 0> Read error. Error code: I2C_READ002 -25
Taj, das sagt ja auch nur: Funzt nicht.
Kannst du mal dein ganze Slave-Projekt hier anhängen?
Oliver
Peter D. schrieb:> Aber der jeweils 8. SCL-Puls ist eindeutig zu kurz.
Dem Slave ist nur erlaubt, nach der 1-0 Flanke vom Master den SCL länger
auf low zu halten. Vielleicht ist der Bitzähler falsch gesetzt, so daß
es auf der falschen Flanke erfolgt. Ohne den konkreten Code läßt sich
das nicht feststellen.
Heinrich schrieb:> Hast du dir mal den Attiny 841 angesehen?
Es ist zwar keine große Hilfe, dem TO einfach einen anderen Controller
vorzuschlagen, aber in diesem Fall ein guter Rat, dies beim nächsten Mal
zu berücksichtigen.
Selber hatte ich auch einmal ein TWI auf USI-Basis zum Laufen gebracht,
aber es war eine blöde Gurkerei. Im hiesigen Fall hat die als einfach
vermutete Zusammenklickerei von LIBs ja auch nicht den erhofften,
schnellen Erfolg gebracht.
Wenn ein 8-pol. AVR mit TWI benötigt wird, würde ich die neueren
Versionen wie ATtiny412 +++ empfehlen. Nicht perfekt aber immerhin
schnell erledigt.
Die Library liegt Im Netz in diversen Formen, teilweise stark
modifiziert, teilweise nicht compilierbar, vor. Ich wundere mich in
letzter Zeit nicht mehr...
Der ursprüngliche Ringbuffer konnte volllaufen, deshalb habe ich ihn
durch unit getesteten Code ersetzt. Jetzt werden alte Daten einfach
weggeworfen, wenn der Puffer droht vollzulaufen. Was interessiert mich
der alte Sch...!
Das hat aber erst einmal nichts mit der Übertragung zu tun, weil es auch
bei hard codiertem festen Wert nicht funzt!
Das Problem wird wahrscheinlich durch die Werte der einzelnen Bits im
Status-Register verursacht.
Im Anhang die deprecated Lib die momentan noch ziemlicher Murks ist...
Peter D. schrieb:> Zur Qualität der Arduino-Libs kann ich nichts sagen.
Das ist keine Arduino Lib.
Das ist irgendwas anderes.
Das implementiert noch nicht mal das Interface einer Arduino Wire/I2C
Lib
Von Arduino gab es nie, irgendeine I2C Implementierung für Tinys
(soweit mir bekannt)
Aus meiner Sicht ist die einzige Gemeinsamkeit mit Arduino, dass es vom
AVR gcc kompiliert wird, und sich als Lib in die IDE integrieren lässt.
Oliver S. schrieb:> Oliver S. schrieb:>> Wenn’s ohne Arduino auch geht, würde ich mir das hier anschauen:>> http://www.jtronics.de/avr-tutorial/avr-library-i2c-twi-slave-usi/>> Das wäre immer noch einen Versuch wert.
Kommt Ihr da drauf? Ich bekomme die Seite vom Virenscanner gesperrt!
Auch wenn ich bestätige. Ich müßte eine Ausnahme einfügen oder den
Virenscanner abschalten...
Danke auch an alle. Die Library unterscheidet sich nicht stark von
meiner umgestellten Lib. Ich habe nur den Puffer überlaufsicher gemacht.
Die originale Library funktionierte bei mir allerdings beim Read (vom
Master aus gesehen) nicht zuverlässig bzw nur mit 00 oder FF. Das Timing
funktioniert mit der ungeänderten Lib nur wenn ich den ATTiny85 mit 8
MHz laufen lasse und writes sende. Bei anderen Zahlen mit Read fällt der
ATTiny 85 I2C Slave auf die Nase. Ich änderte die Baudrate nach unten
und nach oben. Es wurde immer nur die Adresse und das Ack vom Read
geschickt.
Inzwischen sendet der ATTiny85 auch ganze Antworten ungleich 00 und FF
bei Frequenzen 1 MHz, 8 MHz und 16 MHz.zurück. Die 16 MHz scheinen
jedoch stabiler zu laufen.
Die Wahrscheinlichkeit bei (Hex-)Zahlen wie 1,3,6,7,8,9 ist sehr hoch
dass sie korrekt übertragen werden. Hex-Zahlen wie 2, EA oder 0A werden
mit fast 100%iger Sicherheit nicht übertragen. Da scheint der Master
(MCP2221) vorher hineinzukätschen und ein Stop-Bit zu senden.
Das sieht dann wie im Anhang aus! Wie kann man das verhindern? So ein
Problem hatte ich mit dem MCP2221 noch nicht!
Hier noch mal das Ende der Bitfolge bei einer anderemn Messung mit 2A
vom Slave zum Master.
Noch ein Nachtrag: Mit 400000 bps läuft die Übertagung stabiler!
Hallo Leute,
es hat sich mal wieder erledigt, weil ich an der total falschen Stelle
suchte! Ich war anfangs von falscher Programmierung bzw. Timing
Problemen ausgegangen. Auch falsche Initialisierung zog ich in Betracht.
Aber das war jetzt der Hammer.
Ich habe vor ca. einem Jahr Sensoren ausgetestet. Die machten mit 4,7K
und 10K Pullups Schwierigkeiten. Aus dem Grund verwendete ich im
Testboard damals 2,2K Pullups. Ich hatte nur vergessen die Pullups
wieder durch 10K's auszutauschen. Alledings hätte mir das auch nichts
gebracht. Das versuchte ich heute nämlich auch ohne Erfolg! Als ich dann
aber 4,7K Pullups verwendete funktioniert alles einwandfrei.
Ich weiß daß man Pullups bei I2C grundsätzlich mit 4,7K bemessen sollte.
Das steht im Standard. Allerdings verwenden moderne Architekturen wegen
dem Stromverbrauch oft 10K Pullups.
Mea Culpa; aber daß durch "falsche" Pullup's der ganze AtTiny85 crasht
finde ich doch sehr schrottig!!!
Die Slave-Lib kann ich also jetzt auch verwenden. Der Puffer kann bei
mir jedenfalls nicht volllaufen! Im Gegensatz zur originalen Lib habe
ich das eleiminiert!
Die Aussage daß die Library nur mit 8 MHz läuft ist schlichtweg falsch!
Mit 1 MHz oder 16 MHz läuft sie auch. Allerdings erhöht sich bei höheren
Taktfrequenzen im Prozesser, wie ich das gerade gemerkt habe, die
Stabilität des Bauteils. Also besser mit 16 MHz programmieren. 1 MHz ist
jedenfalls grenzertig wegen den elektrischen Eigenschaften die im
Datenblatt angegeben sind.
Andreas V. schrieb:> Ich weiß daß man Pullups bei I2C grundsätzlich mit 4,7K bemessen sollte.
Nö, wer sagt dass? Halte dich doch eher an den Empfehlungen in der I²C
Spezifikation.
https://www.nxp.com/docs/en/user-guide/UM10204.pdf#page=50
Dort wird maximal 3 mA empfohlen (bzw. 20 mA für den exotischen "fast
mode plus").
Mit den im Arduino Umfeld üblichen 10 kΩ hatte ich auch schön öfters
Probleme. Ich verwende 2,2 kΩ bei 3,3 V.
Stefan ⛄ F. schrieb:> Mit den im Arduino Umfeld üblichen 10 kΩ hatte ich auch schön öfters> Probleme. Ich verwende 2,2 kΩ bei 3,3 V.
Und genau mit 2,2K bringt es den AtTiny zum Absturz! Ich habe mehrere
AtTiny85 IC's ausprobiert! Ich konnte es nicht glauben!
Mit 3V finktioniert es! Ich hatte die AtTiny Power im 5V Pin des Arduino
Power-Pin stecken! Wobei der AtTiny ja eine Betriebsspannung bis 5V
verträgt. Allerdings waren dann die Pullup's Out of Spec!
Andreas V. schrieb:> Und genau mit 2,2K bringt es den AtTiny zum Absturz!
Erzähl mal Genaueres über den Testaufbau. Was sind da alles für I2C-ICs
dran, wie lang sind die Leitungen.
Z.B. ein COG-LCD ist sehr hochohmig, das kann keine 3mA treiben.
Der ATtiny85 hat allerdings auch kein normgerechtes I2C, die
vorgeschriebenen Filter fehlen:
"The USI two-wire mode is compliant to the Inter IC (TWI) bus protocol,
but without slew rate limiting on outputs and without input noise
filtering."
Ein Widerstand 100R in Reihe zu SDA/SCL ist daher zu empfehlen.
Aber auch viele andere Atmel AVRs und 8051 patzen leider beim
I2C-Standard, d.h. halten ihn nicht ein. Alle, die ich probiert habe,
sind nicht Multimaster fähig (z.B. ATmega8, AT89C51ID2).
Auch der Nachbau des Philips P89C668, der Tekmos TK89C668, kann kein
Multimaster. Ob der überhaupt I2C kann, habe ich nicht geprüft, er
stürzt schon beim Init ab.
Stefan ⛄ F. schrieb:> Nö, wer sagt dass? Halte dich doch eher an den Empfehlungen in der I²C> Spezifikation.> https://www.nxp.com/docs/en/user-guide/UM10204.pdf#page=50
Hallo Stefan! Danke für die Info! Das ist aber ein Empfehlung von
Philipps. AtTiny ist Microchip bzw. Atmel. Mit 2K bzw. 2,5 mA bzw. 5V
habe ich mir einen AtTiny gekillt. Es kann natürlich sein daß er vorher
schon einen Schaden hatte. Aber auch der zweite AtTiny macht bei den
Werten Mucken.
Es kann natürlich sein das mein Händler (aus der Bucht) mir da
minderwertige Ware verkauft hat. Es war halt sehr günstig! Das
Datenregister hat jedenfalls auf Bit 0 nur noch den Wert 1. Laut
Datenblatt entnahm ich 10 mA Sink bei 5V. Irgendwie triftet da Theorie
und Praxis auseinander!
Siehe Seite 162 / Punkt 5:
https://cdn-reichelt.de/documents/datenblatt/A300/ATTINY25-ATTINY45-ATTINY85_DATASHEET.pdf#page=162
Ich bestellte mir noch einmal AtTiny's. Mal sehen ob die der
Spezifikation gerecht werden...
Andreas V. schrieb:> Es kann natürlich sein das mein Händler (aus der Bucht) mir da> minderwertige Ware verkauft hat.
Sag doch nicht soetwas! Es gibt eben Bauteile, die bei gewissen
Funktionen patzen und die man am besten meidet. Deine Widerstandsauswahl
finde ich auch äußerst grenzwertig. Meist wird damit eine andere "Macke"
kaschiert.
Bei mir laufen IIC-EEPROMs allein mit den Pullups eines STM32 mit 100
kHz. Es geht eben, wenn man weiß, was man macht, und sich zur Sicherheit
die Signale auch mal ansieht.
Peter D. schrieb:> Z.B. ein COG-LCD ist sehr hochohmig, das kann keine 3mA treiben.
Dann ist es aber nicht zur I²C Spezifikation konform, denn die fordert
mindestens 3 mA.
Andreas V. schrieb:> Mit 2K bzw. 2,5 mA bzw. 5V habe ich mir einen AtTiny gekillt.
Das kann nicht sein. Die Ausgänge sind mehr als 10x so hoch belastbar.
Da muss etwas anderes schief gelaufen sein.
> Siehe Seite 162 / Punkt 5
Das sind die Angaben zur Stromaufnahme des gesamten Mikrocontrollers
ohne externe Beschaltung. Die Limits stehen im Kapitel 21.1 "Absolute
maximum ratings"
> DC Current per I/O Pin 40.0 mA
So oder so! Es haut alles nicht hin.
Dummerweise habe ich mir die Signale nur mit dem Logic Analyzer
angeschaut, weil ich an einen Programmmierfehler meinerseits dachte.
Zur Beschaltung gibt es nicht viel zu sagen:
PC <=> USB-I2C-Bridge <=> AtTiny
Bridge: MCP2221
Attiny: AtTiny85
Pullup-Widerstände 2K (funzt nicht bei 5V), 10K funzt überhaupt
nicht,4,7K funzt bei 5V und 3,3V
So, Leute gestern habe ich mir auf dem Oszi die Signale angeschaut. Die
Signale sehen aus wie man das bei einem so billigen Bauteil erwartet.
Sie sind ein bisschen abgerundet, aber akzeptabel.
Was mich dabei ein bisschen gewundert hat:
Szenario 1:
Ich kann den AtTiny85-12c-Slave über einen Rotary Encoder in 5-er
Schritten (von 0-100) einstellen. Ungerade Werte werden über die
USB-i2c-Bridge zu 100% richtig an den PC übertragen. Sende ich aber
gerade Werte wie 10, 20, 30, ... dann bekomme ich in 2% bis 3% der Fälle
falsche Werte angezeigt. Und zwar genau immer eins zuviel; - also: 11,
21, 31, ...
Das ist bei 3V immer der Fall egal wie ich die Baudrate verändere.
Pullups: 10K
Szenario 2:
Aufbau wie bei Szenario 1, - nur mit anderer(SOP) USB-i2c-Bridge. Die
Fehlerquote verringert sich auf 0%. Pullups: 10K
Szenario 3:
Aufbau wie bei Szenario 1, - mit dritter(SOP) USB-i2c-Bridge. Die
Fehlerquote ist bei 1,5 %. Pullups: 10K
Szenario 4:
Aufbau wie bei Szenario 1, - mit vierter USB-i2c-Bridge.
Die Fehlerquote ist bei 0,06 %. Pullups: 10K
Szenario 5:
Aufbau wie bei Szenario 1, - mit fünfter(SOP) USB-i2c-Bridge. Die
Fehlerquote ist bei 0,07 %. Pullups: 10K
Szenario 6:
Aufbau wie bei Szenario 1, - mit selbstgebauter (DIP) USB-i2c-Bridge.
Fehlerquote ist bei 0 %. Pullups: 2K
*alle USB-i2c Bridges basieren auf dem MCP2221
FAZIT:
Was mir dabei immer wieder zu denken gibt. Viele "professionelle" Geräte
verlassen sich darauf daß immer alles korrekt übertragen wird. Sei es
Datenübertragung über Ethernet oder RS232. Da kenne ich einige Geräte
die ihre Daten nicht mit CRC's übertragen und abprüfen. Gut Ethernet hat
gewisse Prüfmechanismen, aber die CRC32 geht nur über die Header.
In der Praxis habe ich allerdings erlebt dass Auswuchtmaschinen aus
unerkärlichen Gründen in das Futter fahren oder medizinische Geräte auf
einmal unerklärlich irgendwelche Dinge machen die sie nicht tun sollen.
Hinterher kann man den Schaden nicht nachvollziehen. Immer wenn das der
Fall ist wurden keine CRC32 Prüfsummen gebildet bzw. überprüft.
Gut, das sind keine Bauteile die man mit denen in der Industrie oder MIL
vergleichen kann, aber das zeigt mal wieder eindrucksvoll daß man sich
auf Hardware NIE verlassen darf. Allerdings hätte ich nicht geglaubt
dass die Werte sich je nach Bridge-Adapter so unterscheiden würden.
Also: Immer CRC32 bilden und prüfen und Sequenznummern schaden auch
nicht....
Andreas V. schrieb:> Gut, das sind keine Bauteile die man mit denen in der Industrie oder MIL> vergleichen kann, aber das zeigt mal wieder eindrucksvoll daß man sich> auf Hardware NIE verlassen darf.
Stell dir vor, in deinem PC wird bei der Übertragung von Daten
vom Prozessor ins RAM oder vom RAM in den Prozessor sich darauf
verlassen dass das fehlerfrei funktioniert. Und das viele
tausende oder millionen Male pro Sekunde.
Das zeigt mal wieder eindrucksvoll daß man sich auf Hardware
NIE verlassen darf.
beo bachta schrieb:> Stell dir vor, in deinem PC wird bei der Übertragung von Daten> vom Prozessor ins RAM oder vom RAM in den Prozessor sich darauf> verlassen dass das fehlerfrei funktioniert. Und das viele> tausende oder millionen Male pro Sekunde.
Ich kann mich noch an billigen Speicher erinnern der hatte kein ECC und
nur Paritätsprüfung!....