Bascom Werte aus Beschleunigungssensor vergleichen

luckyluke

Neues Mitglied
10. März 2013
4
0
0
Sprachen
Guten Abend liebe Forum-Gemeinde,

ich habe nun schon seit zwei Tagen eine Denkblokade :hmmmm: in Bascom und würde mich über eure Hilfe freuen.

Ich lese über I²C die Werte der Beschleunigung (x, y, z) von dem Sensor (bma020) ein und lasse sie umrechnen und formatieren.
Nun möchte ich, dass wenn sich ...

a) einer (z.B. x)
b) zwei (z.B. x und y)
c) drei (z.B. x und y und z)

dieser Werte innerhalb von 30 Sekunden nicht ändert, eine aktion (LED) eingeschaltet wird und nach weiteren 10 Sekunden eine zweite Aktion (2. LED) eingeschaltet wird.

PS: Timer1 läuft nebenbei im 3 Sekunden Takt und zeigt den Programmstatus an (Toggle LED).

Vielen Dank im Voraus.

Programmaufruf:

Code:
   [COLOR="#0000CD"]Do

         Config Debounce = 3000
         Debounce aktivieren , 1 , aktivierung ,      'Deaktivieren

         Gosub Messen

   Loop[/COLOR]

Werte Auslesen und Formatieren:
Code:
[COLOR="#0000CD"]Messen:


         I2cstart

' Sensor adressieren
         I2cwbyte Acc_w

' acc Datenregister adressieren
         I2cwbyte &H02

' I2cstop
         I2cstart
         I2cwbyte Acc_r             ' daten lesen

         For I = 1 To 5
            I2crbyte V(i) , Ack
         Next I
            I2crbyte V(6) , Nack
         'I2cstop

' Format konvertieren
         Ax = Ax / 64
         Ay = Ay / 64
         Az = Az / 64


'In beschleunigungen umrechnen & ausgeben
         Locate 2,2
         Sx = Ax * D2g
         Zx = Str(Sx)
         Zx = Fusing (Sx, "#.##")   'x- Achse
         LCD Zx
         Print Zx ;


         Locate 2,7
         Sy = Ay * D2g
         Zy = Str(Sy)
         Zy = Fusing (Sy, "#.##")   ' y- Achse
         LCD Zy
         Print " ";Zy ;

         Locate 2,12
         Sz = Az * D2g
         Zz = Str(Sz)
         Zz = Fusing (Sz, "#.##")   ' z- Achse
         LCD Zz
         Print " "; Zz
Return[/COLOR]
 
Was nicht ganz klar ist: was soll geschehen, wenn sich nach 32s was ändert? Soll die erste LED dann ausgehen? soll dann trotzdem nach 40s die 2te angehen? Und wenn sich zB nach 'ner Minute was ändert?

Wie oft (und regelmäßig) liest Du denn die Daten aus? Wäre ja möglicherweise auch 'ne Zeitbasis. Wenn das angenommenerweise einmal pro Sekunde ist, würdest Du Dir immer den letzten Zustand für den Vergleich merken.
Bei jeder neuen Messung zählst Du einen Zähler eins rauf, dann vergleichst Du die neuen mit den alten Werten. Hat sich was geändert, setzt Du den Zähler zurück und überschreibst die alten Werte mit den neuen. Jetzt kannst Du prüfen, ob der Zähler 30 (ggf auch 40 - war ja nicht ganz klar) erreicht hat, und entsprechend die LEDs an-/ausschalten.
 
Was nicht ganz klar ist: was soll geschehen, wenn sich nach 32s was ändert? Soll die erste LED dann ausgehen? soll dann trotzdem nach 40s die 2te angehen? Und wenn sich zB nach 'ner Minute was ändert?

Wie oft (und regelmäßig) liest Du denn die Daten aus? Wäre ja möglicherweise auch 'ne Zeitbasis. Wenn das angenommenerweise einmal pro Sekunde ist, würdest Du Dir immer den letzten Zustand für den Vergleich merken.
Bei jeder neuen Messung zählst Du einen Zähler eins rauf, dann vergleichst Du die neuen mit den alten Werten. Hat sich was geändert, setzt Du den Zähler zurück und überschreibst die alten Werte mit den neuen. Jetzt kannst Du prüfen, ob der Zähler 30 (ggf auch 40 - war ja nicht ganz klar) erreicht hat, und entsprechend die LEDs an-/ausschalten.

Hallo, danke für deine Antwort und sorry für die nicht genaue Beschreibung.

1.) Nachdem die erste Aktion gestartet wurde (1. LED an) kann diese mit einer Bewegung wieder beendet werden.
2.) Sobald die zweite Aktion ausgelöst worden ist (2. LED an) kann diese nur durch betätigung eines Schalters quittiert werden.

