Hi, so I'm making a 5V Solar Powerbank for a YouTube video, the solar and Powerbank part works fine, it uses a tiny microcontroller - DFRobot Beetle board to measure the Li-Ion battery's voltage, then displays how charged it is on a 4-pin Battery Capacity Indicator module, that part all works fine. What I'm trying to do is to be able to press a pushbutton once and get the display module going, then press it again to turn it off.
My issue in making this simple feature possible is coding for this, I'm having trouble figuring out what function name to call out to start and stop the batteryDisplay function from the module's TM1651 library.
Pasted below is my full code (including my attempts in coding for the feature), though my changes didn't bring the Battery Capacity Indicator module to turn off or on when I pushed the push button.
Code:
#include "TM1651.h"
#define CLK 10//pins definitions for TM1651 and can be changed to other ports
#define DIO 9
#define cellPin A0
#define buttonPin 11
int val = 0;
int value = 0; //Val used to store input of Switch or pin 7
int state = 0; //0 Shows LED off 1 is LED on
int old_val = 0; // Previous version of val
TM1651 batteryDisplay(CLK, DIO);
void setup()
{
Serial.begin(9600); // Debugging only
batteryDisplay.init();
batteryDisplay.set(7);//0 ~ 7 mean to different brightness;
batteryDisplay.frame(FRAME_ON);//light the frame of the battery display or FRAME_OFF to turn off the frame of the battery display
pinMode(cellPin, INPUT);
}
void loop()
{
value = digitalRead(buttonPin); //Reads the value of the button and stores
if ((value == HIGH) && (old_val == LOW))
{
state = 1 - state; //Check if state has changed
// delay(10);
}
old_val = value; // Val is now old val so its stored
switch (state)
{
case 1:
_start(); //starting battery display animation
break;
case 0:
_stop(); //stopping battery display animation
break;
}
charging(); //initializing function
val = analogRead(cellPin);
Serial.println(val);
delay(1000);
}
void charging() //for displaying battery lvl | through a charging animation (which is disabled here)
{
if (val <= 550)
{
for (uint8_t level = 0; level < 1; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 600)
{
for (uint8_t level = 0; level < 2; level ++) /*the following lines of code see if battery's ADC analog value is greater than or equal to a certain value,
then makes the module display so many bars as a percentage accordingly.*/
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 650)
{
for (uint8_t level = 0; level < 3; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 700)
{
for (uint8_t level = 0; level < 4; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 750)
{
for (uint8_t level = 0; level < 5; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 800)
{
for (uint8_t level = 0; level < 6; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
}
I usually get around such small things quicker than the problem I'm having now, but this time it really got me stuck, so that's why you're seeing my post on the forum.
If any of you could suggest a quick tip, code modification, or method to make this little feature work-in with my battery display, that would be great.
Any help would be much appreciated, thanks!
Edit:
I figured out the solution, what I should have instead done to make the button switch turn the TM1651 Battery display on and off was to add this:
void loop()
{
indicatorOff();
void indicatorOff()
{
for (uint8_t level = 0; level < 1; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
batteryDisplay.frame(FRAME_OFF);
}
It's to give an option to this part of the code:
void loop()
{
val = analogRead(cellPin);
Serial.println(val);
delay(200);
indicatorOff();
value = digitalRead(buttonPin); //Reads the value of the button and stores
if ((value == HIGH) && (old_val == LOW))
{
state = 1 - state; //Check if state has changed
delayMicroseconds(10);
}
old_val = value; // Val is now old val so its stored
switch (state)
{
case 1:
charging(); //initiallizing
break;
case 0:
indicatorOff(); //deactivating
break;
}
}
to have a deactivating condition for the thing to switch to, so the display module won't show anything when the button is debounced to a low state.
Fully working updated code:
#include "TM1651.h"
#define CLK 10//pins definitions for TM1651 and can be changed to other ports
#define DIO 9
#define cellPin A0
#define buttonPin 11
int value = 0; //Val used to store input of Switch or pin 7
int state = 0; //0 Shows LED off 1 is LED on
int old_val = 0; // Previous version of val
int val = 0;
TM1651 batteryDisplay(CLK, DIO);
void setup()
{
Serial.begin(9600); // Debugging only
batteryDisplay.init();
batteryDisplay.set(7);//0 ~ 7 mean to different brightness;
batteryDisplay.frame(FRAME_ON);//light the frame of the battery display or FRAME_OFF to turn off the frame of the battery display
pinMode(cellPin, INPUT);
pinMode(buttonPin, INPUT);
}
void indicatorOff()
{
for (uint8_t level = 0; level < 1; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
batteryDisplay.frame(FRAME_OFF);
}
void loop()
{
val = analogRead(cellPin);
Serial.println(val);
delay(200);
indicatorOff();
value = digitalRead(buttonPin); //Reads the value of the button and stores
if ((value == HIGH) && (old_val == LOW))
{
state = 1 - state; //Check if state has changed
delayMicroseconds(10);
}
old_val = value; // Val is now old val so its stored
switch (state)
{
case 1:
charging(); //initiallizing
break;
case 0:
indicatorOff(); //deactivating
break;
}
}
void charging() //for displaying battery lvl | through a charging animation (which is disabled here)
{
batteryDisplay.frame(FRAME_ON);
if (val <= 550)
{
for (uint8_t level = 0; level < 1; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 600)
{
for (uint8_t level = 0; level < 2; level ++) /*the following lines of code see if battery's ADC analog value is greater than or equal to a certain value,
then makes the module display so many bars as a percentage accordingly.*/
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 650)
{
for (uint8_t level = 0; level < 3; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 700)
{
for (uint8_t level = 0; level < 4; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 750)
{
for (uint8_t level = 0; level < 5; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
if (val >= 800)
{
for (uint8_t level = 0; level < 6; level ++)
{
batteryDisplay.displayLevel(level);
delayMicroseconds(5);
}
}
}
I happened to find the solution myself, writing some code from my own experience and logic
Though, thanks to those of you who lead me in the right direction!
I hope this will help anyone reading this who also wants a similar feature in their project.