Forum: Mikrocontroller und Digitale Elektronik Funktion mehrfach aufgerufen geht nicht mehr.


von Stefan (Gast)


Lesenswert?

Hallo,

ich habe mir eine Funktion geschrieben die mehrmals mit 
unterschiedlichen Übergabewerten aufgerufen werden soll.
Diese Funktion gibt etwas auf der seriellen Schnittstelle aus.
In meinen Fall merke ich, dass nur Eine alleine funktioniert. Sobald ich 
eine zweite
1
TasterDimmenAufAb (xx,xx);
 aufrufe, funktioniert das nicht mehr. Auch der, der  schon funktioniert 
hat streikt.

Weiss jemand wodran das liegen könnte und mir dieses mitteilen?! Danke!
1
uint8_t TasterDimmenAufAb (uint8_t BitEingang, uint8_t BitStatus)
2
{
3
static uint16_t Tasterdruck_in_Zyklen=0;    
4
static uint8_t memmTasteGedrueckt=0;
5
static uint8_t aufab=0;    
6
static uint16_t Takt;
7
8
//#######################################################################
9
//Taster auswerten
10
//#######################################################################
11
     //Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet wird wenn hochgedimmt wurde!
12
   if (R_TRIG(!Eingang[BitEingang]) && Tasterdruck_in_Zyklen<500 && licht_status[BitStatus] && (!memmTasteGedrueckt))
13
    {
14
    licht_schalten[BitStatus] = 1;
15
    }
16
    
17
  //Einschalten wenn noch nicht an ist  
18
  if (R_TRIG(Eingang[BitEingang]) && (!licht_status[BitStatus]))
19
    {
20
    licht_schalten[BitStatus] = 1;
21
    memmTasteGedrueckt=1;
22
    }
23
    
24
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
25
  if    (R_TRIG(!Eingang[BitEingang]))
26
    {
27
    memmTasteGedrueckt=0;
28
    }
29
    //Länge des Tastendruckes aufzeichnen
30
  if (Eingang[BitEingang])
31
    {
32
    Tasterdruck_in_Zyklen++;
33
    }
34
  else
35
    {
36
    Tasterdruck_in_Zyklen=0;
37
    }
38
    
39
//#######################################################################
40
//Dimmen
41
//#######################################################################
42
43
       // Wenn Taste länger gedrückt wird
44
  if (Tasterdruck_in_Zyklen >500)
45
    { 
46
        
47
          //Nach Zeit Dimmwert erhöhen      
48
          Takt++;
49
     
50
            if (Takt==15)
51
            {         
52
53
              if (u8SpeicherDimmwert[BitStatus] == 100) aufab = 1;
54
              if (u8SpeicherDimmwert[BitStatus] == 5) aufab = 0;
55
      
56
              //Wenn unter 100%, dann plus
57
              if (u8SpeicherDimmwert[BitStatus] <100 && !aufab)    
58
              {
59
              u8SpeicherDimmwert[BitStatus]++;          
60
              }
61
              // wenn 100 erreicht wurde wieder minus
62
              else if (u8SpeicherDimmwert[BitStatus] >5 && aufab)
63
              {
64
              u8SpeicherDimmwert[BitStatus]--;          
65
              }
66
              
67
              Takt=0;
68
            }
69
    }
70
//#######################################################################
71
//#######################################################################
72
  return   u8SpeicherDimmwert[BitStatus];
73
74
}


So werden beide Funktionen mit unterschiedlichen Übergabewerten 
aufgerufen:
1
if (1)
2
{
3
uint8_t memm1;
4
uint8_t memm1old;
5
6
memm1 = TasterDimmenAufAb (0,12);
7
8
   if (memm1!= memm1old)
9
     {
10
     memm1old=memm1;
11
     LichtDimmenAn (PSTR("88|11|05|%1i\n"),PSTR("89|11|05|01\n"),PSTR("98|11|05|%1i\n\r"),memm1 );
12
    }
13
}
14
     
15
  
16
if (1)
17
{
18
uint8_t memm2;
19
uint8_t memm2old;
20
21
memm2 = TasterDimmenAufAb (1,44);
22
23
   if (memm2!= memm2old)
24
     {
25
     memm2old=memm2;
26
     LichtDimmenAn (PSTR("88|15|05|%1i\n"),PSTR("89|15|05|01\n"),PSTR("98|15|05|%1i\n\r"),memm2 );
27
    }
28
}

von meinName (Gast)


Lesenswert?

Stefan schrieb:
> Diese Funktion gibt etwas auf der seriellen Schnittstelle aus.

An welcher Stelle gibt die Funktion denn etwas auf der seriellen 
Schnittstelle aus?

Woher weißt du, dass die Funktion nur einmal funktioniert?
Deine Fehlerbeschreibung finde ich etwas dürftig.
Lass eine LED kurz aufleuchten, wenn du in die funkion springst, schiebe 
den Aufleuchtbefehl schritweise durch die Funktion, wenn du meinst, es 
läge an der Funtkion - kurz gesagt - such dir ein Mittel für einfaches 
debuggen und stell fest, was eigentlich nicht so funktioniert, wie es 
geplant war

von tripod (Gast)


Lesenswert?

Wieso nutzt du in deiner Funktion Statische Variablen?? Das verursacht 
Seitenefekte die nicht immer gewünscht sind also das Schlüsselwort 
"static" nur gut überlegt verwenden.

von Stefan (Gast)


Lesenswert?

tripod schrieb:
> Wieso nutzt du in deiner Funktion Statische Variablen?? Das verursacht
> Seitenefekte die nicht immer gewünscht sind also das Schlüsselwort
> "static" nur gut überlegt

Glaub da ist auch mein Fehler. Was genau passiert mit den Static wenn 
die Funktion das zweite mal, mit anderen Übergabewerten, aufgerufen 
wird?
Generell steht Static ja für:
 Im Kontext einer Variablendeklaration innerhalb einer Funktion sagt 
