Forum: Mikrocontroller und Digitale Elektronik Signalerkennung


von Sven W. (sickone4)


Lesenswert?

Hallo Leute,

ich hab da eine Frage,

ich hab einen 12fach Wahlschalter. Dieser hat keinen Anschlag -> 360° 
drehbar!

ZIEL: Schalter nach rechts -> n + 1
      Schalter nach links  -> n - 1

kann ich irgendwie mit dem µC die Drehrichtung erkennen, bzw das Ziel 
dort realisieren?

prinzipiell müsste ich wissen, wo steht der schalter und von wo kommt 
er/wo geht er hin.

wie kann ich an sowas rangehen?

von Bro (Gast)


Lesenswert?

Vom Prinzip her kannst du jeden Schalterkontakt an einen µC Pin hängen. 
Dann weißt du schonmal, wo genau der Schalter steht. Wenn man sich die 
aktuelle Position merkt und dann sich die neue anschaut, dann weiß man 
auch in welche Richtung gedreht wird.

Um nicht 12 µC-Pins zu belegen würde sich dann ein Multiplexer anbieten.

von Sven W. (sickone4)


Lesenswert?

ja einen multiplexer hab ich hier liegen

-> 8/1 multiplexer - 74HC 251 von reichelt.

das system muss ich aber erstmal verstehen, weil ich von multiplexen 
wenig/keine ahnung habe!

der 8/1er war auch eher für ne 7 Segmentanzeige vorgesehen


ich denke ich werde zunächst die 12 pin lösung programmieren und dann 
die multiplex variante, um das system von grundauf zu verstehen

von Route_66 (Gast)


Lesenswert?

Hallo!
Widerstände ran und A/D-Wandler geht nicht?

von Sven W. (sickone4)


Lesenswert?

@ Route_66

was meinst du mit der A/D Wandlung? hab doch nen Schalter. kein poti

oder hab ich dich da nun falsch verstanden??


@BRO: hab mir gerade mal schnell bei wikipedia die infos über 
multiplexer angeschaut. "multiplexer arbeiten wie drehschalter" steht 
da, warum noch nen multiplexer hinter einen drehschalter?

von Sam P. (Gast)


Lesenswert?

Man kann mit nur 3 Leitungen auskommen, wenn sicher ist, dass eine 
Position niemals übersprungen wird:

1 - 2 - 3 - 1 - 2 - 3 - 1 - 2 - 3 ...

Man merkt sich, wo der Schalter zuletzt stand, und guckt sich dann die 
neue Position an.

Beispiel:

Alte Position ist "2"
Kommt dann "1", ist er nach links, bei "3" nach rechts gedreht worden.

Entsprechend für die anderen beiden Startpositionen.

Wenn man sich eien 4. Leitung spendiert, kann man mit der eine 
Nullstellung markieren, falls nötig.

Mit einem Rudel Dioden (Ist das richtig? Oder heisst das bei Dioden 
"Herde", oder gar "Schwarm"?) wiederum kann man durch gleichzeitiges 
Schalten zweier Leitungen all das in 2 I/O-Ports machen, bei erheblich 
höherem Bauteileaufwand.

von Route_66 (Gast)


Lesenswert?

Hallo!
> hab doch nen Schalter
Man kann aus einem 12-stufigen Schalter mit 11 gleichen Widerständen ein 
"Stufen"-Poti bauen. Wenn man keine gleichen Widerstände da hat, kann 
man das trotzdem so machen. Dann muß man alles so verschalten, daß bei 
jeder Schalter(Poti)-Stellung am Schleifer eine andere, auswertbare 
Spannung ansteht.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> @ Route_66
>
> was meinst du mit der A/D Wandlung? hab doch nen Schalter. kein poti

Aber du kannst aus deinem Drehschalter leicht ein 'Poti' machen.
Zwischen jeweils 2 Anschlüsse ein Widerstand und am Anfang an GND bzw am 
Ende an Vcc.
Was kriegst du?
1
 GND  +--R--+--R--+--R--+--R--+ Vcc
2
      |     |     |     |     |
3
      |     |     |     |     |
4
       \    |     |     |    /
5
        \    \    |    /    /
6
         \    \       /    /
7
          \     #         /
8
           ---    O   ----
9
                  |
10
                  |
11
                ADC Pin

Einen Spannungsteiler, bei dem an jedem Abgriff eine andere Spannung 
anliegt. Mit dem Drehschalter wählst du eine davon aus und mit dem ADC 
misst du sie. Schon kannst du zurückrechnen, wo der Drehschalter steht.

von Sven W. (sickone4)


Lesenswert?

hey leute!

@ Sam P.

