mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LED Blinken zur Datenflusskontrolle


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

einfaches Problem:

Ich möchte eine LED Blinken lassen um den Datenfluss einer Seriellen
Schnittstelle zu visualisieren, dabei soll die LED umso schneller
Blinken (Sichtbares Blinken), je schneller die Daten kommen

Ich finde keine einfache lösung, die den Prozessor nicht zu stark
belastet, bitte helft mir

Autor: Bolle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Findest Du denn eine einfache Lösung für das Problem "LED mit
konstantem Takt blinken lassen, bei minimaler Prozessorbelastung"?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich denke mal mit timer wird dass gehen

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LED an die RXD- und TXD-Leitung über einen Treiber anschliessen und
schon blinken die Dinger, sobald Datenfluß vorhanden ist.
Andere Möglichkeit:
PortPin in der InterruptServiceRoutine togglen. Oder einen Timer
beschreiben, der wiederum das Blinken der LED verursacht.

Übrigens 1A-schwammig ausgedrückt: Welche serielle Schnittstelle? Die
eines Mikrocontrollers oder die eines PC? So Festplatten-LED mässig...

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meine die Serielle Schnittstelle eines AVR und die LEDs sollen
SICHTBAR Blinken 115 KBd sind nicht gerade sichtbar !!!

Autor: Bolle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ist es!  Arbeitet Dein Programm auf Timerbasis?  Oder gibt es
"Delayschleifen" nach Art von "FOR i=0...100000 TueNichts"?  Falls
die erste Alternative zutrifft, ist Dein Problem relativ leicht lösbar
(merke: Timer = schlau, Delayschleifen = doof!). Wie groß (ms) ist das
"Tickintervall" des Timers der Dein Programm steuert?

Autor: Ratber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wärs denn mit folgender Überlegung:


Wenn die Schnittstelle Aktiv ist dann springst du ja in die
entsprechende Routine um die Schnittstelle zu bedienen (Daten
Holen/Abliefern)

Was spricht dagegen am Afang der Routine die LED einzuschalten und am
ende wieder aus ?

Je nach Zugrif dürfte sich dann eine art "Pseudo-PWM-Effekt"
einstellen.
Jedenfalls sieht man wenn die Serielle aktiv ist.


Oder du verwendest die Ide von Rahul und verfeinerst sie einwenig in
Bezug auf Geschwindigkeitsanzeige.
Die Methode kostet dann überhaupt keine Rechenzeit.


Probier einfach mal .
Ne Transe nebst Widerstand und evtl. Kondensoator hatse ja wohl noch
inner Schublade.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt noch keinen Timer in meinem Programm
und nur für eine LED einen Timer verheizen, ich weis nicht
Eine Delayschleife geht auch nicht wegen der Prozessorauslastung

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich will einfach nur den Effekt haben den man bei externen
Festplattengehäusen (die LED daran) oder der HDD LED eines PC´s hat,
Schneller Datenverkehr --> schnelles Blinken

Autor: Bolle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Eine Delayschleife geht auch nicht wegen der Prozessorauslastung

Richtig!  Und deshalb bleibt nur der Timer.  Allerdings: Wenn Du nicht
nur die UART-Strom-Anzeige-Blink-LED haben willst, sondern z. B. auch
noch eine Echtzeituhr in Deine Software integrieren willst, dann
brauchst Du nicht je einen Timer für die LED und die Uhr, sondern Du
brauchst nur einen Timer für beide Aufgaben!  So ein µC hat genügend
Leistung, um locker 28 Aufgaben zeitgleich zu bewältigen (1.
Echtzeituhr, 2. Temperatursensor auslesen plus Daten loggen, 3.
Siebensegmentanzeige im Multiplexverfahren ansteuern, 4. Mit PC über
UART kommunizieren, 5. Relais für 1 min einschalten wenn Temperatur zu
klein, 6. Zustand einer Pumpe überwachen, 7. ..., 8. ... usw.).  Damit
das alles geordnet abläuft, muß so ein Multitasking-Programm
timergesteuert arbeiten.  *Aber*: Du brauchst nicht für jeden Task
einen eigenen Timer, sondern bloß einen Timer für alle Tasks.  Man
könnte sagen, Du hängst praktisch Dein komplettes Programm an einem
einzigen Timer auf.  Damit relativiert sich das dann auch mit dem
"Verheizen" ;-).