dieses Schlüsselwort, dass diese Variable auf einer festen 
Speicheradresse gespeichert wird. Daraus ergibt sich die Möglichkeit, 
dass eine Funktion, die mit static-Variablen arbeitet, beim nächsten 
Durchlauf die Informationen erneut nutzt, die in der Variablen 
gespeichert wurden (wie in einem Gedächtnis).

Gilt das denn auch wenn die Funktion das zweite mal mit anderen 
Übergabewerten aufgerufen wurd? Dann sollen natürlich neue Variablen 
angelegt werden. Die dann jeweils in der Funktion benutzt werden können.

von Björn B. (elmo)


Lesenswert?

Stefan schrieb:
> Glaub da ist auch mein Fehler. Was genau passiert mit den Static wenn
> die Funktion das zweite mal, mit anderen Übergabewerten, aufgerufen
> wird?

Normal werden lokale Variablen innerhalb einer Funktion erst beim 
Aufrufen der Funktion erzeugt und nach dem Verlassen wieder freigegeben. 
Dadurch kann man die Funktion z.B. mehrfach verschachtelt (rekursiv) 
aufrufen, ohne dass es zu Problemen kommt.

Mit dem Ausdruck "static" ändert sich dieses Verhalten. Die Variablen 
innerhalb der Funktion sind permanent im Speicher, quasi wie globale 
Variablen. Verlässt man die Funktion, bleiben die Werte erhalten. Ruft 
man die Funktion zweimal "gleichzeitig" auf, zB einmal im Hauptprogramm, 
einmal im Interrupt, knallts so richtig ;-)

Gruß
Björn

von DirkB (Gast)


Lesenswert?

Und die Initialisierung wird nur einmal (beim ersten Aufruf oder davor) 
durchgeführt. Danach behalten die static-Variablen ihren Wert.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefan schrieb:
> Gilt das denn auch wenn die Funktion das zweite mal mit anderen
> Übergabewerten aufgerufen wurd?

Selbstverständlich. Was der Funktion beim Aufruf übergeben wird hat 
keinerlei Einfluss darauf, wo Variablen abgelegt werden, die die 
Funktion nutzt. Statische Variablen existieren genau einmal.

> Dann sollen natürlich neue Variablen angelegt werden.

Dann kannst Du dafür keine statischen Variablen verwenden, sondern musst 
automatische Variablen nutzen (die halt nur während der Laufzeit der 
Funktion gültig sind und bei jedem Aufruf neu angelegt werden).

von Klaus (Gast)


Lesenswert?

DirkB schrieb:
> Und die Initialisierung wird nur einmal (beim ersten Aufruf oder davor)
> durchgeführt. Danach behalten die static-Variablen ihren Wert.

Die Variablen werden noch vor dem start von main() initialisiert. Genau 
wie normale globale Variablen. Deswegen kann man die static variablen 
auch nur mit (zum Compilierzeitpunkt) konstanten Werten initialisieren, 
und nicht etwa in der Funktion erst berechnen.

static Variablen in einer Funktion sind also eigentlich völlig identisch 
zu normalen globalen Variablen. Mit einem Unterschied: du kannst nur 
innerhalb der Funktion drauf zugreifen. Außerhalb sind sie unsichtbar.

von Michael (Gast)


Lesenswert?

Stefan schrieb:
> Gilt das denn auch wenn die Funktion das zweite mal mit anderen
> Übergabewerten aufgerufen wurd? Dann sollen natürlich neue Variablen
> angelegt werden.

Den als Static deklarierten Variablen ist es schnurzpiepegal, mit was 
für Übergabewerten die Funktion aufgerufen wird.

von Stefan (Gast)


Lesenswert?

Vielen dank!

von Stefan (Gast)


Lesenswert?

Leider funktioniert es doch nicht. Ich dachte erst, dass wäre der Fehler 
mit dem "static". Habe es Spaßeshalber mal so gelöst (s.unten). Keine 
Änderung des Fehlers

1
uint8_t memmTasteGedrueckt[50] = {[0 ... 49] = 0};  
2
uint16_t Tastendruck_in_Zyklen[50] = {[0 ... 49] = 0};  
3
uint8_t aufab[50] = {[0 ... 49] = 0};;
4
uint16_t Takt[50] = {[0 ... 49] = 0};;
5
6
//Per Lichttaster Lampen auf Ab Dimmen
7
uint8_t TasterDimmenAufAb (uint8_t BitEingang, uint8_t BitStatus)
8
{
9
10
11
//#######################################################################
12
//Taster auswerten
13
//#######################################################################
14
     //Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet wird wenn hochgedimmt wurde!
15
   if (R_TRIG(!Eingang[BitEingang]) && Tastendruck_in_Zyklen[BitEingang]<500 && licht_status[BitStatus] && (!memmTasteGedrueckt[BitEingang]))
16
    {
17
    licht_schalten[BitStatus] = 1;
18
    usart_writePC("---2---\n\r");
19
    }
20
    
21
  //Einschalten wenn noch nicht an ist  
22
  if (R_TRIG(Eingang[BitEingang]) && (!licht_status[BitStatus]))
23
    {
24
    licht_schalten[BitStatus] = 1;
25
    memmTasteGedrueckt[BitEingang]=1;
26
    usart_writePC("---3---\n\r");
27
    }
28
29
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
30
  if    (R_TRIG(!Eingang[BitEingang]))
31
    {
32
    memmTasteGedrueckt[BitEingang]=0;
33
    usart_writePC("---4---\n\r");
34
    }
35
    //Länge des Tastendruckes aufzeichnen
36
  if (Eingang[BitEingang])
37
    {
38
    Tastendruck_in_Zyklen[BitEingang]++;
39
    }
40
  else
41
    {
42
    Tastendruck_in_Zyklen[BitEingang]=0;
43
    }
44
    
45
//#######################################################################
46
//Dimmen
47
//#######################################################################
48
49
       // Wenn Taste länger gedrückt wird
50
  if (Tastendruck_in_Zyklen[BitEingang] >500)
51
    { 
52
        usart_writePC("---5---\n\r");
53
          //Nach Zeit Dimmwert erhöhen      
54
          Takt[BitEingang]++;
55
     
56
            if (Takt[BitEingang]==15)
57
            {         
58
59
              if (u8SpeicherDimmwert[BitStatus] == 100) aufab[BitEingang] = 1;
60
              if (u8SpeicherDimmwert[BitStatus] == 5) aufab[BitEingang] = 0;
61
      
62
              //Wenn unter 100%, dann plus
63
              if (u8SpeicherDimmwert[BitStatus] <100 && !aufab[BitEingang])    
64
              {
65
              u8SpeicherDimmwert[BitStatus]++;          
66
              }
67
              // wenn 100 erreicht wurde wieder minus
68
              else if (u8SpeicherDimmwert[BitStatus] >5 && aufab[BitEingang])
69
              {
70
              u8SpeicherDimmwert[BitStatus]--;          
71
              }
72
              
73
              Takt[BitEingang]=0;
74
            }
75
    }
76
//#######################################################################
77
//#######################################################################
78
  return   u8SpeicherDimmwert[BitStatus];
79
80
}

