Jugurtha
Member
Hello, everyone..
This is some code I wrote for the Temperature control. This is the first PIC program I actually write from scratch. Nigel Goodwin's tutorial 11 on Analog(ue) inputs (still can't get used to the UK spelling
) helped a bunch.
I have some questions:
- I noticed that in some programs, people don't bother with the OPTION register. How come ?
- I think I do not have to initialize the ADC (ADCON1, etc) everytime I want to do a conversion, am I right ? Is the code relating to the ADC correct, i.e : Do I only have to load the ADCON0 every conversion, or is that un-necessary too and I only have to set the GO bit and wait for it to complete ?
- I think the PIC in question can operate without an external oscillator: Is my __CONFIG correct ?
- The LM35 has a 10mV/°C characteristic. Say for Temp, there's a voltage of Voltage_Sensor..
Voltage_Sensor = 10/1000* Temp (Unit = volts)
I chose the Left justification, so I only have to read the ADRESH byte.
- This being the higher byte of the conversion result, I do have to multiply it by 256, right ?
Another point:
Let's say that to a certain temperature, the conversion gives 256. On 10 bits, 256 gives:
A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
0 1 0 0 0 0 0 0 0 0
A1 and A0 are dismissed.
Or, the result being Left justified, I get :
A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
0 0 0 0 0 0 0 1 0 0
Then multiply 00000001 by 256 (shift 8 times) to get the result 256 = 1 * 256.
I think this makes more sens, since it's a high byte.
I know this might be obvious, but I'd rather not have assumptions.
Thank you.
This is some code I wrote for the Temperature control. This is the first PIC program I actually write from scratch. Nigel Goodwin's tutorial 11 on Analog(ue) inputs (still can't get used to the UK spelling
I have some questions:
- I noticed that in some programs, people don't bother with the OPTION register. How come ?
- I think I do not have to initialize the ADC (ADCON1, etc) everytime I want to do a conversion, am I right ? Is the code relating to the ADC correct, i.e : Do I only have to load the ADCON0 every conversion, or is that un-necessary too and I only have to set the GO bit and wait for it to complete ?
- I think the PIC in question can operate without an external oscillator: Is my __CONFIG correct ?
- The LM35 has a 10mV/°C characteristic. Say for Temp, there's a voltage of Voltage_Sensor..
Voltage_Sensor = 10/1000* Temp (Unit = volts)
I chose the Left justification, so I only have to read the ADRESH byte.
- This being the higher byte of the conversion result, I do have to multiply it by 256, right ?
Another point:
Let's say that to a certain temperature, the conversion gives 256. On 10 bits, 256 gives:
A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
0 1 0 0 0 0 0 0 0 0
A1 and A0 are dismissed.
Or, the result being Left justified, I get :
A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
0 0 0 0 0 0 0 1 0 0
Then multiply 00000001 by 256 (shift 8 times) to get the result 256 = 1 * 256.
I think this makes more sens, since it's a high byte.
I know this might be obvious, but I'd rather not have assumptions.
Thank you.
Code:
;*******************************************************************************************
;* PCB Etching Tank - Temperature Control v 0.D *
;*-----------------------------------------------------------------------------------------*
;* Jugurtha Hadjar - Raouf Moualdi - Iheb Renai *
;*-----------------------------------------------------------------------------------------*
;* Pr. Youcef Smara Dr. Samir Boukhenous *
;*-----------------------------------------------------------------------------------------*
;* Université des Sciences et de la Technologie Houari Boumédiène *
;*-----------------------------------------------------------------------------------------*
; PIC used: PIC 16F887 40 PIN, Dual in line. 10 bit ADC. Only 8 bits will be used.
; Sensor : LM 35 (as of this version) . 10mv/°C slope.
; TODO: Project Due for June, 26th 2012. Give to Pr Smara.
; TODO: Figure out OPTION_REG.
; TODO: Delete the goto START line if there's nothing between
; that line and the START label.
; TODO: Delete the goto Initialize_PIC if there's nothing below it.
; We'll use some subroutines for temperature checks, etc...
;***********************************************************************************
;* THE SETUP *
;***********************************************************************************
LIST p=16F887, r=dec, f=inhx8m
#include "p16F887.inc"
__config _CPD_OFF & _LFOSC & _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTOSC
;Watchdog Timer OFF
;Power Up Timer ON
#define Relay_Pin PORTB,1
#define Sensor_Pin PORTA,0
cblock 0x20 ; General Purpose Registers start here in a PIC16F887.
Delay_Counter_1, Delay_Counter_2, Temp_Sensor, Voltage_Sensor_ADC
endc
;******************************************************************************************
;* OPTION_REG Description *
;*----------------------------------------------------------------------------------------*
;* Bit7:RBPU(active low) PORTB Pull-Up Enable Bit (1, Disabled) *
;* Bit6:INTEDG, Interrupt Edge Select Bit(0, Interrupt on falling edge B0/INT) *
;* Bit5:T0CS, TMR0 Clock Source Select Bit (0, Internal Instruction Cycle Clock) *
;* Bit4:T0SE, TMR0 Source Edge Select Bit(1, Increment on Hi-to-Lo transition on RA4) *
;* Bit3:PSA,PRESCALER Assignment Bit(0, Prescaler assigned to TMR0 module) *
;* Bit2-0:PRESCALER Select Bits (110, 1:128) *
;******************************************************************************************
org 0x00 ;Reset Vector.
goto Initialize_PIC
Initialize_PIC
clrf PORTA
clrf PORTB ; This includes the Relay_Pin (PORTB, 1 - Heater) which is
; cleared (turned off) by default for security measures.
clrf PORTC
bcf STATUS, RP0
movlw 0x96
banksel OPTION_REG
movwf OPTION_REG ; Configure OPTION_REG (81h in Bank1).
goto START ; Here we go..
START
Initialize_ADC
banksel ADCON1
movlw b'0000000' ; Left justified. The ADC has a resolution of 10 bits.
; We'll read the higher 8 bits in ADRESH, and sacrifice
; the remaining 2 bits in the higher end of ADRESL.
; VDD & VSS for VCFG1 & VCFG0
movwf ADCON1
banksel TRISA
bsf TRISA, 0 ; Set RA0 (Pin2) to Input
banksel ANSEL
bsf ANSEL, 0 ; Set RA0 as Analog ..
; Now RA0 is Analog, and is Input.
; RA0 is ready to receive information
; from the sensor.
banksel ADCON0
movlw b'11000001' ; The ADCON0 Register:
; ADCS1 ADCS0 CHS2 CHS1 CHS0 GO_DONE - ADON
; ADCS1 ADCS0 : 11 Conversion Clock frequency Frc
; 4 us typical.
; CHS2 CHS1 CHS0 : 000 RA0
; GO_DONE : 0 . Setting it to 1 starts conversion.
; automatically cleared when conversion is done.
; ADON : 1 . The ADC is enabled.
movwf ADCON0
ADC_Get
movlw d'100' ; A value which will be decreased to lose some time.
movwf Delay_Counter_2
call Delay ; Acquisition Time : See Datasheet "ADC time requirements".
; Might as well be the best example of Cargo Cult Programming from me.
bsf ADCON0, GO ; Start Analog to Digital Conversion.
btfsc ADCON0, GO ; Check if the conversion is finished.
goto $ - 1
banksel ADRESH
movf ADRESH, w ; Get the ADRESH byte and put it in Voltage_Sensor_ADC
movwf Voltage_Sensor_ADC ; The value is the digitized analog voltage from the sensor.
; In order to compare it with a temperature, we need to
; calculate to which temperature in Celsius a certain
; voltage from the LM35 corresponds. (10mv/°C).
; Need to figure out an "easy" way to do multiplication.
;Check_Low_Threshold
movlw d'40' ; That's our Low Threshold
call Check_Temperature ; In order to know if the temperature from
; the sensor is lesser or greater than our
; threshold, we need to perform a substraction
; the Carry flag in the STATUS register tells us
; something about the sign, thus is it greater or lesser?
btfsc STATUS, C ; Is the result of the substraction in Check_Temperature positive?
; If yes, it means that the temperature from the sensor
call Temp_Is_Low ; is less than our Low Threshold, hence we need to
; turn the Relay_Pin on. We call the Temp_Is_Low subroutine for that.
;------------------------------------------------------------------------
;Check_High_Threshold
;------------------------------------------------------------------------
movlw d'42' ; That's our High Threshold
call Check_Temperature
btfss STATUS, C ; Is the Temperature from the Sensor
; greater than the High threshold (42°C) ?
call Temp_Is_High ; If yes, i.e the temperature is HIGH, then
; it's time to turn off the heater.
; If not, i.e the Temperature from the sensor
; is less than the High threshold and it's more
; than the Low Threshold, then do nothing.
Hysteresis
goto ADC_Get ; Here land all cases that need to keep the state of the heater.
; Basically, all cases have been checked (> High Threshold ? < Low Threshold ? Between the two?)
; And the only thing to do now, is to perform another conversion and
; start a new cycle.
; goto START TODO: Remove that line at the end if it's not necessary.
;----------------------------------------------------------------------------------
; SUBROUTINES
;----------------------------------------------------------------------------------
; -----------------------------------------------
Check_Temperature
subwf Temp_Sensor, w
return
; -----------------------------------------------
; -----------------------------------------------
Temp_Is_Low
btfss Relay_Pin ; Is the relay ON ? If it is, then return. (let it that way)
bsf Relay_Pin ; If it's OFF, then turn it ON and return.
return
; -----------------------------------------------
; -----------------------------------------------
Temp_Is_High
btfsc Relay_Pin ; Is the Relay OFF? If it is, then return. (let it off).
bcf Relay_Pin ; If it's ON, then turn it OFF and return.
return
; -----------------------------------------------
; -----------------------------------------------
Delay
decfsz Delay_Counter_2, f ; Teenage wasteland. Lose some time.
goto Delay ; Emo stuff...
return
; -----------------------------------------------
end
Last edited: