I have never used an Arduino before, so I decided to learn how to program one. Since I'm interested in power electronics, I decided to start by trying to write a code to alter the PWM of a digital pin using push buttons and interrupts (to control the brightness of an LED, to begin with).
I've connected two push buttons to digital pins 2 and 3 (one to increment the dutycycle and the other to decrement) and an LED to pin 9. I've enabled the input pull-up resistors for the two digital pins and the interrupt mode is LOW.
But when I run the simulation, the dutycycle doesn't change at all when I push either of the push buttons:
The duty cycle is stuck at 0 and won't increment even though I've held the 'increment duty cycle' push-button down (the DMM reads 0V instead of 5V, confirming that the button has been pushed down).
Here's the code that I've written:
// C++ code
//
#define DEC 3
#define INC 2
#define PWM 9
int dutycycle = 0;
void setup()
{
Serial.begin(9600);
pinMode(DEC, INPUT_PULLUP);
pinMode(INC, INPUT_PULLUP);
pinMode(PWM, OUTPUT);
analogWrite(PWM, 0);
attachInterrupt(digitalPinToInterrupt(DEC), DEC_ISR, LOW);
attachInterrupt(digitalPinToInterrupt(INC), INC_ISR, LOW);
}
void DEC_ISR()
{
if(dutycycle>0)
--dutycycle;
}
void INC_ISR()
{
if(dutycycle<255)
++dutycycle;
}
void loop()
{
analogWrite(PWM, dutycycle);
Serial.println("Duty cycle: ");
Serial.print(dutycycle);
Serial.println();
}
Please let me know what I've done wrong.
-
\$\begingroup\$ test if ISR is being called ... reduce the code to minimum ... turn on LED in one ISR ... turn off LED in other ISR \$\endgroup\$jsotola– jsotola2021年07月17日 05:38:38 +00:00Commented Jul 17, 2021 at 5:38
-
\$\begingroup\$ @jsotola I replaced the interrupt mode to FALLING instead of LOW and it works. But for some reason, the LOW level triggering isn't working. The ISR is not called when the interrupt mode is LOW for some reason. \$\endgroup\$Prathik Prashanth– Prathik Prashanth2021年07月17日 05:41:41 +00:00Commented Jul 17, 2021 at 5:41
1 Answer 1
I tested your code, and it seems that setting the interrupt mode to LOW actually means that the ISR is called repeatedly as long as the input is low. Of course, that blocks the main thread from executing. (Note that there's no output while a button is pressed) Since the change to the dutyCycle
variable is very fast, you'll never get anything other than max and min.
I would therefore say that the interrupt mode LOW
is unusable for most situations. You can either use FALLING
or polling instead, if you want that long presses decrement/increment the light stepwise. For such a simple sketch as yours, you don't really need the interrupts, actually.
Maybe something like:
void loop()
{
analogWrite(PWM, dutycycle);
Serial.print("Duty cycle: ");
Serial.print(dutycycle);
Serial.println();
if (digitalRead(INC) == 0)
{
if(dutycycle<255)
++dutycycle;
}
else if (digitalRead(DEC) == 0)
{
if(dutycycle>0)
--dutycycle;
}
delay(100);
}
-
\$\begingroup\$ "it seems that setting the interrupt mode to LOW actually means that the ISR is called repeatedly as long as the input is low." Yes, that's what I wanted. "Of course, that blocks the main thread from executing." Even after releasing the pushbutton, the duty cycle remained unchanged. Infact, it didn't even enter the ISR. After changing it to falling, it worked, but that means I need to press the pushbutton 255 time to reach 100% dutycycle. " if you want that long presses decrement/increment the light stepwise." yes, this is what I want. I hoped by using LOW, that would happen. \$\endgroup\$Prathik Prashanth– Prathik Prashanth2021年07月17日 09:14:50 +00:00Commented Jul 17, 2021 at 9:14
-
\$\begingroup\$ Maybe I should build a 0.5Hz square wave generator and connect it to the interrupt pin through the push button to get the slow increase in the duty cycle that I want. \$\endgroup\$Prathik Prashanth– Prathik Prashanth2021年07月17日 09:20:29 +00:00Commented Jul 17, 2021 at 9:20
-
\$\begingroup\$ @PrathikPrashanth I used real hardware, so there could also be some difference in behavior. On the real hardware, I saw the behavior as described above. Adding a square wave generator is an option, but seems a bit to complicated for the purpose. \$\endgroup\$PMF– PMF2021年07月17日 09:28:07 +00:00Commented Jul 17, 2021 at 9:28
-
\$\begingroup\$ Actually, I think that might be the best solution for me. In the future (once I fully figure out how to program uCs), I will build a digitally controlled DC-DC converter with pushbuttons to adjust the o/p voltage (and current limit) using the STM32. I plan to use one push button to increment the output voltage by one volt (up to 30V) and another to increment the voltage by 100mV. Having a 0.5Hz square wave to trigger the interrupt will let me increment/decrement the output voltage/current limit smoothly by holding the push button down until I reach the desired value. \$\endgroup\$Prathik Prashanth– Prathik Prashanth2021年07月17日 09:33:37 +00:00Commented Jul 17, 2021 at 9:33
-
\$\begingroup\$ Or is there a way to block an interrupt from executing for a short period of time just after it runs, even if the interrupt request signal is still there? \$\endgroup\$Prathik Prashanth– Prathik Prashanth2021年07月17日 09:48:59 +00:00Commented Jul 17, 2021 at 9:48