Jetzt kommt's darauf an, ob Du Dich mit der Timersache anfreunden
kannst. Nochmal: Auf Delayschleifenbasis wirst Du die Blink-LED nicht
realisieren können.

Autor: Ithamar Garbe (antimon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal ne generelle Frage zum Thema: Bei Festplatten geht ne LED an, wenn
Daten übertragen werden, bei Netzwerkkarten ist es meist so, dass die
LED ausgeht wenn Traffic fliesst, also quasi andersrum wie bei
Festplatten.
Aber bei beiden zeigt die Blinkfrequenz die Auslastung an - wie wird
das da realisiert? Läuft das irgendwie gequantelt mit bestimmten Stufen
ab? Bei ein oder zwei Bytes wird vermutlich ja noch kein Blinken zu
erkennen sein oder?

Autor: Jochen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ach wenn meine festplatte auf volllast ist blinkt bei mir übrigens nix
mehr
du hats uns ja sehr genau beschriben wie es blinken soll ????? :)
na wenn du nicht programmieren willst bzw. den µC nicht belasten willst
bleibt nur noch die digitaltechnik überig
bastel dir halt was aus cmos 4xxx bausteinen und hängs an die rdx tdx
leitungen
hab mir kurz was überlegt siehe anhang

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach hab nen fehler reingebracht das xnor gatter ist ein nor gatter

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass muss doch irgendwie einfacher gehen, ohne timer, ohne extra
Hardware. Ist doch nur ne LED

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> und nur für eine LED einen Timer verheizen, ich weis nicht.

Wieso "verheizen"? Wer hält dich davon ab, den Timer noch für andere
Sachen zu verwenden?

> Dass muss doch irgendwie einfacher gehen, ohne timer, ohne extra
> Hardware. Ist doch nur ne LED

Du willst keine Rechenzeit verbrauchen, keine anderen Ressourcen der
MCU, aber auch keine externe Hardware verwenden. Wie soll die LED denn
dann wissen, wann sie leuchten soll?


Egal. Warum nicht einfach so: In der Interrupt-Routine der
Schnittstelle dekrementierst du für jedes übertragene Byte eine
Zählvariable, die vorher auf einen vorgegebenen Wert initialisiert war.
Wenn sie bei 0 angekommen ist, toggelst du die LED und initialisierst
den Zähler wieder neu. Bei vielen Bytes pro Sekunde blinkt sie dann
schnell, bei weniger Bytes langsam, und über den Anfangswert des
Zählers kannst du das Verhältnis zwischen Datenrate und
Blinkgeschwindigkeit leicht anpassen.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ich schon probiert, wenn ich aber mit dem Terminalprogramm einzelne
Bytes verschicke, geht garnichts mit der LED da durch die Zählvariable
immer nur jedes Hundertste Byte angezeigt wird.

ABER dies ist die Lösung die mir bis jetzt am besten gefällt da sie
sehr Rechenzeitsparend ist.

Mein Problem ist noch:

Die LED dienen in den Sendepausen als indikatoren ob die RS232
überhaupt freigeschaltet ist oder nicht (kann vom PC aus gesteuert
werden über einen USB Baustein)

ALSO:

LED an --> RS232 berreit
LED aus --> RS232 nicht freigeschaltet
LED Blinken --> RS232 arbeitet

Mein Problem

Die LED soll immer AN sein (wenn rs232 aktiv) und bei Datenverkehr
blinken, dies ist aber durch toggeln nicht gewährleistet und wenn ich
die LED in der Hauptschleife immer wieder anschalte sieht man kein
Blinken mehr, da die Hauptschleife 90% aller Zeit beansprucht

Autor: Bolle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal angenommen, ich stelle Dir folgende Aufgabe:

--------------------------------------
"Zeitschaltuhr": Beim Drücken einer Taste soll eine LED angehen, 3
Sekunden lang leuchten und danach ausgehen.  Das ist alles, was der µC
zu erledigen hat.
--------------------------------------

Diese Aufgabe ist leicht lösbar, und es gibt sogar zwei Ansätze: Mit
Delayschleife oder mit Timer.

Voll easy, meinst Du sicher.  Aber warte, denn jetzt kommt die nächste
Aufgabe:

