1

I'm using a Raspberry pi model B 512MB with 3 HC-SR04 sonarsensors. I want the program to run for a couple of weeks none stop. I am doing it in three separate python-scripts. Every python-script is generating a csv-file with the data in it. I have made a script in /etc/init.d/ so the scripts will be starting when the raspberry pi boots. My problem is that after a few hours the scripts stop working. I can see the processes are still alive through the command: "ps aux". Here the process have a "R" in the STAT column.

Any idea why the scripts stop working? I have tried to log all exceptions with a try/except-loop, and the use of the library logging but it doesn't show anything.

I suspect that there is some Raspberry Pi configuration that i need to do to keep it running "forever" but i don't know.

EDIT: I have added my code for one of the sonarsensors below.

AfstandsmaalerX.py:

#!/usr/bin/python
import sys
import logging
import RPi.GPIO as GPIO                    #Import GPIO library
import time                                #Import time library
import shutil
import os
import fcntl, socket, struct
from os import path, mkdir
import subprocess
GPIO.setmode(GPIO.BCM)                     #Set GPIO pin numbering 

def getHwAddr(ifname):
   s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))
   return ':'.join(['%02x' % ord(char) for char in info[18:24]])

def checkDirectory(thePath):
   if (not path.isdir(thePath)):
       mkdir(thePath)

MACAddress = getHwAddr('eth0')

TRIG = 23                                  #Associate pin 23 to TRIG
ECHO = 24                                  #Associate pin 24 to ECHO
x = 0
antalMaalingerPrFil = 300
newdest = '/home/pi/Result'

print "Distance Measurement Initiated"

GPIO.setup(TRIG,GPIO.OUT)                  #Set pin as GPIO out
GPIO.setup(ECHO,GPIO.IN)                   #Set pin as GPIO in
GPIO.setwarnings(False)
oldDistance = 0
distance_pic = 0
time_start = time.time()

logging.basicConfig(level=logging.DEBUG, filename='/home/pi/failX.log')

while True:
   try:
     import csv
     timestamp = time.strftime("_%H-%M-%S-%d-%m-%Y")
     filenameRange = "".join([MACAddress, timestamp,"_RangeX", ".csv"])
     RangeFile = open(filenameRange, "wb")
     csv_writerRange = csv.writer(RangeFile, delimiter=";")

     GPIO.output(TRIG, False)                 #Set TRIG as LOW
     print "Waitng For Sensor To Settle"
     time.sleep(1)                            #Delay of 1 seconds

     while x<antalMaalingerPrFil:
        GPIO.output(TRIG, True)                  #Set TRIG as HIGH
        time.sleep(0.00001)                      #Delay of 0.00001 seconds
        GPIO.output(TRIG, False)                 #Set TRIG as LOW

        pulse_start = time.time()
        while GPIO.input(ECHO) == 0:             #Check whether the ECHO is LOW
           pulse_start = time.time()              #Saves the last known time of LOW pulse

        pulse_end = pulse_start
        timeUp = time.time()
        while GPIO.input(ECHO) == 1:              #Check whether the ECHO is HIGH
           pulse_end = time.time()                #Saves the last known time of HIGH pulse
           timeDown = time.time()
           timeOut = timeDown - timeUp
           if timeOut > 0.050:
               break 

     pulse_duration = pulse_end - pulse_start #Get pulse duration to a variable

     distance = pulse_duration * 17150        #Multiply pulse duration by 17150 to get distance
     distance = round(distance, 2)            #Round to two decimal points
     distance = distance - 0.5

     timestamp_range = time.strftime('%T %d-%m-%Y')
     tmpRange = [timestamp_range]
     tmpRange.extend([distance])
     csv_writerRange.writerows([tmpRange])
     time.sleep(2)

     x += 1

  RangeFile.close()

  checkDirectory(newdest)

  x = 0

  source = os.listdir("/")
  destination = newdest
  for files in source:
     if files.endswith("RangeX.csv"):
        shutil.move(files,destination)


except:
    logging.exception("Fail:")

