Pulse Width Modulation Control

Hi All, could I please get assistance on the following:
The objective is to control the brightness of an LED using both a potentiometer and buttons
Button 1 - decrease brightness
Button 2 - increase brightness
Potentiometer - increase / decrease brightness

The challenge Im facing is controlling the LED independently via the buttons and potentiometer on the
analogWrite, as both the potentiometer and the buttons affect the led at the same time. Is there no way to stop potentiometer, work the buttons only and visa versa

Code Below:

#include <LiquidCrystal.h>
#include <Wire.h>

int LED1  = 7;   //LED
int pdown = 6;   // -
int pup   = 8;   // +
int lux = 0;         //luminate the LED
// ------------------------------------------------------------
int potValue1 = 0;
int potValue2 = 0; // final display variable

int potPin= A0;  //Declare potPin to be analog pin A0
int readValue;  // Use this variable to read Potentiometer
int writeValue; // Use this variable for writing to LED
// ------------------------------------------------------------
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  pinMode (potPin, INPUT); //set potPin to be an input
  pinMode (LED1,  OUTPUT); //
  pinMode (pdown, INPUT ); //  -
  pinMode (pup,   INPUT ); //  +
  lcd.clear ();
}

void loop(){
// ------------------------------------------------------------  
   readValue = analogRead(potPin);  //Read the voltage on the Potentiometer
   writeValue = (255./1023.) * readValue; //Calculate Write Value for LED
   analogWrite(LED1, writeValue);      //Write to the LED
 
    potValue1 = analogRead(potPin) / 10;
    potValue2 = potValue1 / 1.02;
  
    lcd.setCursor(0,0);
    lcd.print("Potent=");
    lcd.print(potValue1);
    lcd.print("%");
    delay(100);
    lcd.print(" ");
    delay(1);
    
// ------------------------------------------------------------   
 lcd.setCursor (0,1);
 lcd.print ("lux=");
 lcd.print (lux);
 lcd.print ("   ");
 
 if (digitalRead (pup) == LOW){
  lux = lux + 1;
  if (lux == 255){
    lux = 254;
  }
 }
 if (digitalRead (pdown) == LOW){
  lux = lux - 1;
  if (lux < 0){
    lux = 0;
  }
 }
 analogWrite (LED1, lux);
 delay (5);
}

You need some other input to select buttons or pot - without that how can the Arduino know what you want to do

Hi Hammy,

I can work the components individually, both buttons and pot work. However they are working concurrently. Meaning if the Pot is fully wound, the buttons are void.

Unless if there is a way to disable the potentiometer if the buttons are active.

Hi, could I please get assistance
How do I stop the LED from flickering when the brightness gets higher, and keep it calm instead.

I updated the code from the initial one, without the potentiometer, everything works just fine.

#include <LiquidCrystal.h>
#include <Wire.h>

int LED1          = 9;
int ButtonLeft    = 8;
int ButtonRight   = 6;
int brightness    = 220;
// ------------------------------------------------------------
int potValue1 = 0;
int potValue2 = 0; // final display variable

int potPin= A0;  //Declare potPin to be analog pin A0
int readValue;  // Use this variable to read Potentiometer
int writeValue; // Use this variable for writing to LED
// ------------------------------------------------------------
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  pinMode (potPin, INPUT); //set potPin to be an input
  pinMode(LED1,OUTPUT);        // Set pin 13 to be in output mode
  pinMode(ButtonLeft,INPUT);   // Set pin 7 to be in input mode
  pinMode(ButtonRight,  INPUT);   // Set pin 8 to be in input mode
  lcd.clear ();
}

void loop(){
// ------------------------------------------------------------  
   readValue = analogRead(potPin);  //Read the voltage on the Potentiometer
   writeValue = (255./1023.) * readValue; //Calculate Write Value for LED
   analogWrite(LED1, writeValue);      //Write to the LED
 
    potValue1 = analogRead(potPin) / 10;
    potValue2 = potValue1 / 1.02;
  
    lcd.setCursor(0,0);
    lcd.print("Potent=");
    lcd.print(potValue1);
    lcd.print("%");
    delay(100);
    lcd.print(" ");
    delay(1);
    
// ------------------------------------------------------------   
  if(digitalRead(ButtonLeft) == LOW) brightness--;   // If button on pin 7 is pressed, reduce brightness
  if(brightness < 0) brightness = 0;        // Don't let brightness drop below zero
  if(digitalRead(ButtonRight) == LOW) brightness++;   // If button on pin 8 is pressed, increase brightness
  if(brightness > 255) brightness = 255;    // Don't let brightness get above 255
  analogWrite(LED1, brightness);              // Set pin 13 to the new brightness level
  delay(10);    
  
 lcd.setCursor (0,1);
 lcd.print ("Brightness=");
 lcd.print (brightness);
 lcd.print ("   ");
}
analogWrite(LED1, writeValue);      //Write to the LED
analogWrite(LED1, brightness);

You have two different analogWrite() statments. If the two duty cycle values are different, and most likely they are, you will not be applying a consistent pwm to the led.

Unless if there is a way to disable the potentiometer if the buttons are active.

Please explain more about how you want the program to function. What does "buttons active" mean to you? Do you want a selector switch which sets either potentiometer or button input? Do you want the potentiometer enabled if there is no change from the buttons after a period of time? If the analogWrite() values are different, which do you want to use? When do you want to return control to the button input? Do you want a default input method (buttons?) to be enabled at the start of the program?

Please think through our program design in detail. and come back with a description of how your really want it to operate. How do you want the two input methods to be coordinated? You clearly can't have them both active at the same time with two different analogWrite() values.

dube_ga: Hi Hammy,

I can work the components individually, both buttons and pot work. However they are working concurrently. Meaning if the Pot is fully wound, the buttons are void.

Unless if there is a way to disable the potentiometer if the buttons are active.

That suggests that you need to re-read Reply #1

...R

Hi Cattledog,

What is required is controlling the brightness of an LED using both Buttons and a Potentiometer,
Button A: Increase
Button B: Decrease /Dim

Potentiometer: Increase and Decrease,

This however must happen on 1 single circuit and must display the results on an LCD.

If I do this separately, meaning buttons without potentiometer and visa versa, I win, the moment I combine the two. I get flickering when working the buttons, due to the potentiometer.

I have written two types of code and have considered using smoothing for the potentiometer using capacitors. And I’m still losing, I’m not sure what to do.

This below is my current code im running on Tinkercad.
Im open to any ideas
:confused: :confused:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

int LED1          = 9;
int ButtonLeft    = 8;
int ButtonRight   = 6;
int brightness    = 100;
// ------------------------------------------------------------
int potValue1 = 0;
int potValue2 = 0; // final display variable

int potPin= A0;  //Declare potPin to be analog pin A0
int readValue;  // Use this variable to read Potentiometer
int writeValue; // Use this variable for writing to LED
// ------------------------------------------------------------
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  pinMode (potPin, INPUT); //set potPin to be an input
  pinMode(LED1,OUTPUT);        // Set pin 13 to be in output mode
  pinMode(ButtonLeft,INPUT);   // Set pin 7 to be in input mode
  pinMode(ButtonRight,  INPUT);   // Set pin 8 to be in input mode
  lcd.clear ();
}

void loop(){
// ------------------------------------------------------------  
   readValue = analogRead(potPin);  //Read the voltage on the Potentiometer
   writeValue = (255./1023.) * readValue; //Calculate Write Value for LED
   analogWrite(LED1, writeValue);      //Write to the LED
 
    potValue1 = analogRead(potPin) / 10;
    potValue2 = potValue1 / 1.02;
  
    lcd.setCursor(0,0);
    lcd.print("Potent=");
    lcd.print(potValue1);
    lcd.print("%");
    delay(100);
    lcd.print(" ");
    delay(1);
    
// ------------------------------------------------------------   
  if(digitalRead(ButtonLeft) == LOW) brightness--;   // If button on pin 7 is pressed, reduce brightness
  if(brightness < 0) brightness = 0;        // Don't let brightness drop below zero
  if(digitalRead(ButtonRight) == LOW) brightness++;   // If button on pin 8 is pressed, increase brightness
  if(brightness > 255) brightness = 255;    // Don't let brightness get above 255
  analogWrite(LED1, brightness);              // Set pin 13 to the new brightness level
  delay(10);    
  
 lcd.setCursor (0,1);
 lcd.print ("Brightness=");
 lcd.print (brightness);
 lcd.print ("   ");
}

Code Design 2.JPG

What is required is controlling the brightness of an LED using both Buttons and a Potentiometer, Button A: Increase Button B: Decrease /Dim

Potentiometer: Increase and Decrease,

This however must happen on 1 single circuit and must display the results on an LCD.

There is a saying "A person with two watches never knows what time it is".

An LED driven by analogWrite(LED,value) with two different values, one from the pot, and one from the buttons, does not know what brightness to be.

I don't think you can achieve both input methods active at the same time. At least I'm not clever enough to figure it out. :(

What is the application, and do you really require what you are asking for?

Hi Cattledog,

This is a varsity assignment [subject _ Microcontrollers]
Even if I change the code to understand button states, it makes no difference on the flickering.

Research: https://www.instructables.com/id/Smooth-Potentiometer-Input/

Alternatively I need to smooth the signal produced by the potentiometer.

New Code Below:

#include <LiquidCrystal.h>
#include <Wire.h>
// ------------------------------------------------------------

int LED1          = 9;
int ButtonLeft    = 8;
int ButtonRight   = 7;
int brightness    = 0;

// ------------------------------------------------------------
byte buttonState1     = 0;
byte lastButtonState1 = 0;

byte buttonState2     = 0;
byte lastButtonState2 = 0;

unsigned long switchMillis;

// ------------------------------------------------------------

int potValue1 = 0;
int potValue2 = 0;
int potPin= A0;
int readValue;
int writeValue;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// ------------------------------------------------------------
void setup() {

  lcd.begin(16, 2);
  pinMode (potPin, INPUT);
  pinMode(LED1,OUTPUT);
  pinMode(ButtonLeft,INPUT);
  pinMode(ButtonRight,  INPUT);
  lcd.clear ();
}

// ------------------------------------------------------------
void loop(){

    if (millis() - switchMillis >= 5)
  {
    switchMillis = millis();
    checkSwitches();
  }
  
   readValue = analogRead(potPin);  
   writeValue = (255./1023.) * readValue;
   analogWrite(LED1, writeValue);
 
    potValue1 = analogRead(potPin) / 10;
    potValue2 = potValue1 / 1.02;
  
    lcd.setCursor(0,0);
    lcd.print("Potent=");
    lcd.print(potValue1);
    lcd.print("%");
    delay(100);
    lcd.print(" ");
    delay(1);
}

void checkSwitches() {
  
    analogWrite(LED1, brightness);
    delay(10); 
  
  buttonState1 = digitalRead(ButtonLeft);
  
  if(buttonState1 == HIGH){ 
    brightness--;
    if(brightness < 0){
      brightness = 0;
    }
  }
  
  buttonState2 = digitalRead(ButtonRight);
  
  if(buttonState2 == HIGH){
    brightness++;
    if(brightness > 255){
      brightness = 255;
    }
  }
  
 lcd.setCursor (0,1);
 lcd.print ("Brightness=");
 lcd.print (brightness);
 lcd.print ("   ");
}

This is a varsity assignment [subject _ Microcontrollers]

Are you certain you understand the requirement for two concurrently active input methods correctly? Is adding a mode selector switch not allowed?

Alternatively I need to smooth the signal produced by the potentiometer.

I don't think this will be very useful.

Here's two ideas.

1) Average or otherwise combine the values from the pot and the buttons to create one value for analogWrite(). You will have to figure out how to get full range out of this approach.

2) Use the two independent control modes--button input and potentiometer input-- and if you can't use a selector switch, you will have to use the buttons or the pot to establish the control mode.

With the buttons you might be able to use both pressed as button mode selector which toggles between the buttons and the pot as enabled input. You may be able to toggle between button/pot mode with some pattern of presses. Up then down within a certain time period.

The pot may be easier. If the pot is full max, pass control to the buttons. If the pot is at minimum give control to the pot.

With the two modes, there will be a brightness shift when you change modes and that would be something to work on to smooth that transition.

You have done a poor job laying out your requirements. Here's a few things off the top of my head that you've failed to specify:

  • Must the Pot and Buttons act concurrently? Or, are you allowed to have a separate control (say a switch) that determines whether the Pot or Buttons are in control at any given time?

  • What happens if you set one control for full brightness and then start turning down the other control? Does the second control then "override" the first?

  • Same question if you turn the LED full off with one control then try to turn it up with the other?

  • The Pot has full clockwise and anti-clockwise physical stops. What happens if you turn it to the full brightness stop and then use buttons to turn the LED down? You'll never be able to turn it back up with the Pot because it's already at the stop.

You are controlling a variable brightness from two different sources, that is a button pair and a potentiometer. The last active source takes precedence. You will have two problems though. 1. The analog value of the potentiometer may be unstable so control continually reverts to it. You can solve that by applying hysteresis. See https://forum.arduino.cc/index.php?topic=526806.0 2. The transition from button control to potentiometer control may not be smooth because the potentiometer “rememberers” its last value. For example, if the potentiometer was on zero but the brightness was on 255 set via the buttons, the next change in the potentiometer value will cause the brightness to change immediately from 255 to 0.

gfvalvo: You have done a poor job laying out your requirements.

It's not impossible that the original assignment wording from the lecturer is crap, of course, although we may also have a "broken telephone" here.

Since OP has already said it's a uni assignment, perhaps s/he should just go all the way and post the original question.

And @OP, don't forget to cite any help you get from the forum in your bibliography. Your lecturers probably have their eyes on the forum too.....

hammy: You need some other input to select buttons or pot - without that how can the Arduino know what you want to do

Or make one of the buttons do the mode toggle with a long press.

The original assignment was a copy and paste situation from the last semester. I have attached what he [the lecturer] gave us for this semester [same same].

They’re using a PIC, but we have the option of using whatever gets the job done, so discussed in class. Hence I’ve opt for an Arduino.

You have done a poor job laying out your requirements. Here’s a few things off the top of my head that you’ve failed to specify:

I understand where you’re coming from, and to address your statement in the best way I can.

  • 1: The pot and buttons dont have to act concurrently but they should do what the other can do
  • 2: No override is required, logically that would break the state whichever component is in.
  • 3: Its best to start brightness on 0, and pot on zero and work 1 by 1, not 2 at a time or 1 then 2.
  • 4: This address point 3

The idea is to control the Brightness of an LED using a Pot and 2 Buttons. I’m asking for help cause I’m not sure how to do it in the most efficient way.

Your assignment (which is obviously not written for an Arduino) says you need to use another pushbutton (RA4) to decide whether the buttons OR the potentiometer control the brightness. That makes sense but you seem to be completely ignoring that part of the assignment.

Steve

Here is OP's task:

It looks like analogWrite() would do a lot of that without much effort on your part, but I'm sure that is not the idea of this exercise. You are to select the means of controlling the PWM duty cycle (potentiometer/buttons etc.) by a pushbutton (PIC RA4 pin)

Crossed with @SlipStick

And once you do that selection, I'm wondering what you anticipate happening when the pot is at position P and you change the value with the buttons to a value that should be P' for the pot. When you go back to the pot, should the value go immediately back to the right one for P, or stay at the one for P' with the pot now in the wrong place?

As is always the case, and has been seen in a few recent threads, the coding is often the least of the worry: understanding and describing wtf it's supposed to do is the hard part.

My approach to using a third button to change mode, would be to look at the state change detection example, then use that counter as the key into a switch.. case. In one case use the buttons, in the next use the pot, and in the third do it automatically (which I don't recall you mentioning before, but haven't been following too closely.)