Pages: [1]   Go Down
Author Topic: Display battery state of charge graphic on LCD  (Read 429 times)
0 Members and 1 Guest are viewing this topic.
South UK
Offline Offline
God Member
*****
Karma: 5
Posts: 587
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all. I would like to display the state of charge of a 3 cell lipo pack on a lcd. I would like to use one of the lines to give me 16 steps of resolution, corresponding to a voltage range of 9.3-12.6v.

And I think i will need to map 9.3-12.6 to give a range of 0-16, then ideally I would like to make some custom chars, and have them display a image of a battery with both solid and empty sections. Reading a voltage is not a problem, and I can make custom characters.

The part I will need help with is how to code this up, would I have to use an array to display the chars?

An example would be when the voltage is  <9.3v, to display something similar to the following..
_________________
|________________|

hope that makes sense, thanks
Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 106
Posts: 3772
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What kind of display? 16x2, or an actual TFT 3.2" display?

You can use the same method I made here. LCD Bargraph You can create your custom characters, and display them as so.
Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

South UK
Offline Offline
God Member
*****
Karma: 5
Posts: 587
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, thanks for the reply. I forgot to say I'm using a 16x2 LCD in parallel mode.

Thanks, I have just read through that thread, It is a similar concept to some test code that I have just written.

I have tested it and it doesn't work as I had hoped, the SOC only displays 0, 5, 10 or 15 and no increments inbetween?

Code:
int analoginput = A1;
int soc = 0;
float vin = 0.0;

void setup(){
  Serial.begin(9600);
  delay(100);
}

void loop(){
  vin = analogRead(analoginput)*5.09/1024*3.15;
  soc = map(vin, 9.3, 12.6, 0, 15);
  //soc = constrain(soc, 0, 15);
  Serial.print(vin, 3);
  Serial.print("  ");
  Serial.println(soc);
  delay(1400);
}



« Last Edit: October 05, 2013, 07:16:19 pm by dtokez » Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 106
Posts: 3772
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your minimum and maximum numbers are too small. Multiply vin by 10 and then typecast it as an INT, so instead of 9.3 and 12.6, it will 93 and 126.
Code:
int number = 93;

void setup()
{
Serial.begin(9600);

while( number < 127)
  {
    Serial.print(number);
    Serial.print(" mapped: ");
    Serial.println(map(number, 93, 126, 0, 15));
    number ++;
    delay(100);
  }
}

void loop() {
 
}


This code produces this: Nice and smooth.
Quote
93.00 mapped: 0
94.00 mapped: 0
95.00 mapped: 0
96.00 mapped: 1
97.00 mapped: 1
98.00 mapped: 2
99.00 mapped: 2
100.00 mapped: 3
101.00 mapped: 3
102.00 mapped: 4
103.00 mapped: 4
104.00 mapped: 5
105.00 mapped: 5
106.00 mapped: 5
107.00 mapped: 6
108.00 mapped: 6
109.00 mapped: 7
110.00 mapped: 7
111.00 mapped: 8
112.00 mapped: 8
113.00 mapped: 9
114.00 mapped: 9
115.00 mapped: 10
116.00 mapped: 10
117.00 mapped: 10
118.00 mapped: 11
119.00 mapped: 11
120.00 mapped: 12
121.00 mapped: 12
122.00 mapped: 13
123.00 mapped: 13
124.00 mapped: 14
125.00 mapped: 14
126.00 mapped: 15

whereas the other only showed (0, 5, 10, 15).
« Last Edit: October 05, 2013, 08:12:13 pm by HazardsMind » Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

South UK
Offline Offline
God Member
*****
Karma: 5
Posts: 587
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks! I took me a while to grasp what you were saying but it makes sense now. I thought the values might get scaled up or something.

This works now.. time to start working out the LCD bit smiley

Code:
int analoginput = A1;
int soc = 0;

float vin = 0.0;


