0

I have developed multiple YouTube Raspberry PI clock projects since 2014 and all of them require iterative loops checking for the time (seconds) to change to update a digital, binary or roman numeral displays. With the latest Python 3.5.3 and Raspbian (NOPS 2.8.2) operating system, the iterative loop is no longer reliable. The same problem occurs on PI Zero-WIFI, 3B, and A+ platforms, but not PC.

I wrote a simple iterative program (listed below) that checks for the change in time (seconds), counts the number of loop iterations between seconds, and watches for intervals when there have been no iterations. No iterations indicate that Python is getting ready to completely hang and the mouse will become unreliable, later it will quit driving the HDMI display. I collected data the first time a zero-iteration count was detected between seconds. I average number of iterations and seconds of proper operation on each platform is as follows:

PLATFORM -- AVERAGE ITERATIONS/SECOND -- AVERAGE SECONDS TO FAILURE -- SAMPLES
MODEL A+ --           4,995           --          27,569            --   10
ZERO WIFI--           8,384           --          94,288            --   10
MODEL 3B --          47,199           --         208,571            --   10 
PC (I5)  --       1,000,000           --   DID NOT FAIL IN 12 DAYS  --    1

I tried using different power supplies, avoiding use of an external USB hub, and disconnecting WIFI from A+ without making any difference. Insured all platforms were using the current Raspbian downloaded from the website on 11/07/2018. No overclocking options were added.

I have pictures of the screen and unit being used at the time of failure.

# OPSYS-BUG# 11/02/18 Jim Roberts
# Import system subroutines.
from time import sleep         
import time

# CONSTANTS
lastsec=''                      # LAST SECOND PROCESSED
ct=1                            # LOOP COUNTS BETWEEN LCD REFRESH
ctot=0
cnbr=0
csec=0
mx=10
try:                            # ESTABLISH ERROR HANDLING FOR CTRL+C
    while mx>0:
        s=int(time.localtime().tm_sec)          # SECONDS
        if s != lastsec:
            lastsec=s    
            h=time.localtime().tm_hour          # HOURS
            m=time.localtime().tm_min           # MINUTES
            out=str(h+100)[1:3]+':'+str(m+100)[1:3]+':'+str(s+100)[1:3]  
            ctc=str(ct)         
            if ct < 10000:
                ctc = " " + ctc
            csec=csec+1    
            print(ctc + "   " + out+"   "+str(csec)+"   "+str(csec/(60*60*24)))
            cnbr=cnbr+1
            ctot=ctot+ct
            if ct==0:           # ERROR OCCURING - STOP AFTER MX OCCURENCES
                mx=mx-1     
                print("LOOPS- ", ctot, "COUNTS- ", cnbr, "AVG- ", ctot/cnbr)
                print("CYCLES             SINCE--START")       
                print("PER-SEC HH:MM:SS   SECS    DAYS") 
            ct=0
        else:
            ct=ct+1                 # BUMP LOOP CYCLE BETWEEN LCD REFRESHES
except KeyboardInterrupt:        
    GPIO.cleanup()                  # IF CTRL+C ENTERED, CLEAN UP AND EXIT
  • Please place your code in a code block. – CoderMike Jan 28 at 15:49
  • What else have you got running on your Pi's? In my experience Pi's usually start hanging when memory is low or being swapped to disk - which might suggest why the A+/Zero fail earlier. – CoderMike Jan 28 at 18:06
  • I have not consciously started any other tasks than the normal opening window, I started a Python window, then selected my test code and pressed RUN. Nothing else was started. – JTRoberts Jan 28 at 22:07
  • Before I developed the test program, all three platforms would totally cease to even paint the HDMI terminal, the mouse was unresponsive or extremely slow (if the screen was still visible). The program senses the platform is about ready to seize and ten detections of the error. When the program seizes, all platforms have very sluggish or no response or no HDMI screen status. Will be glad to all the SLEEP logic, but fear it is something deeper. – JTRoberts Jan 28 at 22:15
  • This is not a Pi specific question. Tight loops like this are poor practice. Linux includes utilities that efficiently execute code at intervals e.g watch -n 1 date will display time every second. You could replace date with a program which displays on your clock. – Milliways Jan 29 at 0:48
1

As there is no delay / sleep in the code, you are hitting the CPU & the underlying Linux systems pretty hard - I'd imagine that at some point some housekeeping is being triggered and I've seen SD Card writes tie up a Pi for a second or two.

Can you put a sleep(0.01) at the bottom of your while loop - this will reduce accuracy / response time by a 100th of a second but you can tune it accordingly.

Doing this reduces the CPU load on my iMac from ~95% to 1%.

I'm offering this as a pragmatic solution to test - the underlying details of what exactly is going on seems a bit academic - a loop to check the time for the next second to update a clock display running at a rate of 100 per second seems appropriate.

  • This was about to be my answer too - i don't like CPU intensive loops. On my Pi3B+ adding time.sleep(0.01) reduces overall CPU from approx 25% to approx 1% (presumably 1 core). – CoderMike Jan 28 at 18:21
  • 25% in top or similar is a core - in my answer the ~95% refers to a single core as Activity Monitor is happy to tell you that a process is using 533% which can be rather confusing! – Nick McCloud Jan 29 at 9:33
  • While I admit the program is a bit academic (developed for a high school class), after the program defects ten faults (no loop iterations occurring during during an elapsed second) it exits. The program is no longer active, yet all three platforms are no longer dependable. The mouse is extreme slow (if at all), mouse depresses are usually ignored, and sometimes the HDMI monitor is no longer painted. While I agree there are needs for house keeping, those routines should not leave the platform in a unreliable state after the program exits. – JTRoberts Jan 29 at 14:25
  • Anything that takes a hammering is going to take time to recover but with many other things, we wouldn't give it a hammering in the first place due to the consequent negative consequences. A loop such as this is not demonstrating good programming practise under any circumstances. If you want some other commands with negative outcomes, try 'sudo rm -rf /*' - just because you can type it, means to say you should. – Nick McCloud Jan 29 at 19:45
  • 1) First, I grant tight loop if not great coding, but you have to start somewhere. Putting that aside. 2) I have been working on this code for educational purposes for several years. It used to not cause the operating system to crash, it does now. 3) Operating systems are built to recover from some of the worst programmers. 4) If a program ends, there should not be permanent impairment to the operating system being able to start someone thing else. 5) How to I escalate this to someone who needs to be aware of such a problem. It will affect others interested in industrial use dependability. – JTRoberts Jan 29 at 22:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.