blackdog
Golden Member
Daar de mens het noodzakelijke niet kan volbrengen, streeft hij naar het overbodige (Goethe)
Hi,
Ik ben met een stukje code bezig voor mijn PID testprintje, dat laat ik later nog zien.
Nu wil ik een drukknopje hebben zodat ik tussen twee temperaturen kan schakelen en met een extra sensor aan het oventje aangesloten op een van mijn DMM's
zodat ik de grafiek van het temperatuur verloop kan zien.
Dit om de P, I en uiteindelijk de D waarde optimaal te kunnen instellen.
De drukknop gaat op het display laten zien, of ik de oven op zeg 45 of 50 °C ingesteld heb, dus kleine sprongen om de PID stabiliteit te testen.
De Code
const int buttonPin = 5; // Pin for the push button
const int ledPin = 6; // Pin for the LED
bool lastButtonState = LOW; // Previous state of the button
bool ledState = false; // Current state of the LED
unsigned long lastDebounceTime = 0; // Last time the button state changed
unsigned long debounceDelay = 50; // Debounce time in milliseconds
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Set button pin as input with internal pull-up resistor
pinMode(ledPin, OUTPUT); // Set LED pin as output
digitalWrite(ledPin, ledState); // Initialize LED state
Serial.begin(9600); // Start serial communication for debugging
}
void loop() {
int reading = digitalRead(buttonPin); // Read the current state of the button
// Print the current button state for debugging
Serial.print("Button State: ");
Serial.println(reading == LOW ? "Pressed" : "Not Pressed");
Serial.println(lastButtonState); Deze waarde veranders van 1 naar 0 bij indrukken van knop
// Check if the button state has changed
if (reading != lastButtonState) {
lastDebounceTime = millis(); // Reset the debounce timer
}
// Only toggle the LED if the button state has been stable for the debounce delay
if ((millis() - lastDebounceTime) > debounceDelay) {
// Check for a button press
if (reading == LOW && lastButtonState == HIGH) { // Button is pressed (transition from HIGH to LOW)
ledState = !ledState; // Toggle the LED state
digitalWrite(ledPin, ledState ? HIGH : LOW); // Set the LED state
Serial.println(ledState ? "LED ON!" : "LED OFF!"); // Print the current LED state
}
}
lastButtonState = reading; // Save the reading as the last button state
}
De code komt van contollino.io en is zeker niet vrij van errrors, ik moet er altijd wel wat foutjes uit halen,
maar ik leer er ook van, juist omdat ik het snel kan testen.
Verder om gestructureerd vragen te stellen, dit om een beter resultaat te krijgen uit de code generator.
Een paar keer aangegeven in de AI machine dat het niet werkt, en heb wat testen gedaan met alleen de drukknop en alleen de LED om te zien of de code dit goed inleest en aanstuurd.
Het probleem is dat de LED status niet veranderd als ik het knopje gebruik. (de bedoeling is dat deze toggled en niet veranderd van status als je het toetsje ingedrukt houd.
In de debug code kan ik zien wanneer het knopje is ingedrukt en ik heb dit nog toegevoegt om te zien of dit item van waarde veranderd en die gaat van 1 naar 0 bij het indrukken van het knopje.
Serial.println(lastButtonState);// Deze waarde veranders van 1 naar 0 bij indrukken van knop
Zien jullie de fout, ik niet. 
Dank en groet,
Bram
Ik denk dat deze nooit werkt:
if (reading == LOW && lastButtonState == HIGH) { // Button is pressed (transition from HIGH to LOW)
omdat je ook een debounce hebt, dan is op de laatste regel lastButtonState tijdens de debouncedelay ook al weer laag gezet en gaat die 'lastButtonState== HIGH' nooit werken.
Ik denk dat je die:
lastButtonState = reading; // Save the reading as the last button state
Ook in de debounce if kan zetten..
Ik heb het niet helemaal doordacht maar ik gok dat daar ergens je probleem zit.
Roches
Domoticz en ESP8266, goede combo!!!
// Only toggle the LED if the button state has been stable for the debounce delay
if ((millis() - lastDebounceTime) > debounceDelay) {
// Check for a button press
if (reading == LOW && lastButtonState == HIGH) { // Button is pressed (transition from HIGH to LOW)
ledState = !ledState; // Toggle the LED state
digitalWrite(ledPin, ledState ? HIGH : LOW); // Set the LED state
Serial.println(ledState ? "LED ON!" : "LED OFF!"); // Print the current LED state
} else if (reading == HIGH && lastButtonState == LOW) { // Button is pressed (transition from LOW to HIGH)
ledState = !ledState; // Toggle the LED state
digitalWrite(ledPin, ledState ? HIGH : LOW); // Set the LED state
Serial.println(ledState ? "LED ON!" : "LED OFF!"); // Print the current LED state
}
}
Denk dat het dit moet zijn...
if (reading == LOW && lastButtonState == HIGH)
Bovenstaande conditie wordt nooit bereikt. Want als reading en lastButtonState verschillen dan wordt de deboucetijd opnieuw gestart en bovenstaande code wordt dan nooit uitgevoerd zoals K7Jz ook al zei.
Feitelijk moet je bijhouden of de debounce al is gestart en je moet bijhouden of je al getoggled hebt. Dat kan het makkelijkste met een klein state machientje:
Dat kan bijv zo:
const int buttonPin = 5; // Pin for the push button
const int ledPin = 6; // Pin for the LED
int buttonState = 0;
bool ledState = false; // Current state of the LED
unsigned long lastDebounceTime = 0; // Last time the button state changed
unsigned long debounceDelay = 50; // Debounce time in milliseconds
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Set button pin as input with internal pull-up resistor
pinMode(ledPin, OUTPUT); // Set LED pin as output
digitalWrite(ledPin, ledState); // Initialize LED state
Serial.begin(9600); // Start serial communication for debugging
}
void loop() {
int reading = digitalRead(buttonPin); // Read the current state of the button
// Print the current button state for debugging
Serial.print("Button State: ");
Serial.println(reading == LOW ? "Pressed" : "Not Pressed");
if(reading == LOW)
{ if(buttonState == 0)
{ lastDebounceTime = millis(); // Reset the debounce timer
buttonState = 1;
}
if( (buttonState == 1) && ( (millis() - lastDebounceTime) > debounceDelay) )
{ buttonState = 2;
ledState = ledState ? LOW : HIGH; // Toggle
digitalWrite(ledPin, ledState); // Set the LED state
Serial.println(ledState ? "LED ON!" : "LED OFF!"); // Print the current LED state
}
}
else
{ buttonState = 0;
}
}
buttonState is nu een int:
- 0 als de button niet ingedrukt is.
- 1 als de debounce tijd loopt
- 2 als de debouncetijd al afgelopen is
De toggle van de led gebeurt nu op de overgang van 1 naar 2.
Er is nu geen debounce op het loslaten van de button. Als dat wel nodig is dan moet er nog een state bij.
PS: O wacht, De button is active low natuurlijk. Dus dan moet je op low testen. Aangepast in de code.
EricP
mét CE
De enige fatsoenlijke debounce die ik ooit gezien heb, is een counter:
if button low and counter > 0 then counter--
if button high and counter < MAX then counter++
if 0==counter // apparently button is low
if MAX==counter // apparently button is high
Daar kun je alle kanten meer variëren. En 'MAX' moet natuurlijk een beetje in relatie zijn met de snelheid van de loop waarin getest wordt en je counter moet MAX ook kunnen hebben qua waarde (duh...). Als je bijvoorbeeld in een ISR elke 10mS de boel leest, dan zou 20 ofzo best wel eens een leuke waarde kunnen zijn.
Houd ff in de gaten dat 'millis' een eng ding kan zijn. Het wrapped op sommige controllers best vaak en daar moet je code wel tegen kunnen.
blackdog
Golden Member
Daar de mens het noodzakelijke niet kan volbrengen, streeft hij naar het overbodige (Goethe)
Hi deKees,
Dank, dat werkt, ik was ondertussen er ook al achter gekomen dat in deze regel de blokkade zat, want mijn Serial.println("Jaap"); werd niet in de serial monitor weergegeven,
maar de Serial.println("Wim"); die er voor stond wel.
if (reading == LOW && lastButtonState == HIGH) { // Button is pressed (transition from HIGH to LOW)
Bij elkaar toch knap lastig voor een simpele functie, een uitgang toggelen met debounce en als je de knop ingedrukt houd, dat de status dan niet steeds veranderd.
Ik sla dit stukje code even op in mijn archief, altijd handig!
Debounce bij het loslaten is niet nodig, ik heb een van mijn slechste drukknopjes er bij gepakt en de debounce tijd op 10mSec geset, no problemo.
Verder dit toegevoegt in de "Setup" om de LED uitgang laag te houden bij Power Up => ledState = HIGH;
Mijn dank is weer groot Heren.
Groet,
Bram
marcob
Honourable Member
People tend to overestimate what can be done in one year and to underestimate what can be done in five or ten years
Er bestaat ook een Library voor. Zelf nog nooit gebruikt. Kan handing zijn als je meerdere knoppen hebt.
https://github.com/Dlloydev/Toggle
blackdog
Golden Member
Daar de mens het noodzakelijke niet kan volbrengen, streeft hij naar het overbodige (Goethe)
Hi marcob,
Dank je voor de link, die "Dlloydev" Library had ik nog niet, wel heb ik twee andere library's voor drukknopjes.
Mijn doel was vandaag, er zelf eens mee te spelen, kijken hoever ik kwam, niet zo ver dus. 
De code van is "gecompileerd" vrijwel even groot als de code die ik liet zien.
Daar zit geen voordeel in, maar die "Dlloydev" library heeft wel veel functionaliteit, ook één voor mij om te onthouden.
Het mooie is, dat deze library bouwer ook een PID library heeft, welke misschien handig voor mijn gebruik is.
Groet,
Bram