Forum: Mikrocontroller und Digitale Elektronik BMA020 Selftest_0


von Robin (Gast)


Lesenswert?

Hi ich Programier noch nicht lang und dachte mir, zum lernen schreib ich 
mal ne BMA020 Klasse.
Ich nutze eclipse zusammen mit einem Arduino Uno.

Soweit klappt auch alles, jetzt schreib ich aber die Funktion um den 
Selftest_0 auszuführen. Aber ich bekomm immer nur 0 also nicht 
geschafft.

Meine Frage also hab ich nen Logikfehler oder ist der BMA020 kaputt?
1
bool BMA020_AIO::selftest(){
2
  uint8_t reg = readRegister(REG_ST);
3
  reg |= (1 << 2);
4
  setRegister(REG_ST, reg);
5
6
  while(!(readRegister(REG_ST) & (1 << 2)));
7
  return (readRegister(REG_STR) & (1 << 8)) ? 1 : 0;
8
}

readRegister und setRegister funktionieren und sind jawohl 
sebstsprechend ;)

Danke schon mal im vorraus.
Gruß Robin

von Stefan F. (sfrings)


Lesenswert?

1<<8 ergibt 0 bei einer 8-Bit Operation. Das Status bit ist Bit 7, nicht 
8.
Die letzte Zeile scheint mir auch unnötig kompliziert. Vorschlag:
1
return (readRegister(REG_STR) & (1 << 7));

von Robin (Gast)


Lesenswert?

danke für die hilfe,
hab ich voll übersehen das mit der 8 xD

Sonst ist aber alles in ordnung? gibt nämlich immer noch 0 -.-

von Peter (Gast)


Lesenswert?

Robin schrieb:
> while(!(readRegister(REG_ST) & (1 << 2)));

Wartet solange das bit nicht gesetzt. Versuch mal das "!" weg zu 
lassen.

von Robin (Gast)


Lesenswert?

Juhuu. Vielen dank für den tipp es funkt^^

Aber da muss ich gleich noch ne frage dran hängen.
Wenn man im BMA020 nen Interrupt erzeugt geht der dann immer auf den 
pin-INT oder ist da irgent was über twi? Hab mich noch nicht wirktlich 
mit Interrupts auseinander gesetzt.

von Peter (Gast)


Lesenswert?

Über den INT-Pin. Das ist ja das tolle daran, dass du nicht ständig über 
TWI pollen musst, sondern den µC schlafen legen kannst und ihn über den 
Interrupt wecken lassen kannst.

Einfach mal das Datenblatt aufmerksam lesen, dann klappt das schon ;)

von Peter Enis (Gast)


Lesenswert?

Der Slave (BMA020) kann nicht von sich aus senden sondern muss immer vom 
Master abgefragt werden (Polling). Deswegen gibt es den Interrupt-Pin um 
den Master über neue Daten o.ä. zu informieren.

von Robin (Gast)


Lesenswert?

Ahso jetzt hab ichs kapiert. Danke für die erklärung.
Hab das Datenblatt zwar gelesen aber da waren so viele Fremdwörter da 
war mein Englisch dann nicht mehr gut genug ;)

von Robin (Gast)


Lesenswert?

Und noch was versteh ich net Selftest_1 steht:
"This self test bit (address 0Ah, bit3) does not generate any 
electrostatic force in the MEMS
element but is used to verify the interrupt function is working 
correctly and that microprocessor
is able to react to the interrupts.
0g acceleration is emulated at ADC input and the user can detect the 
whole logic path for
interrupt, including the PCB path integrity. The LG_thres register must 
be set to about 0.4g
while LG_dur = 0 to generate a low-g interrupt"

Aber wo kann man das ergebnis abfragen? Auch im selftest_result?

von Robin (Gast)


Lesenswert?

Kann mir keiner sagen wie das mit dem Selftest_1 geht?

von Stefan (Gast)


Lesenswert?

Das Ergebnis vom Selbsttest 1 ist ein Interrupt Signal am 
Interrupt-Ausgang. Du musst die Leitung mit dem Mikrocontroller 
verbinden, um sie abzufragen.

