News:

;) This forum is the property of Proton software developers

Main Menu

Using LM35 Temperature

Started by M3NDex, Mar 15, 2026, 03:04 PM

Previous topic - Next topic

M3NDex


I tried to make a temperature control with lm35 and pic877a, but the button and control functions of lm 35 don't work well, considering I'm not very skilled, I hope the members here can help me to find the problem, here is my code below :
'******************************************************************************
'* Name    : LM35_Pro_Controller.BAS                                           *
'* Device  : PIC16F877A                                                        *
'* Crystal : 4 MHz                                                             *
'*******************************************************************************

;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ***********************************************
; Use the Fuse Configurator plug-in to change these settings

Device = 16F877A

Config FOSC_HS, WDTE_OFF, PWRTE_OFF, BOREN_ON, LVP_OFF, CPD_OFF, WRT_OFF, DEBUG_OFF, CP_OFF

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------
'----------------------Declare Xtal 4 Mhz --------------------------------------
Declare Xtal = 4
'-------------------------------------------------------------------------------

'-------------- LCD Diplay pins ------------------------------------------------
Declare LCD_DTPin PORTB.4
Declare LCD_ENPin PORTB.3
Declare LCD_RSPin PORTB.2
Declare LCD_Interface 4
Declare LCD_Lines 2
Declare LCD_Type = 0 
'--------------------------------------------------------------------------------           

'------------- ADC Config -------------------------------------------------------
Declare Adin_Res 10
Declare Adin_Tad FRC
Declare Adin_Stime 50
'---------------------------------------------------------------------------------
'----------PWM Pin output --------------------------------------------------------
Declare HPWM1_Pin = PORTC.0             ' PWM Chn PORTC.0
Declare HPWM2_Pin = PORTC.1             ' PWM Chn PORTC.1
'---------------------------------------------------------------------------------

'---------- State button pins -----------------------------------------------------
Symbol BTN_UP = PORTD.0
Symbol BTN_SET = PORTD.1
Symbol BTN_DN = PORTD.2
'---------------------------------------------------------------------------------

'---------- PORT_PIN_DIRECTION----------------------------------------------------
TRISA = %00000001    'PORTA.0 Input For LM35
TRISB = %00000000    'All PORTB are output
TRISC = %00000000    'All PORTC are output
TRISD = %00000111    'Make PORT RD0, RD1, RD2 as input
'----------------------------------------------------------------------------------

'----------------------IO Analog---------------------------------------------------
ADCON1 = %10000000   ' $80 it will make the I/O analog and right justify the result
'-----------------------------------------------------------------------------------

'------------------------Declare Variables -----------------------------------------
Dim RawValue As Word
Dim TempC As Float
Dim SetPoint As Byte
Dim DutyCycle As Byte
Dim EditMode As Bit   
Dim lastUp As Byte
'------------------------------------------------------------------------------------
'------------------Print First Message ----------------------------------------------
Print At 1, 1, "AUDIO AMPLIFIER "
   DelayMS 500
EditMode = 0                                           'Enter button
SetPoint = ERead 0                                     'Read EEprom 0
    If SetPoint < 10 Or SetPoint > 80 Then SetPoint = 30 'If no number value then put 30
 
Main:

'----------- Read ADC PORTA Pin 0-----------------------------------------------------
RawValue = ADIn 0
TempC = RawValue * 0.488
'--------------------------------------------------------------------------------------

'------------------Handle Button-------------------------------------------------------   
 
    If BTN_SET = 0 Then                                '0
        DelayMS 50                                     ' Debounce
        EditMode = ~EditMode                           ' Toggle mode
        If EditMode = 0 Then EWrite 0, [SetPoint]      'Save when exiting edit
        While BTN_SET = 0 : Wend                                      'Wait for release
    EndIf

   If EditMode = 1 Then                                'Press button Edit Mode status
       If BTN_UP = 0 Then
           SetPoint =SetPoint +1                        'Inc SetPoint 1
          DelayMS 150                                  'Debounce
       EndIf
       
        If BTN_DN = 0 Then
            SetPoint = SetPoint - 1                    'Dec SetPoint 1
            DelayMS 150
        EndIf
        EndIf
'-----------------------Control Fan For Temperature ------------------------------------
    If TempC < SetPoint Then
        DutyCycle = 0
    ElseIf TempC >= SetPoint And TempC < (SetPoint + 5) Then
        DutyCycle = (TempC - SetPoint) * 51
    Else
        DutyCycle = 255
    EndIf
   
    HPWM 1, DutyCycle, 2000                             'Turn 2 KHz PWM
   
'------------------------LCD Display -----------------------------------------------------
    If EditMode = 1 Then
        Print At 1, 1, "SET TARGET TEMP"
        Print At 2, 1, "Target: ", Dec SetPoint, 223, "C  " 'Symbol degree 223 & C Temperature
    Else
        Print At 1, 1, "Temp: ", Dec1 TempC, 223, "C   "
        Print At 2, 1, "Fan: ", Dec (DutyCycle / 2.55), "% Set:", Dec SetPoint
    EndIf
       DelayMS 100                                      'Debounce
GoTo Main       

RGV250

Hi,
I have not got access to Positron but a couple of pointers, you say it doesn't work well but not details of what doesn't work well.
I notice the code uses analogs, display, buttons, HPWM and EEPROM.

Did you write that code or copy it from somewhere.

My suggestion is to break it down into sections and test each separately. I generally use serial out first before a display.

Also have you looked in the samples folder, I would be very surprised if there was not an LM35 example.

Regards,
Bob

RGV250

#2
Hi,
One thing I noticed about your button up /down routine is you have no limit so if the value rolls over from 255 it will go to 0 or from 0 to 255. I would put a stop it the up reaches 255 or down reaches 0 (unless you want it to roll over).
If you are only inc/dec by 1/-1 I find Inc/Dec much neater.

If EditMode = 1 Then                                'Press button Edit Mode status
       If BTN_UP = 0 Then
           Inc SetPoint                        'Inc SetPoint 1
          DelayMS 150                                  'Debounce

       EndIf
       
        If BTN_DN = 0 Then
            Dec SetPoint                    'Dec SetPoint 1
            DelayMS 150
        EndIf
        EndIf

Also I think the program would benefit from Subroutines if using Proton (or procedures if using Positron)

Regards,
Bob

Ivano

Good evening, you haven't included the schematic, so it's not easy to figure out what the problem is. If the buttons don't work properly, you probably haven't installed the pool-up or pool-down resistors. Or you haven't activated the internal pool-up resistors in the PIC, but it seems to me that in the 877 they're only on PORTB.

top204

Your code seems to work, as far as I can tell. However, it will need pull-up resistors for the button pins, otherwise, they will float and cause chaos in the program's operation.

I have re-formatted your code listing, so I could follow it better, and simulate it in proteus, and it is listed below:

' Name    : LM35_Pro_Controller.Bas
'
    Device = 16F877A                                        ' Tell the compiler what device to compile for
    Declare Xtal = 4                                        ' Tell the compiler what frequency the device is operating at (in MHz)
'
' Setup the Alphanumeric LCD
'
    Declare LCD_DTPin     = PORTB.4                         ' Pins PORTB.4 to PORTB.7 connect to the LCD's D4 to D7 pins
    Declare LCD_ENPin     = PORTB.3                         ' Connects to the LCD's EN pin
    Declare LCD_RSPin     = PORTB.2                         ' Connects to the LCD's RS pin
    Declare LCD_Interface = 4                               ' Tell the compiler to use the 4-bit interface to the LCD
    Declare LCD_Lines     = 2                               ' Tell the compiler that the LCD has 2 lines
    Declare LCD_Type      = Alpha                           ' Tell the compiler that the LCD is an Hitachi alphanumeric type
'
' ADC Settings for ADIn
'
    Declare ADin_Res   = 10                                 ' Return a 10-bit result from the ADC
    Declare ADin_Tad   = FRC                                ' Use the FRC clock for the ADC
    Declare ADin_Stime = 50                                 ' Have a 50uS delay between ADC samples
'
' HPWM Pins
'
    Declare HPWM1_Pin = PORTC.0                             ' PWM Chn PORTC.0
    Declare HPWM2_Pin = PORTC.1                             ' PWM Chn PORTC.1
'
' Set the State button pins
'
    Symbol Button_Up_Pin   = PORTD.0
    Symbol Button_Set_Pin  = PORTD.1
    Symbol Button_Down_Pin = PORTD.2