ich hab nun meine 12 wahlstellungen auf 3x4 zusammengefasst.

 1---2---3 --- 1---2---3 --- 1---2---3 --- 1---2---3

die 1er 2er und 3er sidn jeweils zusammen.

nun frag ich mich aber, wie ich das auf n (1-8) umrechnen kann.

ich hab also immer noch nicht den impuls ob rauf oder runtergezählt 
werden soll.

n (1-8) = ich hab nachher 8 verschiedene stellungen, die ich nutze will, 
das sind 8 verschiedene speicherplätze im eeprom, welche ich so 
ansprechen (auslesen) will.

von Uwe (Gast)


Lesenswert?

Du guckst wo du bist und speicherst das. z.B. 1
Jetzt wartest du solange bis sich was ändert also weitergedreht wurde 
z.B. auf 2.
Jetzt überlegst du wenn ich vorher auf 1 war und jetzt auf 2 bin 
wieherum habe ich mich dann gedreht ?
Du guckst wo du bist und speicherst das also 2
Jetzt wartest du solange bis sich was ändert also weitergedreht wurde 
z.B. auf 1.
Jetzt überlegst du wenn ich vorher auf 2 war und jetzt auf 1 bin 
wieherum habe ich mich dann gedreht ?

von Uwe (Gast)


Lesenswert?

Jedesmal wenn du dich links gedreht hat addierst du auf die variable 
aktueller_speicherplatz eine 1 hinzu. wenn du dich rechts gedreht hast 
subtrahierst du eine 1. Da du nur die Unteren 8 Positionen brauchst 
machst du noch ein "aktueller_speicherplatz&=7" nach jedem add oder sub.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> hey leute!
>
> @ Sam P.
>
> ich hab nun meine 12 wahlstellungen auf 3x4 zusammengefasst.
>
>  1---2---3 --- 1---2---3 --- 1---2---3 --- 1---2---3
>
> die 1er 2er und 3er sidn jeweils zusammen.
>
> nun frag ich mich aber, wie ich das auf n (1-8) umrechnen kann.
>
> ich hab also immer noch nicht den impuls ob rauf oder runtergezählt
> werden soll.

rauf/runterzählen ist einfach, das verraten dir die Zahlen.

Ist der vorhergehende Schalterstand 3, dann gibt es bei der nächsten 
Abfrage 3 Möglichkeiten
* Er ist immer noch 3.    Dann hat sich nichts verändert
* Er ist 2                Dann wurde nach links gedreht
* Er ist 1                Dann wurde nach rechts gedreht

Respektive dasselbe für die anderen Positionen.
Hint: Das lässt sich auch in 2 Formeln packen, anstatt das für alle 
Fälle auszuprogrammieren.

Das Problem ist aber, dass du die absoluten Schalterpositionen 1 und 4 
und 7 nicht auseinanderhalten kannst, wenn du bei Programmstart nicht 
weißt, wo der Schalter stand.

Da du nur eine im µC gespeicherte Zahl erhöhen/verringern willst, geht 
das gerade noch. Allerdings hat dann die absolute Schalterstellung mit 
der Auswahl im Programm nichts zu tun.

von Sven W. (sickone4)


Lesenswert?

Hey Karl heinz!

Danke für die Ausführliche Erklärung. bevor du deinen beitrag verändert 
hast, hab ich das verushct zu lösen und auch geschafft!

nun kommt das aber, bzw die verbessungsfrage:
1
       if ( bit_is_clear ( PINB,0 ) )
2
       {  
3
       if (i == 3)  { channel++; }
4
       if (i == 2)  { channel--; }
5
       i = 1;
6
       }
7
     
8
     if ( bit_is_clear ( PINB,1 ) )
9
       {  
10
       if (i == 1)  { channel++; }
11
       if (i == 3)  { channel--; }
12
       i = 2;
13
       }
14
     
15
     if ( bit_is_clear ( PINB,2 ) )
16
       {  
17
       if (i == 2)  { channel++; }
18
       if (i == 1)  { channel--; }
19
       i = 3;
20
       }
21
     
22
     if (channel > 8) { channel = 1; }
23
     if (channel < 1) { channel = 8; }

so sieht mein code aus.
füf die zahlen 1-8 hab ich ne 7 segmentanzeige angesteuert!

das mit der schalterstellung ist richtig.

was wäre aber denn, wenn ich die pinnummern durch variablen ersetze? so 
könnte ich bei jedem systemstart egal wo der schalter steht abfragen, wo 
ein 1 signal ansteht und dieses dann auf 1 setzen, so zumindest der 
gedanke.

mein kleines anders problem ist, dass ich das wohl alles übern haufen 
werfen kann....

dieser wahlschalter ist ein drehschalter am gehäuse. es wird aber eine 
zweite schaltmöglichkeit für die gleiche sache geben. und zwar 
ausgeführt durch 4 taster, die zweifach belegt sind.


programmiere ich nun einen taster hinzu, so wird permanent ein 
schaltzustand angezeigt.

ich müsste also irgendwie die flanke beim wechsel des wahlschalters 
abfragen, nicht den schaltzustand. wie kann ich das denn realisieren? 
laut gcc tut nur mit interupts. aber die haben doch laut meinem 
verständniss ganz andere aufgaben?

von Sam P. (Gast)


Lesenswert?

Das wäre jetzt der Moment, an dem du uns nen Schaltplan zeigst. Das 
klingt nämlich etwas eigenartig. Hast du schon vorgegebene Hardware? 
Hast du dir irgendwas selbst ausgedacht?

Es wäre nützlich zu wissen, was fest vorgegeben ist, und was deine 
vorläufige Planung ist. Vielleicht ist das nur zu kompliziert gedacht.

Wie gesagt, Schaltplan wäre ideal. Da entstehen keine Missverständnisse.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> was wäre aber denn, wenn ich die pinnummern durch variablen ersetze? so
> könnte ich bei jedem systemstart egal wo der schalter steht abfragen, wo
> ein 1 signal ansteht und dieses dann auf 1 setzen, so zumindest der
> gedanke.

Du kannst ja auch dem i erst mal einen Wert geben, bevor du dann laufend 
die Schalterstellung abfrägst.


> ich müsste also irgendwie die flanke beim wechsel des wahlschalters
> abfragen, nicht den schaltzustand.

Na was ist denn eine Flanke?
Eine Flanke ist ein Zustandswechsel. Also: vor 5 Sekunden (respektive im 
letzten Durchlauf durch die Hauptschleife) war der Wahlschalter noch 
nicht auf 2, jetzt aber ist er es. Also muss wohl in der Zwischenzeit 
jemand am Schalter gespielt haben.

> laut gcc tut nur mit interupts.

Vergiss Interrupts.
Wenn du 'externer Schalter/Taster' und Interrupts in einem Satz nennst, 
machst du schon was falsch. Interrupts nimmt man, wenn man eine 
garantiert schnelle Reaktion auf ein externes Ereignis braucht. Aus 
Sicht deines µC ist der Benutzer aber schnarchlangsam.

von Route_66 (Gast)


Lesenswert?

Hallo!
Klingt mir eher wie wechselseitiges Ausmaskieren der Anschlüsse für den 
Drehschalter gegenüber den restlichen Eingangspins für die Taster.

von Dietrich L. (dietrichl)


Lesenswert?

Bei all den Überlegungen sollte man noch berücksichtigen, was der 
Schalter beim Umschalten macht - besonders beim langsamen Umschalten.

Es gibt welchen, die machen in der Zwischenstellung einen Kurzschluss 
zwischen den zwei benachbarten Anschlüssen, und andere, da ist der 
zentrale Anschluss offen. Das kann die Auswertelogik ganz schön 
verwirren...

Gruß Dietrich

von Sven W. (sickone4)


Lesenswert?

naja unter einem flankenwechsel versteh ich als sps-ler aber was 
anderes, als nur einen zustandswechsel?!

ein taster ist das primitivste was sowas angeht denke ich,

in dem moment wo du tastest und sofort loslässt, da haste nen 
flankenwechsel. aber ein schaltzustand, nach dem schalten ist doch keine 
flanke.

so kann man zig if schleifen parallel haben, und nur dann wenn irgend 
ein zustandswechsel passiert kann die betreffende anweisung ansprechen.

nehm ich nun meinen wahlschalter UND einen taster dann ist der 
wahlschalter doch immer auf irgendeiner stellung und hat so auch immer 
bei bit_is_clear eine 1 egal in welcher stellung (vorrausgesetzt ich hab 
keine 0-stlg)

von Route_66 (Gast)


Lesenswert?

Dunkel ist der Rede Sinn.
Entweder
1) Du zeigst erst mal den Schaltplan
2) zeigst den kompletten Code
Oder
3) Mach Deinen Dreck aleene!

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> naja unter einem flankenwechsel versteh ich als sps-ler aber was
> anderes, als nur einen zustandswechsel?!

Nämlich,
Was verstehst du darunter.

Wenn im Bad vor einer halben Stunde noch kein Licht brannte, jetzt aber 
schon, dann hat wer das Licht eingeschaltet. Also gab es in der 
Zwischenzeit eine Flanke am Lichtschalter. Das Licht ist vom Zustand 
'aus' in den Zustand 'ein' gewechselt.

    ein                  -------------------
                         |
    aus   ----------------

             ^                       ^
             |                       |
          vor einer                jetzt
          halben Stunde


Irgendwann zwischen 'vor einer halben Stunde' und 'jetzt' muss es eine 
Flanke im Signal 'Licht' gegeben haben. Und wie man unschwer sieht, ist 
da tatsächlich eine.

    ein                  -------------------
                         |
    aus   ----------------

                         ^
                         |
                    hier ist die Schalt-Flanke


> in dem moment wo du tastest und sofort loslässt, da haste nen
> flankenwechsel.

2!
2 Flankenwechsel.
Einmal von 0 auf 1 und dann von 1 auf 0


                   --------------
                   |            |
         -----------            ------------

                   ^            ^
              1. Flanke       2. Flanke


> aber ein schaltzustand, nach dem schalten ist doch keine
> flanke.

Der Schaltzustand ist eine andere Sache. Wenn das Licht vor einer halben 
Stunde an war und jetzt ist es ebenfalls an, dann ist der Zustand 'ein'. 
Aber es gab keine Flanke.

Flanke ist immer mit ein Zustands-Wechsel verbunden. Ohne Wechsel kann 
es keine Schaltflanke geben.

von Sven W. (sickone4)


Lesenswert?

:) karl heinz, genau das wollte ich sagen.

da ich aber mit dem befehl bit_is_clear arbeite steht da ja dann eine 1 
an!

wie kann ich also nur die flanke abfragen?

in der sps technik gibts dafür flankenmerker, impulsmerker, p-boxen 
etc....

hat der µC auch sowas?


@Route_66:
1
int i      = 1;
2
  int channel = 1;  
3
4
    while(1)
5
    {
6
           
7
       if ( bit_is_clear ( PINB,0 ) )
8
       {  
9
       if (i == 3)  { channel++; }
10
       if (i == 2)  { channel--; }
11
       i = 1;
12
       }
13
     
14
     if ( bit_is_clear ( PINB,1 ) )
15
       {  
16
       if (i == 1)  { channel++; }
17
       if (i == 3)  { channel--; }
18
       i = 2;
19
       }
20
     
21
     if ( bit_is_clear ( PINB,2 ) )
22
       {  
23
       if (i == 2)  { channel++; }
24
       if (i == 1)  { channel--; }
25
       i = 3;
26
       }
27
     
28
     if (channel > 8) { channel = 1; }
29
     if (channel < 1) { channel = 8; }
30
       
31
     if (bit_is_clear ( PINB,3 ) )
32
     {
33
       channel = 1;
34
     }
35
    
36
     if (bit_is_clear ( PINB,4 ) )
37
     {
38
       channel = 2;
39
     }
40
     
41
     if (bit_is_clear ( PINB,5 ) )
42
     {
43
       channel = 3;
44
     }
45
     
46
     if (bit_is_clear ( PINB,6 ) )
47
     {
48
       channel = 4;
49
     }
50
     
51
     if ( bit_is_clear ( PINB,7 ) )
52
       {  
53
       channel = 5; 
54
       }
55
  
56
     if (i == 1)  { PORTA = 0b10000000; }
57
     if (i == 2)  { PORTA = 0b01000000; }
58
     if (i == 3)  { PORTA = 0b00100000; } 
59
       
60
     if (channel == 1) { PORTD = 0b00000110; }
61
     if (channel == 2) { PORTD = 0b01011011; }
62
     if (channel == 3) { PORTD = 0b01001111; }
63
     if (channel == 4) { PORTD = 0b01100110; }
64
     if (channel == 5) { PORTD = 0b01101101; }         
65
     if (channel == 6) { PORTD = 0b01111101; }
66
     if (channel == 7) { PORTD = 0b00000111; }
67
     if (channel == 8) { PORTD = 0b01111111; }
68
            
69
    }

mehr isses doch nicht... zwei verschiedene schaltmöglichkeite, die auf 
eine variable zugreifen.

p.s. ich hab hier gezielt auf das ansprechen einzelner bite verzichtet 
und direkt den ganzen port angesprochen, da es sich ja nicht um das 
hauptprogramm sondern um einen test-bereich handelt!

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> nehm ich nun meinen wahlschalter UND einen taster dann ist der
> wahlschalter doch immer auf irgendeiner stellung


Das ist er.
Aber wenn der Benutzer daran dreht, dann ändert sich der AUsgang des 
Schalters. Es ist diese Änderung die dich interessiert und die dir sagt: 
Der Benutzer spielt da rum.

Und um eine Veränderung festzustellen .... nun, es gibt Variablen. In 
denen kann man sich Zustände merken.


> und hat so auch immer
> bei bit_is_clear eine 1 egal in welcher stellung (vorrausgesetzt ich hab
> keine 0-stlg)

Ich würde mir ehrlich gesagt auch erst mal eine Funktion machen, die mir 
aus den 3 Einzelpins eine Zahl von 0 bis 2 macht und dann erst mit 
dieser Zahl weiterarbeiten.

von Karl H. (kbuchegg)


Lesenswert?

> da ich aber mit dem befehl bit_is_clear arbeite steht
> da ja dann eine 1 an!

Wie im Nachfolgepost gesagt:

Ich würde mir als allererstes eine Funktion machen, die die 3 Pins 
zusammenfasst und sie in eine Zahl von 0 bis 2 verwandelt.

Und erst damit mach ich dann die Auswertung, ob die Kanalnummer zu 
erhöhen oder zu erniedrigen ist. Denn das ist dann trivial
1
   oldUserNumber = fetchSchalter();
2
3
   while( 1 ) {
4
5
      userNumber = fetchSchalter();   // 0, 1, 2 für die Schalterstellung; 99 für ungültig
6
                                      // zb wegen Schalterzwischenstellungen
7
8
      if( userNumber != 99 && userNumber != oldUserNumber )
9
      {
10
        // die Schalterstellung ist gültig und sie hat sich
11
        // verändert -> Der Benutzer hat drann rumgedreht
12
13
        // wie hat sie sich verändert? Ist sie größer
14
        // oder kleiner geworden?
15
16
        if ((oldUserNumber + 1) % 3 == userNumber)
17
          channelNr++;
18
19
        if (oldUserNumber == (userNumber + 1) % 3)
20
          channelNr--;
21
       
22
        oldUsedNumber = userNumber;
23
      }
24
   }

von Sven W. (sickone4)


Lesenswert?

ok das ist natürlcih was anderes :)

so macht das alles etwas mehr sinn...

problem für mich ist nun aber ein ganz anderes.
wohin schreib ich das da? in mein hauptprogramm, oder schreibe ich mir 
ein unterprogramm dafür?

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> problem für mich ist nun aber ein ganz anderes.
> wohin schreib ich das da? in mein hauptprogramm, oder schreibe ich mir
> ein unterprogramm dafür?

Wie immer du das machen willst.
Es ist dein Programm. Und wenn ich dir alles vorkaue, lernst du nicht 
selber strategisch zu denken. Probiers aus, sieh nach wohin dich das 
führt. Ändern kannst du es immer noch.

Nur weil der Code heute in der Hauptschleife steht, heißt das ja nicht, 
dass du ihn nicht morgen schon in eine eigene Funktion verschieben 
darfst, weil dir die Hauptschleife zu unübersichtlich geworden ist.

von Sven W. (sickone4)


Lesenswert?

oldUserNumber = fetchSchalter();

   while( 1 ) {

      userNumber = fetchSchalter();

die drei zeilen hassen mich^^

wie kann ich denn fetchSchalter definieren? entweder steh ich aufm 
schlauch oder ich weiß es wirklich nicht.

von Sven W. (sickone4)


Lesenswert?

EDIT^^

ok also fetchSchalter ist da, um die Schalterstellung abzufragen....

von Karl H. (kbuchegg)


Lesenswert?

Das ist eine Funktion, die DU zu schreiben hast.

Was soll sie tun?
Ich zitiere mich:
> Ich würde mir als allererstes eine Funktion machen, die die
> 3 Pins zusammenfasst und sie in eine Zahl von 0 bis 2 verwandelt.
bzw. den Kommentar in
1
      userNumber = fetchSchalter();   // 0, 1, 2 für die Schalterstellung; 99 für ungültig
2
                                      // zb wegen Schalterzwischenstellungen

Also
1
uint8_t fetchSchalter()
2
{
3
  ....
4
  .... Was muss hier hin, so dass diese Funktion in der Schalterstellung
5
  .... '1' eine 0 zurück gibt (PINB,0 [und nur PINB,0(!)] ist dann auf 0)
6
  .... '2' eine 1 zurück gibt (PINB,1 [und nur PINB,1(!)] ist dann auf 0)
7
  .... '3' eine 2 zurück gibt (PINB,2 [und nur PINB,2(!)] ist dann auf 0)
8
  ....
9
  .... und wenn möglich soll sie, wenn mehrere der Pins gleichzeitig
10
  .... auf Low sind, oder wenn gar keiner auf Low ist eine 99
11
  .... zurück geben, denn dann ist der Schalter gerade in einer
12
  .... Zwischenposition, die keine Aussage erlaubt.
13
  .... Uns interessieren nur definitive, fixe Schalterstellungen
14
}

denk dir was aus. So schwer ist das nicht. Und es gibt mehrere 
Möglichkeiten wie man das Gewünschte erreichen kann.
Nicht immer ist die erste naive Idee auch die einfachste.
Zum Beispiel sagt kein Mensch, dass man die Pins einzeln abfragen muss. 
Man kann auch den kompletten PINB hernehmen und alle nicht 
interessierenden Bits wegmaskieren (gezielt auf 0 setzen). Dann bleiben 
Zahlen (weil es ja 3 Bits sind) im Bereich 0 bis 7 übrig (weil die Pins 
die Bits 0 bis 2 sind). Und jede dieser Zahlen ist spezifisch für eine 
ganz spezielle Bitsituation. Mit dieser Zahl im Bereich 0 bis 7 kann man 
zb wieder ein Array indizieren und daraus sich den Wert holen, den die 
Funktion zurückgeben soll. Und wann man dann noch im Array die Werte 
entsprechend richtig anordnet, leistet die Funktion genau das 
Gewünschte.

von Sven W. (sickone4)


Lesenswert?

ich hab das nun so gemacht:
1
int a = 0;
2
3
uint8_t fetchSchalter()
4
{
5
  if (bit_is_clear (PINB,0) && bit_is_set (PINB,2) && bit_is_set (PINB,1))  { a = 0; }
6
  if (bit_is_clear (PINB,1) && bit_is_set (PINB,0) && bit_is_set (PINB,2))  { a = 1; }
7
  if (bit_is_clear (PINB,2) && bit_is_set (PINB,1) && bit_is_set (PINB,0))  { a = 2; }  
8
    
9
  return a;    
10
}

das war ein krampf... nur weil ich das return nicht gefunden hab.....

ich werde die pins wohl mit der hammerschlag methode abfragen müssen bez 
der 99 stellung, da ich die anderen pins wohl benötige^^

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
>
1
> int a = 0;
2
> 
3
> uint8_t fetchSchalter()
4
> {
5
>   if (bit_is_clear (PINB,0) && bit_is_set (PINB,2) && bit_is_set
6
> (PINB,1))  { a = 0; }
7
>   if (bit_is_clear (PINB,1) && bit_is_set (PINB,0) && bit_is_set
8
> (PINB,2))  { a = 1; }
9
>   if (bit_is_clear (PINB,2) && bit_is_set (PINB,1) && bit_is_set
10
> (PINB,0))  { a = 2; }
11
> 
12
>   return a;
13
> }
14
>

1
//   0  000      99           4  100      99
2
//   1  001      99           5  101       1
3
//   2  010      99           6  110       0
4
//   3  011       2           7  111      99
5
uint8_t fetchSchalter()
6
{
7
  static uint8_t Werte[8] = { 99, 99, 99, 2, 99, 1, 0, 99 };
8
9
  return Werte[ PINB & 0x07 ];
10
}

Meiner Meinung nach solltest du etwas weniger bit_is_clear benutzen und 
dich dafür lieber mit den Möglichkeiten und Einsatzgebieten der 
Bitoperationen vertraut machen. Du hast einfach mehr davon, wenn du 
weißt, wie bit_is_clear bzw. bit_is_set prinzipiell funktionieren 
(nämlich mit Bitoperationen) UND kannst darüberhinaus die Bitoperationen 
auch noch für dich arbeiten lassen. Nämlich genau dann, wenn du mehr als 
nur 1 Bit von einem Port in eine Operation miteinbeziehst.

Und eigentlich sind genau das (die Bitoperationen) die ersten Übungen 
und Anwendungen, die man in der µC Ausbildung macht.

von Sven W. (sickone4)


Lesenswert?

gute idee, werde ich mir mal anschauen,

frage mich nur schon die ganze zeit, wieso sind die aktiven bits bei dir 
immer auf 0?

bei mir sind die auf 1!?

beispielsweise:
>//   101       1

bei mir wäre eine 1 =
// 010

?!

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> gute idee, werde ich mir mal anschauen,
>
> frage mich nur schon die ganze zeit, wieso sind die aktiven bits bei dir
> immer auf 0?

Weil du hier
Beitrag "Re: Signalerkennung"
bit_is_clear benutzt hast

> bei mir sind die auf 1!?

ok. dann dreh die Werte im Array einfach um.
An den Indexpositionen, an denen es nur 1 Stück 1 Bit gibt, vergibst du 
0,1,2 und alle anderen werden 99


Allerdings:
Du fragst ja auch hier

>   if (bit_is_clear (PINB,0) && bit_is_set (PINB,2) && bit_is_set
> (PINB,1))  { a = 0; }

ab, ob PINB PB0 eine 0 aufweist und alle anderen 1 sind.
Es scheint mir also dann doch so zu sein, dass alle Eingangspins, bis 
auf einen auf 1 liegen und der eine ist auf 0 :-)

von Sven W. (sickone4)


Lesenswert?

das mt dem array versteh ich ja, aber ich hab das mit dem bit_is_clear 
so gelernt.

pullup setzen, pinansprechen,

clear für an = 1 und set für aus = 0. so hab ich das gelernt^^ (in der 
technikerschule^^)

von Karl H. (kbuchegg)


Lesenswert?

1
//   +--- das ist die Dezimalzahl, die als Index ins Array fungieren wird
2
//   |
3
//   |   +---- das sind die 3 Bits PB2, PB1 und PB0, die 'zufällig' genau
4
//   |   |     die Bitdarstellung der Dezimalzahl entsprechen
5
//   |   |
6
//   |   |        +---- und das ist der Codewert, der zur Auswertung geht
7
//   |   |        |
8
//   |   |        |           +------------+  und hier dasselbe nochmal
9
//   |   |        |                           für die restlichen möglichen
10
//   |   |        |                           Kombinationen
11
//   v   v        v
12
//   0  000      99           4  100      99
13
//   1  001      99           5  101       1
14
//   2  010      99           6  110       0
15
//   3  011       2           7  111      99

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> das mt dem array versteh ich ja, aber ich hab das mit dem bit_is_clear
> so gelernt.
>
> pullup setzen, pinansprechen,
>
> clear für an = 1 und set für aus = 0. so hab ich das gelernt^^ (in der
> technikerschule^^)

Tja. Dann habt ihr einen Schritt übersprungen. Und das rächt sich jetzt. 
Ihr habt sozusagen mit einer CNC-Fräse umgehen gelernt aber nie eine 
Feile in der Hand gehabt. Manchmal ist eine Feile dann eben doch 
universeller.

>>> Bitmanipulation <<<

von Sven W. (sickone4)


Lesenswert?

haha ok das würde ggf auch erklären, wieso so viele lücken vorhanden 
sind...
1
//   000      99
2
//   001       0
3
//   010       1
4
//   011      99
5
//   100       2
6
//   101      99
7
//   110      99
8
//   111      99
9
uint8_t fetchSchalter()
10
{
11
  uint8_t Werte[8] = { 99, 0, 1, 99, 2, 99, 99, 99 };
12
13
  return Werte[ PINB & 0x07 ];
14
  
15
}

so sieht das bei mir aus. funktioniert aber nicht, nun steht immer eine 
1 in meiner ausgabe....

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> haha ok das würde ggf auch erklären, wieso so viele lücken vorhanden
> sind...
>
> [code]
> //   000      99
> //   001       0
> //   010       1
> //   011      99
> //   100       2
> //   101      99
> //   110      99
> //   111      99


Ich glaub dir das nicht.
Das deckt sich nicht mit deinem restlichen Code.

Hier zb
>   if (bit_is_clear (PINB,0) && bit_is_set (PINB,2) && bit_is_set
> (PINB,1))  { a = 0; }

fragst du explizit ab, ob PINB, Bit0 auf 0(!) ist und die anderen auf 1.
D.h. du gehst davon aus, dass der Pin, der mit dem Schalter eingestellt 
ist, eine 0 aufweist.

Wenn diese Monsterabfrage korrekt ist, dann ist deine Tabelle falsch und 
meine richtig.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> clear für an = 1 und set für aus = 0. so hab ich das gelernt^^ (in der
> technikerschule^^)


Was'n das für ein Quatsch

  0V - clear - 0 - aus

  5V - set   - 1 - ein

so ist die weltweite Konvention. 0 und 'aus' sind synonym. 1 und 'ein' 
sind synonym.
Wäre das nicht so, würden die logischen Operationen nicht funktionieren.

von Sven W. (sickone4)


Lesenswert?

hm ok

leider muss ich los, aber ich hab mir mal den spass erlaubt einen teil 
der anleitung zu diesem thema aus unserem online portal zu kopieren, vll 
leigt da schon ein fehler.

ich selbst versteh unter set und clear auch was anderes:
1
void main( void )                   // Die Funktion "main" wird aufgerufen,
2
  {                                 // es wird kein Wert mitgegeben (void)
3
                                    // es wird kein Wert zurückgegeben ("void" vor main)
4
     DDRC = 0b00000000;             // Datenrichtung C2 auf EINGANG
5
     PORTC = 0b00000100;            // 5V an C2 üb. internen Pull-Up-Widerstand (ca.35 KOhm)
6
                                    // anlegen.
7
     DDRB = 0b00000001;             // Port B, Pin 0 als AUSGANG definieren
8
     PORTB = 0b00000000;            // Port B, Pin 0 auf LOW (0 V) setzen, LED aus
9
       
10
       while ( 1 )                  // Endlosschleife,
11
         {
12
            if ( bit_is_clear ( PINC,2 ) ) // gedrückter Taster "zieht" Spannung an C2 auf 0 V, LOW
13
              {                            // gesamte Spannung fällt an Pull-Up-Widerstand ab
14
                 PORTB = 0b00000001;       // Port B, Pin 0 auf High (5 V) setzen, LED an
15
         }
16
17
            if ( bit_is_set ( PINC,2 ) )   // Taster gelöst, 5 V wieder über Pull-Up an C2, HIGH
18
              {
19
                 PORTB = 0b00000000;       // Port B, Pin 0 auf LOW (0 V) setzen, LED aus
20
              }
21
          }
22
}

und das ist kein spass

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

>             if ( bit_is_clear ( PINC,2 ) ) // gedrückter Taster "zieht"
> Spannung an C2 auf 0 V, LOW

'Zieht Spannung auf Low, 0V'
D.h. der Pin ist dann auf 0

bit_is_clear ist also die Frage: Ist der Pin auf 0? Ja oder Nein.

von Sven W. (sickone4)


Lesenswert?

klar isser... oh mann.... tz denkfehler....

von Karl H. (kbuchegg)


Lesenswert?

Macht ja nix.
Wichtig ist, dass wir solche Missverständnisse identifizieren und 
ausmerzen.

von Route_66 (Gast)


Lesenswert?

Hallo!
> so hab ich das gelernt^^ (in der
technikerschule^^)

Daram merkst Du: zwischen "gelernt" und "verstanden" ist ein riesiger 
Unterschied, der hoffentlich durch "Erfahrung" und "Praxis" irgendwann 
ausgeglichen wird.

von Sven (Gast)


Lesenswert?

Wenn man nie hinterfragt welchen Zustand das byte hat, dann ist zw 
wissen und verstehen ein Unterschied

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:
> Wenn man nie hinterfragt welchen Zustand das byte hat, dann ist zw
> wissen und verstehen ein Unterschied

Das ist schon ok.
Diesen Fehler hast du einmal gemacht, den machst du nie wieder.
In Zukunft passiert dir sowas einfach nicht mehr. Das ist gemeint mit 
"Es ist eine Sache, etwas irgendwo zu lernen, aber es ist eine ganz 
andere Sache das Gelernte dann auch umzusetzen". Im einen Fall sind die 
Dinge abstrakt im anderen sind sie ganz real, weil du die Auswirkungen 
spürst. Du kannst hundertmal lesen, dass man nicht mit Sandalen in die 
Berge klettern geht. Aber erst dann, wenn du mit den Sandalen einen Hang 
runterrutscht, hast du verinnerlicht warum das so ist.


Es ist zb eine Sache, in einem Beispielprogramm zu lesen
1
    if ( bit_is_clear ( PINC,2 ) ) // gedrückter Taster "zieht" Spannung an C2 auf 0 V, LOW
2
    {                            // gesamte Spannung fällt an Pull-Up-Widerstand ab
3
      PORTB = 0b00000001;       // Port B, Pin 0 auf High (5 V) setzen, LED an
4
    }
5
6
    if ( bit_is_set ( PINC,2 ) )   // Taster gelöst, 5 V wieder über Pull-Up an C2, HIGH
7
    {
8
      PORTB = 0b00000000;       // Port B, Pin 0 auf LOW (0 V) setzen, LED aus
9
    }

es ist aber eine ganz andere Sache, dann selbst zu schreiben
1
  if ( !(PINC & ( 1<<PC2)) )
2
  {
3
    PORTB |= ( 1 << PB0 );
4
  }
5
  else
6
  {
7
    PORTB &= ~( 1 << PB0 );
8
  }

die 2.te Version ist um Größenordnungen besser, als die erste (aus 
mehreren Gründen). Und noch besser ist sie, wenn man schreibt
1
#define TASTER_ROT    PC2
2
#define LED_GELB      PB0
3
4
5
  if ( !(PINC & ( 1 << TASTER_ROT)) )
6
  {
7
    PORTB |= ( 1 << LED_GELB );
8
  }
9
  else
10
  {
11
    PORTB &= ~( 1 << LED_GELB );
12
  }

Und da kann man jetzt noch weitere Transformationen anschliessen lassen, 
die den Code zwar nicht in der Funktionalität, sondern in der 
Codequalität verbessern.

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.