Strange problem with an 18F4580 based project


Closed Thread
Results 1 to 11 of 11
  1. #1
    malc-c's Avatar
    malc-c Guest

    Default Strange problem with an 18F4580 based project

    Guy's, this is probably aimed at DT or Henrik as they are really familiar with my thermostat project, but I'm open to suggestions.

    My prototype thermostat unit (details can be found at http://www.picbasic.co.uk/forum/showthread.php?t=12712) has been running now for around 6 months, but recently I've had two incidences where the unit appears to be running, but has actually locked up in some way, after I tried fixing a problem with a light that is driven from the unit.

    The first instance the light was out, so whilst everything was still running I detached the cable and reseated the tube then plugged the light (an under cabinet florescent T5 tube) back in. Everything seemed OK until I noticed the snake in each vivarum move right up the cold end of the enclosure. The temperature on the LCD still showed 33.1C and both LEDs were pulsing away as normal, but on opening the viv the heat was obvious. I reset the controller and off went the alarms as both vivs were running at 45c (which was now shown on the display).

    The second instance was the same, but this followed a simple tapping of the tube to get it to light. Only this time I noticed that the temperature readings from the DS18B20's didn't fluctuate (normally they are constantly changing every few seconds by +/- 0.1c).

    It is as if the program in the chip stops running the PID loop or something but where you would expect the LCD to blank out, or the LEDs to stop pulsing if the chip stopped running that doesn't happen. Could it be the fuse settings? Can a PIC go into a state of limbo like this ??

    I've been told that some of the commercial companies hang out on the reptile forums have got wind of my project so I don't really want to paste up the current version of the code in full, so PM me if you need the files. I can obviously post up spinets, if required.

    Comments please

  2. #2
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Hi, Malc

    @ First sight ... I could think the DS1820 do not update its scratchpad for any reason.
    I read you use fluorescent tubes for lighting ... that rings my bell and I ask you

    1) Which value for the pullup resistor ( usually 4.7k ... when sensor close to processor ! )
    2) do you use ground shielded wire to connect your DSs ???
    3) could you post me the DS identification and temp reading section of your program ? ( to see if any " health " control of the sensor is done )

    may be we could think to some enforced DS chip " good running check " ...
    some control like " heating power always rises, but temp not = default somewhere )

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  3. #3
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Hi Alain, and thanks for posting.

    Yes I'm using 4.7K resistors on each of the DS18B20's. The cable length is approx 2m from the tip of the sensor to the unit, and made up of three wires twisted (used a drill). My research didn't throw up anything about having to use shielded cable between the sensor and the PIC.

    I'll zip up all the code (including the includes !) and let you check the code. To make things simpler, could you pm me your e-mail address.

    Thanks

  4. #4
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default code snippets

    Hope the following help

    Initialization
    Code:
    ;----[DS1820 Options]----Value----Default-----------------------------------
    DEFINE  DS1820_DECIMALS    1                    ' 1
    DEFINE  DS1820_VERIFYCRC   YES                  ' NO
    DEFINE  DS18B20_ONLY       YES                  ' NO
    INCLUDE "DT18x20.pbp"                           ' Include DT18x20 module
    Code:
        FOR Bvar = 0 to 3                               ; assume all sensors are working
            SensorActive(Bvar) = 1
        NEXT Bvar
            
        FOR pid_Channel = 0 TO 3                        ; Set # of bits in resolution
            GOSUB SelectSensor                          ; for all sensors
            GIE = 0                                     ; disable interrupts before 1-wire
            @ DS1820_Resolution 12            
            GIE = 1                                     ; enable interrupts after 1-wire
        NEXT pid_Channel
            
        LOW HeaterOut1                                  ; set heater pins Output to off
        LOW HeaterOut2
        LOW HeaterOut3
        LOW HeaterOut4
        
        Low Lights1                                     ; set lighting pins to off
        Low Lights2
    
        GOSUB SendPWRstat
    The subroutine referred to above
    Code:
    SendPWRstat:
        Bvar = 0
        Bvar.0 = ChannelPWR(0)
        Bvar.1 = ChannelPWR(1)
        Bvar.2 = ChannelPWR(2)
        Bvar.3 = ChannelPWR(3) 
    RETURN
    Now for the main part

    Code:
        FOR pid_Channel = 0 TO 3                        ; cycle thru all sensors
            GOSUB SelectSensor
            DS1820_Error = 0                            ; clear any previous errors
            DS1820_Flags = 0                            ; clear status flags
            GIE = 0                                     ; disable interrupts before 1-wire
              @ DS1820_Stat                             ; check the sensors status
            GIE = 1                                     ; enable interrupts after 1-wire
            PAUSEUS 20
            IF !DS1820_Done THEN SensorError            ; if it's not done by now, error
            GIE = 0                                     ; disable interrupts before 1-wire
              @ DS1820_Read                             ; get the temperature result
            GIE = 1                                     ; enable interrupts after 1-wire
            GOSUB Check4Zeros
            
            DS1820_Flags = 0
            GIE = 0                                     ; disable interrupts before 1-wire
              @ DS1820_Stat
            GIE = 1                                     ; enable interrupts after 1-wire
            IF (DS1820_Error = 0) AND DS1820_Done THEN  ; if there were no errors
                Temperatures(pid_Channel) = TempC
                pid_Error = SetPoints(pid_Channel) - TempC
                GOSUB PID
                IF pid_Out.15 THEN pid_Out = 0          ; only keep positive values
                IF ChannelPWR(pid_Channel) THEN
                    HeaterDrives(pid_Channel) = pid_Out
                ELSE
                    HeaterDrives(pid_Channel) = 0
                ENDIF
    IF Temperatures(pid_Channel) >  alarmhigh(pid_Channel) and Alarm = 1 then AlarmPin = 1
    IF Temperatures(pid_Channel) >  alarmhigh(pid_Channel) and Alarm = 0 then AlarmPin = 0
    IF Temperatures(pid_Channel) <=  alarmhigh(pid_Channel) then AlarmPin = 0
    IF Temperatures(pid_Channel) <=  alarmlow(pid_Channel) then AlarmPin = 0
    if Temperatures(pid_Channel) < alarmlow(pid_Channel)  and Alarm = 1 then AlarmPin = 1
    if Temperatures(pid_Channel) < alarmlow(pid_Channel)  and Alarm = 0 then AlarmPin = 0
       
            GOSUB ShowLCD 
              
            ELSE
        SensorError:
               HeaterDrives(pid_Channel) = 0            ; turn off heater if sensor's bad
               SensorActive(pid_Channel) = 0
               GOSUB ShowError                          ; display error message
            ENDIF
        NEXT pid_Channel
    The other two parts you may be interested in is the checking and displaying sections

    Code:
    AllZeros  VAR Bit
    Check4Zeros:
        AllZeros = 1
        FOR Bvar = 0 TO 8
            IF DS1820_Buffer(Bvar) != 0 THEN AllZeros = 0
        NEXT Bvar
        IF AllZeros THEN DS1820_CRCfailed = 1
    ;------------------------------------------------------------------------------ 
    
    ;----[show output on LCD]------------------------------------------------------- 
    ShowLCD:
        LOOKUP pid_Channel,[$80,$C0,$89,$C9],Bvar       ; Find location
        LCDOUT $FE,Bvar,DEC1 pid_Channel+1,"= "         ; print to LCD     
        TempWD = TempC : GOSUB TempToLCD                ; display TempC
        LCDOUT $DF                                      ; deg symbol
    and the select sensor sub
    Code:
    SelectSensor:
      SELECT CASE pid_Channel
        CASE 0 : @ DS1820_Select  _TempSensor1      ; Select the DS18x20 pin
        CASE 1 : @ DS1820_Select  _TempSensor2
        CASE 2 : @ DS1820_Select  _TempSensor3
        CASE 3 : @ DS1820_Select  _TempSensor4
      END SELECT  
    RETURN

    If you need more drop me an e-mail or I can post up more snipets
    Last edited by malc-c; - 18th December 2010 at 13:46. Reason: added more code

  5. #5
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Malcolm,

    The heater outputs are interrupt driven, so if the main program locks up somewhere due to an unexpected condition, the heaters will continue pulsing at the last drive level given from the PID loops.

    I can't imagine all four DS18B20's having a problem at the same time. The program is checking CRC's.
    If 1 VIV got hot and the others were OK, I might suspect a DS.

    You may need to use the WDT to monitor the main loop.
    Then it'll reset the processor if it gets lost.

    Using ...
    DEFINE NO_CLRWDT 1
    PBP will not add CLRWDT instructions throughout the code.
    Then "strategically" placing CLRWDT statements in your program will clear it as long as the loop is running.

    I say strategically, because if you place a CLRWDT in the area where it's locking up, it won't help.

    Since the problem seems to be repeatable by fiddling with the lights, it should be fairly easy to locate good placements of the CLRWDT statements.

    Blinking an LED in the main loop may help identify when or if it's locked.
    DT

  6. #6
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Darrel,

    Thanks for your input - with your prior knowledge of this project I thought you would be best placed to know what is going on.

    OK I'll be perfectly honest, I'm not 100% sure where I would need to place the CLRWDT commands, so here is the main program loop

    Code:
    ;-----------------------------------------------------------------------------
    ; *****  MAIN PROGRAMMING LOOP *****
    ;-----------------------------------------------------------------------------
    
    Main:
    
    
    If SetButton=0 then                                 ; jump to programming
    Gosub SetButtonRelease
    goto mainmenu
    endif
    
    If DecButton=0 then
    Gosub SetButtonRelease
    goto lightoveride                                   ; manual overide of light
    endif
    
    If IncButton=0 then
    Gosub SetButtonRelease
    goto cancelalarm                                   ; manual overide of alarm
    endif
    
    
        FOR pid_Channel = 0 TO 3                        ; cycle thru all sensors
            GOSUB SelectSensor
            GIE = 0                                     ; disable interrupts before 1-wire
            @  DS1820_Convert                           ; start a temperature conversion
            GIE = 1                                     ; enable interrupts after 1-wire
        NEXT pid_Channel
         
    ;----[check for data on com port] 
    
        FOR TempWD = 0 TO 10000
            IF RCIF THEN GOto coms
            PauseUs 100
        NEXT TempWD
    ;--------------------------------    
    
    
        FOR pid_Channel = 0 TO 3                        ; cycle thru all sensors
            GOSUB SelectSensor
            DS1820_Error = 0                            ; clear any previous errors
            DS1820_Flags = 0                            ; clear status flags
            GIE = 0                                     ; disable interrupts before 1-wire
              @ DS1820_Stat                             ; check the sensors status
            GIE = 1                                     ; enable interrupts after 1-wire
            PAUSEUS 20
            IF !DS1820_Done THEN SensorError            ; if it's not done by now, error
            GIE = 0                                     ; disable interrupts before 1-wire
              @ DS1820_Read                             ; get the temperature result
            GIE = 1                                     ; enable interrupts after 1-wire
            GOSUB Check4Zeros
            
            DS1820_Flags = 0
            GIE = 0                                     ; disable interrupts before 1-wire
              @ DS1820_Stat
            GIE = 1                                     ; enable interrupts after 1-wire
            IF (DS1820_Error = 0) AND DS1820_Done THEN  ; if there were no errors
                Temperatures(pid_Channel) = TempC
                pid_Error = SetPoints(pid_Channel) - TempC
                GOSUB PID
                IF pid_Out.15 THEN pid_Out = 0          ; only keep positive values
                IF ChannelPWR(pid_Channel) THEN
                    HeaterDrives(pid_Channel) = pid_Out
                ELSE
                    HeaterDrives(pid_Channel) = 0
                ENDIF
    IF Temperatures(pid_Channel) >  alarmhigh(pid_Channel) and Alarm = 1 then AlarmPin = 1
    IF Temperatures(pid_Channel) >  alarmhigh(pid_Channel) and Alarm = 0 then AlarmPin = 0
    IF Temperatures(pid_Channel) <=  alarmhigh(pid_Channel) then AlarmPin = 0
    IF Temperatures(pid_Channel) <=  alarmlow(pid_Channel) then AlarmPin = 0
    if Temperatures(pid_Channel) < alarmlow(pid_Channel)  and Alarm = 1 then AlarmPin = 1
    if Temperatures(pid_Channel) < alarmlow(pid_Channel)  and Alarm = 0 then AlarmPin = 0
       
            GOSUB ShowLCD 
              
            ELSE
        SensorError:
               HeaterDrives(pid_Channel) = 0            ; turn off heater if sensor's bad
               SensorActive(pid_Channel) = 0
               GOSUB ShowError                          ; display error message
            ENDIF
        NEXT pid_Channel
    
         
    ;   ---------------------------------------------------------------------------
    ;   check lighting periods and turn lights on or off accordingly
    ;   ---------------------------------------------------------------------------
    
        fn = 0                                                      ; select the first Lights
        if lightover = 0 then GOSUB CheckTimes                      ; if manual override set to off then go compare the programed period
        if lightover = 1 then progON=1                              ; if manual override flag set to on then lights on flag set to 1
        IF ProgON THEN                                              ; If in the program period
           IF Lights1 = 0 THEN Lights1 = 1
        ELSE
           IF Lights1 = 1 THEN Lights1 = 0
           IF Lights1 = 0 then LCDOut $FE, $94+9,"          " 
        ENDIF
    
        fn = 1                                                      ; select the second Lights
        if lightover = 0 then GOSUB CheckTimes                      ; compare the programed period
        IF ProgON THEN
            IF Lights2 = 0 THEN Lights2 = 1
    
        ELSE
            IF Lights2 = 1 THEN Lights2 = 0
         LCDOut $FE, $94+9,"          "
         ENDIF
        IF Lights1 = 1 then LCDOut $FE, $94+9,"Light 1 ON"
        IF Lights2 = 1 then LCDOut $FE, $94+9,"Light 2 ON"   
        if Lights1 = 1 and Lights2 = 1 then LCDOut $FE, $94+9,"Lights ON "
        If Lights1 = 0 and Lights2 = 0 then LCDOut $FE, $94+9,"          "
    
         
    ;   ---------------------------------------------------------------------------
    ;   Check for night time drops - if condition matched, drop temp
    ;   ---------------------------------------------------------------------------
    
        fn = 0                            ; select the first setting
        GOSUB CheckTimes2                   ; compare the programed period
        IF ProgON2 THEN
        SetPoints[0]=Droptemp[0]          ; change the corresponding set point to the drop temperature
        LCDOut $FE, $94,"Night"
        ELSE
        SetPoints[0]= normtemp[0]          ; change the corresponding drop temperature to set point
        LCDOut $FE, $94,"     "
        ENDIF    
      
        fn = 1                              ; select the second setting
        GOSUB CheckTimes2                   ; compare the programed period
        IF ProgON2 THEN
        SetPoints[1]=Droptemp[1]          ; change the corresponding set point to the drop temperature
        LCDOut $FE, $94,"Night"
        ELSE
        SetPoints[1]= normtemp[1]          ; change the corresponding drop temperature to set point
        LCDOut $FE, $94,"     "
        ENDIF  
         
        fn = 2                              ; select the third setting
        GOSUB CheckTimes2                   ; compare the programed period
        IF ProgON2 THEN
        SetPoints[2]=Droptemp[2]          ; change the corresponding set point to the drop temperature
        LCDOut $FE, $94,"Night"
        ELSE
        SetPoints[2]= normtemp[2]          ; change the corresponding drop temperature to set point
        LCDOut $FE, $94,"     "
        ENDIF  
         
        fn = 3                              ; select the fouth setting
        GOSUB CheckTimes2                   ; compare the programed period
        IF ProgON2 THEN
        SetPoints[3]=Droptemp[3]          ; change the corresponding set point to the drop temperature
        LCDOut $FE, $94,"Night"
        ELSE
        Setpoints[3]= normtemp[3]          ; change the corresponding drop temperature to set point
        LCDOut $FE, $94,"     "
        ENDIF   
         
         
         
    ;----[Flash Star on LCD]-------------------------------------------------------              
    If alarm=1 then
        LCDOUT $FE,$80 + 18,("*"&FlashStar*$FF)|(" "&~(FlashStar*$FF)) ; flash a star to show sample time, but used to indicate Alarm settings monitored
        FlashStar = !FlashStar 
    endif                             
    
    
    
    
    ;-----------------------------------------------------------------------------
    ; *****  MAIN PROGRAMMING LOOP END *****
    GOTO Main                                
    ;-----------------------------------------------------------------------------
    Could you advise me ??

    Thanks

  7. #7
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Darrel, just checked the hardware file and these are the settings

    Code:
    ASM 
      __CONFIG    _CONFIG1H, _OSC_HSPLL_1H
      __CONFIG    _CONFIG2L, _PWRT_ON_2L  
      __CONFIG    _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
      __CONFIG    _CONFIG3H, _PBADEN_OFF_3H
      __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
    ENDASM
    If I read that then the WDT is running, and as I've not inserted DEFINE NO_CLRWDT 1 into the code then I assume that PBP has automatically inserted the resets through the code automatically. However on checking the corresponding asm file there are just the following references to CLRWDT in that file (towards the beginning)

    Code:
    ;---[Add an Interrupt Source to the user's list of INT Handlers]--------------
    INT_Handler  macro  IntFlagReg, IntFlagBit, Label, Type, Reset
      list
        local AfterSave, AfterUser, NoInt
    INT_Count += 1
    PrList#v(INT_Count)R = IntFlagReg
    PrList#v(INT_Count)B = IntFlagBit
    PrList#v(INT_Count)Priority = Priority
            GetIntInfo   IntFlagReg, IntFlagBit
            if (Found == YES)
                btfss    INT_Enable_Reg, INT_Enable_Bit, 0  ; if INT is enabled
                goto   NoInt
                btfss    INT_Flag_Reg, INT_Flag_Bit, 0      ; and the Flag set?
                goto     NoInt
                if (Priority == H)
                    bsf      _Serviced_H, 0
                else
                    bsf      _Serviced_L, 0
                endif
                ifdef NO_CLRWDT
                    if  (NO_CLRWDT != 1)
                        CLRWDT
                    endif
                else
                    CLRWDT
                endif
                    
                if (Type == PBP)                         ; If INT handler is PBP
                  if (Priority == H)
                    ifdef ReEnterHPused
                        GetAddress21  AfterSave, RetAddrH  
                        L?GOTO  _SavePBP_H        ; Save PBP system Vars in HP INT
                    else
        error "ReEnterPBP-18 must be INCLUDEd to use High Priority PBP interrupts"
                    endif
                  else ; Priority = L
                    ifdef ReEnterLPused
                        GetAddress21  AfterSave, RetAddrL  
                        L?GOTO  _SavePBP_L        ; Save PBP system Vars in LP INT
                    else
       error "ReEnterPBP-18LP must be INCLUDEd to use Low Priority PBP interrupts"
                    endif
                  endif
                endif

    I've searched for info on using the watchdog timer and came across Mel's post in 2003 ??? which helps explain how PBP uses the timer... but still a bit confused given the complexity of our code

  8. #8
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    To see where the CLRWDT instructions are inserted, you would have to look at the .LST file because they are part of the library, not the generated .ASM code.

    The one's you found are part of DT_INTS, and as you can see they also respond to the NO_CLRWDT define.

    The base period of the WDT on a 4580 is 4ms, and with a postscaler of 512 it will timeout after about 2 seconds.

    Your main loop will take less than 2 seconds each time so a single CLEARWDT statement at the end of the loop just before GOTO Main should suffice, although it may be advantageous to put it in the area where it updates the heater drives just to be sure that is getting accomplished. But then if you turn off power to all 4 channels, you'll have to clear it somewhere else or it will reset every 2 seconds. You may just have to play with it and see what works best.
    Code:
                IF ChannelPWR(pid_Channel) THEN
                    HeaterDrives(pid_Channel) = pid_Out
                    CLEARWDT
                ELSE
                    HeaterDrives(pid_Channel) = 0
                ENDIF
    HTH,
    DT

  9. #9
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Darrel Taylor View Post

    The base period of the WDT on a 4580 is 4ms, and with a postscaler of 512 it will timeout after about 2 seconds.

    Your main loop will take less than 2 seconds each time so a single CLEARWDT statement at the end of the loop just before GOTO Main should suffice,
    Darrel,

    I've added DEFINE NO_CLRWDT 1 at the start of the code along with other defines. Then added one CLEARWDT just before the GOTO MAIN -

    Just before the main loop the code jumps to a simple section that displays the current version
    Code:
    about:
        LCDOUT $FE,2,"   Multi - Therm    "
    lcdout $FE, $C0, "    Thermostat      "
    
    lcdout $FE, $D4, " Firmware Ver 4.60  "
    Pause 2000
    LCDOUT $FE,1
    goto main
    No with the CLEARWDT inserted as suggested the code is constantly displaying the about screen. IE its constantly resetting which looking at the pause 2000 line in the about the same as the WDT.

    So I commented out the GOTO About and the program ran fine, however if I jump to the main menu it quickly resets before you get chance to make any changes. So I guess I have to go through each section of the code to ensure that I insert enough CLEARWDT statements to allow the program to function, but not defeat the purpose of the WDT ?

  10. #10
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Yup, that's part of that "strategically" idea.

    And now you will appreciate the idea of "Event Driven" software, instead of GOSUB somewhere then return when it's finished, whenever that is.

    With event driven, everything keeps running, even if you're moving through menu's on an LCD.

    Keep in mind that if your light bulb spark is causing a false button press and it's going off into one of those routines ... the WDT won't help unless that routine times out eventually because now you've added CLEARWDT's to it.
    DT

  11. #11
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Darrel Taylor View Post
    Yup, that's part of that "strategically" idea.

    And now you will appreciate the idea of "Event Driven" software, instead of GOSUB somewhere then return when it's finished, whenever that is.

    With event driven, everything keeps running, even if you're moving through menu's on an LCD.

    Keep in mind that if your light bulb spark is causing a false button press and it's going off into one of those routines ... the WDT won't help unless that routine times out eventually because now you've added CLEARWDT's to it.
    Yeah, having to work through the sub-routines to add the CLEARWDT so that it doesn't reset, but then to add some form of time out routine so that if nothing is pressed it returns to the main menu.

    I must admit my old brain finds it comfortable with the goto / gosub way of coding... the "if button pressed gosub xyz", and I wouldn't know how to re-work the code for event driven routines... still learning ! I'll keep plodding away through the code to insert the CLEARWDT hear and there, at least it will provide some form protection.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts