Eric_O
Advanced Member level 4
- Joined
- May 31, 2020
- Messages
- 107
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 16
- Activity points
- 1,024
void main()
{
PORTB = 0; // Initialisation du PORT B à 0.
PORTC = 0; // Initialisation du PORT C à 0.
PORTD = 0; // Initialisation du PORT D à 0.
ANSEL = 0b00001000; // b3 = 1 (ANS3) : sets pin 5 (AN3) as analog input.
ANSELH = 0b00000000;
TRISB = 0b00000000; // PORT B : b0 à b7 configurés en sortie.
TRISC = 0b00000000; // PORT C : b0 à b7 configurés en sortie.
TRISD = 0b00000000; // PORT D : b0 à b7 configurés en sortie.
C1ON_bit = 0; // CMC1CON register > b7 > C1ON bit = 0 > Disable comparator 1.
C2ON_bit = 0; // CMC2CON register > b7 > C1ON bit = 0 > Disable comparator 2.
SCS_bit = 0; // OSCCON register > b0 > SCS bit = 0 > External oscillator (quartz) is used as a clock source.
LCD_Init_v4 (void);
pointeur_de_char = &texte[0]; // pointeur_de_char pointe sur le premier élément du tableau "texte", soit texte[0].
// Autrement dit, pointeur_de_char contient l'adresse (&) de texte[0].
do
{
float adc;
float volt, temp;
char txt[13];
ADC_initialization();
TRISD = 0x00;
while(1)
{
adc = (ADC_read(3)); // Reads analog values.
volt = adc * 4.88281; // Converts it into the voltage.
temp = volt / 10.0; // Gets the temperature values.
temp = temp - 273; // Converts Farenheit to Celcius.
StrConstRamCpy(pointeur_de_char, "Temperature ... "); // OK.
LCD_Write_String_At(0, 0, pointeur_de_char); // OK. Voir dans void LCD_Write_String(char *msg), le while(*(msg + k) > 0).
float2ascii_v2(temp, &txt[0], 2);
LCD_Write_String_At(1, 0, &txt[0]); // Write txt in 2nd row, starting at 1st digit.
LCD_Write_String_At(1, 13, " °C"); // Write " °C" in 2nd row, starting at 14th digit.
delay_ms(3000);
}
}
while(1);
}
TonyLM35 GND (pin 3) : connected to GND of MCU.
LM35 output (pin 2) : connected to ADC 3 of MCUand also to VCC thru a 2.2 K resistor.
LM35 output (pin 1) : Vcc= 4~20Vnot connected (instead of connected to VCC in some cases)
Dear Brian,
Here under my code ... While running, temperature displayed on LCD start from a negative value a increase to 3 or 4°C ... No more. While room temp is around 20°C now.
Code:void main() { PORTB = 0; // Initialisation du PORT B à 0. PORTC = 0; // Initialisation du PORT C à 0. PORTD = 0; // Initialisation du PORT D à 0. ANSEL = 0b00011000; // b3 = 1 (ANS3) : sets pin 5 (AN3) as analog input. // b4 = 1 (ANS4) : sets pin 7 (AN4) as analog input. //Or //ANSEL = 24; ANSELH = 0b00000000; TRISB = 0b00000000; // PORT B : b0 à b7 configurés en sortie. TRISC = 0b00000000; // PORT C : b0 à b7 configurés en sortie. TRISD = 0b00000000; // PORT D : b0 à b7 configurés en sortie. C1ON_bit = 0; // CMC1CON register > b7 > C1ON bit = 0 > Disable comparator 1. C2ON_bit = 0; // CMC2CON register > b7 > C1ON bit = 0 > Disable comparator 2. SCS_bit = 0; // OSCCON register > b0 > SCS bit = 0 > External oscillator (quartz) is used as a clock source. LCD_Init_v4 (void); pointeur_de_char = &texte[0]; // pointeur_de_char pointe sur le premier élément du tableau "texte", soit texte[0]. // Autrement dit, pointeur_de_char contient l'adresse (&) de texte[0]. do { int voltage_at_Vout_pin, voltage_at_GND_pin; float temp; char txt[13]; ADC_initialization(); TRISD = 0x00; while(1) { voltage_at_Vout_pin = ADC_read(3); // Reads analog voltage at Vout pin of LM35DZ. voltage_at_GND_pin = ADC_read(4); // Reads analog voltage at GND pin of LM35DZ. temp = (voltage_at_Vout_pin - voltage_at_GND_pin) * 4.888; // Reads analog voltage and converts it to Celsius degrees (4.888 = 5000 mV / 1023). 5000 mV = 5V = VCC of MCU. temp = temp / 10; // With LM35, each 10 mV output correspond to 1°C. StrConstRamCpy(pointeur_de_char, "Temperature ... "); // OK. LCD_Write_String_At(0, 0, pointeur_de_char); // OK. Voir dans void LCD_Write_String(char *msg), le while(*(msg + k) > 0). //float2ascii_v1(temp, &txt[0], 2); float2ascii_v2(temp, &txt[0], 2); LCD_Write_String_At(1, 0, &txt[0]); // Write txt in 2nd row, starting at 1st digit. LCD_Write_String_At(1, 13, " °C"); // Write " °C" in 2nd row, starting at 14th digit. delay_ms(3000); } } while(1); }
Thanks for enlighten me.
Eric
I did all, except check Vout with a DMM or oscillo.Tony
0.0 to 1.0V = 0 to 100'C
Fix: Connect Vcc , remove R , verify Output with Vdc on a DMM and verify each pin always then code!
Thanks !Also move these out of the 'do' loop, they only need defining once.
float adc;
float volt, temp;
char txt[13];
I don't have the data sheet with me at the moment but the conversion of Fahrenheit to Celsius looks very wrong to me. From my memory the LM35 output is 10mV/C so it doesn't need converting at all.
Try disconnecting the output from the LM35 and instead connect a potentiometer across VCC and Ground with its slider connected to the ADC. As you turn it you should see the temperature go from one end to the other of its scale. If it doesn't, the results should give some clues about why it isn't working. Don't forget you have a 3 second delay in your loop so the reading will be slow to respond.
Brian.
Will monitor the different variables with the MikroE Debugger.What is the code in 'ADC_initialization()' as that will determine how the values are being represented in the 'Voltage_at_...' variables. Ditto the code in 'ADC_read()'.
Have you tried to debug the code?
In particular what are the values that you have in the 'Voltage_at_...' variables? If they are not right then your calculations are somewhat meaningless.
Susan
then at least check with DMM for 220 mV at 22'CI did all, except check Vout with a DMM or oscillo.
Dear Susan,I did all, except check Vout with a DMM or oscillo.
--- Updated ---
Thanks !
I removed these lines in my last code here below.
You're are right, connecting a potentiometer is the smarter way. Will do that.
--- Updated ---
Will monitor the different variables with the MikroE Debugger.
void ADC_initialization()
{
ADCON0 = 0b01000001;
ADCON1 = 0b10000000;
}
unsigned int ADC_read(unsigned char channel)
{
static unsigned int k;
ADCON0 = ADCON0 & 0b11000011;
channel = channel << 2;
ADCON0 = ADCON0 | channel;
Delay_ms(2);
ADCON0.GO_DONE = 1;
_asm NOP;
while (ADCON0.GO_DONE == 1);
{
k = ADRESL + (ADRESH * 256);
}
return(k);
}
while (ADCON0.GO_DONE == 1);
{ } // wait for conversion to become finished
k = ADRESL + (ADRESH * 256); // finíshed, now read the ADConversion result
return(k);
Merci !then at least check with DMM for 220 mV at 22'C
Merci !You might also need to add a cast like this:
k = (unsigned int)ADRESL + (unsigned int)(ADRESH * 256);
the reason being that both ADC results are probably of 'char' type.
Not sure why you make 'k' a static variable but never use its previous value.
Brian.
Merci !
I did that. When room temperature is 23°C, voltage between Vout (pin 2) and GND (pin 3) of LM35 is 230 mV … But when displayed temp on LCD change every 5 sec (due to the delay in my code) as shown on attached pics, temp is consistent only once every four samplings.
You might also need to add a cast like this:
k = (unsigned int)ADRESL + (unsigned int)(ADRESH * 256);
the reason being that both ADC results are probably of 'char' type.
Not sure why you make 'k' a static variable but never use its previous value.
Brian.
Hi, your code reads the conversion result many times in a loop while the conversion is still in process.. try this:Code:while (ADCON0.GO_DONE == 1); { } // wait for conversion to become finished k = ADRESL + (ADRESH * 256); // finíshed, now read the ADConversion result return(k);
Thank’s.Hi,
your code reads the conversion result many times in a loop while the conversion is still in process..
try this:
Code:while (ADCON0.GO_DONE == 1); { } // wait for conversion to become finished k = ADRESL + (ADRESH * 256); // finíshed, now read the ADConversion result return(k);
Thank you for this smart remark. I make correction.Hi,
your code reads the conversion result many times in a loop while the conversion is still in process..
try this:
Code:while (ADCON0.GO_DONE == 1); { } // wait for conversion to become finished k = ADRESL + (ADRESH * 256); // finíshed, now read the ADConversion result return(k);
Do some body have an idea, concerning my problem ? ThanksMerci !
I did that. When room temperature is 23°C, voltage between Vout (pin 2) and GND (pin 3) of LM35 is 230 mV … But when displayed temp on LCD change every 5 sec (due to the delay in my code) as shown on attached pics, temp is consistent only once every four samplings.
--- Updated ---
Merci !
I make correction. When room temperature is 23°C, voltage between Vout (pin 2) and GND (pin 3) of LM35DZ is almost 0 mV always … And displayed temp on LCD that change every 5 sec (due to the delay in my code) never exceed 2 degrees as shown on attached pics,
--- Updated ---
--- Updated ---
Merci !
I make correction. When room temperature is 23°C, voltage between Vout (pin 2) and GND (pin 3) of LM35DZ is almost 0 mV always … And displayed temp on LCD that change every 5 sec (due to the delay in my code) never exceed 2 degrees as shown on attached pics,
Dear Brian,Do some body have an idea, concerning my problem ? Thanks
Multimeter (V) | LCD (mV) |
0.02 | 1.96, 2.44, 2.93, 3.42, 3.91, 4.89 |
0.25 | 24.93, 25.42, 25.91, 26.40, 26.88, 27.37, 27.86 |
0.50 | 50.35, 50.84, 51.32, 51.81, 52.30, 52.79 |
0.75 | 74.79, 75.28, 75.76, 76.25, 76.74, 77.23 |
1.00 | 100.20, 100.69, 101.18, 101.67, 102.16, 102.65 |
1.25 | 125.62, 126.11, 126.60, 127.09, 127.60 |
1.50 | 150.55, 151.04, 151.53, 152.02, 152.51 |
1.75 | 175.48, 175.97, 176.46, 176.95 |
2.00 | 200.90, 201.39, 201.87, 202.36 |
2.25 | 225.83, 226.31, 226.80 |
2.50 | 251.24, 251.73, 252.22, 252,71 |
2.75 | 276.17, 276.66, 277.15 |
3.00 | 301.10, 301.59, 302.08 |
3.25 | 326.52, 327.01 |
3.50 | 351.94, 352.42 |
3.75 | 377.35, 376.86 |
4.00 | 402.28, 402.77 |
4.25 | 427.21, 427.70 |
4.50 | 452.14, 452.63 |
4.75 | 477.07, 477.56, 478.05 |
4.96 | 498.58, 499.06, 499.55 |
LM35 is 10 mV/deg CYou have a factor of 10 difference, is that scope measurement and your probe setting
wrong ?
Regards, Dana.
Your display shows five significant figures yet your resolution is two of them, which is 0.49. This means you should be rounding off or you could add noise and average.Dear Brian,
Regarding your advices, here under is the table of measurements values and the code in the attached file :
Almost for each voltage value set every 0,25 V with potentiometer (values displayed on Multimeter > first column), voltages values dispayed on LCD (second column) switch to several close values, with a step of 0,50 mV and loop. Most of the time one or two of the middle values in the list, appears most frequently.
Multimeter (V) LCD (mV) 0.02 1.96, 2.44, 2.93, 3.42, 3.91, 4.89 0.25 24.93, 25.42, 25.91, 26.40, 26.88, 27.37, 27.86 0.50 50.35, 50.84, 51.32, 51.81, 52.30, 52.79 0.75 74.79, 75.28, 75.76, 76.25, 76.74, 77.23 1.00 100.20, 100.69, 101.18, 101.67, 102.16, 102.65 1.25 125.62, 126.11, 126.60, 127.09, 127.60 1.50 150.55, 151.04, 151.53, 152.02, 152.51 1.75 175.48, 175.97, 176.46, 176.95 2.00 200.90, 201.39, 201.87, 202.36 2.25 225.83, 226.31, 226.80 2.50 251.24, 251.73, 252.22, 252,71 2.75 276.17, 276.66, 277.15 3.00 301.10, 301.59, 302.08 3.25 326.52, 327.01 3.50 351.94, 352.42 3.75 377.35, 376.86 4.00 402.28, 402.77 4.25 427.21, 427.70 4.50 452.14, 452.63 4.75 477.07, 477.56, 478.05 4.96 498.58, 499.06, 499.55
Thanks.
Eric
You have a factor of 10 difference, is that scope measurement and your probe setting
wrong ?
wrong pointerLM35 output but the range selector knob seems to be set to the 200mA current range, perhaps it is just the camera angle.
Brian.
do
{
int adc;
float millivolts, temp;
char txt[13];
ADC_initialization();
...
TRISD = 0x00;
Thanks Brian.Thee is certainly a noise and resolution problem but I suspect the real issue is simply the small range of voltages from the LM35. The ADC input voltage and the LCD reading are in accord, aside from possibly being scaled by 10 so the ADC itself seems to be working OK. However if the LM35 is only measuring a limited range of temperature, the voltage it will produce is being lost in the resolution. Most of the ADC range is beyond what the LM35 can produce, even at high temperature.
There are two solutions, one is to amplify the output voltage of the LM35 so it covers more of the ADC range, the other is to reduce the ADC's Vref to expand its scale. Both require additional circuitry and both introduce new problems of their own.
Something puzzles me, in the photographs the test meter is presumably measuring the voltage at the LM35 output but the range selector knob seems to be set to the 200mA current range, perhaps it is just the camera angle.
Personally, I would consider replacing the LM35 with an MCP9701A, they have a wider temperature range and the output is optimized for an ADC to read. You do have to subtract a voltage measurement to set 0C but that's unavoidable if measuring negative temperatures. I've used lots of them very successfully, I put them in my fridge alongside a calibrated thermometer for 30 minutes then measure the output voltage to get the exact offset voltage to use for high accuracy.
Brian.
Thank you Paul.Hello Leo,
Probleme in your code in Thermometer_with_LM35_and_LCD_v7_edaboard.c
char txt[13]; is too short..
if overflow of txt table, you can get somme strange behavior or a MCU reset !
with a 16chars wide LCD , you must use a minimum of 17 bytes
so char txt[17];
in case of using a string of 16chars ( with Zero terminator, means 17 bytes long) !
For safety usage you can add *(txt+16)=0; before sending to LCD
and is not usual to put variable init inside a code loop ...
Code:do { int adc; float millivolts, temp; char txt[13]; ADC_initialization(); ... TRISD = 0x00;
put them just after
void main()
{
Thank you Brian.Thee is certainly a noise and resolution problem but I suspect the real issue is simply the small range of voltages from the LM35. The ADC input voltage and the LCD reading are in accord, aside from possibly being scaled by 10 so the ADC itself seems to be working OK. However if the LM35 is only measuring a limited range of temperature, the voltage it will produce is being lost in the resolution. Most of the ADC range is beyond what the LM35 can produce, even at high temperature.
There are two solutions, one is to amplify the output voltage of the LM35 so it covers more of the ADC range, the other is to reduce the ADC's Vref to expand its scale. Both require additional circuitry and both introduce new problems of their own.
Something puzzles me, in the photographs the test meter is presumably measuring the voltage at the LM35 output but the range selector knob seems to be set to the 200mA current range, perhaps it is just the camera angle.
Personally, I would consider replacing the LM35 with an MCP9701A, they have a wider temperature range and the output is optimized for an ADC to read. You do have to subtract a voltage measurement to set 0C but that's unavoidable if measuring negative temperatures. I've used lots of them very successfully, I put them in my fridge alongside a calibrated thermometer for 30 minutes then measure the output voltage to get the exact offset voltage to use for high accuracy.
Brian.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?