I am simulating the LM35 sensor with Proteus and Codevision application. The project is to show the temperature on the LCD and 7seg.
Now everything is working but it does not show the Negative numbers (It show 0.0C).
But for positive numbers it show approximately right!
I have tried a lot of codes but none of them worked. I have also tried adding 2*10k resistor for the LM35 to make it 2.5v and making the bias circuit.
#include <mega16.h>
#include <delay.h>
#include <alcd.h>
#include <stdio.h>
#define ADC_VREF_TYPE ((0<<REFS1)|(1<<REFS0)|(0<<ADLAR))
const unsigned char seg_patterns[11] = {
0xC0, // 0
0xF9, // 1
0xA4, // 2
0xB0, // 3
0x99, // 4
0x92, // 5
0x82, // 6
0xF8, // 7
0x80, // 8
0x90, // 9
0xBF // Minus sign '-'
};
volatile unsigned char display_digit = 0;
volatile unsigned char digits[4] = {0xFF, 0xFF, 0xFF, 0xFF};
volatile unsigned char decimal_points[4] = {0, 0, 1, 0};
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
TCNT0 = 240;
PORTB &= ~0xF0;
if (digits[display_digit] != 0xFF) {
PORTC = seg_patterns[digits[display_digit]];
if (decimal_points[display_digit]) PORTC &= ~0x80;
} else {
PORTC = 0xFF;
}
PORTB |= (1 << (display_digit + 4));
display_digit = (display_digit + 1) % 4;
}
unsigned int read_adc(unsigned char ch) {
ADMUX = ch | ADC_VREF_TYPE;
delay_us(10);
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
return ADCW;
}
void update_display(float temp) {
int temp_int;
unsigned char is_negative = 0;
// Check if temperature is negative
if (temp < 0) {
is_negative = 1;
temp_int = (int)((-temp) * 10); // Make positive for digit extraction
} else {
temp_int = (int)(temp * 10);
}
// For negative numbers: -26.0 should show as "-26.0"
// digits[0] = minus, digits[1] = 2, digits[2] = 6, digits[3] = 0
if (is_negative) {
digits[0] = 10; // Minus sign
if (temp_int >= 100) { // Two digits before decimal (e.g., -26.0)
digits[1] = (temp_int / 100) % 10; // Tens digit
digits[2] = (temp_int / 10) % 10; // Units digit
digits[3] = temp_int % 10; // Decimal digit
} else { // One digit before decimal (e.g., -5.2)
digits[1] = 0xFF; // Blank
digits[2] = (temp_int / 10) % 10; // Units digit
digits[3] = temp_int % 10; // Decimal digit
}
} else {
// Positive numbers
if (temp_int >= 1000) { // Three digits (e.g., 125.4)
digits[0] = (temp_int / 1000) % 10;
digits[1] = (temp_int / 100) % 10;
digits[2] = (temp_int / 10) % 10;
digits[3] = temp_int % 10;
} else if (temp_int >= 100) { // Two digits (e.g., 25.5)
digits[0] = 0xFF; // Blank
digits[1] = (temp_int / 100) % 10;
digits[2] = (temp_int / 10) % 10;
digits[3] = temp_int % 10;
} else { // One digit (e.g., 5.2)
digits[0] = 0xFF; // Blank
digits[1] = 0xFF; // Blank
digits[2] = (temp_int / 10) % 10;
digits[3] = temp_int % 10;
}
}
// Set decimal point position (after digit 2)
decimal_points[0] = 0;
decimal_points[1] = 0;
decimal_points[2] = 1; // Decimal point here
decimal_points[3] = 0;
}
void main(void) {
DDRB = 0xF1;
DDRC = 0xFF;
PORTC = 0xFF;
TCCR0 = (1 << CS01);
TIMSK |= (1 << TOIE0);
TCNT0 = 240;
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
lcd_init(16);
#asm("sei")
lcd_clear();
// Test counter for simulating different temperatures
int test_counter = 0;
while (1) {
unsigned int adc_value = read_adc(0);
float voltage = (adc_value * 5.0) / 1024.0;
float temp = voltage / 0.01; // LM35 output 10mV per °C
// TEMPORARY: Simulate negative temperatures for testing
// Remove this section once you confirm negative display works
if (test_counter < 10) {
temp = -26.5; // Test negative temperature
} else if (test_counter < 20) {
temp = -5.2; // Test single digit negative
} else if (test_counter < 30) {
temp = 25.5; // Test positive temperature
} else {
test_counter = 0; // Reset counter
}
test_counter++;
// END OF TEST SECTION
char lcd_text[16];
if (temp < 0) {
sprintf(lcd_text, "Temp: -%.1fC", -temp);
} else {
sprintf(lcd_text, "Temp: %.1fC", temp);
}
lcd_clear();
lcd_puts(lcd_text);
update_display(temp);
delay_ms(500);
}
}