--------------------------------------
"Doppel-Zeitschaltuhr": Es gibt ZWEI Tasten Ta und Tb, und ZWEI LEDs
La und Lb. Beim Drücken der Taste Ta soll die LED La angehen, 3
Sekunden lang leuchten und danach ausgehen.  Genauso soll es sich mit
Tb und Lb verhalten.  Beide Zeitschaltuhren sollen völlig unabhängig
voneinander sein (genau so, als liefe jede auf einem eigenen µC).
--------------------------------------

So, und jetzt denk mal darüber nach, wie kompliziert oder einfach das
ist, wenn Du die Einzel_Zeitschlatuhr mit Delayschleifen realisiert
hast, und wie kompliziert oder einfach es ist, wenn Du sie mit einem
Timer realisiert hast.  Wie lauten Deine Antworten?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jochen: Bei mir blinkt keine LED mehr, wenn die Festplatte läuft.
Zumidest sehe ich es nicht, weil sie im Gehäuse liegt...

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Mr Bolle,

wiso sprichst du immer in Rätseln???

Natürlich wird deine aufgabe mit doppelter Zeitschaltuhr nur mit
Timer(n) möglich sein die einen Interrupt auslösen.

Aber was heisst das für meinen Fall.

Wie würdest du das Konkret Regeln für eine Serielle Schnittstelle mit
RX und TX Kanal die Beide eine LED Blinken lassen sollen bei
Datenverkehr???

Autor: TravelRec. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zähle die Bytes pro Timerumlauf, nimm diese Zahl X und subtrahiere sie
von einer anderen Zahl Y, die Du alle paar Timerumläufe auf 255
initialisierst (an die gewünschte Blinkfrequenz anpassen). Durch diese
Zahl Y teilst Du die umlaufende Timerfrequenz in einem Softwarezähler,
den Du in der Timer-ISR mit decrementierst und was dabei ´rauskommt,
gibst Du auf die LED. Wenn kein Byte transferiert wird und Zahl Y immer
255 ist, ist die LED an (Vergleich auf 255 ausführen). Wenn ein Byte
transferiert wurde und Y demzufolge 254 ist, dann soll der Teil-Zähler
in der Timer-ISR loslaufen und die LED blinkt 1 mal. Ist danach Y
wieder 255, dann war´s das mit blinken, wenn nicht, blinkt´s weiter. Je
kleiner Y wird, weil mehr Bytes pro Timerdurchlauf transferiert wurden,
desto öfter und schneller blinkt´s. Die an/aus-Zeiten der LED kann man
in dem Softwarezähler durch Vergleiche festlegen.

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
machs so wie rolf
und ein timer kannst dazu verwenden die LED nach entsprechender zeit
wieder auf high zu setzen
z.b.
timer hat T=1ms
flag für verkehr während des letzten 1ms
wenn verkehr
flag zurücksetzten
wenn kein verkehr
LED high setzen
evtl. auch zähler in den isr der rs232 rücksetzen

da du leider nicht angibts ab wann was blinken soll ....

T bestimmt hier die zeit in der ein byte übertragen werden muss damit
es als verkehr/arbeit durchkommt

ach ja und ich würde sofort bei ner isr der rs232 das LED low setzen
nähmlich wenns nur ein byte war wird es spätesten eben nach T=1ms
zurückgesetzt und das ist eher weniger sichtbar

Autor: Storr der Schnitter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wär's hiermit:

//------------------------------//
#define OFF    0  //
#define ON    1  //
        //
#define BLINK_MAX  100  // Gesamtzyklen
#define BLINK_ON  50  // Zyklen fuer On-Zeit
        //
unsigned char uiCount;    // Zaehlregister
unsigned char ucState;    // Statusregister
        //
//------------------------------//
void v_Blink (void)    //
{        //
uiCount++;      // Zaehlregister inkrementieren
if(uiCount <= BLINK_ON)    // ON waehrend On-Zeit
   ucState = ON;    //
else {        //
   if(uiCount < BLINK_MAX)  // OFF waehrend Off-Zeit
  ucState = OFF;    //
   else  {      //
  uiCount = 0x00;    // Zaehlregister ruecksetzen
  ucState = OFF;    //
  }      //
   }        //
}        //
//------------------------------//
void main (void)    //
{        //
while(1)      //
   {        //
   v_Blink();      //
        //
   }        //
}        //
//------------------------------//

Du brauchst jetzt nur noch das Statusregister ucState, verknüpft mit
dem Status der Schnittstelle, auf den LED-Port zu geben und schon
blinkt Deine LED. Außerdem müssen noch die Anzahl der Zyklen an die
while-Schleife angepasst werden.

