Displaying Volume control on LCD using Digital potentiometer and Arduino - Page 1
Forum section: electronics / general

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 06:57:15 am
content: Hello,I am working on project which is speaker and where I am using digital potentiometer to change the volume. This varying of volume will display on LCD and decrease or increase of volume take place via button (up for Increase button and down for decrease button). The display show the number of volume i.e (0, 16, 32, 48, 64, 80, 96, 112, 128), also it diplay "Min Volume" when reached to 16 and "Max Volume" when reached to 128. Here is the code:Code:/*MCP4018T103E connected to arduino BoardCS >>> D10SCLK >> D13DI >>> D11PA0 TO VCCPBO TO GNDPW0 TO led with resistor 100ohm .*/#include <SPI.h>#include <LiquidCrystal.h>LiquidCrystal lcd(12, 9, 5, 4, 3, 2); //RS = 12, E = 9,byte address = 0x11;const int CS= 10;int i=0;int vol = 0;const int DOWN_BUTTON_PIN = 1;const int UP_BUTTON_PIN = 0;volatile boolean up = false;volatile boolean down = false;long time = 0;long debounce = 200;void setup(){lcd.clear();lcd.begin(16, 2); //LCD have 16 column and 2 rowslcd.setCursor(1,0); //LCD cursor set at 1st clomn and 0 rowspinMode(UP_BUTTON_PIN, INPUT_PULLUP); //buttonpinMode(DOWN_BUTTON_PIN, INPUT_PULLUP);pinMode (CS, OUTPUT);SPI.begin();// adjust high and low resistance of potentiometer// adjust Highest Resistance .digitalPotWrite(0); //0delay(1000);// adjust wiper in the Mid point .digitalPotWrite(64); //64delay(1000);// adjust Lowest Resistance .digitalPotWrite(128); //128delay(1000);}void loop(){checkIfDownButtonIsPressed(digitalRead(DOWN_BUTTON_PIN));checkIfUpButtonIsPressed(digitalRead(UP_BUTTON_PIN));if (up || down){ // Slow the up/down menus a bitdelay(1000);}for (i = 0; i <= 127; i=i+16){if (up) { //UP Button Logicsup = false;i = i + 16;vol = digitalPotWrite(i);lcd.setCursor(1,0); //Column 1 and Row 0lcd.print("Volume: vol");if ( i == 127){lcd.setCursor(1,1);lcd.print(" MAX VOLUME ");delay(10);}}}delay(500);for (i = 128; i > 0; i= i-16){if (down) { //DOWN Button Logicsdown = false;i = i - 16;vol = digitalPotWrite(i);lcd.setCursor(1,0); //Column 1 and Row 0lcd.print("Volume: vol");if ( i == 16){lcd.setCursor(1,1);lcd.print(" MIN VOLUME ");delay(10);}}}void checkIfDownButtonIsPressed(int newState){static int lastDownButtonState = 0;checkButton(down, lastDownButtonState, newState);}void checkIfUpButtonIsPressed(int newState){static int lastUpButtonState = 0;checkButton(up, lastUpButtonState, newState);}void checkButton(volatile boolean &output, int &oldState, int newState) {if (oldState != newState) {if (newState == 1) {output = true;}delay(50);}oldState = newState;}int digitalPotWrite(int value){digitalWrite(CS, LOW);SPI.transfer(address);SPI.transfer(value);digitalWrite(CS, HIGH);}Problem I am facing :1st : Code show error of digitalPotWrite is not in the scope.2nd: LCD just glow and doesn't show anything in LCD.Please help, I am new here. Please enlighten me from your knowldge.

author: HB9EVI
author_rank: Frequent Contributor
timestamp: September 23, 2018, 08:37:25 am
content: If you declare a function, it has to be placed above the code, where the function is going to be used, otherwise it's - like it says - out of scope.I don't know the arduino lcd functions so good, so far the code seems ok to me, but I can be wrong; except from a code problem, it could be wired in a wrong way

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 09:27:50 am
content: You meanint digitalPotWrite(int value){digitalWrite(CS, LOW);SPI.transfer(address);SPI.transfer(value);digitalWrite(CS, HIGH);}would be declare above the funtion usage?

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 09:52:30 am
content: Quote from: HB9EVI on September 23, 2018, 08:37:25 amHi, you are right. It solve my problem.But, as according to code when I simulate it. It diplay something different on LCD. Can you help me what to improve in it? Please see the below picture.https://postimg.cc/mcTZrMmJ

author: sokoloff
author_rank: Super Contributor
timestamp: September 23, 2018, 03:35:34 pm
content: I'd be inclined to something like this (untested, of course):In your first version, you got the digitalPotWrite was not in scope because you had unbalanced braces. You were missing a brace logically between line 93 and 94.The Arduino environment is excessively lax (IMO) about allowing you to call functions before declaring or defining them. In my code below, I've tried to define functions before calling them, but you can get away without that in most cases in Arduino environment.The LCD not displaying was a result of confusion around the for loops in the loop function. I don't know what the original intent of the for loop was around the up or down button handling. It just wasn't correct (nor is a loop needed there).Code:/*MCP4018T103E connected to arduino BoardCS >>> D10SCLK >> D13DI >>> D11PA0 TO VCCPBO TO GNDPW0 TO led with resistor 100ohm .*/#include <SPI.h>#include <LiquidCrystal.h>LiquidCrystal lcd(12, 9, 5, 4, 3, 2); //RS = 12, E = 9,byte address = 0x11;const int CS= 10;int g_volume = 0;const int DOWN_BUTTON_PIN = 1;const int UP_BUTTON_PIN = 0;volatile boolean up = false;volatile boolean down = false;long time = 0;long debounce = 200;void updateLCDScreen(int volume) {lcd.clear(); // If you don't do this, the MIN/MAX volume will remain (like the OFF of the other program)lcd.setCursor(1,0); //Column 1 and Row 0lcd.print("Volume: ");lcd.print(volume);if (volume == 128){lcd.setCursor(1,1);lcd.print(" MAX VOLUME ");}if (volume == 16) // What about 0 volume?{lcd.setCursor(1,1);lcd.print(" MIN VOLUME ");}}void digitalPotWrite(int value){digitalWrite(CS, LOW);SPI.transfer(address);SPI.transfer(value);digitalWrite(CS, HIGH);}void checkButton(volatile boolean &output, int &oldState, int newState) {if (oldState != newState) {if (newState == 1) {output = true;}delay(50);}oldState = newState;}void checkIfDownButtonIsPressed(int newState){static int lastDownButtonState = 0;checkButton(down, lastDownButtonState, newState);}void checkIfUpButtonIsPressed(int newState){static int lastUpButtonState = 0;checkButton(up, lastUpButtonState, newState);}void setup(){lcd.clear();lcd.begin(16, 2); //LCD have 16 column and 2 rowslcd.setCursor(1,0); //LCD cursor set at 1st clomn and 0 rowspinMode(UP_BUTTON_PIN, INPUT_PULLUP); //buttonpinMode(DOWN_BUTTON_PIN, INPUT_PULLUP);pinMode (CS, OUTPUT);SPI.begin();// adjust high and low resistance of potentiometer// adjust Highest Resistance .digitalPotWrite(0); //0delay(1000);// adjust wiper in the Mid point .digitalPotWrite(64); //64delay(1000);// adjust Lowest Resistance .digitalPotWrite(128); //128delay(1000);}void loop(){static int old_volume = -1;// Check the buttons. This code looks good (and familiar... ;) )checkIfDownButtonIsPressed(digitalRead(DOWN_BUTTON_PIN));checkIfUpButtonIsPressed(digitalRead(UP_BUTTON_PIN));// Now, handle the up/down buttons.if (up) { //UP Button Logicsup = false;g_volume += 16;}if (down) { //DOWN Button Logicsdown = false;g_volume -= 16;}// Range check the volume// This is a helpful function, though you could use two if statements as wellg_volume = constrain(g_volume, 0, 128);// Only update the LCD and pot if the volume changed from previous timeif (old_volume != g_volume){updateLCDScreen(g_volume);digitalPotWrite(g_volume);old_volume = g_volume;// Slow the up/down menus a bitdelay(1000);}}

author: sokoloff
author_rank: Super Contributor
timestamp: September 23, 2018, 03:41:48 pm
content: Also, if you tell the LCD to display "Volume: vol" that's exactly what you'll get.You need to tell it first to display the string "Volume: " and then a second call to display the value of the variable. (see lines 31 & 32 below):Code:lcd.print("Volume: ");lcd.print(volume);digitalWritePot didn't return any value originally, so vol was going to be set to some undefined value.Go into your Arduino preferences and make sure that Compiler Warnings is set to "All"Then get in the habit of understanding every red warning message that the compiler gives you.At the "Default" setting for compiler warnings, you didn't get a warning on that function, which didn't help you at all. (Fixing just that wouldn't have been a complete fix, but it would have perhaps given you a clue that something was wrong there anyway.)

