Indicator for the PICaxe Utilisation % or Idle Time

AllyCat

Senior Member
Hi,

I've recently been developing a program to display the time and date on a bit-mapped (graphics) OLED display (SSD1306). To keep the program simple, every second I updated not only the displayed Time (and Temperature and Supply Voltage) but also the Date (around 40 characters in total), which seemed to work well. So I tried a "quick and dirty" (by my standards) software measurement of the amount of time that remained whilst the processor was waiting for the seconds value to increment. Here, I won't explain in detail again that the PICaxe "Timer 1" Special Function Register increments at a 1 MHz (1us period) rate, and overflows exactly every 20 ms. This program simply measures the time to the first Timer1 rollover that it encounters, then adds 2 (20 ms = 2%) for each subsequent rollover, until the "seconds" is found to have incremented.

The program code is only appropriate where a 1 second polling loop can be used, which can be controlled either by the PICaxe's internal "time" variable, or by an external Real Time Clock (specified by the "useRTC" Conditional Compilation variable). The first couple of values using the RTC may be spurious (I haven't bothered too much about initialisation) and then the reported value should settle to about 7% less than the remaining time (1000 ms minus the test delay). This lost period is the execution time of the program itself, particularly the SERTXD report which amounts to around 25 characters at ~2.5ms each (at 4800 baud) = ~60+ ms. However, when using the "time" variable, the report starts at almost 100% which gives interesting confirmation that the "time" variable does not take into account the period that elapses whilst the program is transmitting serial data (and other similar functions).

The reported value "bottoms out" at about 2 - 3%, but doesn't jump up again when the target 1 second cycle/polling time is exceeded. Of course the program cannot be tested on the Simulator (only with a "real" PICaxe) because it uses data from a SFR (which is not emulated). Operation at a SETFREQ of other than 4 MHz may be possible, but complicates the calculation.

Code:
#picaxe 08m2        ; And most others (only M2s if the "time" variable is used)
#no_data

symbol tempb = b1
symbol delay = w1                                ; Test Delay
symbol idle = b4
symbol index = b5
symbol secs = b6
symbol secsnow = b7
symbol TMR1H = $17                            ; SFR Timer 1 High byte (~256 us units)
; #define useRTC                                ; Uncomment if RTC is available and initialised

#ifdef useRTC
symbol RTCSADD = $D0                    ; For Maxim 3231 and some other RTCs ; $DE for MCP7940,
symbol I2CSPEED = i2cfast
    hi2csetup i2cmaster, RTCSADD,I2CSPEED,i2cbyte
#endif

do
    secsnow = secs
main:                    ; ** PUT THE FUNCTIONAL PART OF THE PROGRAM HERE **
    pause delay                                    ; Example Test delay
freetime:                                        ; Measure time to next RTC/time rollover 
    peeksfr TMR1H,tempb                        ; Present value in Timer1
    idle = 256 - tempb / 39 max 2            ; 10ms units before Timer1 rollover
    do while secs = secsnow
        do
            index = tempb
            peeksfr TMR1H,tempb
        loop while tempb > index
        idle = idle + 2 max 100                    ; Another 20ms has elapsed
#ifdef useRTC
        hi2cin 0 , (secs)                    ; If RTC chip is available (and initialised)
#else
        secs = time
#endif
    loop
    sertxd(#delay," ms delay; Idle = ",#idle,"%",cr,lf)       ; ~25 chars at ~2.5ms each (4800 baud) = ~60 ms (6%)
    delay = delay + 10       ; Milliseconds
loop

Cheers, Alan.
 
Last edited:

PhilHornby

Senior Member
... which gives interesting confirmation that the "time" variable does not take into account the period that elapses whilst the program is transmitting serial data (and other similar functions...).
I've used HSerout, with inverted output, as a replacement for sertxd, which overcomes this problem. It allows for higher baud rates without winding the clock frequency up and is slightly asynchronous (it completes while the last character is still being transmitted).
On the 08M2 and 14M2, it even uses the same pin as sertxd.
 

AllyCat

Senior Member
Hi,
.... it completes while the last character is still being transmitted.
Yes, that's an important proviso; using HSEROUT is not necessarily "much" faster than SEROUT or SERTXD. I think if you want to avoid "blocking" (and/or retain better time variable accuracy), you may still need to break the "text" into individual characters (or at least small groups) using a LOOKUP or similar method.

It struck me that the program above is also a "poor man's" (or perhaps easier to use) version of my program which measures execution times (since it uses the same principles). But it does need a RTC to be present (for better accuracy) although this use is largely "non-invasive" (e.g. it won't corrupt the time/date) if an I2C RTC does happen to be available.

So I've revised the program to use HSEROUT in place of SERTXD (for 08 and 14M2 chips only) and to also demonstrate that it is possible to mix HSEROUT and SERTXD even with these chips. Now, when using the "time" variable as reference, the "Idle time" tops out at about 95% , i.e. taking into account the period spent sending the "report" to the terminal emulator. But if you uncomment the "Hello World" text line, it will appear "invisible" to the measurement, if using the "time" variable as reference.

Code:
#picaxe 08m2                    ; Only for 08 and 14M2 if using HSEROUT to replace SERTXD
#no_data

symbol tempb = b1
symbol delay = w1                       ; Test Delay
symbol idle = b4
symbol index = b5
symbol secs = b6
symbol secsnow = b7
symbol TMR1H = $17                      ; SFR Timer 1 High byte (~256 us units)
; #define useRTC                        ; Uncomment if RTC is available and initialised

#ifdef useRTC
symbol RTCSADD = $D0                    ; For Maxim 3231 and some other RTCs ; $DE for MCP7940,
symbol I2CSPEED = i2cfast
    hi2csetup i2cmaster, RTCSADD,I2CSPEED,i2cbyte
#endif

do
    secsnow = secs
main:                    ; ** PUT THE FUNCTIONAL PART OF THE PROGRAM HERE **
;    pause delay                               ; Example Test delay (commented out)
    hsersetup OFF
;    sertxd("Hello World and more and more and more",cr,lf)        ; Optional Test Data
freetime:                                    ; Measure time to next RTC/time rollover 
    peeksfr TMR1H,tempb                      ; Present value in Timer1
    idle = 256 - tempb / 39 max 2            ; 10ms units before Timer1 rollover
    do while secs = secsnow
        do
            index = tempb
            peeksfr TMR1H,tempb
        loop while tempb > index
        idle = idle + 2 max 100              ; Another 20ms has elapsed
#ifdef useRTC
        hi2cin 0 , (secs)                    ; If RTC chip is available (and initialised)
#else
        secs = time
#endif
    loop
   hsersetup B4800_4 , 2
   hserout 0,(#delay," ms delay; Idle = ",#idle,"%",cr,lf)
    pause 5                                                ; Avoids a spurious character being received
;    delay = delay + 10     ; Milliseconds (commented out as delay is reported but not currently used)
loop
Cheers, Alan.
 
Top