And here is my script in /etc/init.d to run the script above from boot.

afstandsmaalerX:

#!/bin/bash

### BEGIN INIT INFO
# Provides:     afstandsmaalerX
# Required-Start:   $remote_fs $syslog
# Required-Stop:    $remote_fs $syslog
# Default-Start:    2 3 4 5
# Default-Stop:     0 1 6
# Short-Description:    afstandsmaalerX at boot time
# Description:      afstandsmaalerX
### END INIT INFO


case "$1" in
    start)
            echo "Starting sonarsensorX"            
            /home/pi/codes/Data_Acquisition_System/Maalere/AfstandsmaalerX.py &
            ;;
    stop)
            echo "Stopping sonarsensor X"
            killall AfstandsmaalerX.py
            ;;
    *)
            echo "Wrong Command"
            exit 1
            ;;
esac

exit 0

I have made the script executeable and I have ran the command: "sudo update-rc.d afstandsmaalerX defaults"

This is only the code for one of the sonarsensors, but the code is similar for the two others.

  • 1
    Without seeing your code it will be impossible to tell what causes the failure. Almost certainly it will be a coding error, – joan Aug 5 '15 at 6:49
  • Are you overflowing the size of an int or the max number of rows in your spreadsheet? – Steve Robillard Aug 5 '15 at 7:16
  • The most likely reason is a duff reading method has been used. Almost all the web examples I have seen will hang in busy spins under not particularly unusual situations. I'd also be interested in knowing what precautions have been taken to prevent the three sensors from interfering with each other. – joan Aug 5 '15 at 7:45
  • hmm im only writing 300 lines in the spreadsheet, so I don't think so. :) – Mattie Aug 5 '15 at 7:47
  • 1
    How do you know that the echoes aren't a return from another HC-SR04? – joan Aug 5 '15 at 7:59
1

The code is more robust than most I have seen. At least it only appears to hang in one position.

 while x<antalMaalingerPrFil:
    GPIO.output(TRIG, True)       #Set TRIG as HIGH
    time.sleep(0.00001)           #Delay of 0.00001 seconds
    GPIO.output(TRIG, False)      #Set TRIG as LOW

    pulse_start = time.time()
    while GPIO.input(ECHO) == 0:  #Check whether the ECHO is LOW
       pulse_start = time.time()  #Saves the last known time of LOW pulse

The code assumes that the echo signal cannot go high then back low between the GPIO.output(TRIG, False) and the while GPIO.input(ECHO) == 0: line. That assumption is wrong. The target may be very close or the script may be rescheduled at that point.

  • Oh never thought of that. Here the target aren't close. But considered that it stops after a few hours may be because the script is rescheduled! I will try to change that right away. - thanks! – Mattie Aug 5 '15 at 8:11
  • @Mattie Any old timeout should do, e.g. while.GPIO.input(ECHO) == 0 and done_this_loop < 100000: – joan Aug 5 '15 at 8:18
  • not sure what you mean by this: "done_this_loop < 100000:"? – Mattie Aug 5 '15 at 8:33
  • @Mattie I just mean before the loop add a done_this_loop = 0 line. Within the loop add a done_this_loop += 1 line. That way you know the loop will end either by reaching an impossible loop count or by seeing the echo line rise. – joan Aug 5 '15 at 8:44
1

Three suggestions:

  1. I echo @joan's comments that the three sensors should be run from the same script to avoid conflicts. That said, if you are using completely different pins for each sensor then you should not have an issue. If you are using the same pins for trigger, well then that might be your issue.

  2. You could hack a solution to the symptom. Write a watchdog type script that checks to see the last time the .csv file was updated. If too long, just reboot. It's ugly, but it will get it to run continuously.

  3. Debug the old fashioned way. Use logging.debug. Ugly but effective. Add debug statements at key points in your script. That way, if used in conjunction with #2, you could see exactly where it is hanging. Later it is easy to change the logging level so you only see the failures. Once you identify what line is causing the hang it should be easy to fix.

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.