Gruss, Jan

Autor: Storr der Schnitter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wär's hiermit:

//------------------------------//
#define OFF             0       //
#define ON              1       //
                                //
#define BLINK_MAX       100     // Gesamtzyklen
#define BLINK_ON        50      // Zyklen fuer On-Zeit
                                //
unsigned char uiCount;          // Zaehlregister
unsigned char ucState;          // Statusregister
                                //
//------------------------------//
void v_Blink (void)             //
{                               //
uiCount++;                      // Zaehlregister inkrementieren
if(uiCount <= BLINK_ON)         // ON waehrend On-Zeit
   ucState = ON;                //
else {                          //
   if(uiCount < BLINK_MAX)      // OFF waehrend Off-Zeit
        ucState = OFF;    //
   else  {                       //
        uiCount = 0x00;         // Zaehlregister ruecksetzen
        ucState = OFF;          //
        }                       //
   }                            //
}                               //
//------------------------------//
void main (void)                //
{                               //
while(1)                        //
   {                            //
   v_Blink();                   //
                                //
   }                            //
}                               //
//------------------------------//

Du brauchst jetzt nur noch das Statusregister ucState, verknüpft mit
dem Status der Schnittstelle, auf den LED-Port zu geben und schon
blinkt Deine LED. Außerdem müssen noch die Anzahl der Zyklen an die
while-Schleife angepasst werden.

Gruss, Jan

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke wenn diese Schleife mit einem Prozessor an 14745600 Hz
durchlaufen wird, blinkts ganz schoen schnell, oder nicht ??

Wie meinst du dass mit dem Verknüpfen der Seriellen Schnittstelle und
ucState, und wo gehe ich auf den PORT der LED ???

Autor: Bolle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> wiso sprichst du immer in Rätseln???

Es gibt hier eine Menge anti-timer-eingestellte User.  "Timer? Braucht
man nicht! Nur Verschwendung wertvoller Ressourcen! Geht alles mit
Delayschleifen!  Ich will doch nur [irgendeine Aufgabenstellung, die
darauf hinausläuft, daß mehrere Tasks gleichzeitig parallel ausgeführt
werden sollen], aber ich möchte es auf jeden Fall mit Delayschleifen
programmieren, denn die kenne ich, damit kam ich bisher prima zurecht,
weshalb ich nicht sehe, wozu ich mich jetzt mit Timern beschäftigen
sollte (nur unnötig kompliziert...)".

Ich wollte Dir mit dem Doppelt-Zeitschaltuhr-Beispiel verdeutlichen,
daß mit Delayschleifen eben nicht alles geht, sondern im Gegenteil, daß
der Delayschleifen-Ansatz extrem begrenzt ist: Schon bei zwei
unabhängigen Zeitschaltuhren ists Essig. Wie kann man dann aber eine
Anwendung realisieren, bei der es gefordert ist, daß der Controller 5
oder 12 oder 30 Aufgaben parallel bewältigt?  Delayschleifen? Keine
Chance! Wenn dem aber so ist, dann bleibt nur noch der Timeransatz.
Weiter oben im Thread habe ich schon mal geschrieben "Timer = schlau,
Delayschleifen = doof".  "Schlau" weil mit Timern alle
Multitasking-Möglichkeiten offenstehen.  Damit ich Dir helfen kann,
mußt Du das jedoch erstmal verstanden haben.

>Natürlich wird deine aufgabe mit doppelter Zeitschaltuhr nur mit
>Timer(n) möglich sein die einen Interrupt auslösen.

Ja!  Aber wieviele Timer benötigt man? Zwei? Oder geht es auch mit
einem?  Wieviele Timer würde man für eine Zehnfach-Zeitschaltuhr
benötigen? Zehn oder einen?  Wüßtest Du eine Lösung, die nur einen
Timer benötigt?  Wie sähe sie aus?  Die Antworten auf diese Fragen sind
wichtig.

>Wie würdest du das Konkret Regeln für eine Serielle Schnittstelle mit
>RX und TX Kanal die Beide eine LED Blinken lassen sollen bei
>Datenverkehr???

Soviel vorweg: Mit Timer ist die Aufgabe ein Klacks.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon wiedr Rätsel ;)

Also zu deinen Zehn Zeitschaltuhren:

Zehn Zählvariablen die bei Tastendruck freigegeben werden durch Meker

(Strom --> AN)

und dann in EINER Timerroutine hochgezählt werden bis zum Zielwert

(Strom-->wieder aus)

Also war dass Korrekt???

>Soviel vorweg: Mit Timer ist die Aufgabe ein Klacks.

Jetzt kannst du mir ja mal deine Klacks verraten

Autor: Bolle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon wiedr Rätsel ;)

>Also zu deinen Zehn Zeitschaltuhren:
>
>Zehn Zählvariablen die bei Tastendruck freigegeben werden durch Meker
>
>(Strom --> AN)
>
>und dann in EINER Timerroutine hochgezählt werden bis zum Zielwert
>
>(Strom-->wieder aus)
>
>Also war dass Korrekt???

Korrekter geht's gar nicht.  Verstehst Du, daß sich die Zählvariablen
sozusagen als *Software*-Timer interpretieren lassen?  Jede
Zeitschaltuhr stellt einen Task dar, und jeder der Tasks hat seinen
eigenen Software-Timer (je nach Anwendung könnte es natürlich auch
Tasks geben, die mehrere Softwaretimer haben). Software-Timer sind
nämlich keine knappe Ressource, sie benötigen ja nur RAM-Speicher.
Hardware-Timer stellen eine knappe Ressource dar (der ATMega8 hat z. B.
nur drei Stück), aber dafür benötigt man nur einen Hardware-Timer, der
die 28 Software-Timer (oder wieviele alle Tasks halt zusammen haben)
"antreibt".

Wichtig ist auch, verstanden zu haben, daß der Hardware-Timer, der die
28 Software-Timer in einem timergesteuerten Programm treibt, niemals
gestoppt werden muß.  Er läuft permanent.  Gestartet und gestoppt
werden nur die Software-Timer; für sie gibt es den Zustand
"läuft"/"aktiv" und den Zustand "läuft nicht"/"inaktiv" (Deine
"Merker"-Variable dient dazu, diesen Zustand zu speichern).

Eine Frage bleibt noch: Mit welcher Frequenz soll der Hardware-Timer
laufen?  Dazu kann man nur sagen: Sie darf nicht zu hoch und nicht zu
niedrig sein.  Sie darf nicht zu hoch sei, damit der µC noch eine
gewisse Anzahl von Befehlen abarbeiten kann, bevor er die
Timer-Interruptroutine wieder verläßt.  Und sie darf nicht zu niedrig
sein, damit das Programm noch genügend schnell auf z. B. Tastendrücke
reagiert.  Damit ist man in der Praxis ganz grob auf den Bereich 1 ms
...100 ms eingeschränkt.  Während 1 ms schafft ein ATMega8 bei 4 MHz
noch ca. 2000 Instruktionen; bei 10 Tasks darf dann jeder immerhin noch
200 Instruktionen rechnen.

So, jetzt bist Du bestens vorbereitet.

>Jetzt kannst du mir ja mal deine Klacks verraten

Die Aufgabe besteht offensichtlich aus zwei Tasks:
1. Der Pro-Zeiteinheit-eintreffende-UART-Daten-Zähl-Task
("PZEUD-Task"), und
2. Der LED-Blink-Task ("LB-Task").

In den Interrupt-Handler des Hardware-Timers, der Dein Programm
steuert, fügst Du also zu der Liste der Tasks, die dort schon stehen,
folgende Unterroutinen hinzu:

Run_PZEUD_Task
Run_LB_Task

Der PZEUD-Task hat wie schon erwähnt die Aufgabe, die pro Zeiteinheit
eintreffenden UART-Daten zu zählen.  "Pro Zeiteinheit" deutet schwer
darauf hin, daß der Task einen Software-Timer benötigt.  Ich nenne ihn
"k".  k zählt ununterbrochen von 0 bis zu einem Maximalwert und
startet danach wieder bei Null.  Der Maxwert definiert die Zeiteinheit
("Torzeit").  Sie könnte z. B. bei 250 ms liegen.

Kommt nun über den UART ein Byte hereingeschneit, dann muß das
registriert werden, in einer Zählvariable "DataInAkku".  In den
USART-Receive-Interrupt mußt Du also ein "Inc(DataInAkku)" einfügen.


