Forum: Mikrocontroller und Digitale Elektronik Zeitliches deaktiveren bestimmter Eingangspins


von Arne (Gast)


Lesenswert?

Hallo zusammen,
ich bin neu hier und rätsel jetzt schon eine ganze Zeit an folgendem 
Problem:
Ich möchte mit einem ATMega8 die Signale von 10 Lichtschranken 
auswerten. Wenn der Lichtstrahl unterbrochen wird liegt am AVR ein 
High-Level an, die Schaltung lässt sich aber auch schnell so umbauen, 
dass sich ein Low-Level ergibt, falls das in irgendeiner Art helfen 
sollte.

Jede dieser Lichtschranken wird jetzt unabhängig von den anderen für 
sagen wir ca. 500ms unterbrochen, die genaue Länge der Signale ist 
jedoch bei jedem Signal (nicht nur bei jedem Kanal) individuell 
unterschiedlich.
Hat jemand eine Idee wie ich die Signale sinnvoll zählen kann? Weil wenn 
ich einfach nur jede Lichtschranke abfrage erhalte ich ja je nach Länge 
des Signals Mehrfachzählungen, und mit wait kann ich nicht arbeiten, da 
in diesem Fall alle Kanäle gestoppt würden...
Meine Idee war den Eingangspin für so lange zu deaktivieren bis er 
einmal wieder ein High erhalten hat.
Ich hab das Handbuch schon bemüht, ebenso das Internet, und so langsam 
verzweifel ich an dieser Aufgabe.

Ich möchte das ganze gerne in Bascom programmieren, eine andere Sprache 
beherrsche ich momentan nicht.

von Max H. (hartl192)


Lesenswert?

Ich würde eine Flankenerkennung machen. In C könnte das so aussehen, ich 
hoffe du kannst damit was anfangen:
1
    PORTBnew=PORTB;
2
    flankeB=~PORTBold;
3
    flankeB=flankeB&PORTBnew;
4
    PORTBold=PORTBnew;
5
    
6
    if(flankeB&(1<<1))      // RB1
7
    {
8
9
    }  
10
    if(flankeB&(1<<2))      // RB2
11
    {
12
      
13
    }    
14
    if(flankeB&(1<<4))      // RB4
15
    {
16
    
17
    }    
18
    if(flankeB&(1<<0))      // RB0: 
19
    {
20
      
21
    }
~ Bitweiße NOT
& Bitweiße UND

Im Prinzip macht das Programm einfach das Bitweiße UND aus dem neuen 
Zusatand von PORTB und dem alten (in PORTBold gespeichert) negiert. Das 
Ergebnis ist dann eine 8bit Zahl, ist ein Bit in dieser Zahl gesetzt, 
war am entsprechenden Eingang eine Steigende Flanke

: Bearbeitet durch User
von Arne (Gast)


Lesenswert?

Ich glaube ich habe so grob verstanden was du meinst.
Ich werde das die Tage mal in Bascom ausprobieren, auch wenn ich mir 
damit im Zweifel das Leben schwerer mache als nötig...
Aber das ist ein Ansatz der mir weiterhilft, danke :)

von Axel S. (a-za-z0-9)


Lesenswert?

Arne schrieb:

> Ich möchte mit einem ATMega8 die Signale von 10 Lichtschranken
> auswerten.

> Jede dieser Lichtschranken wird jetzt unabhängig von den anderen für
> sagen wir ca. 500ms unterbrochen, die genaue Länge der Signale ist
> jedoch bei jedem Signal (nicht nur bei jedem Kanal) individuell
> unterschiedlich.
> Hat jemand eine Idee wie ich die Signale sinnvoll zählen kann? Weil wenn
> ich einfach nur jede Lichtschranke abfrage erhalte ich ja je nach Länge
> des Signals Mehrfachzählungen, und mit wait kann ich nicht arbeiten, da
> in diesem Fall alle Kanäle gestoppt würden...

> Meine Idee war den Eingangspin für so lange zu deaktivieren bis er
> einmal wieder ein High erhalten hat.

Im Prinzip ganz richtig gedacht. Aber natürlich willst du nicht den 
Eingang "deaktivieren", sondern nur so lange nicht auf den aktiven Pegel 
reagieren, bis du nicht wenigstens einmal einen inaktiven Pegel gesehen 
hast.

Und dazu mußt du nichts weiter machen, als dir jeweils den letzten 
Zustand jedes der 10 Eingänge zu merken. Dein Programm läuft in einer 
Endlosschleife. Bei jedem Durchlauf fragt es den neuen Zustand der 
Eingänge ab und vergleicht mit dem alten Zustand. Jetzt gibt es 3 
Möglichkeiten:

1. der alte und der neue Zustand eines Eingangs sind gleich. Dann hat 
sich nichts geändert (die Lichtschranke ist entweder immer noch offen 
oder immer noch unterbrochen) und du hast nichts zu tun.

2. der Zustand wechselt von "Lichtschranke offen" zu "Lichtschranke 
unterbrochen".

3. der Zustand wechselt von "Lichtschranke unterbrochen" zu 
"Lichtschranke offen".

Je nachdem, bei welchem der beiden Übergänge du zählen willst, mußt du 
deinen Zähler entweder bei 2. oder bei 3. hochzählen.

Sparsame Programmierer werden sich den Zustand der 10 Eingänge in 10 
Bits merken (wie Max oben). Du kannst aber genausogut ein Array mit 10 
Einträgen verwenden. Oder sonst irgendwas, das das 
Informationsäquivalent von 10 Bits speichern kann.


XL

von Peter D. (peda)


Lesenswert?

Du brauchst ne Flankenerkennung.
Die 10 Eingänge in eine 16Bit Variable ablegen und dann mit dem 
vorherigen 16Bit-Wert EXORen und mit der gewünschten Flanke verUNDen.
1
  static uint16_t old;
2
  uint16_t new, rising_edge, falling_edge;
3
4
  new = PINA | (PINB<<8);
5
  rising_edge = (new ^ old) & new;
6
  falling_edge = (new ^ old) & old;
7
  old = new;
Und dann für alle gesetzen Bits den Wert hochzählen.

von Uwe (de0508)


Lesenswert?

Sehr elegant Peter ! :-)

von Falk B. (falk)


Lesenswert?

Eine Variable new sollte man besser nicht nutzen, das ist ein 
Schlüsselwort in C++ (jaja, in C geht es), es bringt einem aber in den 
meisten Editoren ein falschen Syntax Highlighting.

von c-hater (Gast)


Lesenswert?

Arne schrieb:

> Jede dieser Lichtschranken wird jetzt unabhängig von den anderen für
> sagen wir ca. 500ms unterbrochen, die genaue Länge der Signale ist
> jedoch bei jedem Signal (nicht nur bei jedem Kanal) individuell
> unterschiedlich.
> Hat jemand eine Idee wie ich die Signale sinnvoll zählen kann?

Du willst vermutlich eine funktionierende Personenzählung mittels 
Lichtschränke. Da haben sich schon wesentlich kompetentere Leute die 
Zähne dran ausgebissen. Also gleich vorbeugend: eine perfekt 
funktionierende Lösung dafür ist theoretisch und deshalb natürlich auch 
praktisch unmöglich. Nur, wenn mittels baulicher Maßnahmen eine 
Personenvereinzelung vorgenommen wird, ist eine Lösung realisierbar, die 
zumindest solange recht zuverlässig funktioniert, wie es keine Absicht 
gibt, diese auszutricksen.

Wie auch immer: Deine Definition ist doch schon fast hinreichend für 
eine sinnvolle Zählung (wie gesagt: wenn es eine physische 
Personenvereinzelung gibt). Die geforderte Mindestlänge für eine 
Unterbrechung soll also 500ms sein. Es fehlt noch die Definition dafür, 
wie lange innerhalb so einer Unterbrechung diese Unterbrechung auch mal 
wieder aufgehoben sein darf, ohne daß das zu einer Mehrfachzählung 
führt. Genau diese beiden Größen sind dann letztlich der Knackpunkt der 
Sache. Wenn man clever googelt, gibt es sogar dazu Statistiken zu 
finden...

Der Rest ist triviale Programmierung: Flankendetektion, Timeouts und 
Statusmaschinen.

> Ich möchte das ganze gerne in Bascom programmieren, eine andere Sprache
> beherrsche ich momentan nicht.

Das Verrückte ist: Wenn man programmieren kann (d.h. im Wesentlichen 
einfach nur: wenn man logisch denken kann), ist die Sprache weitgehend 
egal. Man muß sie halt nur lernen, um sie benutzen zu können, d.h.: 
entscheiden zu können, wie man das Problem mit den verfügbaren 
Sprachmitteln umsetzen kann. Dazu muß man im Minimum aber wenigstens 
alle wichtigen Features der verwendete Sprache kennen...

Du kannst aber offensichtlich nichtmal wirklich BASCOM, denn dein 
Problem scheint einfach die Zahl der Lichtschranken zu sein, d.h.: du 
hast wohl nicht gelernt, daß sowas wie Datenstrukturen und/oder Felder 
existiert und wie man das Zeug sinnvoll benutzt, wenn man dieselbe nicht 
völlig triviale Sache für mehr als eine Instanz von Irgendwas tun will.

Wie kannst du das lernen? Ganz einfach: systematisch.

1) Implementiere den Kram erstmal für nur genau eine Lichtschranke mit 
dem, was du bisher kannst.
2) Überlege, welche der im Programm verwendeten Variablen für die 
Lichtschrankenfunktion selber relevant ist.
3) Fasse diese Variablen zu einer Datenstruktur zusammen.
4) Schreibe dein Programm so um, daß des statt mit den ursprünglichen 
Einzelvariablen mit dieser Datenstruktur arbeitet.
5) Lerne, was Arrays sind.
6) Erzeuge ein Array deiner Datenstruktur mit sovielen Elementen, wie es 
Lichtschranken gibt. Schreibe deine Datenstruktur auf irgendeine 
Arrayposition, bloß nicht auf die erste.
7) Schreibe dein Programm so um, daß es mit der dieser Datenstruktur 
irgendwo im Array umgehen kann. Schreibe sie zum Test immer mal wieder 
auf irgendeine andere Position. Sorge dafür, daß diese Position 
programmweit gültig an genau einer Stelle festgelegt werden kann.
8) Letzter Schritt: Schreibe dein Programm so um, daß es alles, was es 
mit dem einen Arrayelement tut, mit allen gleichermaßen tut.

Fertig. Und du hast nebenbei ganz wesentliche Grundlagen des 
Programmierens ganz allgemein gelernt. Dann du wirst bald auch 
herausfinden, daß auch andere Sprachen Datenstrukturen, Arrays und 
Kontrollstrukturen wie If/else/endif oder for/next anbieten, auch wenn 
sich die Syntax im Detail unterscheidet, am Ende ist es immer nur wieder 
ein- und dieselbe langweilige Soße. Jedenfalls solange du im Bereich der 
Anweisungssprachen bleibst...

von Arne (Gast)


Lesenswert?

Mittlerweile läuft es für drei Kanäle, ich denke das auszuweiten auf 10 
wird jetzt kein großes Problem mehr sein.
Danke für die ganze umfangreiche Hilfe :)

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.