Pages: [1]   Go Down
Author Topic: Programmkonzept allgemein  (Read 618 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo...

ich habe hier ein Arduino Uno mit viel ext. Hardware.
Dazu zählen Entfernungssensoren (0...5V) TSOP, LCD(i²C), Motortreiber-Shield, sonstige Eingänge(i²c), Eine Echtzeituhr(i²c), und ein Buetooth-Modul.

Jetzt möchte ich einen Roboter programmieren.

Aber wie mache ich es, dass ich die Signale nicht verpasse, z.B. wenn ich die i²c Routine aufrufe oder die Spannung messe, oder in einem Unterprogramm bin ?

Waäre super, wenn jemand seine Erfahurung dazu posten kann.  :-)

MfG
Logged

Germany
Offline Offline
Full Member
***
Karma: 1
Posts: 130
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo werauchimmer,

der Loop() wird im Prinzip so schnell hintereinander ausgeführt, wie der dahinterliegende Code benötigt.
Wie du schon korrekt erkannt hast, würde also ein Funktionszweig der sehr lange benötigt, eine andere Funktion in diesem Zeitraum "sperren".

Um das zu umgehen, sollten die Methoden möglichst schlank programmiert werden und ohne Verzögerungstimer auskommen. Soll etwas künstlich verlangsamt werden, so speichere die aktuelle Zeit, laufe weiter den Loop durch und rufe die Methode erst auf wenn eine bestimmte Anzahl von Ticks vergangen ist.
Genauso mit Schleifen. Bevor du ein for(int i=0; i<99999;i++) nutzt, lagere den Methodenaufruf in den Loop aus und erstelle eine globale Variable für den Zähler.

Das sind so die beiden Sachen auf die ich beim Design achten würde. Der Rest kommt von allein smiley
Logged

Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bevor du ein for(int i=0; i<99999;i++) nutzt, lagere den Methodenaufruf in den Loop aus und erstelle eine globale Variable für den Zähler.

Hallo,

kannst Du evtl. konkretisieren, was Du mit "auslagern" meinst.

Danke.

Gruß Chris
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Beispiel:

ich habe ja diesen TSOP. Um festzustellen, ob diese Signale empfängt ist ja noch einfach, aber um das gesamte Paket zu empfangen brauch ich ja eigenlich schon ein mal millisekunden. In der Zeit kann ich aber andere TSOPs nicht auswerten.

In den Beispielen wird leider immer nur gezeigt, wie man eine Sache machen könnte. Ein Mix gibt es als Beispiel eigentlich nie.

Beispiel BLINK LED
so ungefähr (Schemenhaft)
Start:
led=ein
warte 1 Sekunde
Led=aus
Warte 1 Sekunde
Gehe zu Start

Da ist nichts mehr mit TSOP... smiley-confuse

Oder hat jemand ein Beispiel, wie man das Protokoll von 2..3 TSOPs auswertet, ein LCD (i²c) beschreibt, weitere Eingänge/oder die RTC mittels i²c abfragt/setzt, ggf. auf einen Interupt wartet und darauf reagiert usw ???

Wäre super wenn man sowas mal in echt sehen könnte...

MfG
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich vermute mal, das folgendes gemeint ist.

Aus:
Code:
...
void loop() {
    //irgendwelcher Code

    for(int i=0;i<9999;i++) {
        //mache irgendwas 9999 mal und blockiere dabei alles andere solange
    }

}
...
wird:
Code:
int counter = 0; //globaler zähler

void loop() {
    //irgendwelcher Code

    if(counter++ < 9999)
        run_code();
    ...
    //irgendwann wird counter wieder auf 0 gesetzt, damit die 9999er schleife wieder von vorn anfängt zu laufen
    if(wasauchimmer) counter = 0;
}

void run_code {
        //mache irgendwas, aber blockiere dabei nicht alles andere solange
    }

...

Damit wird der Code in der Funktion "run_code()" auch 9999 aml ausgeführt, aber ohne für diese Zeit den restlichen Code in loop() zu blockieren, weil pro loop() Durchlauf das run_code() nur einmal aufgerufen wird.

Das ist natürlich nur ein "abstraktes" Beispiel, eine konkrete Umsetzung hängt immer von der Aufgabe ab.

Mario.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ein noch nicht durchdachter Grundgedanken wäre, inen Interupt zu nutzen der z.B. alle 0,1 ms eine Routine aufruft.
In dieser routine wird dann über select case jeweils nur eine andere Unteroutine aufgerufen

