Forum: Mikrocontroller und Digitale Elektronik Flankenerkennung


von Sven W. (sickone4)


Lesenswert?

Hallo Leute,

ich möchte gerne eine Flankenerkennung für ein Signal benutzen.

Ich kenne die Flankenerkennung pos/neg aus Step7 (SPS) sowie in SCL 
(SPS)
und kann sie in KOW/FUP/AWL/SCL programmieren, d.h. ich verstehe wie sie 
funktioniert.

Nun möchte ich diese in C programmieren.

SCL ->
1
IF E0.0=1 AND FM=0 THEN IM:=1;
2
ELSE IM:=0;
3
END_IF
4
FM:=0;

für die positive Flanke.

in meinem Script habe ich eine ADC, welche mir zu definierten Zählwerten 
ein Signal auf einen Pin gibt. Dieses Signal möchte ich nutzen, um die 
Flankenerkennung anzusteuern.
Mit jeder Flanke soll ein Unterprogramm gestartet werden.

// Für die ADC habe ich einen 10Stufen Poti benutzt, dessen 
Mittelabgriff ich mit einer 10bit ADC auslese //

nun habe ich mir 
http://www.mikrocontroller.net/articles/Entprellung#Flankenerkennung 
diesen Artikel durchgelesen, finde aber, dass er mich nicht wirklich zum 
Ziel führt. Genauso habe ich die SuFu benutzt, um andere Beiträge 
gleichen Themas zu lesen. Leider werden diese Themen meist vom Ersteller 
nach "Erfolg" nicht mit dem fertigen Code gefüttert.

Da ich nun verschiedenste Möglichkeiten kenne/gelesen habe möchte ich 
gerne wissen, wie es am geschicktesten gemacht wird.

ADC Signal bekomme ich am PIN C 0

Gruß Sven

von Peter II (Gast)


Lesenswert?

Was soll denn bei dir eine Flanke sein? du hast ein analogen signal? 
Soll es irgendwelche Schwellwerte geben, trigger schwellen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

FM wird im Beispielcode immer 0 sein, weil nie etwas anderes zugewiesen 
wird...

Die letzte Zeile müsste FM := E0.0 heissen. Wobei FM dann nicht mehr mit 
"Flankenmerker" übersetzt werden darf.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> in meinem Script habe ich eine ADC, welche mir zu definierten Zählwerten
> ein Signal auf einen Pin gibt. Dieses Signal möchte ich nutzen, um die
> Flankenerkennung anzusteuern.

Man kann zar auch mit analogen Dingen eine Flankenerkennung machen, aber 
dazu sollte die Flanke dann schon sehr eindeutig sein. Besser (und auch 
einfacher) ist es aber, wenn ganz klar nur 2 Zustände im Spiel sind, man 
also ein digitales Signal hat. Oder wo ist denn bei diesem 
Spannungsverlauf


                               *
                              *
                          ****
                         *
                       **
            ***********
         ***

die Flanke?



Das Kennzeichen einer Flanke ist es




                       *******************
                       *
                       *
                       *
            ************

das ein Eingangssignal eindeutig seinen Pegel ändert. D.h. wenn man vom 
Digitalpin laufend eine 0 bekommt





            ************

und dann plötzlich eine 1


                       *******************
                       *
                       *
                       *
            ************


dann war beim Übergang von 0 auf 1 die Flanke

                       *******************
                       *
                       *
                       *
            ************
                       ^
                       |
                       |
                       +---  hier ist die Flanke.


D.h. eine Flanke stellt man fest, indem man den momentanen Pegel mit dem 
Pegel zeitlich kurz davor vergleicht. Das klappt zwar auch mit analogen 
Signalen, ist aber nicht so eindeutig, weil man ja nicht jede kleine 
Änderung als Flanke akzeptieren kann und auf der anderen Seite auch mit 
Änderungen klar kommen muss, bei der sich die Spannung nur langsam an 
den Maximalwert 'anschleicht'. D.h. sinnvollerweise wird man das analog 
Signal vorher sowieso diskretisieren. Dann kann man es aber auch gleich 
als Digitalsignal einlesen.

In C muss man dann eben eine Variable benutzen, in der man sich den 
Zustand des Einganges von vorher merkt und wenn sich der jetzige Zustand 
von dem genügend unterscheidet, dann hat man eine Flanke.


   vorher = Zustand am Pin

   while( 1 ) {      // Hauptschleife

     jetzt = Zustand am Pin

     if ( jetzt != vorher ) {
       // Flanke erkannt

     }

     vorher = jetzt
   }


Der jeweils in einem Schleifendurchlauf gültige Zustand am Pin wird in 
einer Variablen gemerkt, damit er im nächsten Schleifendurchlauf mit dem 
jeweils neuen Zustand verglichen werden kann.

von Sven W. (sickone4)


Lesenswert?