void setup(){
  Serial.begin(9600);
  delay(100);
}



void loop(){
  vin = analogRead(analoginput)*5.09/1024*3.15;
  soc = map((vin*10), 93, 126, 0, 15);
  soc = max(soc, 0);
 
  Serial.print("Vin: ");
  Serial.print(vin);
  Serial.print("V  SOC: ");
  Serial.println(soc);
 
  delay(1400);
}
Logged

South UK
Offline Offline
God Member
*****
Karma: 5
Posts: 587
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Result, I have got it doing exactly what I wanted it to do. but the code is very over the top, clumsy and probably stupidly inefficient - how could it be optimized?



The whole code is to long to post but this gives you an idea of the section i need to improve :
Code:
soc = map(((vin*10) + 2), (underVoltage*10), 126, 0, 16);  // Scale up number and add small offset, then map to 1-16
    soc = max(soc, 0);
    soc = min(soc, 16);

    if (soc == 0)
    {
      lcd.setCursor(0, 1);

      lcd.write((uint8_t)3);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)5);
    }

    if (soc == 1)
    {
      lcd.setCursor(0, 1);

      lcd.write((uint8_t)7);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)5);
    }

    if (soc == 2)
    {
      lcd.setCursor(0, 1);

      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)5);
    }

    if (soc == 3)
    {
      lcd.setCursor(0, 1);

      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)5);
    }

    if (soc == 4)
    {
      lcd.setCursor(0, 1);

      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)5);
    }

    if (soc == 5)
    {
      lcd.setCursor(0, 1);

      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)7);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)4);
      lcd.write((uint8_t)5);
    }

    }
Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 106
Posts: 3772
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could use the Createchar function.

This is my method for my bar graph.
Code:
// Simple LCD Bar Graph
// By: Andrew Mascolo

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
uint8_t bar0[8]  = {
  0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
uint8_t bar1[8]  = {
  0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10};
uint8_t bar2[8]  = {
  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18};
uint8_t bar3[8]  = {
  0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
uint8_t bar4[8]  = {
  0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E};
uint8_t bar5[8]  = {
  0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
int i,j=0, number=1;

LiquidCrystal_I2C lcd(0x20,20,4);  // set the LCD address to 0x20 for a 16 chars and 2 line display

void setup()
{
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd
  lcd.backlight();
  lcd.createChar(0, bar0);
  lcd.createChar(1, bar1);
  lcd.createChar(2, bar2);
  lcd.createChar(3, bar3);
  lcd.createChar(4, bar4);
  lcd.createChar(5, bar5);
  lcd.home();
  lcd.print("Hello world...");
  delay(1000);
}

void loop()
{
  bargraph(analogRead(A6),1,20);
  //bargraph(analogRead(A6),3,20);
}

void bargraph(unsigned int data, unsigned int row, unsigned int lcd_size)
{
  j = map(data, 0, 1023, 0, (6 * lcd_size));
  if(number <= j)
  {
    for(number; number < j; number++)
    {
      i = number / 6;
      lcd.setCursor(i,row);
      lcd.write(number % 6);
    }
  }
  else
  {
    for(number; number > j; number--)
    {
      i = number / 6;
      lcd.setCursor(i,row);
      lcd.write(number % 6);
    }
  }
  //Serial.print(number);
  // Serial.print(" ");
   //Serial.println(i);
}

You can modify it however you like.
« Last Edit: October 05, 2013, 10:05:42 pm by HazardsMind » Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

South UK
Offline Offline
God Member
*****
Karma: 5
Posts: 587
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks, I will load it up later and try and work out how you have done it smiley
Logged

South UK
Offline Offline
God Member
*****
Karma: 5
Posts: 587
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just thought of a more efficient way that I could adjust my code, I could draw a empty battery on the LCD then just write over it with the segments that need to be filled in, should make the code a little smaller!

I will still be trying Hazards method though smiley
Logged

Pages: [1]   Go Up
Jump to: