Forum: Mikrocontroller und Digitale Elektronik STM32F407 Beschleunigungssensor LIS3DSH


von Andy S. (andy_st)


Lesenswert?

Hallo allerseits,
ich habe einen STM32F407 mit einem LIS3DSH Beschleunigungssensor. Mein 
Ziel ist es, die Beschleunigungsdaten in 3 Achsen in 1ms-Abstand in ein 
Array zu schreiben.
Leider mein erster Micocontroller (außer Arduino) den ich programmiere, 
und jetzt steh ich gewaltig auf dem Schlauch...

Ich lasse Timer7 mit einer 1us takten. LED blinken lassen, etc. hat 
alles soweit funktioniert, mit dem Beschleunigungssensor komme ich aber 
auf keinen grünen Zweig...
also habe ich hier: 
http://mikrocontroller.bplaced.net/wordpress/?page_id=3932
eine library runtergeladen und an mein Programm angepasst, check.
Im Beispiel geht die LED an, in welche Richtung man die Platine kippt, 
check.
Jetzt will ich die Daten abspeichern, dafür möchte ich aber die 1,6kHz 
data rate einstellen, diese ist aber in der lib nicht beachtet.
Im Allgemeinen kann ich da nur sehr wage nachvollziehen, was der Autor 
so gemacht hat und deshalb die Frage,
ist es nicht den Beschleunigungssensor ähnlich wie eine LED zu 
initialisieren? etwa:
1
// Initialisierung LEDs
2
   GPIO_IntStructure.GPIO_Pin    = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
3
   GPIO_IntStructure.GPIO_Mode   = GPIO_Mode_OUT;
4
   GPIO_IntStructure.GPIO_OType  = GPIO_OType_PP;
5
   GPIO_IntStructure.GPIO_Speed  = GPIO_Speed_50MHz;
6
   GPIO_IntStructure.GPIO_PuPd   = GPIO_PuPd_NOPULL;
7
   GPIO_Init(GPIOD, &GPIO_IntStructure);

Schlussendlich sollen meine Daten so abgespeichert werden:
1
for(Index_Messwerte_Zeile = 0; Index_Messwerte_Zeile < 2048; Index_Messwerte_Zeile++)
2
   {
3
   while(Timer_us <= get_time_us()) {}
4
5
   UB_LIS3DSH_Read();
6
   Messwerte[0][Index_Messwerte_Zeile] = LIS3DSH.x_achse;
7
   Messwerte[1][Index_Messwerte_Zeile] = LIS3DSH.y_achse;
8
   Messwerte[2][Index_Messwerte_Zeile] = LIS3DSH.z_achse;
9
10
   Timer_us = get_time_us() + 1000;
11
}

lg Andy

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Da fehlt aber die Routine get_time_us(). Wie sieht die denn aus? Timer 
Updates sind eine spassige Sache beim F407 und gehen nicht immer sofort. 
Am sinnvollsten erscheint mir im Moment, Timer7 beim gewünschten 
Zeitpunkt einen (Overflow) Interrupt ausführen zu lassen, der dir ein 
Flag setzt, welches du in der Zeile
1
while(Timer_us <= get_time_us()) {}
 abfragst.
Man könnte auch SysTick() benutzen, wenns richtig initialisiert ist.

von Andy S. (andy_st)


Lesenswert?

Die Routine für den Timer und die Funktion sehen so aus:
1
void TIM7_IRQHandler(void)
2
{
3
    interrupt_timer7_us++;
4
    TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
5
}
6
unsigned int get_time_us(void)
7
{
8
   return interrupt_timer7_us;
9
}

Das mit dem Timer funktioniert im Moment aber eigentlich ganz gut, 
soweit ich das bewerten kann.
Das Problem ist, dass ich die Datenrate vom Beschleunigungssensor auf 
1,6kHz setzen muss, dass ich im ms-Takt Daten abfragen kann, ohne 
mehrmals den selber Wert hintereinander zu bekommen.

von hp-freund (Gast)


Lesenswert?

Warum nutzt Du nicht die Interrupt Möglichkeiten des LIS3DSH?
Dann brauchst Du nur Daten einlesen wenn sich Werte geändert haben und 
die dann ggf mit Zeitstempel abzuspeichern.

von Andy S. (andy_st)


Lesenswert?

