C language

Internet Webed: C language

Internet Webed: C language

Showing posts with label C language. Show all posts
Showing posts with label C language. Show all posts

Build Smart Arduino LCD Battery Monitor with Custom Icon Using Arduino

Are you tired of your battery-powered projects dying unexpectedly? Do simple LED indicators leave you wondering if your battery is almost dead or just kinda low? If so, this project is for you! We'll build an intelligent battery monitor using an Arduino and a 20x4 LCD, complete with precise voltage and percentage readings, a custom graphical battery symbol, and a crucial blinking alert for low battery conditions.


Why This Project?

Traditional battery indicators often rely on just a few LEDs, giving you a very rough estimate of remaining power. This Arduino-based solution offers:

  • Precision: Get actual voltage and a calculated percentage, giving you a clear picture of your battery's health.
  • Intuitive Visuals: A custom-designed battery icon on the LCD changes its fill level to visually represent the charge.
  • Early Warning System: The battery icon blinks frantically when power drops below 10%, ensuring you never miss a critical low battery alert.
  • Educational Value: Learn about Analog-to-Digital Conversion (ADC), voltage dividers, LCD custom characters, and non-blocking timing with millis().

Components You'll Need:

  • Arduino Board: Any compatible board (e.g., Uno, Nano, Mega) or even AT89S51 development board like the one I'm using
  • 20x4 LCD Display: A standard 20 character, 4-line Liquid Crystal Display. (Our code assumes direct wiring as shown in the pin definitions, but you can adapt for I2C LCDs with minor library changes).
  • 9V Battery: Or any DC battery you wish to monitor (adjust resistor values and EXPECTED_V_OUT accordingly).
  • Resistors:
    • 1 x 21 kΩ (R1)
    • 1 x 5 kΩ (R2)
  • Breadboard: For prototyping.
  • Jumper Wires: For connections.
  • Multimeter (Optional but Recommended): For verifying voltage divider output and your Arduino's ADC reference voltage.
  • Download the arduino INO file here: Github Link
  • Youtube Short: Link (optional)

The Circuit: Wiring Up Your Battery Monitor

The heart of voltage measurement is a simple voltage divider. Since Arduino's analog input (and its default ADC reference) usually operates around 5V, directly connecting a 9V battery would damage it. The voltage divider steps down the 9V to a safe, measurable level.