author: sokoloff
author_rank: Super Contributor
timestamp: September 23, 2018, 03:46:07 pm
content: I also have to admit a small amount of concern (and I don't mean to be the least bit disrespectful here) that if these are homework assignments, that I might be providing somewhat too much help.If these are homework, please be sure to study carefully the differences between your code and mine (assuming mine works correctly) and figure out why they are different. If you don't understand, come back here and ask, don't just submit the answer and get a good mark on the homework.Related, if you'd prefer that I (and other EEVBlog posters) take more time and lead you to the answer rather than posting working code, I can also do that. That might be frustrating in terms of timezone and limited availability at times.While your immediate goal is probably to submit working homework, I (and you) should be much more focused on you learning how to debug and fix the inevitable errors in code that every programmer makes. I don't want to short-circuit that (pun intended).

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 04:54:26 pm
content: Hi, Thanks for reply:) I am so much gratefulAccording to this codevoid updateLCDScreen(int volume) {lcd.clear(); // If you don't do this, the MIN/MAX volume will remain (like the OFF of the other program)lcd.setCursor(1,0); //Column 1 and Row 0lcd.print("Volume: ");lcd.print(volume);if (volume == 128){lcd.setCursor(1,1);lcd.print(" MAX VOLUME ");}where is written that volume varry from 0 to 128. Isn't we missing that for loop where it increase the volume and reach to 128. Is this g_volume = constrain(g_volume, 0, 128); doing the same function and if yes, then where it declare it is use for g_volume.Please guide me to the right track.haaha.. and yes the code seems similar to you because you once answered my question on menuitem and this logic of button works so well. Thank you so much for this

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 04:56:53 pm
content: Quote from: sokoloff on September 23, 2018, 03:41:48 pmDoneThanks

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 05:04:16 pm
content: Quote from: sokoloff on September 23, 2018, 03:46:07 pmThank you so much for allowing me to ask the differenced of normal coding and your professional one:)Yes, It's not homework or college assignment. It's my own project on which I am working from the last 6-7 months. I done my code for PIC microcontroller. But, before going to PIC I am using Arduino to check my circuit. I learnt Arduino and tried to code but I am still not reaching to good coderCan you suggest me some good material where I learn from and I wanna code like you, So fast, short and accurate without even compiling

author: radhika
author_rank: Regular Contributor
timestamp: September 23, 2018, 05:33:07 pm
content: Why it's not displaying anythinghttps://postimg.cc/yJX2dsBn

author: sokoloff
author_rank: Super Contributor
timestamp: September 23, 2018, 06:00:09 pm
content: Quote from: radhika on September 23, 2018, 04:54:26 pmYes. constrain is an Arduino library function.Doc is here:https://www.arduino.cc/reference/en/language/functions/math/constrain/

author: sokoloff
author_rank: Super Contributor
timestamp: September 23, 2018, 06:03:54 pm
content: Quote from: radhika on September 23, 2018, 05:33:07 pmI'd add something in setup then to just test that the simulator and wiring is all correct.Perhaps change the LCD setup code to something like this:Code:lcd.clear();lcd.begin(16, 2); //LCD have 16 column and 2 rowslcd.setCursor(1,0); //LCD cursor set at 1st clomn and 0 rowslcd.print("Testing");lcd.setCursor(1,1);lcd.print("1..2..3..");delay(10000);

author: sokoloff
author_rank: Super Contributor
timestamp: September 23, 2018, 06:09:20 pm
content: Quote from: radhika on September 23, 2018, 05:04:16 pmWell, I do compile it; I just can't test or simulate your peripherals, so that I have to just reason about and try to write correct code.How to get better at coding?Do alotof it. Struggle through the difficulties. Really work at it, then when you're stuck, ask for help.Read other people's code. Find some open source projects, look at the outcome, think about how they probably did things, then read the code and see if you can figure it all out. Lots of open source software is low quality (like lots of closed source software), but some of it is excellent quality.Read some books. I love Steve McConnell'sCode Completeand Steve Macguire'sWriting Solid Code. I don't know that reading those books is the first thing I'd recommend though; I tend to learn more by doing and struggling personally, then once I have a reasonably good background,thenread the books.But mostly, it's do alotof it...