so ungefähr...

Aufgerufene_Interuptrtroutine:
CC=cc+1
if cc>5 dann xx=1
gosub prüfe_TSOP1
gosub prüfe_TSOP2

if cc=1 dann hole_die_Zeit
if cc=2 dann Messe_den_Abstand
if cc=3 dann Schreibe_das_LCD_wenn_nötig
if cc=4 dann Lese_die_Eingaenge_i2c
if cc=5 dann Lege_die_richtung_fest

ende_Aufgerufene_Interuptrtroutine:

Dann darf natürlich jede Routine nur 0,1ms dauern
man muß ja nicht alle 1ns die Entfernung messen


Könnte das gehen???

Ich brauche dann natürlich viele globale Variablen...

MfG
Logged

AREA COLOGNE
Offline Offline
Edison Member
*
Karma: 15
Posts: 1067
I am 1 of 10 who understands binary
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Für Siganle kannst du ext. Interrupts nehemen.
Hier http://arduino.cc/playground/Main/MsTimer2
sind noch interne Interrupttimer der alls x ms (mininmum 1ms) ein Funktion aufrufen kann. Damit kannst du gut Zeitkritische Signale auswerten.
Ausserdem sollte man die Geschwindigkeit nicht unterschätzen (vorausgesetzt man nutzt keine delays). Ich habe ein Programm für den Arduino der mit SPI extern mit zwei MAX7221 spricht und einige Berechnungen macht ingeseamt 12kB Code und die Durchlaufzeit des Programms ist zwischen 600-900µs.
Ich würde sagen erstmal "so einfach"  wie möglich alles in die Main loop packen und dann sehen ob man Sachen mit Interrupts machen muss. Mein Vorschlag für den Anfang. Der I2C ist ja auch nicht langsam mit seinen max 400kHz. Man konnte von 100 auf 400kHz in der lib umschalten. Korekktur war früher mal.
Gruß
Der Dani
« Last Edit: September 20, 2012, 08:57:38 am by volvodani » Logged

So ist das Leben:
Manchmal bis du das Denkmal, manchmal die Taube!

Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

CC=cc+1
if cc>5 dann xx=1
gosub prüfe_TSOP1
gosub prüfe_TSOP2

if cc=1 dann hole_die_Zeit
if cc=2 dann Messe_den_Abstand
if cc=3 dann Schreibe_das_LCD_wenn_nötig
if cc=4 dann Lese_die_Eingaenge_i2c
if cc=5 dann Lege_die_richtung_fest
Das kannst Du doch ebenso in die loop() schreiben. Denn dauert das Abarbeiten einer Unterroutine länger als 0,1ms dann hast Du eh ein Problem das sich die Aufrufe stapeln. Geht es schneller, dann ist das eher besser als schlechter. Ein timer gesteuerter Interrupt bringt hier keinen großen Vorteil. Wenn Du das Ganze relativ zeitgenau haben willst, dann schau Dir mal Blink without delay an, da ist erklärt, wie man trotz loop() eine definierte Zeit verstreichen läßt, ohne delay zu verwenden.
Ich finde 0,1 ms schon recht wenig, das sind gerade 100 Mikrosekunden.

Code sieht dann ggf. so aus:

Code:
int cc = 0

void loop() {

switch(cc++ % 5) {

    case 0:
                // dann hole_die_Zeit
                break;
    case 1:
                // dann Messe_den_Abstand
                break;
    case 2:
                // dann Schreibe_das_LCD_wenn_nötig
                break;
    case 3:
                // dann Lese_die_Eingaenge_i2c
                break;
    case 4:
                // Lege_die_richtung_fest
                break;

}

}

Logged

AREA COLOGNE
Offline Offline
Edison Member
*
Karma: 15
Posts: 1067
I am 1 of 10 who understands binary
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wozu dieses Switch case dann kann mann das auch einfach hintereinanderwegschreiben. Dann hat man wohl die größte Performance.
Man könnte auch z.B. sagen das das Display nur jede sek. einmal aktualisiert wird oder ähnliches.
Man kann nämlich sehr sehr viel innerhalb 1s machen wenn man sich an eingige Regeln hält.

Logged

So ist das Leben:
Manchmal bis du das Denkmal, manchmal die Taube!

Pages: [1]   Go Up
Jump to: