Delay without using pause


Closed Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 43
  1. #1
    Join Date
    Oct 2009
    Posts
    583

    Default Delay without using pause

    I'm developing one of my old projects and I've hit a stumbling block. The old code simply read 4 x DS18B20's and use the data to control the out put to a heat via Henrik's PID routine. It's been working fine for 5 years now, but I want to add 4 x AM2302's to monitor the humidity and also monitor the temperature in its location. The code includes DT's interrupts, DS18B20, and all digital "library files", and thus a lot of the timings for the period each heater is on is done in the background, and the main code consists of a simple loop that reads the sensors and does the maths.

    However with four sets of information for each of the four viavriums the 20 x 4 LCD is becoming a little crowded. So what I really want to do is to display Viv(x), temp1, humidity1, temp2 on a single line on the LCD. No problem in coding the line to do this, but as the program runs so fast through the data it's impossible to read. The simple way is to add a pause statement so for example the code pauses for 2 seconds before retuning to the main program loop and advancing on to the next set of data. But this then delays the speed at which the probes are monitored and by the time the loop is back to probe 1 the temperature could of gone past the set point, as it's not monitored in real time.

    My hair is now white, and I'm half bald trying to resolve this - the nearest I came was to use some form of counting loop within the main loop, that when it tripped over a set value it increased the value of viv(x) by one, so in essence the main code ran at real time speed, but the LCD was only updated every second or so and thus wouldn't hold up the realtime monitoring. Unless any of you guys can come up with a better suggestion

  2. #2
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Hi Malcom,
    Real time in Human terms is as fast as you can read. Who cares if the machine detects something faster, you cannot respond that fast, so the LCD is much like watching the evening news. What you "might" do is allow "the machine" to run several cycles and then report via LCD the average of those cycles.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  3. #3
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Malcolm,

    I think you're on the right track.

    something like this?

    Code:
    LCDCount_Max con 3000   'Set to what you want
    
    LCDCount var word
    LCDUpdate var bit
    
    goto Main
    
    UpdateLCD:
        'do your LCD Update stuff here
        
        return
    
    Main:
        LCDCount = 1    'Used to display the first time        
    
    CycleLoop:
        if LCDUpdate then
            gosub UpdateLCD
            LCDUpdate = 0
        endif
        
        ''do your normal polling stuff here
       
       '' Then do the LCD test stuff here
        LCDCount = LCDCount - 1
        if LCDCount = 0 then
            LCDCount =  LCDCount_Max
            LCDUpdate = 1
        endif 
    
    
        goto CycleLoop
    Regards,
    TABSoft

  4. #4
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Cheers Ken,

    I'll have a play..... failing that I'll look for an 40 x 4 LCD which might make things easier

  5. #5
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,614


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Hi, Malc

    I don't remember your program, but why not use the time the DS1820s make their measure/conversion to update the LCD, instead of waiting for conversion complete ???

    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 " !!!
    *****************************************

  6. #6
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Malcolm,

    You could also do this via a Timer Interrupt using DT's Instant Interrupts.
    Say, Timer2 (8bit timer) with both a Prescaler and Postscaler, then in the ISR decrement a word variable that is preset to a number that gets you to 3 seconds or whatever time you want. When the var reaches zero set a flag to run the display routine and reset the word var back to your preload value. In your main loop test for the flag and call the display routine if set and then clear the flag.

    This would allow you to hit a time-based delay much easier.
    Regards,
    TABSoft

  7. #7
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Why not just count the number of data updates and after so many, Update the display with a different set of data? That way you won't slow down the data taking and control timing and you will get a "cycling" data display you want. That way there is no need for a delay of any type.
    Dave Purola,
    N8NTA
    EN82fn

  8. #8
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Thanks for the suggestions guys.

    Dave, your suggestions sounds simple enough for me to understand. I guess I could have a variable that is updated every time the program goes around the main loop, then when it reaches a certain value display one set of data for the 1st probe, then when reaches another it displays the second set etc... I'll have a look at implementing that. I guess that provided the program doesn't loop more than 65535 times in 8 seconds then I will be able to use a word variable and each update would be visible for 2 seconds

  9. #9
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Quote Originally Posted by Scampy View Post
    Thanks for the suggestions guys.

    Dave, your suggestions sounds simple enough for me to understand. I guess I could have a variable that is updated every time the program goes around the main loop, then when it reaches a certain value display one set of data for the 1st probe, then when reaches another it displays the second set etc... I'll have a look at implementing that. I guess that provided the program doesn't loop more than 65535 times in 8 seconds then I will be able to use a word variable and each update would be visible for 2 seconds
    And . . . . if you average several samples of each you would see it displayed longer, side bonus a "flier" reading would not upset you as much when averaged than it will if not averaged or discarded.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  10. #10
    Join Date
    Jan 2009
    Location
    Miami, Florida USA
    Posts
    637


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Quote Originally Posted by Scampy View Post
    I guess that provided the program doesn't loop more than 65535 times in 8 seconds then I will be able to use a word variable and each update would be visible for 2 seconds
    Since you are using DT interrupts, another approach would be to use a variable to count every time the program goes to the interrupt routine. After so many hits, then you update the LCD display. Depending on how long you set the time intervals for the interrupts, this might be a "cleaner" solution.
    "No one is completely worthless. They can always serve as a bad example."

    Anonymous

  11. #11
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Guys, thanks for your continued input.

    I've hit a hurdle and it's doing my head in. In the original code the readings from the 4 sensors were displayed constantly on the LCD, so within the main program loop there is a for next loop which runs through and reads the 4 DS18B20's and puts the results into a 4 line array. This results in a fast response in updating the display when temperatures change. Now that I'm also reading an AM2302 and want to display data from that too, the LCD looks cluttered if I follow the same method, hence my idea of displaying the readings from each vivarium on a single line, which would overwrite the values for each vivarium every few seconds. The problem is that if I opt to change this so the for next loop which reads the sensors is changed so that it reads sensor 1 and then goes to a subroutine to display the results for two or three seconds it means that it can take 8 - 12 seconds to go round the loop to read all four sensors, which defeats the object of having fast response times, and in 12 seconds the temp in the vivarium could become dangerously high as this would effect the PID timings.

    I think to only option is to use two 20 x 4 LCD's or one 40 x 4 LCD, or possibly a GLCD

  12. #12
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Can you post a mockup of your display in text and how you use it and how you see using it?
    Regards,
    TABSoft

  13. #13
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    This was the best match, but I have no room to display the time.

    Name:  oldlcd.jpg