Jedesmal, wenn der k-Zähler nun seinen Max-Stand erreicht hat (d. h. es
sind mal wieder 250 ms um), wird der DataInAkku-Zähler in einer Variable
"DataInCount" abgespeichert, und danach auf Null resettet.  Sinn des
Ganzen: DataInCount enthält dann zu jedem Zeitpunkt (!) die Anzahl der
über den UART während der letzten Torzeit empfangenen Bytes. Er stellt
somit ein Maß dafür dar, wieviel gerade auf der UART-Receive-Leitung
los ist. Und er wird mit einem Takt von 250 ms laufend geupdatet.

Nun zum LB-Task. Er kümmert sich um die LED.  Da die LED gemütlich
blinken soll (Sekundentakt), der Hardware-Timer aber rast, brauchen wir
hier ebenfalls einen Software-Timer, repräsentiert durch die Variable
"BlinkIntervalAkku".  BlinkIntervalAkku wird laufend inkrementiert
bis zu einem Max-Stand, dann auf Null resettet und die LED getoggelt.
Man könnte nun stets um 1 inkrementieren; dann bestimmt der Max-Stand
die Blinkfrequenz.  Es steht aber nirgendwo, daß wir nicht z. B. auch
um 8 inkrementieren dürfen; bei 8-fachem Max-Stand führt das zur selben
Blinkfrequenz.  Bei gleichem Max-Stand führt die Inkrementation mit 8
jedoch zur 8-fach schnelleren Blinkfrequenz!  Also: Max-Stand wird auf
einen Wert festgelegt und niemals verändert; der Inkrementationsschritt
i aber ist nicht immer derselbe: i = 1 -> Langsames Blinken, i = 2 ->
doppelt so schnelles Blinken, i = 5 -> fünffach so schnelles Blinken.
Im Grunde wird hier übrigens eine Division durchgeführt, und zwar
Max-Stand/i.

Und jetzt kommt der Clou: Du verwendest als Inkrementationsschritt die
DataInCount-Variable aus dem PZEUD-Task!  Damit bist Du praktisch
fertig.  Eine gesonderte Behandlung benötigt nur noch der Fall, daß mal
während einer Torzeit kein einziges Byte empfangen wird.  Dann würde der
BlinkIntervalAkku auf der Stelle verharren, und die LED ginge gar nicht
mehr an, wenn sie gerade aus ist und umgekehrt, was nicht erwünscht
sein dürfte.  Dagegen läßt sich aber leicht was tun.

Studiere mal diesen Code:


//-------------------------------
// Run_PZEUD_Task
//-------------------------------

Inc(k);

IF (k=...)
  {
  // wird alle 250 ms ausgeführt
  k := 0;
  DataInCount := DataInAkku;
  DataInAkku  := 0;
  }



//-------------------------------
// Run_LB_Task
//-------------------------------

IF (BlinkIntervalAkku=-1) AND (DataInAkku=1)
  {
  [LED aus]
  }
ELSE
  {
  IF (DataInCount=0)
    {
    [LED ein];
    BlinkIntervalAkku := -1
    }
  ELSE
    {
    Inc(BlinkIntervalAkku, DataInCount);

    IF (BlinkIntervalAkku>=...)
      {
      [LED togglen];
      BlinkIntervalAkku = 0
      }
    }

Dort wo "..." stehen, mußt Du passende Werte einsetzen (hängen u. a.
ab vom Tickintervall Deines Hardware-Timers).

War's einigermaßen verständlich?  Ansonsten einfach fragen. Dann
bekommst Du weitere Rätsel ;-).

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denn Cod ehabe ich fast verstanden sind da vieleicht noch einpaar
schreibfehler drin in den Zeilen:

> ...
> IF (BlinkIntervalAkku=-1) AND (DataInAkku=1)
> ...
>
>   [LED ein];
>    BlinkIntervalAkku := -1
> ...

ICH verstehe nicht warum du diese Variablen auf 1 bzw -1 abprüft.
Was bedeutet := ist dass eine Zuweisung? also nur =  ???

Ansonsten vielen Dank für die Hilfe werde dass heute Abend mal testen

____________________________

Ich habe übrigens währenddessen folgende Lösung gefunden und muss sie
mit deiner vergleichen welche schneller ist:

led1_ctr wird in der interruptroutine der Schnittstelle erhöht und
Zählt die bytes

softctr1 ist ein Softwarcounter

und die Merker brauche ich für einen definierten durchlauf der if
bedingungen

