Hallo, ich habe folgendes Problem, ich muss um einen Sensor ansprechen zu können ein Repeated Start ausführen. Aber das klappt leider net, deswegen hoffe ich, Ihr könnt mir helfen und sagen ob das mit meinem I2C Code überhaupt möglich ist. Ich verwende einen ATmega1281 und möchte einen VTI SCP1000 Sensor über I2C ansprechen. So versuche ich die I2C Funktionen zu nutzen: ... i2c_start(VTI,WRITE); i2c_send(0x02); // schreibe in ADDPTR i2c_send(0x29); // den Wert 29h i2c_start(VTI,WRITE); i2c_send(0x01); // schreibe in DATAWR i2c_send(0xAA); // den Wert AAh i2c_start(VTI,WRITE); i2c_send(0x03); // schreibe in OPERATION i2c_send(0x06); // den Wert 6h -> schreibe in EEPROM Zelle 29h Wert AAh i2c_stop(); wait(); // 50ms warten i2c_start(VTI,WRITE); i2c_send(0x03); // schreibe in OPERATION i2c_send(0x05); // den Wert 5h -> lese EEPROM Zelle 29h aus und speicher in DATARD8 i2c_stop(); wait(); // 50ms warten i2c_start(VTI,WRITE); i2c_send(0x7F); // Adresse von DATARD8 i2c_start(VTI,READ); buf[APS_ASDU_OFFSET] = i2c_read(); // gebe Wert von DATARD8 Register zurück i2c_stop(); ... Also ich möchte einfach zum testen erstmal AAh in den EEPROM des Sensors schreiben und dann wieder auslesen. Das Problem ist, beim debuggen sehe ich, wenn ich i2c_start ausführe ohne den Bus vorher zu stoppen, dann bleibt er immer in der while Warteschleife der Funktion hängen. Ich möchte nun wissen ob ein Repeated Start anders realisiert werden muss, also ob mein Code dafür überhaupt geeignet ist, weil ich komm auf keine alternative Lösung. Danke im voraus. Gruß Eugen
Doch doch, ich muss dazu sagen das ich den Code mit einem PCF8574P schon getestet habe, also Lesen/Schreiben. Um genauer zu sein, hab ne LED blinken lassen bzw. Pins des PCF bejumpert um definierte Werte einlesen zu können. Blos jetzt brauch ich explizit ein Repeated Start sonst liefert mir der Sensor keinen Wert, aber dazu komme ich garnet erst. Muss ich eigentlich nach jedem Senden/Lesen warten? Oder darf ich des einfach außenvor lassen?
Außerdem hab ich noch einpaar defines die ich vergessen habe zu erwähnen: #define VTI 17 #define READ 1 #define WRITE 0
Hallo, lange her, daß ich sowas gebraucht habe... Ablauf sieht ok aus, Repeat-Start sagt nur, daß nach dem i2c_write kein i2c_stop folgt sondern ein i2c_start. Sieht bei Dir also ok aus. Aaaaber: wieso sendet i2c_start irgendwelche Adresse??? i2c_start hat eine Startcondition zu setzen, dann wird geschrieben oder eben gelesen. Entweder Du bastelst Dir zum Lesen ein i2c_repeat_start, daß nur die Startkondition setzt oder nimmst i2c_start auseinander und sendest Adresse + Read/Write-Bit mit Deinem i2c_write Gruß aus Berlin Michael
Hallo, ich hab versucht die Repeated Start Funktion umzumoggeln aber klappt immer noch net: ... i2c_start(VTI,WRITE); i2c_send(0x7F); //Sende Start Condition TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //Adresse senden -> (17<<1) + 1 TWDR = 35; //Clear TWINT bit in TWCR to start transmission of address TWCR = (1 << TWINT) | (1 << TWEN); //Warte bis Übertragung beendet ist //while(!(TWCR & (1 << TWINT))); // i2c_start(VTI,READ); buf[APS_ASDU_OFFSET] = i2c_read(); i2c_stop(); ... Ich musste zusätzlich die while-Schleife in der i2c_read Funktion die zur Bestätigung einer erfolgreichen Übertragung dient, Auskommentieren weil beim debuggen blieb ich dort sonst stets hängen. Seit dem ich jetzt des so hab, bekomme ich von i2c_read Funktion den Wert 0x7F zurück. Was nicht das ist was ich erwarte, also einfach nur falsch ist. Jetzt weis ich nicht ob ich einfach auf die Schleifen verzichten und auskommentieren darf. Im Bild was ich angehängt habe sieht man wie man den Sensor ansprechen muss um einen Wert aus dem DATARD8 Register zu erhalten. Gruß Eugen
Die beiden Pullups (1,8...4,7k) hast Du dran? Du solltest Dich mal näher mit dem I2C-Protokoll beschäftigen. Wenn das Interrupt-Bit gesetzt ist, dann mußt Du immer auch den Status auswerten, ob er überhaupt dem erwarteten entspricht. Und setze ACK/NACK (Master Receiver) entsprechend und werte ACK/NACK (Master Transmitter) auch aus (nach jedem Byte!). Peter
Hallo, also der Stand der Dinge ist, das es im Debugmodus hin- und wieder geht. Aber ich möchte verstehen wieso es manchmal hängen bleibt. Also, ich habe den Code einbisschen umgeschrieben. Und zwar möchte ich das REVID 0x00 Register im Luftdruck Sensor auslesen. Dieses Register gibt die Version (Revision) des ASIC zurück und muss 0x03 lauten. Ich habe die I2C Funktionen alle in eine Unterfunktion gepackt. Diese Rufe ich hier auf:
1 | ...
|
2 | buf[APS_ASDU_OFFSET] = VTIReadRevid(); |
3 | //Sende Stop-Condition
|
4 | TWCR= (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); |
5 | uiStatus[7] = TWSR; |
6 | ...
|
Und hier ist die VTIReadRevid();
1 | uint8_t VTIReadRevid() |
2 | {
|
3 | uint8_t i = 0; |
4 | /***********************************************************
|
5 | Reset des VTI SCP1000 D11 Luftdrucksensors zur
|
6 | Initialisierung des Sensors
|
7 | ***********************************************************/
|
8 | //I2C initialisieren, TWBR = 12 -> SCL freq = 100kHz
|
9 | TWBR = 12; |
10 | //Sende Start Condition
|
11 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
12 | //Warte bis Übertragung beendet ist
|
13 | while(!(TWCR & (1 << TWINT))); |
14 | uiStatus[i++] = TWSR; |
15 | |
16 | //Adresse senden
|
17 | TWDR = 34; |
18 | //Clear TWINT bit in TWCR to start transmission of address
|
19 | TWCR = (1 << TWINT) | (1 << TWEN); |
20 | //Warte bis Übertragung beendet ist
|
21 | while(!(TWCR & (1 << TWINT))); |
22 | uiStatus[i++] = TWSR; |
23 | |
24 | //Schreibe Wert 0x01 in Register RSTR 0x06 um Reset auszuführen
|
25 | TWDR = 0x06; |
26 | //Daten senden
|
27 | //Clear TWINT bit in TWCR to start transmission of data
|
28 | TWCR = (1 << TWINT) | (1 << TWEN); |
29 | //Warte bis Übertragung beendet ist
|
30 | while(!(TWCR & (1 << TWINT))); |
31 | uiStatus[i++] = TWSR; |
32 | |
33 | TWDR = 0x01; |
34 | //Daten senden
|
35 | //Clear TWINT bit in TWCR to start transmission of data
|
36 | TWCR = (1 << TWINT) | (1 << TWEN); |
37 | //Warte bis Übertragung beendet ist
|
38 | while(!(TWCR & (1 << TWINT))); |
39 | uiStatus[i++] = TWSR; |
40 | |
41 | //Sende Stop-Condition
|
42 | TWCR= (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); |
43 | |
44 | /***********************************************************
|
45 | 6 * 50ms = 300ms Verzögerung, da der Resetvorgang
|
46 | Minimum 150ms erfordert
|
47 | ***********************************************************/
|
48 | wait(); |
49 | wait(); |
50 | wait(); |
51 | wait(); |
52 | wait(); |
53 | wait(); |
54 | |
55 | /***********************************************************
|
56 | Starten des I2C Busses (SCL = 100kHz) mit der
|
57 | Adresse 34 -> I2C Read; Senden des Adressbyte und der
|
58 | Registeradresse 0x00 von der anschliessend gelesen werden soll
|
59 | ***********************************************************/
|
60 | //I2C initialisieren, TWBR = 12 -> SCL freq = 100kHz
|
61 | TWBR = 12; |
62 | //Sende Start Condition
|
63 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
64 | //Warte bis Übertragung beendet ist
|
65 | while(!(TWCR & (1 << TWINT))); |
66 | uiStatus[i++] = TWSR; |
67 | |
68 | //Adresse senden
|
69 | TWDR = 34; |
70 | //Clear TWINT bit in TWCR to start transmission of address
|
71 | TWCR = (1 << TWINT) | (1 << TWEN); |
72 | //Warte bis Übertragung beendet ist
|
73 | while(!(TWCR & (1 << TWINT))); |
74 | uiStatus[i++] = TWSR; |
75 | |
76 | TWDR = 0x00; |
77 | //Daten senden
|
78 | //Clear TWINT bit in TWCR to start transmission of data
|
79 | TWCR = (1 << TWINT) | (1 << TWEN); |
80 | //Warte bis Übertragung beendet ist
|
81 | while(!(TWCR & (1 << TWINT))); |
82 | uiStatus[i++] = TWSR; |
83 | |
84 | /***********************************************************
|
85 | Restart des I2C Busses (SCL = 100kHz) mit der Adresse 35
|
86 | -> I2C Write; Senden des Adressbyte und lesen von Revidregister
|
87 | -> 0x03 müssten als Wert in TWDR zurückgegeben werden
|
88 | ***********************************************************/
|
89 | //I2C initialisieren, TWBR = 12 -> SCL freq = 100kHz
|
90 | TWBR = 12; |
91 | //Sende Start Condition
|
92 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
93 | //Warte bis Übertragung beendet ist
|
94 | while(!(TWCR & (1 << TWINT))); |
95 | uiStatus[i++] = TWSR; |
96 | |
97 | //Adresse senden
|
98 | TWDR = 35; |
99 | //Clear TWINT bit in TWCR to start transmission of address
|
100 | TWCR = (1 << TWINT) | (1 << TWEN); |
101 | //Warte bis Übertragung beendet ist
|
102 | while(!(TWCR & (1 << TWINT))); |
103 | uiStatus[i++] = TWSR; |
104 | |
105 | //send content of TWDR; TWEA = enable ACK
|
106 | TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); |
107 | while(!(TWCR & (1<<TWINT))); |
108 | uiStatus[i++] = TWSR; |
109 | |
110 | return TWDR; |
111 | }
|
Da man mir empfohlen hat das TWSR Register stets auszuwerten, habe ich das gemacht und habe da ein Problem bzw. Frage. Folgende Werte aus dem TWSR Register erhalte ich:
1 | uiStatus[0] = 0x08 //-> Start condition has been transmitted |
2 | uiStatus[1] = 0x20 //-> SLA+W has been transmitted, NOT ACK has been received |
3 | uiStatus[2] = 0x30 //-> Data byte has been transmitted, NOT ACK has been received |
4 | uiStatus[3] = 0x30 |
5 | uiStatus[4] = 0x08 |
6 | uiStatus[5] = 0x20 |
7 | uiStatus[6] = 0x30 |
8 | uiStatus[7] = 0x10 //-> repeated Start condition has been transmitted |
9 | uiStatus[8] = 0x48 //-> SLA+R has been transmitted, NOT ACK has been received |
Nun meine Frage, ich benötige nach dem senden der bytes stets ein ACK. Kann ich das überhaupt beeinflussen, also durch anpassen meiner Funktionen? Und meistens bleibt der Bus bei den while-Schleifen direkt nach dem Repeated Start oder bevor ich das TWDR lesen will hängen, woran kann das liegen? @Peter Dannegger: Ich habe 2,2k Pull-Ups an SCL und SDA hängen. Gruß Eugen
Hallo, Der Unterschied zwischen zwei TWI-Übertragungen, die jeweils mit einem TWI-Start begonnen werden und zwei Übertragungen, bei der die 2. mit einem TWI_Restart begonnen wird, besteht darin, dass die 1. (!) Übertragung im letzteren Fall NICHT mit einem STOP beendet wird. Dadurch gibt der Master den Bus nicht frei und das folgende START wird als TWI-Restart in TWSR signalisiert. Noch mal mit anderen Worten: Fall 1: zwei unabhängige Übertragungen, ein anderer Master (im Multi-Master-Betrieb) kann hier nach dem STOP die Regierung über den Bus übernehmen. TWI_START ... TWI_STOP ... TWI_START ... TWI_STOP Fall 2: auch zwei unabhängige Übertragungen, aber wegen des fehlenden STOPs wird der Bus zwischendrin nicht freigegeben. TWI_START ... TWI_START ... TWI_STOP Der Unterschied liegt lediglich im fehlenden STOP. Meine Umsetzung: ein Flag einbauen, so dass (im Normalfall) ein STOP gesendet wird, für ein TWI_Restart dagegen nicht. Laut logic-analyser funktioniert das bei mir - den ernsthaften Multi-Master-Betrieb hab ich noch nicht ganz fertiggestellt und somit nicht getestet. Michael S.
Hallo, danke für die ausführliche Antwort aber bei mir ist ja nicht vom Multi Master betrieb die rede. Ich will einen eigentlich "stupiden" Luftdrucksensor über I2C auslesen. Was mich halt wundert ist, laut TWSR register erfolgt der Repeated Start aber dann hab ich Probleme mit dem Übertragungsbestätigungsschleifen. Außerdem verstehe ich nicht wieso ich immer eine NACK zurück bekomme, mit dem PCF8574 Baustein, mit dem ich die I2C Funktion schon erfolgreich getestet habe, bekomme ich stets ein ACK und das erwarte ich hier eigentlich auch. Es würde mich echt freuen falls jemand ähnliche Erfahrung hatte und einen Tipp geben könnte woran des liegen mag. Gruß Eugen
Wenn Du ein NACK empfängst, sendest Du entweder an ne Adresse, auf die kein Slave anspricht oder der Slave ist intern beschäftigt (z.B. EEPROM schreiben). Das einzig Sinnvolle ist, danach ein Stop zu senden. Denn weitere Daten an niemanden zu senden, ist relativ witzlos. Ob ein Slave nach bestimmten Aktionen ne Weile beschäftigt ist, mußt Du dem Datenblatt entnehmen. Peter
Achso, ok das kann gut sein. Es könnte auch sein das ich vllt ne falsche Adresse anspreche, würde dann auch an NACK kommen? Ich schau mir das Datenblatt des Sensor genau an bezüglich nötiger delays und sag dann Bescheid. Danke für den Hinweis schonmal. Ich hatte das halt so verstanden, Daten wurden übertragen und Slave fordert durch das NACK kein weiteres Byte an. Gruß Eugen
Hallo, wenn ich mir diesen traurigen Monolog ansehen, dann stelle ich fest: Der Slave hat nie geantwortet. Ich würde erst einmal eine grundlegende Verbindung herzustellen versuchen. > uiStatus[0] = 0x08 //-> Start condition has been transmitted > uiStatus[1] = 0x20 //-> SLA+W has been transmitted, NOT ACK has been received bevor in der Zeile darüber kein ACK steht, ist alle weitere Liebesmüh vegebens. > uiStatus[2] = 0x30 //-> Data byte has been transmitted, NOT ACK has been received siehe oben > uiStatus[3] = 0x30 > uiStatus[4] = 0x08 > uiStatus[5] = 0x20 > uiStatus[6] = 0x30 > uiStatus[7] = 0x10 //-> repeated Start condition has been transmitted > uiStatus[8] = 0x48 //-> SLA+R has been transmitted, NOT ACK has been received siehe oben Michael S.
Ok, ich vermute das meine Beschaltung des Sensors fehlerhaft ist. Ich werd mal heut Abend die Beschaltung zeichnen und die hier mal reinstellen. Ich hab das mit dem NACK immer falsch intepretiert. Jetzt ist es klar das ich ein NACK bekomme. Der Sensor zieht die SDA Leitung garnicht runter, somit liest der Master stets den High Wert den ich über nen 2,2kOhm PullUp bekomme. Aber danke das Ihr mich net aufgebt :). Gruß Eugen
Hallo, nun hab ich hier den Schaltplan mit drangehangen. Ich habe zugleich eine elementare Frage, darf man Analog Ground und Digital Ground eigentlich zu einem Ground verknüpfen, so wie ich das mache? Was sind die unterschiede zwischen Analog Ground und Digital Ground? Genauso bei AVDD und DVDD, darf man die verknüpfen? Was sind die Folgen wenn man es verknüpft? Und wozu ist ein Analog Supply Voltage und Digital Supply Voltage notwendig, also die Unterschiede zwischen den beiden? Ich stelle mir das so vor das Digital Supply Voltage eine stabile Spannungsversorgung ist. Gruß Eugen
Ach ja, weil ich eine Spannungsversorgung von 3,6 Volt habe, der Sensor jedoch mit maximal 3,3 V betrieben werden darf, habe ich den Spannungsteiler reingemacht. Features SCP1000-D01 SCP1000-D11 Supply voltage 2.4 V – 3.3 V 2.4 V – 3.3 V Measuring range 30 kPa – 120kPa 30 kPa – 120kPa Resolution 1.5 Pa 1.5 Pa Interface SPI max 500 kHz TWI max 400 kHz Temperature output Yes Yes Clock Internal Internal
Es ist genau umgekehrt ;) Die digitale Spannungsversorgung ist durch das schnelle schalten der digitalen Bausteine etwas verrauscht. Das würde Messungenauigkeiten in einem analogen Sensor produzieren. Desshalb wäre es am bessten dem AVDD nen eigenen Spannungsregler zu spendieren. AGND so weit wie möglich getrennt zu halten von GND und nur in einem Punkt möglichst nah an der Quelle verbinden.
Zwei Dinge: Du willst vermutlich die Grundschaltung rechts unten nutzen. Abgesehen von möglichen Störeinflüssen auf den Analogteil ist das vermutlich ok. Allerdings ist in deinem Plan DVDDS nicht beschaltet - da sollten wenigstens 100n ran. Und: hast du mal AVDD oder DVDD gemessen? Wenn die Werte an deinem Spannungsteiler wirklich stimmen, dann kommt da nur noch Müll an, besonders, wenn die I2C-Leizungen bedient werden und damit Strom durch die 2k2-Pullupwiderstände fließt... Ahoi, Martin
Ich nutz den Sensor auf einer Miniplatine, außerdem hängt ein 100nF an DVDDS, ein 470nF an AVDD und 470nF an DVDD, diese Miniplatine will ich "einfach" auf einen angepassten Sockel setzen und nutzen. Da es die integrierten Kondensatoren gibt schätze ich, sind meine zusätzlichen 100nF Kondensatoren überflüssig. Außerdem denke ich, werde ich TRIG, CLK und PD an GND anschliessen. Da die pins net gebraucht werden.
Eugen Kannsnet wrote: > Ach ja, weil ich eine Spannungsversorgung von 3,6 Volt habe, der Sensor > jedoch mit maximal 3,3 V betrieben werden darf, habe ich den > Spannungsteiler reingemacht. Und warum gibst Du ihm dann nur 0,9V? Die Schaltung kann überhaupt nicht gehen, der Pullup an SCL fehlt. Außerdem 2,2k hinter 120k, da bleiben nur noch 0,02V übrig. Peter
Wieso 0,9V? Ich hab das so gerechnet: Iss = 25µA Uges = 3,6V Ich will das am IC 2,7V ankommen. U1 = (Uges * R1)/(R1 + R2) = (3,6V * 120kOhm)/(39kOhm + 120kOhm)= 2,71V U2 = (Uges * R2)/(R1 + R2) = (3,6V * 39kOhm)/(39kOhm + 120kOhm) = 0,88V Der 2,2kOhm PullUp ist ja nur zu da um einen definierten Wert zu liefern zu beginn. Hab des auch gemessen, es kommen an den Pins 2,7V an. Deshalb schätze ich das des passen sollte aber ich bin immer für Überraschungen zu haben.
Aha, dann hast du schonmal die Werte im Schaltbild vertauscht. Ich kann aus deinem Schaltbild auch nicht erkennen, daß du ein fertiges Modul mit Außenbeschaltung einsetzt... (Ich spare mir jetzt denn Glaskugel... salmon). Und nochmal: Wenn SDA auf low geht, fließen über den Pullup-Widerstand ca. 1mA aus 2.7V - wenn dein Spannungsteiler das denn hergeben würde... Da hilft dann auch kein 100nF-Pufferkondensator, der kann zwar für 0.7*C*R = 0.7*100*1E-9*2.2*1E3 = 154µs Energie liefern, immerhin 15 Bitzeiten bei 100kHz, dabei sinkt die Spannung aber auf 1.3V ab. Ob der Sensor damit noch geht? Und zum Wiederaufladen braucht er dann vielleicht 3*C*R = 3*100*1E-9*30*1E3 = 9ms, wegen des hohen Innewiderstands deines Spannungteilers. Solange geht dann also nix mehr. Bei Fehlen dieser Pause bricht die Betriebsspannung schließlich auf 3.6V*(2k2)/(2k2+39k) = 0.2V zusammen. Größere Pufferkondensatoren verlängern die möglich Betriebszeit, in gleichem Maße aber auch die Erholzeit... Nicht berücksichtigt ist dabei, daß die Stromaufnahme des Sensor wohl schwanken wird, abhängig laufenden Messungen und Abfragen. Ahoi, Martin
Falls du das mal ohne Oszi kontrollieren willst: Benutze eine Schleife, um den Sensor dauernd mit Abfragen zu bepflastern, und miß dann mal die Spannung an VDD... Ahoi, Martin
Nimm statt R1 ne 1N4148 und bau den fehlenden Pullup ein, dann sollte es klappen. Der AVR sollte auch an 3,6V laufen, 5V könnte Probleme machen (High-Pegel). Peter
Ich glaube ich habe scheisse gerechnet :), ich hab die ganze zeit mit einem unbelasteten Spannungsteiler gerechnet. Deshalb diese Probleme, ich vermute das Peter die ganze Zeit recht hat. Aber ich hab es net auf anhieb geschnallt. Nun werd ich erstmal die Widerstände tauschen in R1 = 10kOhm und R2 = 39kOhm. Der Widerstand vom Sensor lässt sich doch so bestimmen, das man die gewünschten 2,7V nimmt und durch den typischen Stromverbrauch nimmt. In meinem Fall wären das 2,7V / 25µA = 109kOhm. Kann das in etwa so klappen? Ich hoffe langsam das ich euch net zuviele graue Haare verursache. Gruß Eugen
Also ich hab das jetzt anders gemacht, Spannungsteiler ganz außenvor gelassen und eine Schottky Diode 1N5819 reingemacht damit ein Spannungsabfall von etwa 0,3V erfolgt. Damit sollte ich mit 3,2V bis 3,3V in einem für den Sensor guten Spannungsbereich sein. Aber ich habe dennoch keine Verbindung über I2C, ich bekomme stets ein NACK. Somit kann keine erfolgreiche Verbindung hergestellt werden. Sobald ich i2c_read(); nutzen will hängt sich die Funktion ganz auf bei der while Warteschleife, weil das TWINT nicht gesetzt wird. Nun möchte ich wissen, hat jemand noch eine Idee woran es liegen könnte? Also Leitungslänge ist maximal 15cm. Ich habe SCL schon auf Minimum und Maximum eingestellt, ist beide male egal. Kann es vllt sein das die Signale nicht sauber sind. Das wurde mir vom VTI Support nahe gelegt nachzuprüfen. Das interessante ist, ich habe auch versucht den SPI Sensor zum laufen zu bekommen, da hängt sich zwar nix auf aber ich bekomme immer 0x00. MfG Eugen
Im Anhang ist der I2C Schaltplan. Wäre super wenn mal jemand drüber gucken könnte. Gruß Eugen
Benutzt du die richtige Adresse 0x22 ? Versuche doch nach dem Start erst die EEPROM Bestätigung auszulesen. In Register 0x7F muss 1 stehen. Das Ding läuft bei mir mit 1MHz I2C Takt.
Ich hab schon versucht den DATARD8 EEPROM Check 0x1F bzw. 0x7F auszulesen, aber bekomme bei SPI = 0 und bei I2C nix weil sich das Teil beim lesen aufhängt. @ Henry: Kannst du mir vllt deine Beschaltung des SCP1000 D11 zuschicken? Der Sensor kann doch laut Datenblatt "nur" 400kHz beim I2C. Gruß Eugen
Hier die Beschaltung. Ich benutze eine ZNEO Controller und kann deshalb kaum helfen.
Erstmal danke für die schnelle Hilfe. Also ich sehe keinen großen Unterschied zu meiner Beschaltung. Wozu braucht man die Spule L1? Benutzt du nur den Sensor oder den Sensor mit der Miniplatine? Weil auf der Miniplatine (SCP1000 PCB1) sind ja meiner Meinung nach schon die nötigen Kondensatoren drauf oder? Gruß Eugen
Bei einem 17Bit ADC kann die Versorgungsspannung garnicht gut genug sein. Ist einfach zur Sicherheit weil ich gleich ins reine gebaut habe. Der Sensor ist handgelötet. Beide Seiten des Gehäuses mit Schrägschneider abgeknipst. Etwas nachgefeilt und aufgelötet. Ist aber sehr grenzwertig und schon das Positionieren hat mich 15 Minuten gekostet.
Ja ok, das heißt du hast die Spule reingemacht um Spannungsspitzen zu dämpfen, oder? Und denkst du das ich zusätzliche Kondensatoren reinmachen sollte oder nicht? Meiner Meinung nach sollte das mit dem integrierten Kondensatoren ja auch funktionieren. Übrigens, heiße kleine Dose die du da gebastelt hast. Gruß Eugen
Die Drossel soll hochfrequenten Störungen, hauptsächlich vom Controller, abblocken. So wie man in die Analogspannungszuleitung zum Controller immer eine Drossel rein macht damit der ADC im Controller sauber arbeiten kann. Ob das wirklich was bringt weiß ich nicht. Es schadet und kostet aber nichts. Etwas ist mir noch eingefallen. Der SCP1000 brauch nach anlegen der Betriebsspannung sehr lange bis er bereit ist. Im Datenblatt steht 90ms. Das hat bei mir nicht gereicht und ich habe jetzt ein 300ms Delay im Programm bevor die erste Kommunikation auf dem I2C Bus stattfindet. Auch mit anderen Chips am I2C darf man vorher nicht kommunizieren.
Ja ok, ich hab jetzt eine 68µH Drossel reingemacht zwischen AVDD und DVDD reingemacht. Oder ist die eventuell schon zu groß? Benutzt du eigentlich den PD pin oder hast du Ihn auf GND gezogen? Wenn du Ihn benutzt, machst du das in der Software oder durch Beschaltung? Gruß Eugen
Hab im Schaltplan übersehen das der PD pin auf GND gezogen ist. Sry, ich hätte erst gucken dann schreiben sollen.
Wenn die Drossel größer ist kann das nicht schaden. Die Druck Messwerte filtere ich noch etwas. Die jeweils letzten 4 Messwerte werden gespeichert und daraus dann ein Mittelwert errechnet. P = 1/6*P3 + 1/6*P2 + 2/6*P1 + 2/6*P0 Auf diese Weise steht der Wert so perfekt, dass bei der Anzeige von 1000.00 hPa nur die kleinste Stelle langsam um 1 hoch/runter schwankt.
Ja das wollte ich auch so machen, aber ich komm ja noch nicht soweit das ich ne Antwort von dem Sensor bekomm. Ich werd mich nächste Woche höchstmotiviert ransetzen. Danke schonmal Henry. Gruß Eugen
Also auf dem Oszi scheints zu klappen. Ich hab zum testen erstmal was in den VTI EEPROM geschrieben und wieder ausgelesen und des scheint zu funktionieren, zumindestens auf dem Oszi. Genauer gesagt hab ich die Beispiele in 3.4.1 und 3.4.2 des "VTI SCP1000 PFS" Dokumentation einfach umgesetzt. Ich werd euch auf dem laufendem halten. Gruß Eugen
Hallo, ich hoffe das du das hier siehst Henry. Tust du überhaupt die 4 internen Sensor Speicherbänke nutzen? Weil ich hab nun folgendes Problem. Wie schon gesagt, klappt das auslesen aber leider nur bedingt. Bedingt, weil ich nur die Temperaturwerte kontinuierlich messen kann. Beim messen der Luftdruckwerte bleibt es nach der ersten Messung jeweils hängen. Da hab ich mir gedacht ich könnte vllt die Speicherbänke nutzen um indirekt die Luftdruckwerte in diese Speicherbänke zu kopieren, und von dort aus auszulesen. Oder gibt es zwischen der Temperaturmessung und der Luftdruckmessung unterschiede die man beim auslesen beachten muss? Gruß Eugen
Speicherbänke nutze ich nicht. Die Druckmessung dauert lange. Man muss also abfragen ob die Messung fertig ist. Hier mein Code.
1 | BOOL I2cGetPressureTemperature(volatile float* pfPressure, volatile float* pfTemperature) |
2 | {
|
3 | uint8_t ucStatus; |
4 | int16_t sTemperature; |
5 | float fPressureNew; |
6 | static float fPressure[3]; |
7 | |
8 | union
|
9 | {
|
10 | struct
|
11 | {
|
12 | uint8_t m_uc, m_ucMSB; |
13 | uint16_t m_usLSB; |
14 | }
|
15 | m_HL; |
16 | |
17 | uint32_t m_uValue; |
18 | }
|
19 | Pressure; |
20 | |
21 | Pressure.m_HL.m_uc = 0; |
22 | |
23 | if (!I2cRead(I2C_ADDR_PRESS, STATUS, &ucStatus, sizeof(ucStatus)) || |
24 | !(ucStatus & 0x20)) // Data ready? |
25 | return FALSE; |
26 | |
27 | if (!I2cRead(I2C_ADDR_PRESS, TEMPOUT, &sTemperature, sizeof(sTemperature)) || |
28 | !I2cRead(I2C_ADDR_PRESS, DATARD8, &Pressure.m_HL.m_ucMSB, sizeof(Pressure.m_HL.m_ucMSB)) || |
29 | !I2cRead(I2C_ADDR_PRESS, DATARD16, &Pressure.m_HL.m_usLSB, sizeof(Pressure.m_HL.m_usLSB)) || |
30 | (ucStatus & 0x10)) // Real time error |
31 | return FALSE; |
32 | |
33 | *pfTemperature = 0.05 * ((sTemperature << 2) >> 2); // [Celsius] (fill bit 14 and 15 with sign) |
34 | |
35 | fPressureNew = 0.25 * Pressure.m_uValue; // [Pascal]; |
36 | |
37 | if (fPressure[0] == 0.0) |
38 | fPressure[0] = fPressure[1] = fPressure[2] = fPressureNew; |
39 | |
40 | *pfPressure = (1.0 / 6.0) * (fPressure[2] + fPressure[1] + 2.0 * (fPressure[0] + fPressureNew)); |
41 | |
42 | fPressure[2] = fPressure[1]; |
43 | fPressure[1] = fPressure[0]; |
44 | fPressure[0] = fPressureNew; |
45 | |
46 | return TRUE; |
47 | }
|
Noch ein Nachtrag. Die union Pressure ist vielleicht verwirrend. Ich benutze einen Controller mit Motorola Format. Das high Byte ist dabei auf der niedrigsten Adresse.
Dank dir für die rasante Antwort, ich werd jetzt auch den DRDY Status auslesen bevor ich das auslesen starte. Gruß Eugen
Hallo, ucStatus liest du doch sicherlich auch über I2C aus? Also ich hab das jetzt so, das wenn DRDY-Bit gesetzt ist, ich das Lesen starte. Klappt auch soweit aber halt nur einmal. Dann hängt es sich beim auslesen des Status Registers auf, mein Watchdog springt ein und ich beginn wieder von vorne. Henry kannst du mir vllt deine Email Adresse zuschicken, das ich mit dir direkt kommunizieren kann? Also kurz gesagt: START | Resart Sensor | 60ms delay | setze Messmodus (High Resolution) | 600ms delay <----------------| | | lese Status <-----| | < hier hängt sich | | | dann der I2C Bus auf Status == 0x20 ---| Nein | aber nur wenn ich | | den Luftdruckwert | Ja | ausgelesen habe | | lese TEMPOUT | nur TEMPOUT lesen | | funktioniert problemlos lese DATARD8 | | | lese DATARD16 | | | Berechnung | fTemperature & fPressure | | | |---------------------------| Erneutes lesen Ist der Ablauf im Prinzip so richtig? Gruß Eugen
@Eugen: so wie deine Bildanhänge aussehen und ich Einträge von dir schon einem anderen Thread gelesen habe nutzt du die Meshbean-boards von Meshnetics? Is das richtig? Hast du zufällig mal die I²C-Funktionen des Stacks verwendet? Ich habe auch einen Beschleunigungssensor an das Meshnetics-Modul angeschlossen und möchte Werte auslesen,jedoch komm ich mit den I²C-Funktionen des Stacks nicht so klar. MfG,Sven
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.