'
' Create global variables here
'
    Dim wRawValue  As Word
    Dim fTempC     As Float
    Dim bSetPoint  As Byte
    Dim bDutyCycle As Byte
    Dim tEditMode  As Bit
    Dim bLastUp    As Byte

'------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    Setup()                                                 ' Setup the program and any peripherals

    Do                                                      ' Create a loop      
        wRawValue = ADIn 0                                  ' Read ADC PORTA Pin 0
        fTempC = wRawValue * 0.488
        '
        ' Handle Buttons
        '
        If Button_Set_Pin = 0 Then                          ' Is the Set button pressed?
            DelayMS 50                                      ' Yes. So a simple Debounce
            If Button_Set_Pin = 0 Then                      ' Is the Set button still pressed?
                tEditMode = ~tEditMode                      ' Yes. So Toggle the mode
                If tEditMode = 0 Then EWrite 0, [bSetPoint] ' Save when exiting edit
                While Button_Set_Pin = 0 : Wend             ' Wait for the button release
            EndIf
        EndIf

        If tEditMode = 1 Then                               ' Press button Edit Mode status
            If Button_Up_Pin = 0 Then                       ' Is the Up button pressed?
                DelayMS 50                                  ' Yes. So a simple Debounce
                If Button_Up_Pin = 0 Then                   ' Is the Up button still pressed?
                    bSetPoint = bSetPoint + 1               ' Yes. So increment bSetPoint
                EndIf

            ElseIf Button_Down_Pin = 0 Then                 ' Is the Down button pressed?
                DelayMS 50                                  ' Yes. So a simple Debounce
                If Button_Down_Pin = 0 Then                 ' Is the Down button still pressed?
                    bSetPoint = bSetPoint - 1               ' Yes. So decrement bSetPoint
                    DelayMS 150
                EndIf
            EndIf
        EndIf
        '
        ' Control Fan for Temperature
        '
        If fTempC < bSetPoint Then
            bDutyCycle = 0
        ElseIf fTempC >= bSetPoint And fTempC < (bSetPoint + 5) Then
            bDutyCycle = (fTempC - bSetPoint) * 51
        Else
            bDutyCycle = 255
        EndIf

        HPWM 1, bDutyCycle, 2000                            ' Turn on the 2 KHz PWM
        '
        ' LCD Display
        '
        If tEditMode = 1 Then
            Print At 1, 1, "SET TARGET TEMP",_
                  At 2, 1, "TARGET: ", Dec bSetPoint, 223, "C    "    ' Symbol degree 223 & C Temperature
        Else
            Print At 1, 1, "TEMP: ", Dec1 fTempC, 223, "C     ",_
                  At 2, 1, "FAN: ", Dec1 (bDutyCycle / 2.55), "% St:", Dec bSetPoint
        EndIf
        DelayMS 100                                         ' Debounce
    Loop                                                    ' Loop forever

'-------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()   
    TRISA = %00000001                                       ' PORTA.0 Input for LM35
    PORTA = %00000000
    Low PORTB                                               ' All PORTB are output low
    Low PORTC                                               ' All PORTC are output
    TRISD = %00000111                                       ' Make PORT RD0, RD1, RD2 as input
    PORTD = %00000000
   
    ADCON1 = %10000000                                      ' $80 it will make the I/O analog and right justify the result

    Print At 1, 1, "AUDIO AMPLIFIER "                       ' Print First Message
    DelayMS 500
    tEditMode = 0                                           ' Enter button
    bSetPoint = ERead 0                                     ' Read EEprom 0
    If bSetPoint < 10 Or bSetPoint > 80 Then bSetPoint = 30 ' If no number value then put 30
EndProc

'-------------------------------------------------------------------------------
' Setup the config fuses for a PIC16F877A device.
'
    Config FOSC_HS, WDTE_OFF, PWRTE_OFF, BOREN_ON, LVP_OFF, CPD_OFF, WRT_OFF, DEBUG_OFF, CP_OFF    

Question... Why are you displaying the Fan duty as a floating point percentage? Whould it not be better as an integer only. It would make the code smaller as well. Either work nicely, but I am a savage for efficiency. :-)

And below are two screenshots of the program operating in the proteus simulator. Image 1 is the temperature trip set, and image 2 is the temperature.

LM35_Temp_Trip_Set.jpg    LM35_Temp.jpg

Regards
Les