Dass ganze steht in einem Timmerinterrupt alle 30 ms und funktioniert
schon recht ordentlich.

  // Variable Blinkfrequenz LED1
  if ( led1_ctr )
  {
    softctr1 += led1_ctr;

    if ( (softctr1 > 100) && (merker1 == 2) )
    {
      led1_ctr = 0;
      softctr1 = 0;
      merker1 = 0;
    }

    else if ( (softctr1 > 50) && (merker1 == 1) )
    {
      merker1 = 2;
      led1_on();
    }

    else if (merker1 == 0)
    {
      merker1 = 1;
      led1_off();
    }

  }

Autor: Bolle (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
> ...
> IF (BlinkIntervalAkku=-1) AND (DataInAkku=1)
> ...
>
>   [LED ein];
>    BlinkIntervalAkku := -1
> ...

ICH verstehe nicht warum du diese Variablen auf 1 bzw -1 abprüft.
Was bedeutet := ist dass eine Zuweisung? also nur =  ???

Ja, ":=" ist eine Zuweisung (üblich z. B. in Pascal).

Der Zweck der von Dir angeführten Zeilen ist in der Tat nicht
offensichtlich. Sorry, hab ich nicht dran gedacht.  Hier also die
Erklärung.

  IF (DataInCount=0)
    {
    [LED ein];

Das sollte noch klar sein.  Wenn während eines Torzeit-Intervalls
einmal kein einziges Byte reingekommen ist ("Zero-Traffic"), dann
soll die LED an gehen, und zwar sofort, und danach soll sie dauerhaft
an bleiben, um den "Schnittstelle-Eingeschaltet"-Zustand zu
signalisieren.

Besteht der Zero-Traffic für 5 Minuten, dann ist die LED wie gewünscht
5 Minuten an.  Prima.  Aber dann kommt ein einziges Byte herein!  Du
kannst Dir überlegen, daß ein solches einzelnes Byte bei diesem
Algorithmus unter Umständen nicht reicht, um das LED-Blinken
"auszulösen".  Es wäre also der Fall denkbar, daß Du - z. B. zu
Testzwecken - einzelne Bytes im Sekundenabstand von Deinem PC zu dem
Modul sendest, die LED das aber nicht anzeigen würde; sie würde
einfach konstant an sein.

Das ist nun blöd.  Es wäre sicher toll, wenn bei so einem "einzelnen
Byte" die LED kurz ausgehen würde, um den Eingang zu signalisieren.
Genau dies ist der Sinn hinter dem BlinkIntervalAkku := -1.  Wenn
einmal Zero-Traffic detektiert wurde (DataInCount=0), wird
BlinkIntervalAkku auf den "Zero-Traffic-Spezialwert" -1 gesetzt, und
behält ihn auch, weil "Inc(BlinkIntervalAkku, DataInCount)" keine
Wirkung hat bei DataInCount=0.

Kommt während einer der Zero-Traffic-Phase ein einzelnes Byte, dann ist
die Bedingung "IF (BlinkIntervalAkku=-1) AND (DataInAkku=1)" erfüllt,
und die LED wird sofort ausgeschaltet.  Damit sie wieder an geht, ist
keine weitere Extra-Maßnahme erforderlich, das läuft ganz normal über
den schon vorhandenen Mechanismus.

Interessant ist, daß diese lächerlichen paar Zeilen in der Praxis
verblüffend gut funktionieren.  Ich hatte mit dieser Aufgabenstellung
mal vor längerer Zeit in eigener Sache zu tun, und den Algorithmus zu
Testzwecken in einem Delphi-Programm simuliert.  Du findest es im
Anhang. Das Eintreffen eines UART-Bytes simulierst Du durch Drücken
irgendeiner Taste. Die angezeigte Zahl ist der DataInCount-Wert. Das
Timer-Intervall beträgt 20 ms, die Torzeit 500 ms.

>Ich habe übrigens währenddessen folgende Lösung gefunden und muss sie
>mit deiner vergleichen welche schneller ist:

Äh schneller? Das verstehe ich jetzt nicht.  Inwiefern soll hier eine
Lösung schneller sein, als die andere?

Ich habe Deine Lösung aus Zeitgründen nur überflogen; ich bitte um
Verständnis.  Wenn ich es richtig gesehen habe, verwendest Du keine
feste Torzeit.  Ich weiß nicht, ob das gut ist.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.