meine adc läuft von 0-1023 ich hab einfach mal 10 schwellen abgefragt, 
bei denen je eine flanke sein soll
1
if ((wert == X) || (wert == Y).... {
2
  Flankenerkennung; }

so habe ich mir das vorgestellt.

und mit dem signal der flankenerkennung soll ein sensor etwas tun.

ich versuche mal zu erklären was das alles soll:

ein motor bewegt einen "wagen" über eine schiene. die position des 
wagens erfasse ich mit dem 10step poti. am ende der adc wird di 
drehrichtung mittels l298 gedreht. ein sharp entfernungsmesser soll dann 
alle x-werte die entfernung messen. daher die flankenerkennung.

beispiel: ich habe eine strecke von 10,24cm und möchte alle 5mm den 
entfernungsmesser einmal den abstand messen lassen benötige ich 5,125 
werte eine messung.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> meine adc läuft von 0-1023 ich hab einfach mal 10 schwellen abgefragt,
> bei denen je eine flanke sein soll
>
>
1
if ((wert == X) || (wert == Y).... {
2
>   Flankenerkennung; }
>
> so habe ich mir das vorgestellt.

Es wird eher selten so sein, dass du den genauen Wert von X exakt 
treffen wirst.
Was du eher haben willst, sind Bereiche, in denen sich die Spannung 
bewegen soll, um zu diesem Bereich zu gehören.

     if( wert > X_Untergrenze && wert < X_Obergrenze )

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> beispiel: ich habe eine strecke von 10,24cm und möchte alle 5mm den
> entfernungsmesser einmal den abstand messen lassen benötige ich 5,125
> werte eine messung.


Dazu brauchst du aber keine Flanke. Das ist eine stink normale Division.

von Sven W. (sickone4)


Lesenswert?

hallo karl heinz,

hier mal ein kleiner ausschnitt als beispiel wie ich angefangen habe ->
1
// Unterprogramm "lese" ------------------------------------------------
2
//----------------------------------------------------------------------
3
int lese()       
4
{   
5
    int ergebnis = 0;                  // Variable Ergebnis deklarieren 
6
    ADMUX = (0<<REFS1) | (1<<REFS0);   
7
    ADCSR = 0b11000101;                // Prescaler 64 und ADC aktiv 
8
9
    while (bit_is_set(ADCSR,6));       // Warten
10
11
    ergebnis = ADCW;                   // AD-Wandler -> Ergebnis                  
12
    return ergebnis;                   
13
}
14
15
// Hauptprogramm "MAIN" ------------------------------------------------
16
//----------------------------------------------------------------------
17
18
int main(void)
19
20
{
21
  DDRB   = 0b00011111;
22
                
23
  DDRC   = 0b00000000;              // Port C als Eingang
24
  PORTC  = 0xFF;
25
  
26
  DDRD   = 0b11111111;
27
  PORTD  = 0b00000000;
28
29
  while(1)
30
  {    
31
  // Analogwert X-Richtung fertig
32
      
33
    adwert = lese();                 // Wert der AD-Wandlung
34
    
35
    int wert;                        
36
    wert = adwert;
37
38
// Wendepositionen des Motors X-Achse ----------------------------------      
39
    if (wert < 100)
40
      { PORTD |=  (1 << 7); 
41
        PORTD &= ~(1 << 6);          // Endschalter Links LED AN 
42
        PORTB |=  (1 << 1); 
43
        PORTB &= ~(1 << 0);
44
        PORTB |=  (1 << 3);          //ROT
45
        PORTB &= ~(1 << 2); }        // Eingang 4 = 1; Eingang 3 = 0
46
        
47
        
48
    else if (wert > 924 )          
49
      { PORTD |=  (1 << 6);
50
        PORTD &= ~(1 << 7);          // Endschalter Rechts LED AN 
51
        PORTB |=  (1 << 0);
52
        PORTB &= ~(1 << 1);
53
        PORTB |=  (1 << 2);          // BLAU
54
        PORTB &= ~(1 << 3); }        // Eingang 4 = 1; Eingang 3 = 0
55
           
56
    else
57
      { PORTD &= ~(1 << 7);          // Endschalter LINKS  AUS
58
        PORTD &= ~(1 << 6);          // Endschalter Rechts AUS             
59
        PORTD |=  (1 << 5); }        // Freigabe Motor
60
        
61
        
62
// Sensoransteuerungspunkte -------------------------------------------         
63
    if (   (wert == 150) || (wert == 200) || (wert == 250) 
64
        || (wert == 300) || (wert == 350) || (wert == 400) 
65
        || (wert == 450) || (wert == 500) || (wert == 550) 
66
        || (wert == 600) || (wert == 650) || (wert == 700)
67
        || (wert == 850) || (wert == 900) || (wert == 950) 
68
        || (wert == 1000)) 
69
70
       { flankenerkennung; }  
71
72
// hier soll die flanke abgefragt werden um das unterprogramm für den sensor aufzurufen. Die werte sind beispielhaft und müssen später angepasst werden
73
74
        
75
        
76
    // Ende Analogwertverarbeitung
77
    
78
  }
79
 
80
}

von Sven W. (sickone4)


Lesenswert?

Lothar Miller schrieb:
> Die letzte Zeile müsste FM := E0.0 heissen.

absolut richtig, hab ich falsch geschrieben

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.