2 Attachment(s)
Re: 16f877 with LM335 problem
So this is where I am right now.
First, here's my hardware. What you won't see on the schema is the serial comm lead connected to PIC's PORTB.7 .
Attachment 7797
Here's the code:
Code:
' PIC 16F690 Fuses
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
'_______________________________________________________________________________
' Registers 76543210
OPTION_REG = %10000000 'OPTION REGISTER
ANSEL = %00000100 'Select analog inputs Channels 0 to 7
ANSELH = %00000010 'Select analog inputs Channels 8 to 11
ADCON0 = %00000001 'A/D control register
ADCON1 = %00000000 'A/D control register
CM1CON0 = %00000000 'Comparator1 Module
CM2CON0 = %00000000 'Comparator2 Module
INTCON = %00000000 'INTerrupts CONtrol
TRISA = %00000100 'Set Input/Output (0 to 5)
PORTA = %00000000 'Ports High/Low (0 to 5)
TRISB = %00000000 'Set Input/Output (4 to 7)
PORTB = %00000000 'Ports High/Low (4 to 7)
TRISC = %10000000 'Set Input/Output (0 to 7)
PORTC = %00000000 'Ports High/Low (0 to 7)
'_______________________________________________________________________________
' Defines
DEFINE OSC 4
DEFINE ADC_BITS 10
'_______________________________________________________________________________
' Variables
LM35_Vout var word ' AN2 PORTA.2
LM35_VGND var word ' AN9 PORTC.7
Temperature var word
DataVar VAR WORD(12)
DataTemp var WORD
Counter_A var WORD
'_______________________________________________________________________________
' Program
MAIN:
' LM35_Vout
FOR counter_A = 0 to 11
adcin 2, DataVar(counter_A)
next counter_A
Counter_a = 0
GOSUB SORT
LM35_Vout = DataTemp
' LM35_VGND
FOR counter_A = 0 to 11
adcin 9, DataVar(counter_A)
next counter_A
Counter_a = 0
GOSUB SORT
LM35_VGND = DataTemp
Temperature = (LM35_Vout - LM35_VGND) * 100
GOSUB DISPLAY
pause 1000
Goto main:
'_______________________________________________________________________________
' Subroutine
DISPLAY:
Serout2 PORTB.7,84,["Temp.: ", dec4 temperature," LM35_Vout: ", dec4 LM35_Vout," LM35_VGND: ", dec4 LM35_VGND,13]
RETURN
'_______________________________________________________________________________
' Subroutine
SORT:
' Melanie NEWMAN's array sorting routine
' Aquire 12 values, delete 4 lower and 4 top values, average 4 remaining values
If DataVar(counter_A + 1) < DataVar(counter_A) then
DataTemp = DataVar(counter_A)
DataVar(counter_A) = DataVar(counter_A + 1)
DataVar(counter_A + 1) = DataTemp
If Counter_A > 0 then Counter_A = Counter_A - 2
endif
Counter_A = Counter_A + 1
If Counter_A < 11 then GOTO SORT
' Average four middle values
DataTemp = 0
For Counter_A = 4 to 7
DataTemp = DataTemp + DataVar(counter_A)
next Counter_A
DataTemp = DataTemp / 4
Return
And here is the reading I get right now, knowing the temperature sensor is on my desk close to three other thermometers showing 21°C. Promised, I won't forget to format the "Temp." display in the final version (i.e. "9456" => "94,56°C") :rolleyes:
Attachment 7796
What's wrong with it? :confused:
I have set and defined a 10 bits ADC result. How can I get values over 1023?
I might be wrong with the ADCON0.7 setting but I'm not used to modify it so I'm not sure about that.
Any other idea?
Re: 16f877 with LM335 problem
That's because you have left justified the ADC result in ADRESL and ADRESH.
Set the adcon0 to %10000001.
Also you have this calculation:
Code:
Temperature = (LM35_Vout - LM35_VGND) * 100
What about LM35_Vout being less than LM35_VGND?
I expected you would do this and noted in earlier post (#33) :)
The simplest way is to have an if-then check first like this:
Code:
if LM35_Vout >LM35_VGND then
Temperature = (LM35_Vout - LM35_VGND) * 100
else
if LM35_Vout <= LM35_VGND then
Temperature = (LM35_VGND - LM35_Vout) * 100
endif
Ioannis
1 Attachment(s)
Re: 16f877 with LM335 problem
Quote:
Originally Posted by
Ioannis
...What about LM35_Vout being less than LM35_VGND?
I expected you would do this and noted in earlier post (#33) :)
Sorry, I forgot this one :o . I was focused on the "mysterious" values I was reading.
Quote:
Originally Posted by me
I might be wrong with the ADCON0.7 setting but I'm not used to modify it so I'm not sure about that.
I changed to ADCON0.7 = 1 and the values I read look much better. Still the Temperature value has to be divide by 2 to give the correct reading.
Attachment 7799
Even if it's not the main subject here, can you shortly explain what the difference between ADCON0.7 = 0 and ADCON0.7 = 1 is?
The temporary code is now:
Code:
' PIC 16F690 Fuses
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
'_______________________________________________________________________________
' Registers 76543210
OPTION_REG = %10000000 'OPTION REGISTER
ANSEL = %00000100 'Select analog inputs Channels 0 to 7
ANSELH = %00000010 'Select analog inputs Channels 8 to 11
ADCON0 = %10000001 'A/D control register
ADCON1 = %00000000 'A/D control register
CM1CON0 = %00000000 'Comparator1 Module
CM2CON0 = %00000000 'Comparator2 Module
INTCON = %00000000 'INTerrupts CONtrol
TRISA = %00000110 'Set Input/Output (0 to 5)
PORTA = %00000000 'Ports High/Low (0 to 5)
TRISB = %00000000 'Set Input/Output (4 to 7)
PORTB = %00000000 'Ports High/Low (4 to 7)
TRISC = %10000000 'Set Input/Output (0 to 7)
PORTC = %00000000 'Ports High/Low (0 to 7)
'_______________________________________________________________________________
' Defines
DEFINE OSC 4
DEFINE ADC_BITS 10
'_______________________________________________________________________________
' Variables
LM35_Vout var word ' AN2 PORTA.2
LM35_VGND var word ' AN9 PORTC.7
Temperature var word
DataVar VAR WORD(12)
DataTemp var WORD
Counter_A var WORD
'_______________________________________________________________________________
' Program
MAIN:
' LM35_Vout
FOR counter_A = 0 to 11
adcin 2, DataVar(counter_A)
next counter_A
Counter_a = 0
GOSUB SORT
LM35_Vout = DataTemp
' LM35_VGND
FOR counter_A = 0 to 11
adcin 9, DataVar(counter_A)
next counter_A
Counter_a = 0
GOSUB SORT
LM35_VGND = DataTemp
if LM35_Vout >LM35_VGND then
Temperature = ((LM35_Vout - LM35_VGND) * 100) / 2
endif
if LM35_Vout <= LM35_VGND then
Temperature = ((LM35_VGND - LM35_Vout) * 100) / 2
endif
GOSUB DISPLAY
pause 1000
Goto main:
'_______________________________________________________________________________
' Subroutine
DISPLAY:
Serout2 PORTB.7,84,["Temp.: ", dec2 (temperature/100),",",dec1 (temperature/10),"°C LM35_Vout: ", dec4 LM35_Vout," LM35_VGND: ", dec4 LM35_VGND,13]
RETURN
'_______________________________________________________________________________
' Subroutine
SORT:
' Melanie NEWMAN's
' This subroutine sorts, in this example, 12 elements,
' MyData array in sequence placing the smallest value into MyData[0] and
' the largest value into MyData[11]...
If DataVar(counter_A + 1) < DataVar(counter_A) then
DataTemp = DataVar(counter_A)
DataVar(counter_A) = DataVar(counter_A + 1)
DataVar(counter_A + 1) = DataTemp
If Counter_A > 0 then Counter_A = Counter_A - 2
endif
Counter_A = Counter_A + 1
If Counter_A < 11 then GOTO SORT
' Average four middle values
DataTemp = 0
For Counter_A = 4 to 7
DataTemp = DataTemp + DataVar(counter_A)
next Counter_A
DataTemp = DataTemp / 4
Return
Re: 16f877 with LM335 problem
Roger,
Check out section 9.1.6 "Result Formatting" of the Datasheet.
It shows the difference in the two formatting options.
In essence Right Shifted will place the 10-bit value in bits 9 through 0 (MSB is bit9).
Left Shifted will place the 10-bit value in bits 15 through 6 (MSB is bit15)
So if your ADC reading is 250 then here would be the values.
Right Shifted = 250 (%0000 0000 1111 1010)
Left Shifted = 1600 (%0011 1110 1000 0000)
Re: 16f877 with LM335 problem
Thanks Tabsoft,
I already read that chapter may times but I just can't understand what this feature is meant for.
Why would one choose either option?
I need an example of both usage, maybe this could help :o
Re: 16f877 with LM335 problem
If you want to use only 8 bit (may be it is enough for specific application) then the left justified result will give yout the number in the ADRESH directly. No shifting or dividing required.
But for the full 10 bit results you have to right justify the bytes in the ADRESH-ADRESL to be correct.
Ioannis
ADC - left or right justified result
Okay, I think, I've got it now. Next problem: I need to remember it :D