Forum: Mikrocontroller und Digitale Elektronik I2C Repeated Start klappt nicht


von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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?

von Eugen K. (kannsnet)


Lesenswert?

Außerdem hab ich noch einpaar defines die ich vergessen habe zu 
erwähnen:
#define VTI   17
#define READ  1
#define WRITE 0

von Michael U. (amiga)


Lesenswert?

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

von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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

von Michael S. (Gast)


Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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

von Michael S. (Gast)


Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

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

von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

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

von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

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

von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

noch ein weiterer Anhang

von Klaus (Gast)


Lesenswert?

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.

von Martin Schneider (Gast)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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.

von Martin Schneider (Gast)


Lesenswert?

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

von Martin Schneider (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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

von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

Im Anhang ist der I2C Schaltplan. Wäre super wenn mal jemand drüber 
gucken könnte.
Gruß Eugen

von Henry (Gast)


Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

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

von Henry (Gast)


Angehängte Dateien:

Lesenswert?

Hier die Beschaltung.

Ich benutze eine ZNEO Controller und kann deshalb kaum helfen.

von Eugen K. (kannsnet)


Angehängte Dateien:

Lesenswert?

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

von Henry (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

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

von Henry (Gast)


Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

Hab im Schaltplan übersehen das der PD pin auf GND gezogen ist. Sry, ich 
hätte erst gucken dann schreiben sollen.

von Henry (Gast)


Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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

von Eugen K. (kannsnet)


Lesenswert?

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

von Henry (Gast)


Lesenswert?

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
}

von Henry (Gast)


Lesenswert?

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.

von Eugen K. (kannsnet)


Lesenswert?

Dank dir für die rasante Antwort, ich werd jetzt auch den DRDY Status 
auslesen bevor ich das auslesen starte.

Gruß Eugen

von Eugen K. (kannsnet)


Lesenswert?

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

von Sven (Gast)


Lesenswert?

@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
Noch kein Account? Hier anmelden.