Hallo,
ich habe einen Sensor mit dem I2C Bus, den ich abfragen möchte.
Hier ist mein Beispielprogramm:
1
$regfile = "M8def.dat"
2
$crystal = 16000000
3
$hwstack = 32
4
$swstack = 10 '
5
$framesize = 40
6
$baud = 9600
7
8
9
Dim Lesen1 As Byte
10
11
12
'SDA und SCL definieren
13
Config Sda = Portc.4
14
Config Scl = Portc.5
15
16
I2cinit
17
18
19
I2cstart
20
I2cwbyte &H54h
21
I2cwbyte &HB6
22
I2crbyte Lesen1 , Nack
23
I2cstop
24
25
Print Err
26
27
28
Print "gelesen: "
29
Print Lesen1
30
31
32
End
Die Ausgabe sieht immer so aus:
----------------
1
gelesen:
255
----------------
Datenblatt des Sensors:
www.captured-dreams.de/temp/TSEV01C_Application_Note_0_6.pdf
Hat jemand eine Idee, was ich falsch mache? Ich vermute bei der
Adressierung ist etwas falsch.
Danke!
guten abend gemeinde.
ich habe eine frage bezüglich dem beschreiben von registern.
über meinen mikrocontroller möchte ich werte aus meinem sensor über I2c
auslesen.
das ganze ist ein beschleunigungssensor von bosch (SMB380) und der
controller ist der Atmega1281.lese ich nicht veränderbare register
aus,passt das alles.ich nutze die I2c-ansteuerung von Peter Fleury.
mein problem ist,dass mir ziemlich schwankende beschleunigungswerte
ausgibt,obwohl dieser eigentlich fest montiert ist.die werte schwanken
so in einer spanne von ca. 30dezimal.
meine vermutung ist,dass ich aus versehen bei der einstellung des
registers für den messbereich (register 0x14) etwas falsch gemacht
habe.in diesem register sind die obersten 3 bit (bit 7:5) für wichtige
kalibrierungen nötig und dürfen nicht beschrieben werden.
leider habe ich dies wahrscheinlich mit meinem quellcode
i2c_init(); // Bus initialisieren
i2c_write(0x14); // Register auswählen
i2c_write(0x06); // Daten reinschreiben
i2c_stop(); // Busverbindung beenden
getan.
im user manual steht:
"Bits 4,6 and 7 of register address 0x14 do contain critical sensor
individual calibration data which must not be changed or deleted by any
means.
In order to properly modify address 0x14 for range and(or bandwidth
selection using bits 0,1,2,3 and 4, it is highly recommended to read-out
the complete byte,perform bit-slicing and write back the complete byte
unchanged bits 5,6 and7.Otherwise the reported acceleration data may
show incorrect results."
meine frage ist nun ganz einfach:
wie stelle ich das an was in dem 2.absatz des auszuges aus dem user
manual steht????also nur einzelne bits ändern und die bits 5,6 und 7
nicht "anfassen"!
im forum bei der sensorkommunikation über spi standen so befehle wie:
bit_setzen(data,(1<<5)); -> ist das bei i2c ähnlich?
bin über jede hilfe dankbar!!!
reg = ausgelesenes Einstellungsregister
reg2write = reg & 0b11100000;
reg2write = reg | 0b000XXXXX;
mit XXXXX die gewünschten Einstellungen
gibt wahrscheinlich auch noch bessere Möglichkeiten...
danke erstmal für die antwort.
ich habe mir das so gedacht:
uint8_t aendern;
{
startI2c(0x70); writeI2c(0x14);
rep_startI2c(0x71);
aendern = readAckI2c();
aendern &=~((1<<4)|(1<<2)|(1<<1)); // meine vorzunehmenden Einstellungen
writeI2c(aendern);
stopI2c();
}
mir stellt sich jetzt nur die Frage ob ich nach dem Auslesen des
Registers und Ändern gleich einen write-Befehl anschließen kann,oder
erst noch stop-Befehl und dann nochmal von vorn: start usw.??
the complete byte,perform bit-slicing and write back the complete byte
Damit dürftest du mit deiner Aktion
1
i2c_init();// Bus initialisieren
2
i2c_write(0x14);// Register auswählen
3
i2c_write(0x06);// Daten reinschreiben
4
i2c_stop();// Busverbindung beenden
Genau das gemacht haben was niemals hätte passieren dürfen:
du hast auf die oberen bits einfach Nullen geschrieben.
Besser wäre es entsprechend dem Datenblatt, erst das Register zu lesen,
diesen Wert zu ändern, und dann wieder zurückzuschreiben.
1
uint8_tr14:
2
3
i2c_init();// Bus initialisieren
4
i2c_write(0x14);// Register auswählen
5
r14=i2c_read();// Daten auslesen -- wie auch immer diese funktion
6
i2c_stop();// Busverbindung beenden
7
8
r14&=0xE0;// obere Bits behalten
9
r14|=0x06;// Daten dazu
10
11
i2c_init();// Bus initialisieren
12
i2c_write(0x14);// Register auswählen
13
i2c_write(r14);// Daten reinschreiben
14
i2c_stop();// Busverbindung beenden
Allerdings sind die schwankenden Werte doch eigenartig...
Lies doch mal das Versionsregister 0x01 (al_version und ml_version) aus.
Bekommst du dort richtige und stabile Werte?
BTW:
>... habe.in ...>... ist,dass ...
Mach doch bitte nach Satzzeichen ein Leerzeichen, das erhöht die
Lesbarkeit (mal abgesehen von der Groß- u. Kleinschreibung) ungemein.
EDIT:
> nach dem Auslesen des Registers und Ändern gleich> einen write-Befehl anschließen kann
Probiers mal mit einem Repeated-Sart...
Ist dein i2c_init() das selbe wie ein i2c_start()?
ingo wrote:
> danke erstmal für die antwort.> aendern &=~((1<<4)|(1<<2)|(1<<1)); // meine vorzunehmenden Einstellungen
uns was ist mit den Bits 0 und 3? oder weisst du, dass die vorher
richtig waren?
@Lothar Miller:
Vielen Dank für die ausführliche Antwort! :)
>Ist dein i2c_init() das selbe wie ein i2c_start()?
Nein, in meiner init wird nur das Register TWBR auf den entsprechenden
Wert gesetzt, sonst nichts weiter. Die i2c_start() ist halt die aus der
lib von Peter Fleury.
>Lies doch mal das Versionsregister 0x01 (al_version und ml_version) aus.>Bekommst du dort richtige und stabile Werte?
Ja hab ich gemacht und nicht nur diese Register. Außer den
Achsenregistern sind meine Werte 100% zuverlässig/genau.
Das liegt aber sicher auch daran, dass die nichts mit
Einstellungsregistern zu tun haben.
Ich denke mit dem Code den du mir gepostet hast werde ich es versuchen.
Das repeated_start lasse ich erstmal weg.
Justus Skorps wrote:
>uns was ist mit den Bits 0 und 3? oder weisst du, dass die vorher>richtig waren?
Naja, dass Register hat einen default-Wert. Da steht das die Bist 0 und
3 beide "0" sind. Ändern will ich die ja nicht.
Also langsam verzeifle ich. :(
Hab nun auf ein 2.Modul einen neuen SMB380 draufgelötet und das Programm
draufgeflasht wie Lothar Miller das vorgeschlagen hat (so hatte ich mir
das auch überlegt).
Trotzdem driften die dezimalen Werte auseinander,was eigentlich nicht
sein sollte.
Hab echt keine Ahnung mehr woran das liegen kann. Zum Test hab ich
nochmal voreingestellte Register ausgelesen, d.h. Register 0x12 und 0x13
und die Werte die erwartet werden (162 und 13) kommen immer nach dem
Sensorauslesen raus.
Die Achsendaten werden vom Sensor periodisch mit 3KHz erneuert. Aber
durch das Bit "shadow_dis" wird verhindert, dass MSB und LSB von
unteschiedlichen Samples kommen können.
Ich weiss nicht so recht,ob es evtl an den "new_data *flags" liegen
kann,aber eigentlich signalisieren diese nur,ob die Achsendaten
ausgelesen wurden.
"...new data*flags... can be used to detect if acceleration values have
already been read out."
Hallo!
Wenn ich folgenden Ablauf auf dem I2c-Bus habe, müsste ich doch im
I/O-Fenster des AVR-Studio im TWSR-Register am Ende auch die Statuse
0x50 bzw. 0x58 sehen oder?
initI2c();
startI2c(0x70);
writeI2c(0x02);
rep_startI2c(0x71);
inclination = readAckI2c();
inclination1 = readNakI2c();
stopI2c();
Nach dem Status 0x40 steht nach dem Einlesen der Werte 0xF8!
Ich habe die Library von Peter Fleury.
ist das normal,dass nach einem STOP-Befehl das Statusregister irgendwann
0xF8 anzeigt bevor eine neuerliche START-Bedingung gesendet wird?
Ich versuche hier mit der lib von Peter Fleury ein EEPROM-Register eines
Sensors zu beschreiben. Um überhaupt Zugriff auf das Register zu
bekommen, muss ich vorher noch in einem anderen Register ein Bit auf "1"
setzen um überhaupt Zugriff auf dem EEPROM zu haben.
initI2c();
startI2c(0x70);
writeI2c(0x0A); // Registeradresse wo Bit4 auf 1 soll
writeI2c(0x10); // beschreibe Bit4 mit 1
erlauben = readAckI2c();
stopI2c();
startI2c(0x70);
writeI2c(0x14); // Image von EEPROM-Register
rep_startI2c(0x71);
aendern = readAckI2c();
stopI2c();
aendern &=0xE0;
aendern |= 0x01;
startI2c(0x70);
writeI2c(0x34); // EEPROM-Register;nur schreiben
writeI2c(aendern);
stopI2c();
Eine eigene Frage?
Dieser Thread ist über 17 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.