Pavan Freak
Pavan Freak

Reputation: 1

HIGH TEMPERATURE ALERT using 8051

This is a screenshot from proteus 8

//Code for HIGH TEMPERATURE ALERT SYSTEM using 8051

#include<reg51.h> // Includes 8051 microcontroller definitions

// Function declarations
void delay(unsigned int i); // Generates a delay for LCD enable pulse
void lcd_cmd(unsigned char a); // Sends a command to the LCD
void lcd_data(unsigned char b); // Sends data (characters) to the LCD
void lcd_init(void); // Initializes the LCD
void lcd_str(unsigned char *str); // Displays a string on the LCD
void hex2ascii(unsigned char value); // Converts hex value to ASCII for display

// Pin and port definitions
sbit rs = P2^0; // Register select pin for LCD
sbit en = P2^1; // Enable pin for LCD
sfr ldata = 0xb0; // Data port for LCD (Port 3)
sbit rd = P2^2; // Read pin for ADC
sbit wr = P2^3; // Write pin for ADC
sbit intr = P2^4; // Interrupt pin from ADC
sfr adc = 0x90; // ADC data from Port 1
sbit buz = P2^5; // Buzzer control pin

// Main function
void main ()
{
    // LCD welcome message
    lcd_init(); // Initialize LCD
    buz = 0; // Ensure the buzzer is off at the start
    lcd_str("    WELCOME    "); // Display first line of welcome message
    lcd_cmd(0xc0); // Move to the second line
    lcd_str("   TO PROJECT   "); // Display second line of welcome message
    delay(65000); // Delay for display
    lcd_cmd(0x01); // Clear the display
    
    // Display project title
    lcd_cmd(0x81); // Position the cursor
    lcd_str("  TEMPERATURE  "); // Display project title
    lcd_cmd(0xc2); // Move to the second line
    lcd_str("   ALERT   "); // Display 'ALERT' text
    delay(65000); // Delay for display
    lcd_cmd(0x01); // Clear display
    
    // Display temperature label
    lcd_cmd(0x80); // Move cursor to first line, start position
    lcd_str("  Temp ="); // Display 'Temp =' text
    lcd_cmd(0x8b); // Move cursor to show temperature in degrees
    lcd_data((char)223); // Display degree symbol
    lcd_str("C"); // Display 'C' for Celsius

    // Infinite loop to continuously monitor temperature
    while(1)
    {   
        // ADC conversion process
        rd = 1; // Set read high
        wr = 0; // Start conversion by setting write low
        delay(100); // Wait for conversion
        wr = 1; // Set write high
        while(intr == 1); // Wait until conversion finishes (interrupt flag low)
        delay(100); // Small delay
        rd = 0; // Set read low to fetch ADC result

        // Display temperature value
        lcd_cmd(0x89); // Set cursor position to display temperature value
        hex2ascii(adc*2); // Convert ADC value to ASCII and display
        
        // High-temperature alert condition
        if(adc*2 > 0x1d) // Check if temperature exceeds threshold (29°C)
        {
            // Display alert message and activate buzzer
            lcd_cmd(0xC0); // Move cursor to second line
            lcd_str("HIGH TEMP ALERT!"); // Display high temp alert message
            buz = 1; // Turn buzzer on
        }
        else
        {
            // Clear alert message and turn off buzzer
            lcd_cmd(0xC0); // Move cursor to second line
            lcd_str("                "); // Clear the alert message
            buz = 0; // Turn buzzer off
        }
        intr = 1; // Ready for next ADC conversion
    }
}

// Function to convert hex value to ASCII and display on LCD
void hex2ascii(unsigned char value) 
{
    unsigned char x, d1, d2, d3;
    x = value / 10; // Extract tens digit
    d3 = value % 10; // Extract ones digit
    d2 = x % 10; // Extract tens digit
    d1 = x / 10; // Extract hundreds digit
    //lcd_data(d1 + 0x30); // Display hundreds digit (ASCII)
    lcd_data(d2 + 0x30); // Display tens digit (ASCII)
    lcd_data(d3 + 0x30); // Display ones digit (ASCII)
}