Als Vorbild dienen die sog. Totmannschalter oder auch Bewegungslosmelder welche hauptsächlich bei der Feuerwehr eingesetzt werden. Hier mal eine Demonstradion, wie es funktionieren sollte:

VIDEO

Ab Sekunde 34 wird der Voralarm ausgelöst, welcher anschließend durch Bewegung quittiert wird.

Ab 1:07 wird der Voralarm erneut Ausgelöst (keine Bewegung erkannt), anschließend wird ab ca. 1:12 wird dann der Vollalarm ausgelöst, welcher nur durch Betätigung der Schalter (oder in diesem Fall durch den "Schlüssel") quittiert werden kann.

Grüße
 
Paßt doch soweit. Beim vergleich mit dem Halbalarm-Wert reagiert die entsprechende LED, beim Vergleich mit dem Vollalarm-Wert die andere. Jetzt mußt Du das alles nur noch in eine IF-Abfrage einbauen, die wiederum den Status der Vollalarm-LED als Bedingung hat (PORT-Register-Bit). Und dieses setzt Du nur durch den "Schlüssel" zurück.
 
Hallo luckyluke,

erstmal einige Bemerkungen zu deinem Code:

- nur Codeschnipsel sind ok, aber manchmal ist es hilfreich wenigstens die DIMs zu den Variablen zu kennen
- Config-Anweisungen schreibt man i.a. vor und nicht in die do - loop - Schleife
Zx = Str(Sx)
Zx = Fusing (Sx, "#.##") 'x- Achse
der erste Befehl ist sinnlos, da das Ergebnis in der zweiten Zeile überschrieben wird
- warum sind die I2CSTOP-Befehle auskommentiert ?

Aber nun zu deinem eigentlichen Problem, da die Absolutwerte der einzelnen Achsen für die Anwendung scheinbar unwichtig sind, könntest du nach jeder Messung einfach die x, y und z Werte addieren und mit dem Vorgängerwert vergleichen. Hier sollte aber ein Tolleranzwert (Ansprechschwelle) berücksichtigt werden, da nicht garantiert werden kann, dass die Sensoren immer exakt der gleichen Wert liefern. Je nach konkretem Anwendungsfall kann es auch sinnvoll sein, die Messwerte (z.B. alle 5 sec.) in einen Ringpuffer zu schreiben und den aktuellen Messwert mit dem Durchschnitt des Ringpuffers zu vergleichen. Diese Variante ist z.B. sinnvoll, wenn die zu erkennende Bewegung von einer anderen Bewegung (z.B. fahrendes Fahrzeug) überlagert wird.

- gp177 -
 
Guten Morgan alle zusammen,

- Config-Anweisungen schreibt man i.a. vor und nicht in die do - loop - Schleife
Das hatte ich nur gemacht, falls ich noch weitere Schalter abfregen will mit einer anderen Debounce- Zeit. :)

...der erste Befehl ist sinnlos, da das Ergebnis in der zweiten Zeile überschrieben wird
Also nur
Code:
 Zx = Fusing (Sx, "#.##") 'x- Achse

Hallo luckyluke,
- warum sind die I2CSTOP-Befehle auskommentiert ?
Da er bei der Simulation in Bascom dort nicht weiter macht.​


... du nach jeder Messung einfach die x, y und z Werte addieren und mit dem Vorgängerwert vergleichen. Hier sollte aber ein Tolleranzwert (Ansprechschwelle) berücksichtigt werden, da nicht garantiert werden kann, dass die Sensoren immer exakt der gleichen Wert liefern. Je nach konkretem Anwendungsfall kann es auch sinnvoll sein, die Messwerte (z.B. alle 5 sec.) in einen Ringpuffer zu schreiben und den aktuellen Messwert mit dem Durchschnitt des Ringpuffers zu vergleichen. Diese Variante ist z.B. sinnvoll, wenn die zu erkennende Bewegung von einer anderen Bewegung (z.B. fahrendes Fahrzeug) überlagert wird.
Das hört sich sehr vielversprechend an. Es würde dann wahrscheinlich bei der Programmierung scheiter. :confused:
Ich versuche es die Tage mal.

Über weitere Tipps wäre ich sehr Erfreut.


Grüße
 
Komplettes Programm

So, ich habe es jetzt soweit ich kann eingearbeitet.
Das mit den Zeiten bekomme ich momentan nicht hin :confused: . Ich muss leider jetzt für die FH :banghead: büffeln, sodass ich es heute nicht mehr schaffen werde.
Wenn jemand eine Idee hat wie ich die zuvor genannten Zeiten einarbeiten kann, oder einen Fehler im Code findet würde ich mich über Antworten sehr freuen. (Natürlich auch über alle anderen Antworten :yes4:)

Das komplette Programm sieht folgender maßen aus:

Code:
$sim
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 64 '100
$swstack = 64 '100
$framesize = 64 '100
$baud = 9600

$include "Variablen.inc"


'#############################################################################

'                          Totmann- Bewegungslosschalter

'     Autor:
'     Datum:   06/2014

'     Changelog:     #v1.0    Prototyp


'#############################################################################
'
'                                Softwareversion
Stand = "v1.0"
Datum = "06/2014"

'#############################################################################



Declare Sub Set_acc_range(byval Range As Byte)

$include "LCD.bas"


'++++++ I2C ++++++++++++++
$lib "i2c_twi.lbx"

Config Twi = 400000
Config Scl = Portc.5
Config Sda = Portc.4




'+++++++++++++++++++++++++++++Tasterkonfigurationen+++++++++++++++++++++++++++

'Totmannschalter aktivieren Aktivieren
aktivieren Alias Pind.6
Config aktivieren = Input

'Manueller Alarm
manueller_alarm Alias Pind.7
Config manueller_alarm = Input

'Reset
alarm_reset Alias Pinb.0
Config alarm_reset = Input


'+++++++++++++++++++++++++++Ausgangskonfiguration+++++++++++++++++++++++++++++

RGB_rot Alias Pinb.2
Config RGB_rot = Output
RGB_rot_ein Alias Portb.2                                   'RGB rot

RGB_grun Alias Pinb.3
Config RGB_grun = Output
RGB_grun_ein Alias Portb.3                                  'RGB grüm

RGB_blau Alias Pinb.4
Config RGB_blau = Output
RGB_blau_eim Alias Portb.4                                  'RGB blau

Piezo1 Alias Pinb.5
Config Piezo1 = Output
Piezo1_ein Alias Portb.5                                    'Piezo 1

Flasher Alias PinC.0
Config Flasher = Output
Flasher_ein Alias PortC.0                                   'LED Flasher


'( - leds
Config Portd.7 = Output
Config Portd.6 = Output
Config Portb.0 = Output
Led_gl Alias Portd.7
Led_rt Alias Portd.6
Led_gr Alias Portb.0
')

Enable Interrupts



'+++++++++++++++++++++++++++ I2C Initialisierung +++++++++++++++++++++++++++++

I2cinit

Call Set_acc_range(0)
' messbereich:
' Set_acc_range(0) -> +/- 2g (default)
' Set_acc_range(1) -> +/- 4g
' Set_acc_range(2) -> +/- 8g



'#############################################################################
' Aktivierung erforderlich
aktivierung:

ist_aktiviert = 0
aktivierung_erforderlich = 1
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Stop  TIMER1

Const Timervorgabe = 34286
Const Prescaler = 256

Config Timer1 = Timer, Prescale = Prescaler

Enable Timer1
Timer1 = Timervorgabe
On Timer1 Timer_irq
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++

CLS
Locate 1,1
LCD "aktivieren..."

Config Debounce = 3000




   'Do

        ' Debounce aktivieren , 1 , scharfgeschaltet , 'Aktivieren

   'Loop


'#############################################################################
' Schalter ist scharf
scharfgeschaltet:

aktivierung_erforderlich = 0
ist_aktiviert = 1
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Stop  TIMER1

Const Timervorgabe1 = 42099 ' 3 Sekunden takt
Const Prescaler1 = 1024

Config Timer1 = Timer, Prescale = Prescaler1

Enable Timer1
Timer1 = Timervorgabe1

'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Config Single = Scientific , Digits = 2
CLS
Locate 1,1
LCD "aktiv!"
wait 1

CLS
Locate 1,1
LCD "acc test!"

Dim wert0 As Single
Dim wert0_max As Single
Dim wert0_min As Single

Dim wert1 As Single
Dim wert1_max As Single
Dim wert1_min As Single

' Toleranzwert
Dim Prozent_max As Byte, Prozent_min As Byte

Prozent_max = 10
Prozent_min = 10

dim k as Bit
dim l as Bit

wert0 = 0
wert0_max = 0
wert0_min = 0

wert1 = 0
wert1_max = 0
wert1_min = 0



k=0
l=0


   [B][COLOR="#B22222"]Do


         Config Debounce = 3000
         Debounce aktivieren , 1 , aktivierung ,      'Deaktivieren

         Gosub Messen


         if k = 0 Then

' Addition von x,y,z immer im Wechsel mit der anderen If-Schleife
         wert0 = Sx + Sy
         wert0 = wert0 + Sz