Den Sensor mit einem Interrupt zu betreiben habe ich mir auch schon 
überlegt, habe aber Bedenken, dass ich bei evtl. noch schnelleren 
Abtastraten zu lange für die jeweilige Routine brauche.
Außerdem muss mein Sensor trotzdem auf die 1,6kHz gestellt werden, dass 
sich der Wert mind. 1000x pro Sek verändern kann.
Da ich die Daten für ein anschließende FFT-Analyse nutzen möchte, hat es 
auch keinen Sinn nur Veränderung abzurufen.

von aSma>> (Gast)


Lesenswert?

Servus,

> ich habe einen STM32F407 mit einem LIS3DSH Beschleunigungssensor. Mein
> Ziel ist es, die Beschleunigungsdaten in 3 Achsen in 1ms-Abstand in ein
> Array zu schreiben.
> Leider mein erster Micocontroller (außer Arduino) den ich programmiere,
> und jetzt steh ich gewaltig auf dem Schlauch...

Du meinst eher dich damit.

> Ich lasse Timer7 mit einer 1us takten. LED blinken lassen, etc. hat
> alles soweit funktioniert, mit dem Beschleunigungssensor komme ich aber
> auf keinen grünen Zweig...

wie kommst du auf 1µs timer? Wenn man etwas Kopfrechnen kann, dann merkt 
man, dass der F4 nichts anderes tut außer im ISR zeit zu verbringen.

> Jetzt will ich die Daten abspeichern, dafür möchte ich aber die 1,6kHz
> data rate einstellen, diese ist aber in der lib nicht beachtet.

Was willst du jetzt 1khz oder 1,6khz?

So, wie ich das auf die schnelle überblicke pollt Uwe die Daten. Bei 1ms 
kannst du den SysTick Handler nehmen nehmen.

Auch bei 1khz rauschen die Daten ungemein, sonst nehme einen Timer den 
du auf 1µs konfig hast und setzen den auf deine gewünschte Zeit und 
kopiere dort die Daten in ein Array.

mfg

mfg

von uwe (Gast)


Lesenswert?

ändere im H-File den Define :

#define  LIS3DSH_PWR          0x67   // Power-On (100Hz,X,Y,Z)

in :

#define  LIS3DSH_PWR          0x97   // Power-On (1600Hz,X,Y,Z)

Gruss Uwe

von Andy S. (andy_st)


Lesenswert?

sorry, als Anfänger fehlt mir manchmal etwas die Übersicht, was für ein 
Quellcode wirklich relevant ist.

> wie kommst du auf 1µs timer?
1
   // Initialisierung Timer7 - 84MHz Basis
2
   timInitStruct.TIM_CounterMode = TIM_CounterMode_Up;                      // Timer-Modus hochzählen
3
   timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
4
   timInitStruct.TIM_Prescaler = 0;                                         // Vorteiler 1 -> 84MHz
5
   timInitStruct.TIM_Period = 84;                                           // Timer von 0 bis 84 zählen lassen
6
   TIM_TimeBaseInit(TIM7, &timInitStruct);                                  // vorbereitete Initialisierungstruktur an Timer7 übergeben
7
   TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);                               // Unterbrechung, wenn Timerperiode erreicht und Zählregister neu geladen
8
   TIM_Cmd(TIM7, ENABLE);                                                   // Timer 7 einschalten
9
10
   // Initialisierung NVIC
11
   NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
12
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                          // IRQ einschalten
13
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;             // geringste Priorität zuweisen 15
14
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
15
   NVIC_Init(&NVIC_InitStructure);                                          // vorbereitete Werte übergeben

mit einer Basis von 84MHz
Prescaler 0 (also intern dann 1) -> immernoch 84MHz
dann lasse ich bis 84 (dauert 1us) hochzählen bis der Interrupt 
ausgelöst wird
so habe ich das zumindest mal verstanden und die zeit passt so auch.

> Was willst du jetzt 1khz oder 1,6khz?

Ich möchte Daten mit 1kHz abtasten (Sampletime), der Sensor ist aber nur 
mit 800Hz oder eben 1,6kHz Datenrate skalierbar.

> Auch bei 1khz rauschen die Daten ungemein

Hier gehts um meine Bachelorarbeit, die Auswertung sollte für 
entsprechendes Raschen ausgelegt sein ;)

von Andy S. (andy_st)


Lesenswert?

> ändere im H-File den Define :
>
> #define  LIS3DSH_PWR          0x67   // Power-On (100Hz,X,Y,Z)
>
> in :
>
> #define  LIS3DSH_PWR          0x97   // Power-On (1600Hz,X,Y,Z)

perfekt, das suche ich schon seit Stunden, vielen vielen Dank!!

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.