Views: 999
Size:  38.4 KB

    This is what I'm trying to achieve

    Name:  newlcd.jpg
Views: 952
Size:  30.4 KB

    With line 2 being updated with data for Viv2, Viv3 etc

  14. #14
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    "which would overwrite the values for each vivarium every few seconds. “

    It sounds like you just need to overwrite the appropriate value into the 4 line buffer instead of updating the whole display buffer for every variable,
    or update the LCD location directly, but I would do the former, and write a complete screen every time.

  15. #15
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Does viv mean vivarium? Before you listen to me you should see how professional my setup is
    I like the way the LCD doesn’t have a backlight so I faked it with an LED.




  16. #16
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Nice Beardie -

    yes Viv is for vivarium, currently have a custom unit of three vivs, plus an incubator as my to royals have been locked several times over the past few months. Here's the incubator, and the existing controller, which is a bit neater than your set up - but hey if it works for you that's the main thing


  17. #17
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Well it did six yrs ago

    Can you post the main code that prints to LCD?

    There are a lot of ways to solve it.
    I think I only now properly understand the issue.

    Padding has already been suggested and is one good way.
    Using a word variable you could mean average quite a few
    temperature readings.

  18. #18
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    LOL - same time as I did mine - so you have no excuses

    I've messed around with the version where I was trying to get a single line for the data from each vivarium that's it's all over the place. So I've posted the previous version which displays the data for all four vivariums, 1 per line of the LCD

    Code:
    ;-----------------------------------------------------------------------------
    ; *****  MAIN PROGRAMMING LOOP *****
    ;-----------------------------------------------------------------------------
    
    Main:
    
    
    SetPoint1 = normtemp1
    SetPoint2 = normtemp2 
    SetPoint3 = normtemp3 
    SetPoint4 = normtemp4 
    
    gosub FlushBuffer:
    
    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
    
    gosub read_dht                                  ; Go and read the AM2302 sensor for humidity
    
    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
    
    FOR TempWD = 0 TO 1000
        IF RCIF=1 THEN GOSUB coms                   ; Check to see id PC application connected
        PAUSE 1
    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                                      ; display info on LCD
    
    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 
        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
        ENDIF
         
    ;   ---------------------------------------------------------------------------
    ;   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
        ELSE
        SetPoints[0]= normtemp[0]                   ; change the corresponding drop temperature to set point
        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
        ELSE
        SetPoints[1]= normtemp[1]                   ; change the corresponding drop temperature to set point
        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
        ELSE
        SetPoints[2]= normtemp[2]                   ; change the corresponding drop temperature to set point
        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
        ELSE
        Setpoints[3]= normtemp[3]                   ; change the corresponding drop temperature to set point
        ENDIF   
                                     
    for x = 0 to 3
        LOOKUP x,[5,9,13,17],Bvar       ; Find location  [$80,$C0,$89,$C9]
        LCDOUT $fe,$80,"Set"
        LCDOUT $fe,$80+Bvar,#setpoints(x)dig 2,#setpoints(x)dig 1        ; print to LCD
        LCDOUT $DF         
    next x
    ;-----------------------------------------------------------------------------
    ; *****  MAIN PROGRAMMING LOOP END *****
    ;-----------------------------------------------------------------------------
    
     
    GOTO Main                                
    
    ;------------------------------------------------------------------------------
    Then this is the subroutine which displays the data on the LCD

    Code:
    ;----[Display temperatures, time and set points on LCD]------------------------
    ShowLCD:
    
        LCDOUT $FE,$C0,"Hot"
        LCDOUT $FE,$C0+5        ; print to LCD     
        TempWD = TempC : GOSUB TempToLCD                ; display TempC
        LCDOUT $DF                                      ; deg symbol
           
    I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCYear,RTCCtrl]  ; read DS1307 chip
    If RTCHour.6=1 then
    			
    CounterA=(RTCHour>>4)&$01                           ' Work-Out 12 or 24 hour Display for Hours
    else
    CounterA=(RTCHour>>4)&$03
    endif
    CounterA=CounterA*10+(RTCHour&$0F)                  ' Display Hours appropriately for 12 or 24 hour Mode 
    
    '********* to display time on LCD *****************  Commented out as there is no room on the LCD
    'If RTCHour.6=1 then			
    'LCDOut $FE,$C0+9,"Time ",#CounterA 
    'else
    'LCDOut $FE,$C0+9,"Time ",#CounterA Dig 1,#CounterA Dig 0
    'endif
    'LCDOut ":",#(RTCMin>>4)&$0F,#RTCMin&$0F
    '***************************************************
    
    timeH=(RTCHour>>4)                                  'convert the BCD format of the hours register and store in variable timeH
    timeH=(timeH &$03)*10
    timeH=timeH+(RTCHour&$0F)
    
    timeM=(RTCMin>>4)
    timeM=(timeM &$07)*10
    timeM=timeM+(RTCMin&$0F)                         'convert the BCD format of the mins register and store in variable timeM
    
    ;----[ Time matching - Nighttime temp drop routine ]----- 
    
    CheckTimes2:
    TimeCmpFlags = 0  ; clear flags first 
    
         ; if the Start and Stop times are the same, then Always OFF 
      if (StartHour[fn]=StopHour[fn]) AND _       
         (StartMin[fn]=StopMin[fn]) then AlwaysOFF2                      
    
         ; is it past the Start time?
      if (timeH>StartHour[fn]) OR _              
         (timeH=StartHour[fn] AND timeM >= StartMin[fn])then PastStart2=1
    
         ; is it past the Stop time?
      if (timeH>StopHour[fn]) OR _                
         (timeH=StopHour[fn] AND timeM >= StopMin[fn])then PastStop2=1
    
         ; does the period end the following day?
      if (StopHour[fn]< StartHour[fn]) OR _           
         (StopHour[fn]=StartHour[fn] AND StopMin[fn] < StartMin[fn]) then NextDay2=1
    
      if !NextDay2 then                               ; same day, use AND
          if PastStart2 AND !PastStop2 then ProgON2 = 1
      else                                           ; next day, use OR
          IF PastStart2 OR !PastStop2 then ProgON2 = 1
      endif
        
    AlwaysOFF2:
    return
    
    CheckTimes:
    TimeCmpFlags = 0  ; clear flags first
    
         ; if the Start and Stop times are the same, then Always OFF 
      if (lightsetHR[fn]=lightoffHR[fn]) AND _       
         (lightsetMN[fn]=lightoffMN[fn]) then AlwaysOFF                       
    
       ; is it past the Start time?
      if (timeH>lightsetHR[fn]) OR _              
         (timeH=lightsetHR[fn] AND timeM >= lightsetMN[fn])then PastStart=1
    
         ; is it past the Stop time?
      if (timeH>lightoffHR[fn]) OR _                
         (timeH=lightoffHR[fn] AND timeM >= lightoffMN[fn])then PastStop=1
    
         ; does the period end the following day?
      if (lightoffHR[fn]< lightsetHR[fn]) OR _           
         (lightoffHR[fn]=lightsetHR[fn] AND lightoffMN[fn] < lightsetMN[fn]) then NextDay=1
    
      if !NextDay then                               ; same day, use AND
          if PastStart AND !PastStop then ProgON = 1
      else                                           ; next day, use OR
          IF PastStart OR !PastStop then ProgON = 1
      endif
      
    AlwaysOFF:
    RETURN
    The two subroutines that deal with displaying the non presence of a 18B20 and read the AM2302

    Code:
    ;----[Display Sensor Error]-------------------------------------------------
    
    ShowError:
        LOOKUP pid_Channel,[5,9,13,17],Bvar               ; Find location;LOOKUP pid_Channel,[$83,$C3,$8B,$CB],Bvar [$80,$C0,$89,$C9]             
        LCDOUT $FE,$C0+Bvar,"N/C"           ; print to LCD ;LCDOUT $FE,Bvar," N/C    "                             
    RETURN
    
    ;----[Read humidity sensor]-------------------------------------------------
    
    read_dht:
    
    for loopcount = 0 to 3
        AM2302_Sensor_Num = loopcount+1
        gosub AM2302_Read
        LOOKUP loopcount,[5,9,13,17],Bvar       ; Find location  [$80,$C0,$89,$C9]
        LCDOUT $fe,$94,"Hum"
        LCDOUT $fe,$94+Bvar,dec AM2302_Hum/10,"% "' ".",dec AM2302_Hum//10,"% "         ; print to LCD    
        LCDOUT $fe,$D4,"Cold"
        LCDOUT $fe,$D4+Bvar,dec AM2302_Temp/10
        lcdout $DF
    next loopcount
       
    Return
    I hope that's enough for you to be going on with. ?

    Malc

  19. #19
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    You were saying if the program is allowed to go it’s hardest the temps change so fast you can’t read them,
    and your mock display only shows integer values which means the sensor moves back & forth several entire degrees each reading?

    If you let it go with no unneeded pauses, how many times would you guess the LCD is updated in one second?

    To clarify, you check for death temperatures, and print to LCD straight after, so the temps are degrees C by that time?
    That would be a good place for a FIFO buffer to store several previous values for averaging.

    From what I understand the problem, if you had no deliberate pause statements,
    everything would be great if the temp sensors didn’t give values all over the place
    because even thought the LCD updated fast the temps wouldn’t change much?

  20. #20
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    I discovered what was happening. As I only have one DS18B20 used for testing, the code was running the fore next loop to read the sensors and then printing them to the screen, but as the last three were not fitted it would jump out to the sensor error and display N/C for the for vivs 2, 3 and 4. I also removed the decimal for the temps and humidity simply to make things fit on the display.

    In trying to get the LCD to display the data for viv 1 for a few seconds, then viv 2 etc I tried using case statements, and the Cvar as a counter. The idea being if the counter is between 1 and 10 it jumps to a case statement which displays data for viv 1, if it's between 11 and 20 viv 2 etc. Again that didn't work because it had to be a sub routine in order to jump back and test for sensor error.

    The problem I have in using pause statements is in order to maintain stable temperatures in the vivs, the original code was designed to run through the reading of the sensors, calculating the PID (which was based on real life testing to calibrate the values) and drive the heaters. This works well and I would like to retain that precision, and any pause statements end up delaying the read, display and update process which means the precision is lost.

    The DS18B20 and AM2302 are precise to within 0.5c so the data is stable. As we are only talking + or minus a degree or so being the difference between the PID pulsing correctly or being fully on or completely off, any delay between the read sensor cycle could mean that the heater stays on longer and the temperature overshoots. The result would be that the swing between pulses would be similar to a standard on/off thermostat rather than a pulse proportional one.

  21. #21
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Even basic logic doesn't seem to work !!!

    I have set Cvar as byte and to run from 1 to 40. I then have the following

    Code:
    if Cvar => 1 or Cvar =< 10 then 
        viv=0
        goto showLCD1
    endif
    
    if Cvar =>11 or Cvar =< 20 then 
        viv=1
        goto showLCD2
    Endif
    Then the following for the display

    Code:
    ShowLCD1:
    
        LCDOUT $FE,$C0,"Viv",DEC1 viv +1," "         ; print to LCD
        LCDOUT $fe,$94,dec cVar   
    goto check
        
    ShowLCD2:
    
        LCDOUT $FE,$C0,"Viv",DEC1 viv+1," "         ; print to LCD
        LCDOUT $fe,$94,dec cVar 
    goto check
    So the LCD should in theory display VIV1 and then when Cvar =11 VIV2. It doesn't !!!

    Cvar is counting up at around 1 second intervals, and there is an If Cvar >20 then Cvar =1 so it loops round, which it does. So why the hell does it ignore the IF THEN statement to match the condition and goto the correct LCD display section ! - Sometimes I hate PBP !!!!

    EDIT... seems it likes if Cvar =>11 and Cvar =< 20 then... rather than OR
    Last edited by Scampy; - 3rd May 2015 at 14:29.

  22. #22
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Malcolm,

    Try using () in the tests. Ie. "If (Cvar => 11) And (Cvar <= 20) then"
    Regards,
    TABSoft

  23. #23
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Thanks for the tip.

    I have it working to a degree, and test so far are encouraging

    Here's the main code

    Code:
    ;-----------------------------------------------------------------------------
    ; *****  MAIN PROGRAMMING LOOP *****
    ;-----------------------------------------------------------------------------
     
    Main:
    
    if Cvar >12 then Cvar=0
    
    LCDOUT $fe,$80+5,"Hot",$fe,$80+10,"Cool",$fe,$80+16,"Hum"
    
    Cvar=Cvar+1
    
    SetPoint1 = normtemp1
    SetPoint2 = normtemp2 
    SetPoint3 = normtemp3 
    SetPoint4 = normtemp4 
    
    gosub FlushBuffer:
    
    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
    
    gosub displaytime                               ; update the clock and display the time
    
    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
    
    FOR TempWD = 0 TO 1000
        IF RCIF=1 THEN GOSUB coms                   ; Check to see id PC application connected
        PAUSE 1
    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
    
     
    ELSE
        SensorError:
               HeaterDrives(pid_Channel) = 0            ; turn off heater if sensor's bad
               SensorActive(pid_Channel) = 0
            ENDIF 
    NEXT pid_Channel        
            
    If Cvar >=1 and Cvar <=3 then GOto  ShowLCD1
    If Cvar >=4 and Cvar <=6 then GOto  ShowLCD2                                      ; display info on LCD
    If Cvar >=7 and Cvar <=9 then GOto  ShowLCD3
    If Cvar >=10 and Cvar <=12 then GOto  ShowLCD4
    
    check:  
    
    
    ;   ---------------------------------------------------------------------------
    ;   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 
        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
        ENDIF
         
    ;   ---------------------------------------------------------------------------
    ;   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
        ELSE
        SetPoints[0]= normtemp[0]                   ; change the corresponding drop temperature to set point
        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
        ELSE
        SetPoints[1]= normtemp[1]                   ; change the corresponding drop temperature to set point
        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
        ELSE
        SetPoints[2]= normtemp[2]                   ; change the corresponding drop temperature to set point
        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
        ELSE
        Setpoints[3]= normtemp[3]                   ; change the corresponding drop temperature to set point
        ENDIF   
    
    ;-----------------------------------------------------------------------------
    ; *****  MAIN PROGRAMMING LOOP END *****
    
    GOTO Main                                
    ;-----------------------------------------------------------------------------
    And here are the four LDC routines

    Code:
    ShowLCD1:
       Pid_channel=0
        LCDOUT $FE,$C0,"Viv",DEC1 Pid_channel+1," "         ; print to LCD
        TempC = Temperatures(pid_Channel)
        gosub read_dht 
        LCDOUT $FE,$C0+5 
        TempWD = TempC : GOSUB TempToLCD                ; display TempC
        LCDOUT $DF
        if SensorActive(pid_Channel) = 0 then lcdout $FE,$C0+5,"N/C"
        LCDOUT $fe,$94,dec Cvar 
    goto check
        
    ShowLCD2:
        Pid_channel=1
        LCDOUT $FE,$C0,"Viv",DEC1 Pid_channel+1," "         ; print to LCD
        TempC = Temperatures(pid_Channel)
        gosub read_dht 
        LCDOUT $FE,$C0+5 
        TempWD = TempC : GOSUB TempToLCD                ; display TempC
        LCDOUT $DF
        if SensorActive(pid_Channel) = 0 then lcdout $FE,$C0+5,"N/C"
        LCDOUT $fe,$94,dec Cvar
    goto check
        
    ShowLCD3:
        Pid_channel=2
        LCDOUT $FE,$C0,"Viv",DEC1 Pid_channel+1," "         ; print to LCD
        TempC = Temperatures(pid_Channel)
        gosub read_dht 
        LCDOUT $FE,$C0+5 
        TempWD = TempC : GOSUB TempToLCD                ; display TempC
        LCDOUT $DF
        if SensorActive(pid_Channel) = 0 then lcdout $FE,$C0+5,"N/C"
        LCDOUT $fe,$94,dec Cvar
    goto check
        
    ShowLCD4:
        Pid_channel=3
        LCDOUT $FE,$C0,"Viv",DEC1 Pid_channel+1," "         ; print to LCD
        TempC = Temperatures(pid_Channel)
        gosub read_dht 
        LCDOUT $FE,$C0+5 
        TempWD = TempC : GOSUB TempToLCD                ; display TempC
        LCDOUT $DF
        if SensorActive(pid_Channel) = 0 then lcdout $FE,$C0+5,"N/C"
        LCDOUT $fe,$94,dec Cvar
    goto check
    OK it may be crude, have lots of duplication but it achieves the result I'm after. The good news is that whilst it's cycling around the loop and displaying values for say viv3, the PID still works fine for Viv1. I might then tidy the layout up a bit so I can get the decimals in for the temperatures, but I'm not that bothered about the decimal points - I mean I'm sure my pythons and boa don't care if it's 32.9 or 33.0 C

  24. #24
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,519


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Hi,
    Even basic logic doesn't seem to work !!!
    Code:
    if Cvar => 1 or Cvar =< 10 then
    Can you tell me when the above is NOT evalutated true?
    When CVar is 0? When CVar is 8? When CVar is 11? When CVar is 25?

    EDIT... seems it likes if Cvar =>11 and Cvar =< 20 then... rather than OR
    I think YOU like it better with AND rather than OR. The compiler and the PIC likes either one equally well - and it works as expected, just not the way YOU want it to.....

    /Henrik.

  25. #25
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    You realise a zero value skips that whole block right?
    Speed probably is no issue here, but you’re making it work hard!
    It would matter if you’re watching a tilt sensor on a moving part or something like that.

    Code:
    If Cvar < 13 then
    If Cvar > 9 then ShowLCD4
    If Cvar > 6 then ShowLCD3
    If Cvar > 3 then ShowLCD2
    If Cvar != 0 then ShowLCD1
    endif // Cvar < 13

  26. #26
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    The only difference between the ShowLCDx commands is x constant?
    Code:
    Pid_channel=x
    I had a play with every consideration for the micro, and no consideration for the Human

    Code:
    i var byte; bonus loop counter
    x var byte; initial value to subtract 3 from
    
    
    x = 9
    If Cvar < 13 then
    for i = 3 to 0 step -1
    If Cvar > x then
    Pid_channel=i
    LCDOUT $FE,$C0,"Viv",DEC1 Pid_channel+1," "
    TempC = Temperatures(pid_Channel)
    gosub read_dht 
    LCDOUT $FE,$C0+5 
    TempWD = TempC
    GOSUB TempToLCD
    ; if nothing else calls TempToLCD it can go straight in here
    LCDOUT $DF
    if SensorActive(pid_Channel) = 0 then lcdout $FE,$C0+5,"N/C"
    LCDOUT $fe,$94,dec Cvar
    goto check
    ; I don’t see check in what you’ve posted
    ; but you can drop it straight here if nothing else goes there
    endif
    x = x - 3
    next i
    endif;

  27. #27
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Art,

    Thanks for the suggestion.... like I said my original code was bulky and crude, but worked, but I know it could be made simpler, but after 10 hrs of coding I think my brain just gave up

  28. #28
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    It was really just a play... It's not simpler for the Human to read six months later.
    Wherever there's not likely to be a performance problem,
    and thinking of the possibility of having to adjust those constants later,
    I'd avoid the above code like the plague!
    but would personally go for the smaller block directly above that.

  29. #29
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Quote Originally Posted by Art View Post
    It's not simpler for the Human to read six months later.
    Wherever there's not likely to be a performance problem,
    and thinking of the possibility of having to adjust those constants later,
    I'd avoid the above code like the plague!
    but would personally go for the smaller block directly above that.
    That's the thing, I can see the need for tight compact code in a commercial arena where costs etc matter, but for home projects I like things more simpler to follow. As mentioned, it might not be the best way, but if it gets the end result I'm after, and there is little impact on speed then I'm happy. If it means I have to throw an overkill PIC at it to maintain the performance, or to have enough memory to hold my bloated code then so be it

  30. #30
    Join Date
    Oct 2014
    Location
    Lagos Nigeria
    Posts
    10


    Did you find this post helpful? Yes | No

    Post Re: Delay without using pause

    hi all, i have been scratching my head thinking of how to avoid pbp pause in my routines bcos the command;

    1) seems to change system registers (correct me if i'm wrong),
    2) is the main cause of many problems i have had with ISR's in the past
    3) is blocking, i dont want to waste cycles

    i have been trying to make sense of the previous posts in this thread. pls can someone help with a robust snippet.

    i think of a delay based on an interrupt timer that serves as the heartbeat with a resolution of say 1us. in the isr, multiple regs (each loaded when needed from various routines) are decremented to act as counters, when anyone hits zero a corresponding flag is set etc...

    am i making any sense? i think this is simillar to how some rtos work. is there a better way?

  31. #31
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,519


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Hi,

    > 1) seems to change system registers (correct me if i'm wrong),

    What do you mean with system registers? If you mean the PBP system variables then yes, it has to use something to keep track of time - in the same way as you suggest in your method and the compiler uses its internal variables for that. But I don't really see the problem, are you using the system variables in your code?


    > 2) is the main cause of many problems i have had with ISR's in the past

    How are you "doing" your interrupts and what problems are we talking about?
    If you're spending a lot of cycles in your ISR then a PAUSE in the main program won't be accurate because the main program isn't really executing at the desired speed due to the interrupt "stealing" time away from it. If you're using a PAUSE in the ISR then of course the main program will "halt" during that period.

    > 3) is blocking, i dont want to waste cycles

    It is. Just like all PBP commands.

    > i think of a delay based on an interrupt timer that serves as the heartbeat with a resolution of say 1us. in the isr, multiple regs (each loaded when needed from various routines) are decremented to act as counters, when anyone hits zero a corresponding flag is set etc...

    The overall idea is doable but forget 1us resolution. Even at 64MHz there would only be 16 instructions between each interrupt - perhaps you could manage ONE timer if written in tight ASM but then there wouldn't be much time left for anything else. Depending on the oscillator speed and the number of timers you want to maintain 100us or 1ms might be more appropriate, 10ms certainly doable.

    /Henrik.

  32. #32
    Join Date
    Oct 2014
    Location
    Lagos Nigeria
    Posts
    10


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Thank so much Henrick,

    i am so glad that someone understood what i was trying to say. Elated to hear that it is doable even in the ms range.

    But to answer some of your questions:

    1) By system registers i was thinking that pbp must setup some timers for counting during pause. And this might affect my timers usage.

    2) how i am doing my interrupts. I use DEFINE INTHAND _MYISR1

    Then after saving contexts in asm i do an endasm and gosub a pbp routine. I don't know how to upload a code yet. I would have shown you.

    But at any rate, the results are usually erratic and it seems as if the code is making jumps to the wrong places. On certain ocassions i found out that if i use a timer interupt to delay something rather than pause, the system will work better.

    3) Now since pause is blocking, "just like all pbp commands" (never thought if this) if i can get a way to rig up a macro that i can use such as

    @ myPAUSE msec,SUBNAME

    where msec is the no of ms to delay and SUBNAME is used to keep track of the specific registers to use (i.e the sub that is calling for a delay).

    My problem is: can i call a pbp routine inside asm macro.

    I like to use pbp if statements to in a state-machine-like manner, makes programming more structured. If i can have another type of PAUSE that will simply load a reg and move... i think this will make code more efficient

    Thanks so much.

  33. #33
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,519


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Hi,
    1) By system registers i was thinking that pbp must setup some timers for counting during pause. And this might affect my timers usage.
    No, not at all. The PAUSE and PAUSEUS commands does not use any hardware peripherals (ie timers) on the PIC, it's done in software which is why it's blocking. Basically it sits in a loop, counting cycles.

    2) how i am doing my interrupts. I use DEFINE INTHAND _MYISR1

    Then after saving contexts in asm i do an endasm and gosub a pbp routine. I don't know how to upload a code yet. I would have shown you.

    But at any rate, the results are usually erratic and it seems as if the code is making jumps to the wrong places. On certain ocassions i found out that if i use a timer interupt to delay something rather than pause, the system will work better.
    OK, so there's your problem I think. If you use ASM for your interrupt service routines you can (generally) not use PBP code within the ISR (using a GOSUB does not matter). Why? Because PBP uses its internal system variable for its various commands, if your main program is in the middle of comlex math operation it stores intermediate results in its internal variables and along comes an interrupt. If you then place PBP commands in the ISR chanses are that code wants to use the same internal system variables which will the corrupt the complex math operation that the main program was in the middle of calculating.

    If you want to use PBP within your interrupt servie routine you need to either:

    A) Use ON INTERRUPT - with its drawbacks.
    B) Write the code for the handler, compile and assemble it. Examine the .lst file and determine which of the system variables are being used and then add code to save and restore those registers on ISR entry/exit.
    C) Use Darrel Taylors Instant Interrupt routines. What it does is save and restore ALL PBP system variables on entry/exit. It comes at a cost of interrupt latency (it takes time to save all the registers).

    I've used all three of the above aproaches. By far, option C is "the best". I very very rarely use A. B I've used for stuff where the ISR is simple and I've really needed the speed. Just remember that with option B you need to be very careful, any change to ISR and you need to re-examin the generated code to see if any new PBP system variables are beinng used.

    3) Now since pause is blocking, "just like all pbp commands" (never thought if this) if i can get a way to rig up a macro that i can use such as

    @ myPAUSE msec,SUBNAME

    where msec is the no of ms to delay and SUBNAME is used to keep track of the specific registers to use (i.e the sub that is calling for a delay).

    My problem is: can i call a pbp routine inside asm macro.
    I don't quite follow you with the macro thing (I truly suck at the ASM stuff) but if you mean calling a PBP subroutine from within an ASM interrupt service routine then generally NO, absolutely not.

    /Henrik.

  34. #34
    Join Date
    Oct 2014
    Location
    Lagos Nigeria
    Posts
    10


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    THIS IS AN EYE OPENER.

    Thanks so much for explaining. Now i understand why it didnt work. I have learn a great deal from your post.

    Thanks for the tips, i think option B is what I will go for. Its worth the effort.
    But how can i determine from the .lst, the system variables in use.

    I have used DT Interrupts and they work well (apart from inadvertenly enabling unwanted interrupts sometimes). But to avoid saving every variable all the time and save time is my goal. I need to have more speed.

    Lastly, my question about macros. Can i do something like this;

    Asm
    MACRO myPAUSE msec,subID
    movlw msec
    movwf delay1
    movlw subID
    movwf KeepTrack
    Endasm

    ; then concote any kind of PBP code here

    @ Endm

  35. #35
    Join Date
    May 2013
    Location
    australia
    Posts
    2,386


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    I modified dt's Elapsed_INT-18.bas file so I could use the "Ticks" as a millisecond counter function (like millis() in arduino C ) it rolls over every 65 seconds but using unsigned integer subtracts its very handy for short interval timing and has no blocking issues . the fairly low interrupt rate minimises effect on normal pgm throughput.

    I'm sure Elapsed_INT-14.bas is easily adapted to match , but I have no copy of it




    Code:
    '***************************************************************************
    '*  Name    : Elapsed_INT-18.bas                                           *
    '*  Author  : Darrel Taylor                                                *
    '*  Date    : JUL 11, 2006 : 7/11/2010                                     *
    '*  Version : modified to use ticks useable  as a millisecond   counter                                                      *
    '*  Notes   : Must have DT_INTS-18.bas loaded first                        *
    '*   ver 1.2: Now works at any OSC frequency without using the prescaler   *
    '***************************************************************************
    DISABLE DEBUG
    
    ; syntax =     Handler  IntSource,        Label, Type, ResetFlag?
    DEFINE  Elapsed_Handler  TMR1_INT,  _ClockCount,  asm,  yes
    ; the above define can be used in the INT_LIST macro, if desired (optional)
    
    Ticks            VAR word   ; Counts timer Overflows
    T1Post           VAR BYTE   ; Timer1 postscaler
    Seconds          VAR BYTE
    Minutes          VAR BYTE
    Hours            VAR BYTE
    Days             VAR WORD
    
    SecondsChanged   VAR BIT    ; idicates that the value has changed
    MinutesChanged   VAR BIT
    HoursChanged     VAR BIT
    DaysChanged      VAR BIT
    
    GOSUB ResetTime             ; initialize the Elapsed Timer
    
    Goto OverElapsed            ; skip over the routines
    
    ' -------------- calc timer reload Constants -------------------------------
    ASM
    T1PS = 1                             ; start with 1:1 postscaler
    TimerConst = ((OSC*1000000)/4/100)   ; how many timer ticks will it take
      while TimerConst > 65400           ; if it's more than the timer can count
    T1PS = T1PS * 2                      ;   double the postscaler
    TimerConst = TimerConst / 2          ;   halve the count
      endw
    TimerConst = 65536 - TimerConst + 6  ; final reload value   !!!!! was 8 but clk runs fast
      
      
    ; -----------------  ADD TimerConst to TMR1H:TMR1L -------------------------
    ADD2_TIMER   macro
        BCF     T1CON,TMR1ON, 0       ;  1 Turn off timer
        MOVLW   LOW(TimerConst)       ;  1
        ADDWF   TMR1L,F, 0            ;  1    
        BTFSC   STATUS,C              ;  1/2
        INCF    TMR1H,F, 0            ;  1
        MOVLW   HIGH(TimerConst)      ;  1
        ADDWF   TMR1H,F, 0            ;  1
        endm
    
    ; -----------------  ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
    RELOAD_TIMER  macro
        ADD2_TIMER
        BSF     T1CON,TMR1ON, 0       ;  1   Turn TIMER1 back on  (8 cycles)
        endm
    
    ; -----------------  Load TimerConst into TMR1H:TMR1L ----------------------
    LOAD_TIMER  macro
        MOVE?CT  0, T1CON,TMR1ON
        MOVE?CB  0, TMR1L
        MOVE?CB  0, TMR1H
        ADD2_TIMER
        endm
    ENDASM
    
    ' ------[ This is the Interrupt Handler ]-----------------------------------
    T1PS  CON EXT
    ClockCount:
    @ RELOAD_TIMER                   ; Reload TIMER1
    
        T1Post = T1Post + 1
       
        IF T1Post = T1PS THEN
      
         T1Post = 0
        
        Ticks = Ticks + 1
          
           IF Ticks //100 ==0 THEN
          
    '          Ticks = 0           Seconds = Seconds + 1
               SecondsChanged = 1
               IF Seconds = 60 THEN
                  Seconds = 0
                  Minutes = Minutes + 1
                  MinutesChanged = 1
               ENDIF
               IF Minutes = 60 THEN
                  Minutes = 0
                  Hours = Hours + 1
                  HoursChanged = 1
               ENDIF
               IF Hours = 24 THEN
                  Days = Days + 1
                  DaysChanged = 1
                  Hours = 0
               ENDIF
           ENDIF
        ENDIF
    @ INT_RETURN                     ; Restore context and return from interrupt
    
    '-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------
    
    StartTimer:
        T1CON = 1                    ; 1:1, FOSC4, TMR1ON
    RETURN
    
    ; --------------------------------------------------------------------------
    StopTimer:
        T1CON.0 = 0                  ; Turn OFF Timer1
    RETURN
    
    ; --------------------------------------------------------------------------
    BitSave  VAR  BIT
    
    ResetTime:
        BitSave = T1CON.0            ; Save TMR1ON bit
    @   LOAD_TIMER                   ; Load TimerConst
        T1CON.0 = BitSave            ; Restore TMR1ON bit
        T1Post = 0                   ; clear the postscaler
        Ticks = 0
        Seconds = 0
        Minutes = 0
        Hours = 0
        Days = 0
        SecondsChanged = 1           ; indicate everything has changed
        MinutesChanged = 1           ; so that 00:00:00 is processed
        HoursChanged = 1
        DaysChanged = 1
    RETURN
    
    
    OverElapsed:
    ENABLE DEBUG

  36. #36
    Join Date
    May 2013
    Location
    australia
    Posts
    2,386


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Lastly, my question about macros. Can i do something like this;

    Asm
    MACRO myPAUSE msec,subID
    movlw msec
    movwf delay1
    movlw subID
    movwf KeepTrack
    Endasm

    ; then concote any kind of PBP code here

    @ Endm
    no

    macro is a assembler feature and will not accept pbp code.
    pbp code needs to be compiled and then assembled

    post some code and explain what you are trying to achieve

  37. #37
    Join Date
    Oct 2014
    Location
    Lagos Nigeria
    Posts
    10


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    THANKS TO YOU ALL FOR TRYING TO HELP.

    I have thrown together some wobbly code to try and explain what i'm trying to do.

    I know it might not be the best way, but i can't seem to wrap my head around the whole idea. I just want to be able to use pause in a way that I won't sit and wait for the time to elapse.

    in the mainloop here, i have 4 blocks (which could be doing many different things aside from toggling pins). Each block has a pause somewhere set by the value loaded in DELAYREGx

    Then in the ISR INTERUPTING EVERY 1ms;

    MYISR1:
    IF DELAYREG1>0 THEN
    DELAYREG1=DELAYREG1-1
    IF DELAYREG1=0 THEN
    DELAY1flag=1
    ENDIF
    ENDIF

    IF DELAYREG2>0 THEN
    DELAYREG2=DELAYREG2-1
    IF DELAYREG2=0 THEN
    DELAY2flag=1
    ENDIF
    ENDIF

    IF DELAYREG3>0 THEN
    DELAYREG3=DELAYREG3-1
    IF DELAYREG3=0 THEN
    DELAY3flag=1
    ENDIF
    ENDIF

    IF DELAYREG4>0 THEN
    DELAYREG4=DELAYREG4-1
    IF DELAYREG4=0 THEN
    DELAY4flag=1
    ENDIF
    ENDIF

    ; END OF ISR
    ;

    Then in the mainloop,

    MAINLOOP:

    BLOCK0:

    IF LED0_UPDATE THEN
    HIGH PORTB.0 ;IS IT TIME TO UPDATE LED0?
    @ myPAUSE 1000,1 ;MAKE PORTB.0 HIGH FOR 1000 ms USING DELAYREG1
    LED0_UPDATE=0 ;BUT DON'T WAIT FOR THE TIME TO ELAPSE
    GOTO BLOCK1
    ENDIF

    IF DELAY1flag THEN ;WILL BE SET IN THE ISR ATFTER 1 SECOND
    LOW PORTB.0 ;HAVE WE COME TO THE END OF 1 SECOND?
    ENDIF ;END OF myPAUSE


    BLOCK1:

    IF LED1_UPDATE THEN
    HIGH PORTB.1 ;IS IT TIME TO UPDATE LED1
    @ myPAUSE 4000,2 ;MAKE PORTB.1 HIGH FOR 4000 ms USING DELAYREG2
    LED1_UPDATE=0 ;BUT DON'T WAIT FOR THE TIME TO ELAPSE
    GOTO BLOCK2
    ENDIF

    IF DELAY2flag THEN ;WILL BE SET IN THE ISR ATFTER 4 SECOND
    LOW PORTB.1 ;HAVE WE COME TO THE END OF 4 SECOND?
    ENDIF ;END OF myPAUSE

    BLOCK2:
    IF LED2_UPDATE THEN
    HIGH PORTB.2 ;IS IT TIME TO UPDATE LED2
    @ myPAUSE 2000,3 ;MAKE PORTB.2 HIGH FOR 2000 ms USING DELAYREG3
    LED2_UPDATE=0 ;BUT DON'T WAIT FOR THE TIME TO ELAPSE
    GOTO BLOCK3
    ENDIF

    IF DELAY3flag THEN ;WILL BE SET IN THE ISR ATFTER 2 SECOND
    LOW PORTB.2 ;HAVE WE COME TO THE END OF 2 SECOND?
    ENDIF ;END OF myPAUSE

    BLOCK3:
    IF LED3_UPDATE THEN
    HIGH PORTB.3 ;IS IT TIME TO UPDATE LED3
    @ myPAUSE 400,4 ;MAKE PORTB.3 HIGH FOR 400 ms USING DELAYREG4
    LED3_UPDATE=0 ;BUT DON'T WAIT FOR THE TIME TO ELAPSE
    GOTO BLOCK0
    ENDIF

    IF DELAY1flag THEN ;WILL BE SET IN THE ISR ATFTER 0.4 SECOND
    LOW PORTB.3 ;HAVE WE COME TO THE END OF 0.4 SECOND?
    ENDIF ;END OF myPAUSE

    GOTO MAINLOOP

    Here is what i mean by using pbp within ASM macro;

    ASM
    MACRO myPAUSE msec,subID
    movlw msec
    movwf delay_temp
    movlw subID
    movwf KeepTrack
    ENDASM

    SELECT CASE KeepTrack

    CASE 1
    DELAYREG1=delay_temp
    DELAY1flag=0

    CASE 2
    DELAYREG2=delay_temp
    DELAY2flag=0

    CASE 3
    DELAYREG3=delay_temp
    DELAY3flag=0

    CASE 4
    DELAYREG4=delay_temp
    DELAY4flag=0

    CASE ELSE

    @ NOP
    END SELECT

    @ ENDM

    I hope someone might understand and help me...

    thanks.

  38. #38
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Stanon1, I see where you are clearing: LED0_UPDATE=0 but where are you setting it to TRUE? I think you are on the right track but it could be made much more simplistic.
    Dave Purola,
    N8NTA
    EN82fn

  39. #39
    Join Date
    Oct 2014
    Location
    Lagos Nigeria
    Posts
    10


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    Exactly! It could be made simpler. That is the crux of the matter.

    You are right i didn't show where i am setting LED0_UPDATE. these flags themselves, at the right time based on certain parameters, are set by other isr running in parrallel with the heartbeat timer

    thanks for the reply

  40. #40


    Did you find this post helpful? Yes | No

    Default Re: Delay without using pause

    I can suggest a little different approach which I have used...... its similar to how operating systems work ... and since you are using interrupts, you already are doing most of the work...
    I will explain more unless your intent on proceeding with what you have been doing.
    don

Similar Threads

  1. Replies: 6
    Last Post: - 28th October 2014, 06:08
  2. Do I need a pause?
    By tazntex in forum Serial
    Replies: 21
    Last Post: - 29th August 2008, 04:32
  3. 1 us delay
    By Pedro in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 18th February 2006, 17:28
  4. Pause
    By blue in forum General
    Replies: 7
    Last Post: - 29th December 2005, 14:24
  5. pause 0.5
    By detail in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 27th June 2005, 11:32

Members who have read this thread : 3

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