Here's how to connect everything:

  1. LCD Connections (to Arduino Digital Pins):

    • RS (Register Select) to Digital Pin 0
    • EN (Enable) to Digital Pin 1
    • D4 to Digital Pin 2
    • D5 to Digital Pin 3
    • D6 to Digital Pin 4
    • D7 to Digital Pin 5
    • RW (Read/Write) to GND
    • VSS (Ground) to Arduino GND
    • VDD (Power) to Arduino 5V
    • V0 (Contrast) to a 10kΩ potentiometer (outer pins to 5V & GND, middle pin to V0) or directly to GND for full contrast.
    • Backlight A (Anode) to 5V via a 220Ω resistor (optional)
    • Backlight K (Cathode) to GND
  2. Battery Voltage Divider (to Arduino Analog Pin A3):

    • Connect the positive terminal of your 9V battery to one end of the 21 kΩ resistor (R1).
    • Connect the other end of the 21 kΩ resistor to one end of the 5 kΩ resistor (R2).
    • Connect the other end of the 5 kΩ resistor to the GND of your Arduino and the negative terminal of your 9V battery (ensure common ground!).
    • Connect the junction point between the 21 kΩ and 5 kΩ resistors (where they meet) to Arduino Analog Pin A3 (BATTERY_LEVEL_IN).

    Critical Note on REFERENCE_VOLTAGE: In our specific setup, the Analog Reference Voltage (AREF) of the ATmega16 (which your previous code indicated you're using, possibly on a custom board) is set to 2.8V. This is crucial for accurate readings. If your Arduino board uses a different AREF (e.g., default 5V for Arduino Uno), you must adjust the #define REFERENCE_VOLTAGE line in the code accordingly. For example, if using an Uno's default 5V reference, change it to 5.0.

How It Works: Diving into the Code

  1. Constants & Libraries:

    • LiquidCrystal.h: Standard library for interfacing with LCDs.
    • PIN_LCD_RS etc.: Defines the Arduino pins connected to your LCD.
    • BATTERY_LEVEL_IN A3: Specifies which analog pin the voltage divider output is connected to.
    • ANALOGIC_MAX_READING 1023.0: For a 10-bit ADC, the analogRead() function returns values from 0 to 1023. Using 1023.0 ensures accurate floating-point division.
    • REFERENCE_VOLTAGE 2.8: Crucial! This must match the actual analog reference voltage being used by your Arduino's ADC. If you're using a standard Arduino Uno, this is typically 5.0V. If you have an external reference or specific ATmega16 setup, measure it and set it here.
    • R1 and R2: Your voltage divider resistor values.
    • EXPECTED_V_OUT 9.45: This is the voltage you consider to be 100% full for your battery. Adjust this based on your battery's specifications. For a nominal 9V battery, 9.45V might be its peak charge.
    • lastBlinkTime, blinkInterval, blinkState: Variables for the non-blocking blinking feature.
  2. Custom Characters (byte batteryEmpty[8] etc.):

    • These byte arrays define the pixel patterns for each of your battery fill levels. Each Bxxxx represents a 5-pixel row. B1 means the pixel is on, B0 means it's off.
    • In setup(), lcd.createChar(location, char_array); loads these patterns into the LCD's special Character Generator RAM (CGRAM). You can store up to 8 custom characters (locations 0-7).
  3. Voltage Calculation (loop()):

    • value = analogRead(BATTERY_LEVEL_IN);: Reads the analog voltage from your voltage divider.
    • vOut = (value * REFERENCE_VOLTAGE) / ANALOGIC_MAX_READING;: Converts the raw ADC reading (value) into the actual voltage measured at the A3 pin (vOut).
    • vIn = vOut * ((R1 + R2) / R2);: Reverses the voltage divider formula to calculate the actual battery voltage (vIn). This is the magic that converts the low voltage at A3 back to your battery's full voltage.
    • percent = (int)(vIn * 100 / EXPECTED_V_OUT);: Calculates the battery percentage relative to your EXPECTED_V_OUT.
  4. Display Logic & Blinking:

    • lcd.clear();: Clears the screen each time for a fresh display.
    • lcd.setCursor() and lcd.print(): Standard LCD functions to display text and numerical values.
    • batteryChar selection: An if-else if ladder checks the percent and selects the appropriate custom character ID (0-4).
    • Blinking (if (percent < 10) block):
      • It uses millis() to track time, allowing the Arduino to continue doing other tasks without freezing.
      • Every blinkInterval (500ms), blinkState is toggled.
      • If blinkState is true, the batteryChar (which will be the batteryEmpty symbol when less than 10%) is displayed using lcd.write(batteryChar);.
      • If blinkState is false, a blank space is printed, making the character disappear. This creates the blinking effect.
    • delay(100);: A short delay ensures the LCD updates are visible and the blinking is smooth.

Getting Started:

  1. Assemble the Circuit: Follow the wiring instructions above carefully. Double-check all connections, especially the voltage divider and LCD pins.
  2. Copy the Code: Paste the entire Arduino sketch into your Arduino IDE.
  3. Adjust Constants:
    • Crucially, verify and set REFERENCE_VOLTAGE to the actual analog reference voltage of your Arduino. Use a multimeter on your Arduino's AREF pin or 5V pin (if default reference).
    • Adjust R1, R2, and EXPECTED_V_OUT if you are using different resistors or monitoring a battery with a different full voltage.
  4. Upload: Select your Arduino board and port, then upload the code.
  5. Observe! You should now see your battery's status displayed clearly on the LCD.

This project provides a robust and visually appealing way to keep an eye on your battery's health. Give it a try, and say goodbye to unexpected power outages in your projects!

Download the arduino INO file here: Github Link

LCD library for 20x4 display in 4 Bit Mode

20x4 LCD






Below is the code for running 20x4 display LCD in 4 bit mode. You can copy the code and save it as a header file (.h) and then include the same in your main program.

Please don't forget to change the PINs according to your sketch.

Please leave a comment for any queries or feedback

/*

 * lcd_lib.h

 * Created By: Ramandeep Singh

 * Created date: 11-Sep-2023

 */

#include <inttypes.h>

//Defines your PINS accordingly to your configuration

#define LCD_CONTROL_DDR DDRC

#define LCD_CONTROL_PORT PORTC

#define LCD_RS_PIN 6

#define LCD_RW_PIN 5

#define LCD_ENABLE_PIN 4

//

#define LCD_DATA1_DDR DDRC

#define LCD_DATA1_PORT PORTC

#define LCD_DATA1_PIN PINC

#define LCD_D4 0

#define LCD_D5 1

#define LCD_D6 2

#define LCD_D7 3


 void lcd_cmd(uint8_t command)  //used to write instruction to LCD

 {

PORTC = command>>4;

PORTC &= (~(1<<LCD_RS_PIN)); //RS=0

PORTC &= (~(1<<LCD_RW_PIN));  //RW=0

PORTC |= (1<<LCD_ENABLE_PIN); //EN=1

_delay_ms(10); //10ms

PORTC &= (~(1<<LCD_ENABLE_PIN)); //EN=0

 

PORTC = (command & 0x0F);

PORTC &= (~(1<<LCD_RS_PIN)); //RS=0

PORTC &= (~(1<<LCD_RW_PIN));  //RW=0

PORTC |= (1<<LCD_ENABLE_PIN); //EN=1

_delay_ms(10); //10ms

PORTC &= (~(1<<LCD_ENABLE_PIN)); //EN=0

 

}

 

  void lcd_data(uint8_t data)  //for writing data to LCD

  {

  PORTC = data>>4 ;

  PORTC |=(1<<LCD_RS_PIN);  //RS=1

  PORTC &=(~(1<<LCD_RW_PIN));  //RW=0

  PORTC |=(1<<LCD_ENABLE_PIN);  //EN=1

  _delay_ms(10);  //10ms

  PORTC &=(~(1<<LCD_ENABLE_PIN)); //EN=0

  

  PORTC = (data & 0x0F);

  PORTC |=(1<<LCD_RS_PIN);  //RS=1

  PORTC &=(~(1<<LCD_RW_PIN));  //RW=0

  PORTC |=(1<<LCD_ENABLE_PIN);  //EN=1

  _delay_ms(10);  //10ms

  PORTC &=(~(1<<LCD_ENABLE_PIN)); //EN=0

  

  }

  

  void LCD_print(char *str) /* Send string to LCD function */

  {

  int i;

  for(i=0;str[i]!=0;i++) /* Send each char of string till the NULL */

  {

  lcd_data(str[i]);

  }

  }


void LCD_print_xy(uint8_t x, uint8_t y, char *str) {

uint8_t position = 0x80; // Starting address of the first line

if (y == 1) {

position = 0xC0; // Starting address of the second line

} else if (y == 2) {

position = 0x94; // Starting address of the third line

} else if (y == 3) {

position = 0xD4; // Starting address of the fourth line

}

position += x; // Add the x-coordinate to the position

lcd_cmd(position);  // Send the command to set the cursor position

LCD_print(str);

}


void LCD_goto_XY(uint8_t x, uint8_t y) {

// Define the starting addresses for each line of a 20x4 LCD

static const uint8_t line_offsets[] = {0x00, 0x40, 0x14, 0x54};

// Ensure x and y are within bounds

if (x >= 20 || y >= 4) {

return;  // Invalid coordinates

}

// Calculate the DDRAM address based on x and y

uint8_t position = line_offsets[y] + x;

// Set the cursor to the desired position

lcd_cmd(0x80 | position);

}

 void LCD_init()

 {

lcd_cmd(0x02);   //Set cursor to home position

lcd_cmd(0x28);  //4bit mode

lcd_cmd(0x06); //Entry Mode

lcd_cmd(0x0c); //display ON cursor OFF

lcd_cmd(0x01);   //clear the display

lcd_cmd(0x80);   //set cursor at line1

 }

 

void  LCD_clear()

{

lcd_cmd(0x01);

lcd_cmd (0x80);

}


//how to use:

//LCD_init();

//LCD_Print("My String");

//LCD_print_XY(0,0,"My String");

//LCD_goto_XY(16,3); LCD_print("My String");

//LCD_Clear();

Programme for Binary search

Programme for Binary search
#include<stdio.h>
#include<conio.h>
int arr[20];
int x;
void input()
{
int i;
printf("How many elements out of 20:\n");
scanf("%d",&x);
for(i=0;i<x;i++)
 {
    printf("Enter no.=");
    scanf("%d",&arr[i]);
 }
}
void search()
{
    int n,i,mid,low,high,flag=0;
    printf("Enter no which you want to search: \n");

Programme to transpose a matrix

Programme to transpose a matrix
/* Programme to print transpose of matrix */

#include<stdio.h>
#include<conio.h>
void matrix(int x[3][3]);
void main()
{
    int x[3][3],i,j;
    clrscr();
    printf("Enter elements of matrix:\n");
    for(i=0;i<3;i++)
   {
    for(j=0;j<3;j++)
    {
    scanf("%d",&x[i][j]);
    }
   }
   printf("Entered matrix is:\n");

Programme to check Sparse matrix

Programme to check Sparse matrix
/* wap to print sparse matrix */

#include<stdio.h>
#include<conio.h>
#define n 3
void main()
{
int i,j,a[n][n],count=0;
clrscr();
printf("Enter elements of matrix\n");
for(i=0;i<n;i++)
    {
    for(j=0;j<n;j++)
    {
        scanf("%d",&a[i][j]);
    }
}
printf("You Entered matrix:\n");

How To Make a HUT in C language

In this tutorial I had made a programme by which you can make a HUT in C language with the help of graphics. I had also added a image to get directions for you so you can make it...
Enjoy.. :)

/* Programme to make a HUT in C language with graphics */

#include<graphics.h>
#include<conio.h>
void main()
{
int gm,gd=DETECT;
initgraph(&gd,&gm,"C:\\TurboC3\\BGI");
line(20,50,150,50);
line(20,50,5,100);
line(20,50,40,100);
rectangle(5,100,40,180);
rectangle(40,100,180,180);
line(150,50,180,100);
rectangle(85,120,125,160);
line(105,120,105,160);
line(85,140,125,140);
rectangle(10,120,35,180);
line(10,120,17,130);
line(10,180,17,170);
line(35,120,25,130);
line(35,180,25,170);
line(17,130,17,170);
line(25,130,25,170);
circle(20,85,5);
line(10,180,60,340);
line(35,180,180,340);
circle(35,200,5);
circle(55,250,15);
circle(90,310,25);
line(140,200,140,220);
line(160,200,160,220);
line(140,210,160,210);
rectangle(170,200,190,220);