Ich merke, dass die "---4---" auf der seriellen Sschnittstelle dauernd 
kommt, obwohl da nur die steigende Flanke abgefragt wird. Das darf also 
nicht passieren, wird wohl mit dem Fehler zu tun haben. Im Main siehts 
so aus:
1
if    (R_TRIG(Eingang[0]))
2
    {
3
    usart_writePC("---0---\n\r");
4
    }
5
6
7
if    (R_TRIG(!Eingang[0]))
8
    {
9
    usart_writePC("---8---\n\r");
10
    }
11
12
13
14
15
memm1 = TasterDimmenAufAb (0,12);
16
17
   if (memm1!= memm1old)
18
     {
19
     memm1old=memm1;
20
     LichtDimmenAn (PSTR("88|11|05|%1i\n"),PSTR("89|11|05|01\n"),PSTR("98|11|05|%1i\n\r"),memm1 );
21
    }
22
23
24
memm2 = TasterDimmenAufAb (1,44);
25
26
   if (memm2!= memm2old)
27
     {
28
     memm2old=memm2;
29
     LichtDimmenAn (PSTR("88|15|05|%1i\n"),PSTR("89|15|05|01\n"),PSTR("98|15|05|%1i\n\r"),memm2 );
30
    }

Die "---0---" oder "---8---" ommt wie zu Erwarten nur bei steigender und 
fallender Flanke.

Ich weiss nicht wie ich das hin bekomme, was mache ich nur flasch?

von Peter D. (peda)


Lesenswert?

Vielleicht beschreibst Du mal in Worten, was das Programm überhaupt 
machen soll.
Ein PAP wäre natürlich noch besser.
Es sieht doch alles irgendwie aus, wie einfach drauflos programmiert.

Ich vermute mal, mit meiner Tastenroutine (kurz, lang, repeat) würde 
sich ein Großteil des Codes in Luft auflösen.


Peter

von Sepp (Gast)


Lesenswert?

Hallo Stefan!

Hab' jetzt nicht alles om Datail gelesen, aber:

Versuchst Du eine Funktion, die EINE UART verwendet mehrere male 
aufzurufen?
Das könnte zu großen Problemen führen!

von Karl H. (kbuchegg)


Lesenswert?

Was macht eigentlich R_TRIG?


Alles in allem finde ich deinen COde extrem unübersichtlich.
Meherer Arrays parallel zu führen ist immer eine etwas problematische 
Sache. Fasse doch erst mal ALLE Werte, die zu einem Eingang gehören in 
eine gemeinsame Struktur zusammen (und benutze ein paar vernünftige 
kurze Namen für die Member)
1
struct inputDesc_
2
{
3
  uint8_t  inputState;        // war: Eingang
4
  uint8_t  isKeyPressed;      // war: memmTasteGedrueckt
5
  uint16_t pressedCycles;     // war: Tastendruck_in_Zyklen
6
  uint8_t  fadeDown;          // war: aufab
7
  uint16_t pressedClockTicks; // war: Takt
8
};
9
10
typedef struct inputDesc_ InputDesc;

damit hast du alle Werte beisammen, die du für EINEN Eingang benötigst 
(wenn noch was fehlt: nur zu, ruhig ergänzen.

Jetzt hast du aber nicht 1 Taste, sondern du hast 50 davon
1
InputDesc Inputs[50];


und um die Taste mit der Nummer 5 bearbeiten zu lassen, übergibst du 1 
derartige Struktur (per Pointer) an die Funktion
1
  TasterDimmenAufAb (&Inputs[1], 44);

und in der Funktion hast du dann
1
uint8_t TasterDimmenAufAb ( InputDesc& pInput, uint8_t BitStatus)
2
{
3
  //Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet
4
  // wird wenn hochgedimmt wurde!
5
  if (R_TRIG(!pInput->inputState)) &&
6
      input->pressedCycles < 500 &&
7
      !input->isKeyPressed &&
8
      licht_status[BitStatus])
9
  {
10
    licht_schalten[BitStatus] = 1;
11
    usart_writePC("---2---\n\r");
12
  }
13
    
14
  //Einschalten wenn noch nicht an ist  
15
  if (R_TRIG(pInput->inputState) && (!licht_status[BitStatus]))
16
  {
17
    licht_schalten[BitStatus] = 1;
18
    input->isKeyPressed = 1;
19
    usart_writePC("---3---\n\r");
20
  }
21
22
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
23
  if (R_TRIG(!pInput->inputState))
24
  {
25
    input->isKeyPressed = 0;
26
    usart_writePC("---4---\n\r");
27
  }
28
    //Länge des Tastendruckes aufzeichnen
29
  if (pInput->inputState)
30
    pInput->pressedCycles++;
31
  else
32
    pInput->pressedCycles = 0;
33
    
34
//#######################################################################
35
//Dimmen
36
//#######################################################################
37
38
  // Wenn Taste länger gedrückt wird
39
  if (pInput->pressedCycles >500)
40
  { 
41
    usart_writePC("---5---\n\r");
42
43
    //Nach Zeit Dimmwert erhöhen      
44
    pInput->pressedClockTicks++;
45
     
46
    if (pInput->pressedClockTicks == 15)
47
    {         
48
49
      if (u8SpeicherDimmwert[BitStatus] == 100)
50
        pInput->fadeDown = 1;
51
      if (u8SpeicherDimmwert[BitStatus] == 5)
52
        pInput->fadeDown = 0;
53
      
54
      //Wenn unter 100%, dann plus
55
      if (u8SpeicherDimmwert[BitStatus] <100 && !pInput->fadeDown)    
56
        u8SpeicherDimmwert[BitStatus]++;          
57
58
      else if (u8SpeicherDimmwert[BitStatus] >5 && pInput->fadeDown)
59
        u8SpeicherDimmwert[BitStatus]--;          
60
              
61
      pInput->pressedClockTicks = 0;
62
    }
63
  }
64
65
  return   u8SpeicherDimmwert[BitStatus];
66
}

Das hat jetzt 2 Vorteile
* zum einen hast du in der Funktion immer alle Werte eines Eingangs
  mit. Du brauchst nicht wegen einer Erweiterung groß umändern.
  Einfach den neuen Member in die Struktur einfügen und du hast
  den Member in der Funktion zur Verfügung. Und zwar immer den
  richtigen, den der zum jeweiligen Eingang gehört
* zum anderen läufst du nicht Gefahr, dass du dich in der Array-
  Indexierung irgendwo verhaust und irgendwo den falschen Index
  benutzt. Du hast in der Funktion nur 1 Eingang (in Form eines
  Pointers) und alle Werte gehören unter Garantie zu diesem
  Eingang


(Ich hab jetzt deinen Code nur auf eine Struktur umgeändert. An der 
Logik hab ich nichts verändert. D.h. dein Fehler wird immer noch drinnen 
sein.

Deine Form des Source Codes sieht zwar nicht schlecht aus, mir 
persönlich ist das aber zu unübersichtlich, zu sehr in die Länge 
gezogen. Die vielen if am Funktionsanfang kommen mir aber spanisch vor. 
Ich denke da stimmt was nicht. Entweder das, oder so wie du dir R_TRIG 
vorstellst, funktioniert das nicht (und ich kann mir erhlich gesagt 
nicht vorstellen, wie R_TRIG funktionieren soll. Um eine Flanke zu 
erkennen, benötigt man 'alte' Information von einem Eingang um 
vergleichen zu können, ob sich der Eingang verändert hat - aber von 
diesem EINEN Eingang. Nicht von irgendeinem Eingang. D.h. diese "alte" 
Information müsste ebenfalls in der Struktur sein. Ich kann aber in 
deinem Code nicht erkennen wie das über R_TRIG funktionieren könnte - 
und ich kann mir ehrlich gesagt ach nicht vorstellen wie das überhaupt 
funktionieren soll.


PS: Mach dasselbe nochmal für deine Lichter - Struktur einführen, in der 
du dir alle Kennwerte für ein Licht zusammenfasst.
Wartbare und überschaubare Programme zu schreiben, hat auch damit zu 
tun, dass man sich selbst Struktur ins Programm bringt. Einfach einen 
Haufen Variablen zu haben, vielleicht noch das eine oder andere Array - 
das ist noch lange keine Programm-Struktur. Wo das hinführt, siehst du 
jetzt ja: Nichts funktioniert und du hast keine Ahnung warum.



Und das wirklich witzige an der Sache ist, dass wenn du die PeDa 
Entprellung benutzen würdest, dann wäre dieser Teil mit Tastenauswertung 
und Key Repeat regelrecht pipifax.

von Stefan (Gast)


Lesenswert?

Hi Karl Heinz und dem Rest...
Supervielen dank schonmal vorab... Das hilft und lehrt mich sehr 
weiter...
Ich werde das morgen noch einmal neu aufsetzen und testen!
Schonmal so gesagt:
Ich will eine Funktion schreiben die dafür ist eine Lampe zu dimmen, per 
Tastschalter. Auf-abdimmen per gedrückt halten des Tasters. 
Ein-ausschalten per kurzem drücken. Gesinnt wird im anderen 
Mikrocontroller der an der seriellen hängt!

Der R_Trig ist die PeDa EntprellRoutine... Im Eingang[x] ist die 
jeweilige Taste. Bei gedrückt "True" bei losgelassen "False".

Ich meld mich morgen wieder, danke!

von Karl H. (kbuchegg)


Lesenswert?

Stefan schrieb:
> Hi Karl Heinz und dem Rest...
> Supervielen dank schonmal vorab... Das hilft und lehrt mich sehr
> weiter...
> Ich werde das morgen noch einmal neu aufsetzen und testen!
> Schonmal so gesagt:
> Ich will eine Funktion schreiben die dafür ist eine Lampe zu dimmen, per
> Tastschalter. Auf-abdimmen per gedrückt halten des Tasters.
> Ein-ausschalten per kurzem drücken. Gesinnt wird im anderen
> Mikrocontroller der an der seriellen hängt!


EIn paar Gedanken dazu.

Wenn die Taste niedergedrückt wird .... kannst du erst mal noch gar 
nichts aussagen, was passieren soll. Weder in der einen Form noch in der 
anderen. Das einzige was du beim Niederdrücken tun kannst ist: die 
Zähler auf 0 setzen.

Warum ist das so?
Weil du beim Niederdrücken noch nicht weißt, wie lange die Taste 
gedrückt gehalten werden wird (Zukunft).

D.h. das ist schon mal dein erster Fall:
Wird die Taste niedergedrückt?
    Ja --->  alle bereit machen bzw. initialisieren

Der zweite Fall, an dem du eine Unterscheidung einbauen musst, ist der 
Fall: ist die Taste gedrückt?
  In diesem Fall geht dann die Unterscheidung weiter:
  Wie lange ist die Taste schon gedrückt?
  Ist das noch zu kurz, dann tust du wieder gar nichts.
  Bist du über der Grenze drüber, dann wird gedimmt

Und der Schlussendlich letzte Fall ist das Loslassen der Taste.
AUch hier gibt es wieder 2 Fälle. Nämlich
War die Zeit des Niederdrückens zu kurz, so dass das Dimmen nicht 
eingesetzt hat, dann schalte den Ausgang um. (Allerdings würde ich da 
noch eine gewisse Mindestdauer fordern. Das ist dann auch gleich 
automatisch dein Entprellen. Verging vom Niederdrücken bis zum Loslassen 
zu wenig Zeit, dann war das ein Tastenpreller und kein gezieltes 
Niederdrücken).
War die Zeitg aber lang genug, dann tu gar nichts, denn dann hat das 
Dimmen vom Fall-2 bereits die Aktion erledigt.


Das ganze ein wenig vernünftig angeschrieben und eigentlich ist das dann 
kein Problem mehr.

von Stefan (Gast)


Lesenswert?

Funktionieren tat mein Programm für einen Taster auch schon. Aber nicht 
wenn ich die Funktion zweimal aufgerufen hatte für einen zweiten 
Taster...
Ich verinnerliche erst einmal das mit der Struktur und schreibe die 
Funktion um!
Meld mich...

von Stefan (Gast)


Lesenswert?

Ich muss auch noch dazu sagen, dass die vielen Arrays nur entstanden 
sind um die "Static" Variablen einmal zu "überbrücken"...

von Karl H. (kbuchegg)


Lesenswert?

Stefan schrieb:
> Funktionieren tat mein Programm für einen Taster auch schon. Aber nicht
> wenn ich die Funktion zweimal aufgerufen hatte für einen zweiten
> Taster...

Also hat es nicht funktioniert :-)

(Im Ernst: Ich hab zwar die Funktion überflogen, aber nichts gesehen, 
was dein spezifisches Problem verursachen könnte. Das einzige ist das 
Makro R_TRIG, das mir ein in seiner Verwendung ein wenig dubios 
vorkommt.
Und bei der Gelegenheit ist mir aufgefallen, dass der Anfang deiner 
Funktion nicht besonders leicht zu durchschauen ist - falls er überhaupt 
richtig ist. Für eine eigentlich einfache Sache sollte das nicht so 
sein, dass man den Code 10 Minuten studieren muss, ehe man rausfindet 
was da eigentlich die Idee in diesem Codestück ist. Sowas ist oft ein 
Hinweis darauf, dass da in der ganzen Codestruktur was nicht stimmt. Und 
wenn ich dann sehe, dass in jeder Zeile mindestens einmal auf ein Array 
(jeweils ein anderes) mit dem immer gleichen Index zugegriffen wird, 
dann seh ich schon mal das Problem, dass die Datenstruktur nicht 
durchdacht wurde. Gewöhn dich daran: Für ein hinreichend komplexes 
'Objekt' baut man sich eine struct, in der die Daten dieses Objekts 
zusammengefasst werden. VIele Arrays, die parallel gehalten werden 
müssen, sind irgendwann ein 'pain in the ass'. Ich hab hier auch Code 
von einem Vorgänger, der anscheinend ausser Arrays keine anderen 
Möglichkeiten zur Datenstrukturierung kannte. Entsprechend mühsam ist 
es, zu kontrollieren ob er bei Manipulationen in der Reihenfolge in den 
Arrays auch wirklich immer alle entsprechend umsortiert hat. Da gibts 
dubiose Fehler. Nur mit dem Unterschied, dass der Code hier ein paar 
tausend Zeilen hat :-) Ich hab dann gleich mal eine struct eingezogen, 
mit dem Erfolg dass viele duibose Fehler verschwunden sind und dafür im 
Gegenzug neue aufgetaucht sind. Und siehe da: die neuen Fehler sind zu 
einem großen Teil dadurch entstanden, dass er bewusst falsch in die 
Arrays zugegriffen hat, weil er wusste, dass an dieser Stelle die 
Reihenfolge schon falsch ist und er auch weiß, wie sie falsch ist. 
Manchmal möchte man wirklich mit dem nassen Fetzen ....

von Peter D. (peda)


Lesenswert?

Die Repeat-Funktion bei mir funktioniert nur bei einer Person, d.h. eine 
Taste drücken zur Zeit.

Wenn Du aber 50 Tasten anschließen willst, sollen die vermutlich auch 
mehrere Personen drücken. Dann braucht jede ihren eigenen Repeat-Zähler.

Ich würde dann aber jeder Taste + PWM ihren eigenen ATtiny13 spendieren 
und nicht alles einen AVR machen lassen. Das verringert auch erheblich 
das ganze Kabel-Wirrwarr.


Peter

von Stefan (Gast)


Lesenswert?

Hallo,
ich habe folgenden Code jetzt in meiner main.h eingefügt:
1
struct inputDesc_
2
{
3
  uint8_t  inputState;        // war: Eingang
4
  uint8_t  isKeyPressed;      // war: memmTasteGedrueckt
5
  uint16_t pressedCycles;     // war: Tastendruck_in_Zyklen
6
  uint8_t  fadeDown;          // war: aufab
7
  uint16_t pressedClockTicks; // war: Takt
8
};
9
10
typedef struct inputDesc_ InputDesc;
11
12
InputDesc Inputs[50];
13
14
15
//Per Lichttaster Lampen auf Ab Dimmen
16
uint8_t TasterDimmenAufAb ( InputDesc& pInput, uint8_t BitStatus)
17
{
18
  //Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet
19
  // wird wenn hochgedimmt wurde!
20
  if (R_TRIG(!pInput->inputState)) &&
21
      input->pressedCycles < 500 &&
22
      !input->isKeyPressed &&
23
      licht_status[BitStatus])
24
  {
25
    licht_schalten[BitStatus] = 1;
26
    usart_writePC("---2---\n\r");
27
  }
28
    
29
  //Einschalten wenn noch nicht an ist  
30
  if (R_TRIG(pInput->inputState) && (!licht_status[BitStatus]))
31
  {
32
    licht_schalten[BitStatus] = 1;
33
    input->isKeyPressed = 1;
34
    usart_writePC("---3---\n\r");
35
  }
36
37
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
38
  if (R_TRIG(!pInput->inputState))
39
  {
40
    input->isKeyPressed = 0;
41
    usart_writePC("---4---\n\r");
42
  }
43
    //Länge des Tastendruckes aufzeichnen
44
  if (pInput->inputState)
45
    pInput->pressedCycles++;
46
  else
47
    pInput->pressedCycles = 0;
48
    
49
//#######################################################################
50
//Dimmen
51
//#######################################################################
52
53
  // Wenn Taste länger gedrückt wird
54
  if (pInput->pressedCycles >500)
55
  { 
56
    usart_writePC("---5---\n\r");
57
58
    //Nach Zeit Dimmwert erhöhen      
59
    pInput->pressedClockTicks++;
60
     
61
    if (pInput->pressedClockTicks == 15)
62
    {         
63
64
      if (u8SpeicherDimmwert[BitStatus] == 100)
65
        pInput->fadeDown = 1;
66
      if (u8SpeicherDimmwert[BitStatus] == 5)
67
        pInput->fadeDown = 0;
68
      
69
      //Wenn unter 100%, dann plus
70
      if (u8SpeicherDimmwert[BitStatus] <100 && !pInput->fadeDown)    
71
        u8SpeicherDimmwert[BitStatus]++;          
72
73
      else if (u8SpeicherDimmwert[BitStatus] >5 && pInput->fadeDown)
74
        u8SpeicherDimmwert[BitStatus]--;          
75
              
76
      pInput->pressedClockTicks = 0;
77
    }
78
  }
79
80
  return   u8SpeicherDimmwert[BitStatus];
81
82
83
}

bekomme dann aber die Fehlermeldung:
Compiling: main.c
avr-gcc -c -mmcu=atmega1284p -I. -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=main.lst  -fno-inline-small-functions 
-fno-split-wide-types -fno-move-loop-invariants -mcall-prologues 
-ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax 
-std=gnu99 main.c -o main.o
In file included from main.c:21:
main.h:63: error: expected ';', ',' or ')' before '&' token
make.exe: *** [main.o] Error 1


Wenn ich eine Struktur/Pointer einer Funktion übergeben wollte hatte ich 
das bis dato so gelöst: uint16_t Test( struct TestStrukt* theStruktur

von Stefan (Gast)


Lesenswert?

So kriege ich den Code übersetzt:
1
struct inputDesc
2
{
3
  uint8_t  inputState;        // war: Eingang
4
  uint8_t  isKeyPressed;      // war: memmTasteGedrueckt
5
  uint16_t pressedCycles;     // war: Tastendruck_in_Zyklen
6
  uint8_t  fadeDown;          // war: aufab
7
  uint16_t pressedClockTicks; // war: Takt
8
};
9
10
struct inputDesc InputDesc;
11
12
13
14
//Per Lichttaster Lampen auf Ab Dimmen
15
uint8_t TasterDimmenAufAb ( struct inputDesc* pInput , uint8_t BitStatus)
16
{
17
  //Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet
18
  // wird wenn hochgedimmt wurde!
19
  if (R_TRIG(!pInput->inputState) && pInput->pressedCycles < 500 && (!pInput->isKeyPressed) && licht_status[BitStatus])
20
  {
21
    licht_schalten[BitStatus] = 1;
22
    usart_writePC("---2---\n\r");
23
  }
24
    
25
  //Einschalten wenn noch nicht an ist  
26
  if (R_TRIG(pInput->inputState) && (!licht_status[BitStatus]))
27
  {
28
    licht_schalten[BitStatus] = 1;
29
    pInput->isKeyPressed = 1;
30
    usart_writePC("---3---\n\r");
31
  }
32
33
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
34
  if (R_TRIG(!pInput->inputState))
35
  {
36
    pInput->isKeyPressed = 0;
37
    usart_writePC("---4---\n\r");
38
  }
39
    //Länge des Tastendruckes aufzeichnen
40
  if (pInput->inputState)
41
    pInput->pressedCycles++;
42
  else
43
    pInput->pressedCycles = 0;
44
    
45
//#######################################################################
46
//Dimmen
47
//#######################################################################
48
49
  // Wenn Taste länger gedrückt wird
50
  if (pInput->pressedCycles >500)
51
  { 
52
    usart_writePC("---5---\n\r");
53
54
    //Nach Zeit Dimmwert erhöhen      
55
    pInput->pressedClockTicks++;
56
     
57
    if (pInput->pressedClockTicks == 15)
58
    {         
59
60
      if (u8SpeicherDimmwert[BitStatus] == 100)
61
        pInput->fadeDown = 1;
62
      if (u8SpeicherDimmwert[BitStatus] == 5)
63
        pInput->fadeDown = 0;
64
      
65
      //Wenn unter 100%, dann plus
66
      if (u8SpeicherDimmwert[BitStatus] <100 && !pInput->fadeDown)    
67
        u8SpeicherDimmwert[BitStatus]++;          
68
69
      else if (u8SpeicherDimmwert[BitStatus] >5 && pInput->fadeDown)
70
        u8SpeicherDimmwert[BitStatus]--;          
71
              
72
      pInput->pressedClockTicks = 0;
73
    }
74
  }
75
76
  return   u8SpeicherDimmwert[BitStatus];
77
78
79
}


Aber ohne Aufruf :
1
  TasterDimmenAufAb (&Inputs[1], 44);

Wo muss ich das einfügen?
1
InputDesc Inputs[50];

von Stefan (Gast)


Lesenswert?

Ich weiss garnicht wo man das alles hin schreibt... was in der main.h 
und main.c ?!?! Ich kann dies Pointer Sache nicht!

von Stefan (Gast)


Lesenswert?

So ich habe das jetzt so gelöst:
main.h
1
        
2
3
struct inputDesc
4
{
5
  uint8_t  inputState;        // war: Eingang
6
  uint8_t  bitStatus;
7
  uint8_t  keyIsPressed;      // war: memmTasteGedrueckt
8
  uint16_t pressedCycles;     // war: Tastendruck_in_Zyklen
9
  uint8_t  aufab;          // war: aufab
10
  uint16_t takt; // war: Takt
11
12
};
13
14
15
struct inputDesc   Eingang_0   = {0, 12};
16
struct inputDesc   Eingang_1   = {1, 44};
17
18
19
//Per Lichttaster Lampen auf Ab Dimmen
20
uint8_t TasterDimmenAufAb ( struct inputDesc* pInput)
21
{
22
  //Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet
23
  // wird wenn hochgedimmt wurde!
24
  if (R_TRIG(!Eingang[pInput->inputState]) && pInput->pressedCycles < 500 && (!pInput->keyIsPressed) && licht_status[pInput->bitStatus])
25
  {
26
    licht_schalten[pInput->bitStatus] = 1;
27
   // usart_writePC("---2---\n\r");
28
  }
29
    
30
  //Einschalten wenn noch nicht an ist  
31
  if (R_TRIG(Eingang[pInput->inputState]) && (!licht_status[pInput->bitStatus]))
32
  {
33
    licht_schalten[pInput->bitStatus] = 1;
34
    pInput->keyIsPressed = 1;
35
   // usart_writePC("---3---\n\r");
36
  }
37
38
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
39
  if (R_TRIG(!Eingang[pInput->inputState]))
40
  {
41
    pInput->keyIsPressed = 0;
42
   // usart_writePC("---4---\n\r");
43
  }
44
    //Länge des Tastendruckes aufzeichnen
45
  if (Eingang[pInput->inputState])
46
    pInput->pressedCycles++;
47
  else
48
    pInput->pressedCycles = 0;
49
    
50
//#######################################################################
51
//Dimmen
52
//#######################################################################
53
54
  // Wenn Taste länger gedrückt wird
55
  if (pInput->pressedCycles >500)
56
  { 
57
 //   usart_writePC("---5---\n\r");
58
59
    //Nach Zeit Dimmwert erhöhen      
60
    pInput->takt++;
61
     
62
    if (pInput->takt == 15)
63
    {         
64
65
      if (u8SpeicherDimmwert[pInput->bitStatus] == 100)
66
        pInput->aufab = 1;
67
      if (u8SpeicherDimmwert[pInput->bitStatus] == 5)
68
        pInput->aufab = 0;
69
      
70
      //Wenn unter 100%, dann plus
71
      if (u8SpeicherDimmwert[pInput->bitStatus] <100 && !pInput->aufab)    
72
        u8SpeicherDimmwert[pInput->bitStatus]++;          
73
74
      else if (u8SpeicherDimmwert[pInput->bitStatus] >5 && pInput->aufab)
75
        u8SpeicherDimmwert[pInput->bitStatus]--;          
76
              
77
      pInput->takt = 0;
78
    }
79
  }
80
81
  return   u8SpeicherDimmwert[pInput->bitStatus];
82
83
84
}

main.c
1
memm1 = TasterDimmenAufAb (&Eingang_0);
2
3
   if (memm1!= memm1old)
4
     {
5
     memm1old=memm1;
6
     LichtDimmenAn (PSTR("88|11|05|%1i\n"),PSTR("89|11|05|01\n"),PSTR("98|11|05|%1i\n\r"),memm1 );
7
    }
8
9
10
memm2 = TasterDimmenAufAb (&Eingang_1);
11
12
   if (memm2!= memm2old)
13
     {
14
     memm2old=memm2;
15
     LichtDimmenAn (PSTR("88|15|05|%1i\n"),PSTR("89|15|05|01\n"),PSTR("98|15|05|%1i\n\r"),memm2 );
16
    }

Der Fehler besteht, wie vermutet weiterhin!

Durch den R_Trig soll eine steigende oder fallende Flanke erkannt 
werden. Hier ist der Code(PeterDanneger)
1
// Entprellen und R_TRIG
2
3
4
#define R_TRIG( bit )                                          \
5
({                                                                     \
6
  static uint8_t flag = 0;    /* new variable on every macro usage */  \
7
  uint8_t i = 0;                                                       \
8
                                                                       \
9
  if( flag ){                 /* check for key release: */             \
10
    for(;;){                  /* loop ... */                           \
11
     if( (bit) ){             /* ... until key pressed or ... */       \
12
  i = 0;                      /* 0 = bounce */                         \
13
  break;                                                               \
14
      }                                                                \
15
      _delay_us( 98 );        /* * 256 = 25ms */                       \
16
      if( --i == 0 ){         /* ... until key >25ms released */       \
17
  flag = 0;                   /* clear press flag */                   \
18
    i = 0;                    /* 0 = key release debounced */        \
19
  break;                                                               \
20
      }                                                                \
21
    }                                                                  \
22
  }else{                       /* else check for key press: */         \
23
    for(;;){                   /* loop ... */                          \
24
      if( ! (bit) ){          /* ... until key released or ... */     \
25
  i = 0;                       /* 0 = bounce */                        \
26
    break;                                                             \
27
        }                                                            \
28
      _delay_us( 98 );         /* * 256 = 25ms */                      \
29
      if( --i == 0 ){          /* ... until key >25ms pressed */       \
30
  flag = 1;                    /* set press flag */                    \
31
  i = 1;                       /* 1 = key press debounced */           \
32
  break;                                                               \
33
      }                                                                \
34
    }                                                                  \
35
  }                                                                    \
36
  i;                           /* return value of Macro */             \
37
})

Warum geht das denn nicht für zweit Eingänge?!?

von Peter D. (peda)


Lesenswert?

Stefan schrieb:
> Hier ist der Code(PeterDanneger)

Schön, das nach so vielen Postings endlich mal zu erfahren :-(

Stefan schrieb:
> Warum geht das denn nicht für zweit Eingänge?!?

Weil Du die Beschreibung dazu nicht gelesen hast!

Sie darf je Taste nur an einer Stelle aufgerufen werden.
Sie muß für jede Taste separat aufgerufen werden.

3-mal aufrufen und mit Taste als Variable ist also doppelt falsch.

Und 50 Tasten gehen ohne größere Änderungen schon mal garnicht.


Peter

von Stefan (Gast)


Lesenswert?

Hi Peter,

Ok, ich habe mir jetzt mal eine steigende und fallende Flanke selber 
gebastelt.
Ich merke jedoch wenn ich die Funktion in der main hin schreibe 
funktioniert es. Die steigende  Flanke und fallende Flanke wird genau 
einmal erkannt. "---1---" und "---2---" werden passend ausgegeben.
Rufe ich jedoch die Funktion noch einmal auf (memm2 = TasterDimmenAufAb 
(Eingang[1], &Eingang_1);) Sehe ich auf der seriellen ganz oft 
"---1---" und "---2---" wenn ich den Taster - egal ob 0 ooder 1 - 
gedrückt halte.

Wodran kann das denn wohl liegen ? Das ist das gleiche Verhalten wie mit 
deiner Entprellroutine

in der main.c Hauptschleife
1
memm1 = TasterDimmenAufAb (Eingang[0], &Eingang_0);
2
3
   if (memm1!= memm1old)
4
     {
5
     memm1old=memm1;
6
     LichtDimmenAn (PSTR("88|11|05|%1i\n"),PSTR("89|11|05|01\n"),PSTR("98|11|05|%1i\n\r"),memm1 );
7
    }
1
bool bR_TRIG;
2
bool bF_TRIG;
3
bool Hilfsmerker;
4
5
//Per Lichttaster Lampen auf Ab Dimmen
6
uint8_t TasterDimmenAufAb ( bool Input, struct inputDesc* pInput)
7
{
8
9
10
  //Steigende Flanke abfragen
11
  bR_TRIG       = Input && !Hilfsmerker;  
12
  //Fallende Flanke abfragen
13
  bF_TRIG       = !Input && Hilfsmerker;  
14
  Hilfsmerker   = Input;
15
16
if (bR_TRIG) usart_writePC("---1---\n\r");
17
if (bF_TRIG) usart_writePC("---2---\n\r");
18
19
  // Ausschalten wenn nur kurz gedrückt wurd, damit nicht ausgeschaltet
20
  // wird wenn hochgedimmt wurde!
21
  if (bF_TRIG && pInput->pressedCycles < 500 && (!pInput->keyIsPressed) && licht_status[pInput->bitStatus])
22
  {
23
    licht_schalten[pInput->bitStatus] = 1;
24
   // usart_writePC("---2---\n\r");
25
  }
26
  
27
  
28
  
29
  //Einschalten wenn noch nicht an ist  
30
  if (bR_TRIG && (!licht_status[pInput->bitStatus]))
31
  {
32
    licht_schalten[pInput->bitStatus] = 1;
33
    pInput->keyIsPressed = 1;
34
   // usart_writePC("---3---\n\r");
35
  }
36
37
  //Beim Loslassen des Tasters Speicher "TasteGedrückt" löschen  
38
  if (bF_TRIG)
39
  {
40
    pInput->keyIsPressed = 0;
41
   // usart_writePC("---4---\n\r");
42
  }
43
    //Länge des Tastendruckes aufzeichnen
44
  if (Eingang[pInput->inputState])
45
    pInput->pressedCycles++;
46
  else
47
    pInput->pressedCycles = 0;
48
    
49
//#######################################################################
50
//Dimmen
51
//#######################################################################
52
53
  // Wenn Taste länger gedrückt wird
54
  if (pInput->pressedCycles >500)
55
  { 
56
 //   usart_writePC("---5---\n\r");
57
58
    //Nach Zeit Dimmwert erhöhen      
59
    pInput->takt++;
60
     
61
    if (pInput->takt == 15)
62
    {         
63
64
      if (u8SpeicherDimmwert[pInput->bitStatus] == 100)
65
        pInput->aufab = 1;
66
      if (u8SpeicherDimmwert[pInput->bitStatus] == 5)
67
        pInput->aufab = 0;
68
      
69
      //Wenn unter 100%, dann plus
70
      if (u8SpeicherDimmwert[pInput->bitStatus] <100 && !pInput->aufab)    
71
        u8SpeicherDimmwert[pInput->bitStatus]++;          
72
73
      else if (u8SpeicherDimmwert[pInput->bitStatus] >5 && pInput->aufab)
74
        u8SpeicherDimmwert[pInput->bitStatus]--;          
75
              
76
      pInput->takt = 0;
77
    }
78
  }
79
80
  return   u8SpeicherDimmwert[pInput->bitStatus];
81
82
83
}

von Uwe (de0508)


Lesenswert?

Hallo Stefan,

die Funktion ist aus meiner Sicht nur etwas für einen schnelle 
Entprellung eines Tasters.

Für viele hat Peter einen richtige gute Bibliothek geschrieben.

Hier ist der Einstieg in das Thema:

Beitrag "Universelle Tastenabfrage"

von Stefan (Gast)


Lesenswert?

Danke ich werds mal probieren... Danke für die Hilfe von Allen....

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.