Über den I2C oder SPI Bus kannst Du nur das Interrupt Status Flag 
abfragen, was allerdings nicht der Sinn dieses Tests ist. Der Selbsttest 
1 ist dazu gedacht, die Funktion der Interrupt-Leitung zu testen.

von Robin (Gast)


Lesenswert?

Hab ich auch versucht aber das programm hängt sich immer auf.
1
bool BMA020_AIO::Selftest = 0;
2
void BMA020_AIO::selftest_1(int interrupt){
3
  uint8_t reg = readRegister(REG_ST);
4
  reg |= 0x08;
5
  setRegister(REG_ST, reg);
6
}
7
8
void intSelftest(){
9
  BMA020.Selftest_1 = 1;
10
}
11
12
//in Setup() funktion
13
BMA020.resetINT();
14
attachInterrupt(0, intSelftest, CHANGE);
15
Serial.println(BMA020.Selftest_1);

is da was falsch?

von Robin (Gast)


Lesenswert?

mein natürlich:
1
bool BMA020_AIO::Selftest_1 = 0;
Hab mich verschrieben

von Robin (Gast)


Lesenswert?

So er hängt sich jetzt nicht mehr auf aber gibt immer noch 0 wieder.
Kann mir einer helfen das mit den Interrupts richtig zu verstehen?
1
#include <main.cpp>
2
#include <BMA020.h>
3
4
volatile int state = 0;
5
6
ISR(INT0_vect){
7
  state = 1;
8
}
9
10
void setup(){
11
12
  cli();
13
  pinMode(pin, OUTPUT);
14
  BMA020.begin();
15
  Serial.begin(9600);
16
  Serial.print("Selftest_0 result: ");
17
  Serial.println(BMA020.selftest_0());
18
  Serial.print("Selftest_1 result: ");
19
  sei();
20
  BMA020.resetINT();
21
  Serial.println(state);
22
}

Danke schon mal an alle die mir helfen und geholfen haben ;)
Gruß Robin

von Robin (Gast)


Lesenswert?

Lol sry falsches beispiel^^ aber sollte auch gehen^^
hier das richtige (schäm das mir das nicht bei dem Post davor schon 
aufgefallen ist...)
1
#include <main.cpp>
2
#include <BMA020.h>
3
4
volatile int state = 0;
5
6
ISR(INT0_vect){
7
  state = 1;
8
}
9
10
void setup(){
11
12
  cli();
13
  BMA020.begin();
14
  Serial.begin(9600);
15
  Serial.print("Selftest_0 result: ");
16
  Serial.println(BMA020.selftest_0());
17
  Serial.print("Selftest_1 result: ");
18
  sei();
19
  BMA020.selftest_1();
20
  Serial.println(state);
21
}
22
23
//BMA020.cpp
24
#include <avr/interrupt.h>
25
26
void BMA020_AIO::selftest_1(){
27
  uint8_t reg = readRegister(REG_ST);
28
  reg |= 0x08;
29
  setRegister(REG_ST, reg);
30
31
}
Aber irgent wie bekomm ich jetzt gar nix mehr ausgegeben? oO

von Stefan (Gast)


Lesenswert?

sei() erlaubt Interrupts allgemein. Du must aber auch noch festlegen, 
daß Interrupts von dem Eingang INT0 erlaubt werden sollen, sonst sind 
effektiv immer noch keine Interrupts erlaubt.

Siehe Bit 0 in Register PCMSK0.

Weiterhin muss du nach Absetzen des Befehl zum BMA020 auch abwarten, bis 
er mit seinem Test fertig ist. Du fragst momentan sofort nach Absetzen 
des Befehl ab, ob ein Interrupt ausgelöst wurde. Aber so schnell ist der 
Chip nicht. Der Selbsttest dauert eine Weile.

Irgendwo im Datenblatt müsste stehen, wie lange die beiden Tests dauern. 
Ich habe die Angabe beim schnellen Überfliegen jedoch nicht gefunden.

Füge eine Wartepause ein, zwischen dem Absetzen des Test-Kommandos und 
dem Auslesen des Ergebnisses. Ich würde es einfach mal mit einer Sekunde 
versuchen, das sollte reichen. Wenn das klappt, kanst Du ja 
experimentiell herausfinden, wieviel Zeit der Test wirkloiuch benötigt.

von Robin (Gast)


Lesenswert?

Habs jetzt mal so probiert:
1
void intSelftest(){
2
  state = 1;
3
}
4
5
void setup(){
6
  attachInterrupt(0, intSelftest, CHANGE);
7
  uint8_t tmp_sreg;
8
  tmp_sreg = SREG;
9
  cli();
10
11
  pinMode(pin, OUTPUT);
12
  BMA020.begin();
13
  Serial.begin(9600);
14
  Serial.print("Selftest_0 result: ");
15
  Serial.println(BMA020.selftest_0());
16
  Serial.print("Selftest_1 result: ");
17
18
  SREG = tmp_sreg;
19
20
  BMA020.selftest_1();
21
  delay(1000);
22
  Serial.println(state);
23
}

Aber jetzt kommt wenn ich den Arduino anstöpsel kommt "Selftest_0 
result: 1", "Selftest_1 result: 0" und bei einem reset über den taster 
kommt bei beidem 0.

von Stefan F. (sfrings)


Lesenswert?

Reduziere das ganze Programm auf ein Minimum, falls nicht bereits 
geschehen. Und dann zeige uns mal den gesamten Quelltext und den 
gesamten Schaltplan.

Denn mit jedem Stück Quelltext hast du mehr wichtige Teile ausgelassen.

von Robin (Gast)


Angehängte Dateien:

Lesenswert?

Ok dann mal hier alles im anhang:
"setup.cpp" ist das Hauptprogramm.
"BMA020.h" und "BMA020.cpp" die Klassen-lib an der ich schreib.

von Robin (Gast)


Lesenswert?

Ach lol hab voll die beschaltung vergessen...

Ich nutze das BMA020 Modul von elv 
http://www.elv.de/controller.aspx?cid=683&detail=10&detail2=211450
und den Arduino Uno Rev.2

Am BMA020 Modul hab ich UIN mit CSB/UPullup verbunden.

Und die Verbindungen vom BMA020 zum Arduino
UIN mit 3,3V,
GND mit GND,
SCK mit A5,
SDI mit A4
und INT mit 2.

hoffe ich hab nicht noch was vergessen.

Gruß Robin

von Stefan F. (sfrings)


Angehängte Dateien:

Lesenswert?

Du hast etwas vergessen: Schau Dir mal das Foto an. Wenn Du einen 
Tropfen Zinn auf die Kontakteflächen J1 lötest, brauchst Du keine 
externen Pull-Up Widerstände. Es fehlt die blaue Verbindung.

Ich bin kein Arduino Spezialist, aber in diversen Tutorials über 
Interrupts habe ich weder sei() noch cli() Befehle gesehen. cli() 
verbietet Interrupts, ist also ganz sicher falsch. Wenn schon, dann muss 
es sei() heissen, aber bei Arduino scheint ein etsprechender Aufruf 
schon in attachInterrupt() zu stecken.

von Robin (Gast)


Lesenswert?

Durch die verbindung von UIN und UPullup brauch ich auch keine externen 
wiederstände. Und wenn ich nur attachInterrupt nehme spielt das programm 
vllt 10ms wenns hoch kommt. Und da über die "Winterrupts.c" auch die 
"acr/interrupt.h" eingebunden wird warum soll ichs dann nicht nutzen?
Eigentlich funktioniert ja auch alles nur mit den Interrupts bekomm ich 
das halt noch net so hin weil ich damit gerade erst anfang.

von Stefan F. (sfrings)


Lesenswert?

Hallo Robin,
ich habe DIr ja auch geschrieben, dass Du keine externen Pull-Ups 
brauchst.

Hast Du die blaue Brücke eingelötet? Wenn nicht, dann mach das erstmal, 
denn die sind mit Sicherheit nötig. Das geht aus der Beschreibung des 
Moduls von ELV hervor.

Und cli() ist definitiv falsch. Wie gesagt, verbietet cli() 
Interrupts.DU kannst nicht erwarten, dass der Interrupt ausgeführt wird, 
wenn Du ihn vorher ausdrücklich verboten hast.

von Robin (Gast)


Lesenswert?

Ich hab die blaue brücke gelötet und ich erlaube die interuppts doch 
wieder in dem ich den alten SREG wert wieder SREG hinzufüge wie es hier 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts 
steht.

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.