' Prozentualer Maximal- und Minimalwert bestimmen
         wert0_max = wert0 * Prozent_max
         wert0_max = wert0_max / 100
         wert0_max = wert0 + wert0_max

         wert0_min = wert0  * Prozent_max
         wert0_min = wert0_min / 100
         wert0_min = wert0 - wert0_min

         l= 1

         End If



         if k = 1 Then

' Addition von x,y,z immer im Wechsel mit der anderen If-Schleife
         wert1 = Sx + Sy
         wert1 = wert1 + Sz

' Prozentualer Maximal- und Minimalwert bestimmen
         wert1_max = wert1 * Prozent_min
         wert1_max = wert1_max / 100
         wert1_max = wert1 + wert1_max

         wert1_min = wert1  * Prozent_min
         wert1_min = wert1_min / 100
         wert1_min = wert1 - wert1_min



         k = 0
         l = 0

         End If

'Auswertung

         If wert1<wert0_min or wert1>wert0_max Or wert0<wert1_min or wert0>wert1_max Then

         Print "Alarm"

         End If



   Loop[/COLOR][/B]


End

'#############################################################################
[B][COLOR="#B22222"]Messen:



         I2cstart
' Sensor adressieren
         I2cwbyte Acc_w

' acc Datenregister adressieren
         I2cwbyte &H02

' I2cstop
         I2cstart
         I2cwbyte Acc_r             ' daten lesen

         For I = 1 To 5
            I2crbyte V(i) , Ack
         Next I
            I2crbyte V(6) , Nack
         'I2cstop

' Format konvertieren
         Ax = Ax / 64
         Ay = Ay / 64
         Az = Az / 64


'In beschleunigungen umrechnen & ausgeben
         Locate 2,2
         Sx = Ax * D2g
         LCD Sx
         Print Sx ;

         Locate 2,7
         Sy = Ay * D2g
         LCD Sy
         Print " ";Sy ;

         Locate 2,12
         Sz = Az * D2g
         LCD Sz
         Print " "; Sz

         If l=1 Then
         k=1
         End If

Return[/COLOR][/B]


'#############################################################################
Timer_irq:

   if aktivierung_erforderlich = 1 Then

         Timer1 = Timervorgabe
         Toggle RGB_rot_ein      'LED orange/gelb Blinken jede 1 Sekunde

   End if


   if ist_aktiviert = 1 Then

         Timer1 = Timervorgabe1
         Toggle Flasher_ein      'LED Flasher Blinken

   End if

Return
'#############################################################################
Sub Set_acc_range(byval Range As Byte)
   I2cstart
   '
   ' sensor adressieren
   I2cwbyte Acc_w
   '
   ' kontrollregister adressieren
   I2cwbyte &H14
   '
   'I2cstop
   '
   I2cstart                                                 '
   ' kontrollregister lesen
   I2cwbyte Acc_r
   I2crbyte Acc_cntr , Nack
   '
   'I2cstop
   '
   ' kontrollregister manipulieren
   Acc_cntr.3 = Range.0
   Acc_cntr.4 = Range.1
   '
   I2cstart
   '
   ' kontrollregister zurückschreiben
   I2cwbyte Acc_w
   I2cwbyte &H14
   I2cwbyte Acc_cntr
   '
   'I2cstop
   '
   ' umrechnungsfaktor neu berechnen
   D2g = 2 ^ Range
   D2g = D2g * 2
   D2g = D2g / 512
   '
End Sub

Variablen.inc
Code:
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 64 '100
$swstack = 64 '100
$framesize = 64 '100
$baud = 9600
'#############################################################################

'                                Variablen.inc

'#############################################################################

Dim Stand As String * 5
Dim Datum As String * 10


Dim aktivierung_erforderlich AS Bit
Dim ist_aktiviert As Bit
Dim alarm As Bit
Dim voralarm As Bit


'++++ I2C ++++
Dim V(6) As Byte
Dim Ax As Integer At V(1) Overlay
Dim Ay As Integer At V(3) Overlay
Dim Az As Integer At V(5) Overlay

Dim Acc_cntr As Byte
Dim I As Byte
Dim Acc_range As Byte
Dim D2g As Single
Dim Sx As Single
Dim Sy As Single
Dim Sz As Single

Const Acc_w = &H70
Const Acc_r = &H71

LCD.Bas
Code:
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 64 '100
$swstack = 64 '100
$framesize = 64 '100
$baud = 9600
'#############################################################################

'                               LCD Konfiguration

'#############################################################################


Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portd.2 , Db5 = Portd.3 , Db6 = Portd.4 , Db7 = Portd.5 , E = Portd.1 , Rs = Portd.0
Waitms 350
Initlcd
CLS
Locate 1,1
LCD "initialisiert!"
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)