// LCD initialization function
void lcd_init()
{
    lcd_cmd(0x38); // Initialize LCD for 8-bit mode
    lcd_cmd(0x0c); // Display on, cursor off
    lcd_cmd(0x01); // Clear display
    lcd_cmd(0x80); // Set cursor to beginning of first line
}

// Delay function
void delay(unsigned int i)
{
    unsigned int j;
    for(j = 0; j < i; j++); // Simple loop for delay
}

// Function to send command to LCD
void lcd_cmd(unsigned char a)
{
    rs = 0; // Set for command mode
    ldata = a; // Load command to data port
    en = 1; // Enable LCD
    delay(5); // Small delay
    en = 0; // Disable LCD
    delay(5); // Small delay
}

// Function to send data (characters) to LCD
void lcd_data(unsigned char b)
{
    rs = 1; // Set for data mode
    ldata = b; // Load data to data port
    en = 1; // Enable LCD
    delay(5); // Small delay
    en = 0; // Disable LCD
    delay(5); // Small delay
}

// Function to display string on LCD
void lcd_str(unsigned char *str)
{
    while(*str) // Loop until the end of the string
    {
        lcd_data(*str++); // Send each character to the LCD
    }
}

I tried adjusting the formula used in my code to display the temperature values from an ADC connected to an LM35 temperature sensor. Initially, I multiplied the ADC value by 2, but that only displayed even temperatures.

What I Expected: I was expecting the temperature display to show both even and odd values as the sensor reads the temperature. I anticipated a smooth progression of temperature values (e.g., 29°C, 30°C, 31°C) as the sensor detects the changes, without skipping or rounding errors.

Upvotes: -1

Views: 100

Answers (1)

the busybee
the busybee

Reputation: 12653

On a first glance you seem to ask why you have only even values. And as we commented, this is because you multiply the result of the ADC by two.

You cannot have odd results with multiples of two.


After deeper and time consuming investigation, which you could have saved us by adding this information upfront in the question, it is understandable why you multiply by two:

  1. The LM35 produces 10mV per °C. Since it is an analog device, it outputs also (practically) any value in between, proportional to the temperature.
  2. The ADC has 256 steps for its full range of about 5V, giving just about 20mV per step.
  3. Therefore the unmodified result from the ADC is 1 step = 20mV = 2°C.
  4. This led to the "correction" with the factor of two.

Unfortunately the history of your question created this situation with the remaining question here, and the double-posted version at SE/EE deleted, even if that site is better suited. So I feel you deserve an answer anyway, even if it is here. Please put some more effort into your questions the next time to avoid this confusion.


The real question you have is, "how do I measure the voltage in a way that I can distinguish single °C?"

Solution 1: Reduce the Reference Voltage

Since your ADC cannot extend its digital range, you can reduce the reference voltage. See the ADC's data sheet to learn more.

To have the ADC output a digital value resembling the temperature in °C, you need a reference voltage of 2.56V. The pin "VREF/2" needs to be driven by the half of this value, that is 1.28V.

For a quick experiment you can use a common (not an extra-bright) red LED, which has roughly 1.2V forward voltage. The results will not be good, but you will see the effect.

For a real solution you need a more exact reference. There are specialized components for this, you will need to do your own research.

Solution 2: Amplify the Input Voltage

As an alternative you can amplify the voltage of the LM35 by two.

Use an operational amplifier. Since the signal is practically DC, you don't need a fancy high-speed device. Use any common part.

How to build the circuit is left as an exercise, and it clearly beyond the area of StackOverflow.

Final Note

Don't forget to remove the multiplication by two from your code.

Upvotes: 1

Related Questions