Hallo Zusammen Ich habe mehrere Attiny85 die als I2C Slave arbeiten. Jeder Slave erfasst Daten, wie Temperatur, Strom, Spannung, Drehzahl. Die Messwerte werden dann von einem Master ausgelesen. Ich habe schon mehrere solche Sensoren gebaut, und bis jetzt haben alle zuverlässig funktioniert. Jetzt habe ich einen Drehzahlsensor gebaut, und nun habe ich irgendwelche Störungen auf dem I2C Bus. Seltsamerweise funktionierst, wenn der Drehzahlsensor alleine am Bus hängt, sobald ein weitere Sensor, wie zB Temperatur, dazukommt, funktioniert der Drehzahlsensor nicht mehr zuverlässig. Habe schon den ATtiny85 ersetzt, ohne erfolg... Kann mir da jemand weiter helfen ??
ICs haben keine Blockkondensatoren an den Versorgungspins. I2C-Leitungen haben keine Pullup-Widerstände.
An die Versorgungsleitung vom Mikrocontroller könnte vielleicht jeweils ein Kondensator gegen Masse. Wie sehen die Pull-Ups aus? Wo sind die angebracht? Wer ist der Master? Wodran erkennst du die Störungen (Oszi?, oder nur"keine Verbindung")? Code vom Master und vom Slave?
Die Pullup Widerstände befinden sind beim Master. Das Problem bemerke ich daran, das die Messwerte fehlerhaft ankommen. Ich habe zu Testzwecken die ganze Messroutine auskommentiert, und den Drehzahlmesswert auf 5 gesetzt. Der Master sollte jetzt immer 5 vom Slave lesen, manchmal kommt aber 0. Das Problem habe ich mit zwei anderen Slaves nicht. Sollte also nicht am Master liegen. Habe schon eine funktionierende SW von einem "Temperatursensor" Slave geladen, das Problem besteht weiterhin. Seltsam ist jedoch, das das Problem nur besteht, wenn mehrere Slaves am Bus hängen. Nein - ich habe keine Doppelbelegung der Slaveadressen...
Einfacher Versuch: Spiel mal mit den Pull-Up Widerständen: http://dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html
So ich habe nach einer Pause wieder weiter gearbeitet... Ich habe das Problem weiter analysiert. Wenn nur ein Slave am Bus hängt, funktionierts. Kommt ein zweiter dazu, fangen die Probleme an. Der Fehler tritt nicht nur mit dem Drehzahlsensor auf, sonder auch mit den anderen Sensoren. Ich vermute, dass der fehler daran liegt, dass wenn ein Slave die falsche adresse empfängt, er den Bus nicht korrekt frei gibt. Hier ein Kurzfassung des Codes (ist in jedem Slave der gleiche): Enable Interrupts 'Interrupts einschalten Enable Usi_start On Usi_start I2c_slave 'Bei Startbit gehe zu i2c_slave Do 'Hauptprogramm Loop I2c_slave: Usisr = &B11000000 Bitwait Usisr.6 , Set 'Warten bis Slaveadresse empfangen If Usidr = Slave_adress Then 'richtige Slave Adresse ...Senden oder Empfangen... Else 'falsche Slave Adresse Usisr = &B01000000 '<---- ist hier das Problem ?? End If Return Bin mir nicht sicher ob das handling mit der falschen Slave Adresse richtig ist. Komme mit dem Datenblatt nicht ganz zurecht...
Michael L. schrieb: > Ich vermute, dass der fehler daran liegt, dass wenn ein Slave die > falsche adresse empfängt, er den Bus nicht korrekt frei gibt. Negative Logic? Ein Slave sollte sich bei einer "falschen Adresse" überhaupt nicht angesprochen fühlen.
Genau das meine ich auch ! Wenn der Slave eine "falsche Adresse" empfängt, sollte er die SCL Leitung wieder loslassen, und auf einen neue Start-kondition warten. Aber macht er das ? Mit dem Befehl "Usisr = &B01000000" ? If Usidr = Slave_adress Then 'richtige Slave Adresse ...Senden oder Empfangen... Else 'falsche Slave Adresse Usisr = &B01000000 '<---- ist hier das Problem ?? End If Im Datenblatt des ATtiny85 auf Seite 116 ist die Beschreibung zum I2C Bus. Aber irgendwie sehe ich nicht wie ich das genau machen muss...
Hi Namensvetter, kenne den Tiny zwar nicht so genau, aber da ist mir bissel was merkwürdig. Michael L. schrieb: > So ich habe nach einer Pause wieder weiter gearbeitet... > > Ich habe das Problem weiter analysiert. Wenn nur ein Slave am Bus hängt, > funktionierts. Kommt ein zweiter dazu, fangen die Probleme an. Der > Fehler tritt nicht nur mit dem Drehzahlsensor auf, sonder auch mit den > anderen Sensoren. Was läuft bei dir als Master? Evtl. generiert er keine Stop Condition. WIMRE hatte ich das mal bei einem Software-I2C-Master. Da ging dann auch nur 1 Slave. > Ich vermute, dass der fehler daran liegt, dass wenn ein Slave die > falsche adresse empfängt, er den Bus nicht korrekt frei gibt. > > > Hier ein Kurzfassung des Codes (ist in jedem Slave der gleiche): > > Enable Interrupts 'Interrupts einschalten > Enable Usi_start > On Usi_start I2c_slave 'Bei Startbit gehe zu i2c_slave > > Do 'Hauptprogramm > Loop > > I2c_slave: > Usisr = &B11000000 > Bitwait Usisr.6 , Set 'Warten bis Slaveadresse empfangen > If Usidr = Slave_adress Then 'richtige Slave Adresse Wenn du senden und empfangen willst, solltest du bedenken, dass die Slave-Adresse selbst nur 7 Bit lang ist, das 8. Bit ist R/W. > ...Senden oder Empfangen... > Else 'falsche Slave Adresse > Usisr = &B01000000 '<---- ist hier das Problem ?? Hier hab ich heftig gegrübelt! Wenn ich die Doku richtig verstanden habe, bewirkt das Setzen des "Counter Overflow Interrupt Flag" auf 1 das Rücksetzen des Flags auf 0. - Naja, von Atmel etwas abenteuerlich desingt, um es mal vorsichtig auszudrücken. Aber müsstest du nicht generell am Ende des Unterprogramms auch das "Start Condition Interrupt Flag" zurücksetzen? Also
1 | Usisr = &B11000000 |
vor dem return. > End If > Return > > > Bin mir nicht sicher ob das handling mit der falschen Slave Adresse > richtig ist. Komme mit dem Datenblatt nicht ganz zurecht... Ja, das USI ist schon gruselig, da gibt es bessere Lösungen. Aber Vielleicht helfen dir ja meine Anmerkungen weiter. Grüße.
Probiere nun seit Tagen ohne Erfolg... Also im Master sieht das Ganze so aus: I2cstart I2cwbyte Adres 'sende Slave Adresse I2cwbyte &HC1 'Befehl Anzahl Messwerte I2cstart Incr Adres I2cwbyte Adres 'sende Slave Adresse +1 f¸r Lesen I2crbyte H_adr , Ack 'lese Antwort I2cstop Am Bus hängt ebenfalls ein BMP085 und ein Eeprom 24C1024, mit denen hat bis jetzt immer alles funktioniert, sollte also nicht am Master liegen. Zu meinem Versuchsaufbau: zwei Slave am Bus, der erste mit Adresse H28, der zweite H30. Programm Ablauf: 1. Der Master scant alle Adressen von H28 bis H65, d.h. er schreibt auf die erste Adresse (H28) den Befehl HB1, gibt der Slave die Antwort HAA, hängt an der Adresse ein Slave. Das ganze geht so weiter bis alle Adresse geprüft sind. 2. Der Master kennt nun alle belegten Adressen. Bei jedem Slave fragt er nun mit dem Befehl HC1 nach, wieviel Messwerte der Slave besitzt. So und hier bei Punkt 2 fangen die Probleme an. Beim ersten Slave (H28), wird mit dem Befehl HC1 anzahl Messwerte abgefragt, der Slave gibt den Wert "2" zurück, soweit gut. Beim zweiten Slave (H30), mit dem gleichen Befehl (HC1), kommt der Wert "255" zurück, sollte aber "1" antworten. Das Komische --> ändere ich bei Slave(H28) anzahl Messwerte von "2" auf "1", funktioniert auch Slave(H30)
Michael L. schrieb: > Probiere nun seit Tagen ohne Erfolg... > > Also im Master sieht das Ganze so aus: Ich habe mal versucht, das wieder lesbar zu machen ... > I2cstart > I2cwbyte Adres 'sende Slave Adresse > I2cwbyte &HC1 'Befehl Anzahl Messwerte > I2cstart > Incr Adres > I2cwbyte Adres 'sende Slave Adresse +1 f¸r Lesen > I2crbyte H_adr , Ack 'lese Antwort > I2cstop Richtig so? > Am Bus hängt ebenfalls ein BMP085 und ein Eeprom 24C1024, mit denen hat > bis jetzt immer alles funktioniert, sollte also nicht am Master liegen. Wenn mehrere Devices gleichzeitig drann waren und auch mal mehr als 1 Byte pro Devices und mehrere Devices nacheinander erfolgreich gelesen wurden, dann sollte es passen. > Zu meinem Versuchsaufbau: > zwei Slave am Bus, der erste mit Adresse H28, der zweite H30. > > Programm Ablauf: > ... Ich bin jetzt nicht so mit dem Basic-Dialekt vertraut, dass ich jetzt alles richtig durchdringe, aber ich denke der folgende Code definiert den Aufruf der ISR:
1 | On Usi_start I2c_slave |
Das würde allerdings bedeuten, dass du alles in der ISR abhandelst. Möglicherweise liegt das Problem darin, und dein Testergebnis ist nur Zufall. Denn normalerweise ollte eine ISR so *kurz* wie *möglich* gehalten sein. D.h. du solltest möglichst nur die Adresse prüfen, und bei Übereinstimmung nur ACK signalisieren, und den Rest im Hauptprogramm machen. Auch solltest du das clock stretching nicht vergessen, das nimmt dir das USI nicht ab, soweit ich das sehe. Eine Frage ist auch noch offen: Was hast du als Master, und ist das Hardware-I2C oder Software? Grüße.
Ja da hast du recht, die ganze SW in der ISR ist nicht optimal. Ich versuche nun das ganze so zu machen wie es von ATMEL gedacht wäre. Mit START interrupt und OVF Interrupt. Habe nun ein ganz anderes Problem: springe ich von der OVF ISR zurück und beim nächsten OVF wieder hinein, übernimmt BASCOM das byte "I2c_mode" nicht, habe also immer den wert 0 !?! Nun ein ganz einfaches Beispiel: START, 2 Byte zum Slave übertragen, STOP Master: ATtiny45, SW I2C Bascom-Code: i2cstart i2cwbyte &h30 'Slave Adresse i2cwbyte &hB1 'Daten byte i2cstop Slave: ATtiny85, HW USI Bascom-Code: Enable Interrupts 'Interrupts einschalten Enable Usi_start On Usi_start I2c_start 'Bei Startbit gehe zu I2c_start On Usi_ovf I2c_read_write 'Bei Daten¸berlauf gehe zu I2c_read_write Do 'Hauptprogramm Loop End I2c_start: I2c_mode = 0 Acknowledge = 0 Enable Usi_ovf Usisr = Bits(7 , 6) 'Reset Startbit, Reset Counteroverflow Usidr = 0 Return I2c_read_write: If Acknowledge = 0 Then Select Case I2c_mode Case 0 'Adress Mode Select Case Usidr Case Slave_adress I2c_mode = 1 Acknowledge = 1 Usisr = 14 'ACK Usidr = 0 Usisr = Bits(6) Case Master_read I2c_mode = 2 Case Else 'Usisr = Bits(6) 'Disable Usi_ovf End Select Case 1 'Master write Mode Printbin #1 , Usidr Case 2 'Master read Mode End Select Else Usisr = 0 Usidr = Bits(7) Usisr = Bits(6) Acknowledge = 0 End If Return Bei der START-kondition springt der Slave zu "I2c_start:" und schaltet das Overflow Interrupt ein. Bei einen Counter Overflow, springt der Slave zu "I2c_read_write:", prüft die empfangene Adresse und setzt das "I2c_mode" byte auf 1. Bei einem erneuten OVF interrupt ist das "I2c_mode" byte wieder 0 ! Bascom übernimmt den wert irgendwie nicht !?! Die Adresse wird vom Slave richtig empfangen, und das "I2c_mode" byte wird auch wirklich auf 1 gesetzt, an dem liegt es nicht.
Hi, ich bin jetzt nicht der BASCOM-Experte, habe es mehr mit ASM und C. Aber wenn der Wert der Variablen scheinbar nicht gespeichert wird, könnte es daran liegen, dass diese nur lokal (und damit üblicherweise flüchtig) ist. Du musst sie also global definieren. Grüße.
ja genau das wird es sein. Die Variable wird wahrscheinlich im SRAM durch etwas anderes überschrieben. Aber wie mache ich das genau ? Ich habe mal mit $hwstack = 32, $swstack = 10, $framesize = 40 probiert, ändert aber am resultat nichts. Die Variable kann ich an einer bestimmten Adresse im SRAM ablegen, geht aber auch nicht. DIM i2c_mode as byte at &h100 overlay In Bascom kann man doch irgendwo schauen, an welcher adresse im SRAM welche Variable abgelegt wird ?
Da kann ich dir leider nicht helfen. Mir fällt da nur noch ein: 1. Variable auf jeden Fall global deklarieren 2. Hab noch gesehen, das BASCOM beim ISR-Aufruf Variablen sichert und am Ende wiederhstellt. Das kann man auch steuern, aber musst du dir selbst mal richtig anschauen. Viel Erfolg noch.
Wie sieht denn die Verdrahtung des I²C-Busses aus? Ist es noch ein Bus? Zwei Slaves die selbe Adresse? Ist das richtig, dass der Master nicht die Hardware TWI benutzt? Gruß Jobst
So die Sache mit den Variablen funktioniert. Auch mehrere bytes empfangen funktioniert ebenfalls. Nun habe ich Probleme beim Senden. Der Code im Master: I2cstart I2cwbyte &H31 'sende Slave Adresse I2crbyte A , Ack 'lese Antwort I2cstop Printbin #1 , A Der Code vom Slave oben im Anhang. Zur Funktionsweise des Slaves: 1. Startkondition empfangen, Adress_mode, setzte i2c_mode = 0 2. Slave Adresse empfangen -> Master_read mode, setzte i2c_mode = 12 3. ACK an Master, setzte i2c_mode = 2, Byte zum senden ins Datenregister (USIDR = 52) legen. bis dahin funktionierts, nun kommt aber beim Master nichts an !? Kommt immer 0 an. Bin mir nicht sicher ob ich das mit dem INPUT und OUTPUT richtig mache
Ich weis einfach nicht wie ich das machen muss, die Daten werden einfach nicht zum Master übertragen. Beim Master kommt jetzt immer &HFF an. Der SDA Pin sollte doch einfach auf OUTPUT geschaltet werden und so sollten die Daten zum Master übertragen werden ?!?
Michael L. schrieb: > Ich weis einfach nicht wie ich das machen muss Vielleicht solltest Du einfach mal die Fragen beantworten, die Dir gestellt werden ...
> Wie sieht denn die Verdrahtung des I²C-Busses aus? Ist es noch ein Bus? SDA und SCL Leitung mit je einem 4.7k Pullup > Zwei Slaves die selbe Adresse? Unmöglich, da nur ein Slave dranhängt > Ist das richtig, dass der Master nicht die Hardware TWI benutzt? Nein, ist SW mit Bascom Mein Versuchsaufbau: Master: Attiny45, SW I2C mit Bascom Slave: Attiny85, HW I2C mit Bascom sonst hängt da nichts mehr am Bus Wie gesagt an der HW und am Master liegts nicht, es geht jetzt nur darum wie ich das USI vom Slave programmieren muss, damit er die Daten an den Master sendet.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.