PWM via Taster

Guten Tag

Ich wollte ein Programm entwerfen, das mir unter anderem mittels PWM einen Lüfter steuert:

  • mittels Taster soll die Geschwindigkeit in 4 Stufen (Aus, langsam, mittel, schnell) geschaltet werden

Das Programm habe ich soweit geschrieben:

/*  I/O-Ports  */
  const byte bytPWMLuefter = 3;                              // PWM-Ausgang für Lüftergeschwindigkeit
  const boolean blnLuefterTaster = 15;                       // Taster Umschaltung Lüfer-Speed

/*  Variablen  */
  boolean blnTasterLuefterStatus = 0;                        // Taster gedrückt?
  byte bytLevelLuefterspeed = 0;                             // Levelzähler (0,1,2,3)
  byte bytLuefterspeed = 0;                                  // Speedwert (0-255)

/* ----------------------------------------------------------------------------------------------------------------- */
void setup(){
  /*  I/O-Ports  */                                              
    pinMode(bytPWMLuefter, OUTPUT);                          // D2 auf Ausgang
    pinMode(blnLuefterTaster, INPUT);                        // A1 auf Eingang
      digitalWrite(blnLuefterTaster, HIGH);                    // Pull-Up für A1
      
  /*  Displays  */                                           
    Serial.begin (9600);                                     // Startet die serielle Kommunikation
    delay (1000);                                            // Startzeitverzögerung
}

/* ---------------------------------------------------------------------------------------------------------------- */
void loop(){
  // Zähler für den Speed-Level
  if(blnTasterLuefterStatus == 0 && digitalRead(blnLuefterTaster) == LOW){
    blnTasterLuefterStatus = 1;
    bytLevelLuefterspeed ++;
    if(bytLevelLuefterspeed > 3){
     bytLevelLuefterspeed = 0;
    }
  }
  if(digitalRead(blnLuefterTaster) == HIGH){
    blnTasterLuefterStatus = 0;
  }
  
  
  Serial.print("Level: ")  ;
  Serial.println(digitalRead(bytLevelLuefterspeed));
  
  
  if (analogRead(bytLuefterspeed) == 0){
    bytLuefterspeed = 0;
  }
  if (analogRead(bytLuefterspeed) == 1){
    bytLuefterspeed = 70;
  }
  if (analogRead(bytLuefterspeed) == 2){
    bytLuefterspeed = 150;
  }
  if (analogRead(bytLuefterspeed) == 3){
    bytLuefterspeed = 255;
  }
  analogWrite(bytPWMLuefter, analogRead(bytLuefterspeed));
  
  
  Serial.print("PWM: ")  ;
  Serial.println(digitalRead(bytLuefterspeed));
}

Von der Logik her würd ich sagen es sollte gehen ... tut es aber 0 =(

Wenn ich mir dann den Wert des Levels via SM ausgeben lasse steht da beim Start "1"?
--> byte bytLevelLuefterspeed = 0; sollte doch eigentlich einen Startwert von 0 haben ... auch zählt der nicht einfach hoch sondern wechselt immer nur zwischen 1 und 0 hin und her

Start: 1

  1. Tastendruck: 0
  2. Tastendruck: 0
  3. Tastendruck: 0
  4. Tastendruck: 1

Und selbst wenn ich den Wert 1 habe müsste ja der PWM Ausgang angesteuert werden ... da passiert genauso wenig etwas ...

Kann mir jemand nen Hinweis geben, was ich falsch mache? - hab in den letzten Stunden soviel Sachen umgeschrieben das ich echt nur noch Chaos sehe ...

Gruß Scorch

Hallo,
In deinem Programm sind einige Fehler. Dir sollte auch bewusst sein, dass der Taster vielleicht prellt.

Zu den Fehlern:

Serial.println(digitalRead(bytLevelLuefterspeed));

Das digitalRead musst du wecklassen, du willst ja einfach die Variable ausgeben.
Mit digitalRead kannst du nur abfragen ob ein Pin HIGH oder LOW ist.

if (analogRead(bytLuefterspeed) == 0)

Hier das gleiche, analogRead braucht es nicht, du kannst direkt fragen welchen Wert bytLuefterspeed hat.

Die Variable in einer analogRead-Funktion(auch digitalRead) gibt den Pin an, an welchem der Wert eingelesen werden soll.

Der fast gleiche Fehler tritt noch ein paar mal auf.

Grüße,
J3RE

Serial.println(digitalRead(bytLevelLuefterspeed));  
  
  if (analogRead(bytLuefterspeed) == 0){
    bytLuefterspeed = 0;
  }
  if (analogRead(bytLuefterspeed) == 1){
    bytLuefterspeed = 70;
  }
  if (analogRead(bytLuefterspeed) == 2){
    bytLuefterspeed = 150;
  }
  if (analogRead(bytLuefterspeed) == 3){
    bytLuefterspeed = 255;
  }
  analogWrite(bytPWMLuefter, analogRead(bytLuefterspeed));

Du hast ein Verständnisproblem.

bytLevelLuefterspeed ist die Variable die sagt welche der 3 Geschwindigkeitsstufen aktiv ist.
digitalRead(bytLevelLuefterspeed) ergibt keinen Sinn. Du liest den Zustand der Pins 0-3 und hat gar nichts mit der Steuerung zu tun.
analogRead(bytLuefterspeed) Du liest den Zustand der Analogen Eingänge A0 bis A3. Da diese unbeschaltet sind, liest Du Störungen die in de Luft sind; sicher aber keine Wete Zwischen 0 und 3. So wird der PWM-Wert bytLuefterspeed nie gesetzt.
analogWrite(bytPWMLuefter, analogRead(bytLuefterspeed)); Hier setzt Du den PWM-Ausgang 3 auf einen Zufälligen Wert. Genaugesagt verwendest Du die unteren 8 bit eines 10 bit Wertes. Das ist in diesem Fall egal.

Du mußt zuerst den Taster entprellen, dann so einlesen daß Du nur auf den Wechsel von nicht gedrückt zu gedrückt auswertest.

Dann den PWM-Ausgang Schaltest. Bei niedrigen PWM Werten kann der Lüfter nicht anlaufen. also 2 Sekunden vollgas und dann auf den gewollten Wert zurückfahren.

Grüße Uwe

Hallo Scorch,
das erste was mir auffällt, du hast blnLuefterTaster als boolean deklariert und auf 15 gesetzt. boolean kann aber nur true oder false sein. Dann hast du blnLuefterTaste als Input deklariert und und auf high gesetzt. Ich vermute mal du möchtest den Pin 15 als Eingang für den Taster verwenden, dann solltest du int oder Byte verwenden.
Weiterhin liest du den Analogen Eingang 0 und prüfst ihn auf werte zwischen 0 und 3, ich glaube das wird bei 1024 Werten recht ungenau.
Gruß Ardubu

Erstmal nen riesen Dankeschön für die schnelle Hilfe an euch 3!!!

@ J3RE:
Das mit dem digital/analogRead war mir schon seit Anfang an etwas suspect ... mein 1. Programm hat erst funktioniert NACHDEM ich an vielen Stellen den Read-Befehl vor der Variable / dem Port eingebaut habe ... es hat zwar funktioniert, war dann vermutlich net gerade "sauber" geschrieben :~

Wenn ich das jetzt richtig verstanden habe liest man mit dem digital/analogRead die Pin-Nummer des I/O aus

digitalRead(pinD2) --> 2

bzw. man kann ihn auf HIGH / LOW abfragen

if (digitalRead(pinD2) == LOW) {
...

Will man den Zahlenwert auslesen z.B. 117 dann einfach nur den Variablen-Namen.
--> Wenn das jetzt richtig ist, sollte ich mir den alten Sketch nochmal ansehen ... das muss echt Zufall sein das es da funktioniert hat. :grin:

--> Hab den Code jetzt abgeändert und mein Level-Zähler funktioniert endlich - THX^^

@ uwefed:
Die Taster prellen nur selten --> hatten wir in einem Versuchsaufbau in der Schule getestet.
Der Code soll bei mir ausschließlich verhindern das wenn man die Taste dauerhaft, drückt der Zähler weitertaktet.

 if (bytLuefterspeed == 1){
    bytLuefterspeed = 70;

ist natürlich Blödsinn - hab ich so oft umgeschrieben und vor dem Posten hier garnet gemerkt was übrig geblieben ist :blush:

 if (bytLevelLuefterspeed == 1){
    bytLuefterspeed = 70;

So klapp - zu dem nun funktionierenden Level-Zähler - auch mein PWM-Ausgang Happy

@ ardubu:
Mit

const boolean blnLuefterTaster = 15;
...
pinMode(blnLuefterTaster, INPUT);

weise ich doch der Boolean mit dem Namen blnLuefterTaster den 15. PIN (Beim Nano A1) zu - und Boolean da ich ja an diesem Pin nur High/Low abfragen will.
--> In die Schaltung kommen noch einige Funktionen rein und da ich keinen Analog-I benötige nutze ich sie als digital-Eingange :wink:
Hatte auch anfangs int genutzt, aber dann gelesen das ich wenn nur HIGH / LOW abgefragt werden soll auch Boolean nutzten kann da dies den Speicher schont.

Alles in Allem:
Das Prog läuft, fehlerhafte Kenntnisse wurden ausgebügelt und ich kann mit der nächsten Funktion anfangen - vielen, vielen Dank!

Gruß Scorch

Wenn ich das jetzt richtig verstanden habe liest man mit dem digital/analogRead die Pin-Nummer des I/O aus

digitalRead(pinD2) --> 2

Das ist nicht ganz richtig, man liest den Zustand des Pins ein, nicht die Pin-Nummer!
Die Pin-Nummer ist ja der Wert welcher in pinD2 gespeichert ist.

@ ardubu:
Mit

const boolean blnLuefterTaster = 15;

...
pinMode(blnLuefterTaster, INPUT);



weise ich doch der Boolean mit dem Namen blnLuefterTaster den 15. PIN (Beim Nano A1) zu - und Boolean da ich ja an diesem Pin nur High/Low abfragen will.
--> In die Schaltung kommen noch einige Funktionen rein und da ich keinen Analog-I benötige nutze ich sie als digital-Eingange smiley-wink
Hatte auch anfangs int genutzt, aber dann gelesen das ich wenn nur HIGH / LOW abgefragt werden soll auch Boolean nutzten kann da dies den Speicher schont.

Nein du weist der Variable blnLuefterTaster den Wert 15 zu. Die Variable, in welche du den Zustand speicherst könnte vom Datentyp Boolean sein.

boolean zustand;
unsigned int blnLuefterTaster = 15;
...
pinMode(blnLuefterTaster, INPUT);
...
zustand = digitalRead(blnLuefterTaster);

Grüße,
J3RE

@ uwefed:
Die Taster prellen nur selten --> hatten wir in einem Versuchsaufbau in der Schule getestet.

Es kommt auf die Taster an. Es gibt solche, die extra so konstruiert wurden, daß sie nicht prellen.

Ich würde, auch wenn Du wenig prellende Tasten hast, entprellen vorsehen. Ein delay von 5mS nach dem lesen der Taste genügt um zu entprellen.

Grüße Uwe