I asked this question in January here on the platform and thought that the reason for my Pi crashing was the raspistill script I used. This turned out to be a false positive.
After some hassle and trying, I decided to give this issue another go and completely re-setup my RPi with the latest
RASPBIAN JESSIE LITE
released at 2016-03-18
and gave it another try about 20 hours ago.
After about 12 hours of operation my RPi hung up / crashed again and only a hard reboot (power cut) could fix it.
Side info, the RPi is used for weather tracking + timelapsing. It gathers weather data from BMP085, DS18b20 and DHT22 sensors. Images are taken with the Raspberry Pi Camera module rev 1.3.
To my setup:
Raspbery PI model B
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 8.0 (jessie)
Release: 8.0
Codename: jessie
Linux carbon 4.1.19+ #858 Tue Mar 15 15:52:03 GMT 2016 armv6l GNU/Linux
root@hostname ~ # python --version
Python 2.7.9
root@hostname ~ # python3 --version
Python 3.4.2
Upon my Pi crashing I get this message in my kern.log
file.
As one can easily see, the crash seems to be caused by my weatherPi
script which is called every minute via a cronjob. But why?
This is my script:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# This software is used to gather basic environmennt data from sensors
# connected to the Rapsberry Pi Model B. The gathered data is stored into
# MySQL database and printed to the console.
import os
import sys
import re
import Adafruit_DHT
import Adafruit_BMP.BMP085 as BMP085
import MySQLdb
import time
# make sure script is run as root
euid = os.geteuid()
if euid != 0:
print('Script not started as root. Running sudo...')
args = ['sudo', sys.executable] + sys.argv + [os.environ]
# the next line replaces the currently-running process with the sudo
os.execlpe('sudo', *args)
# create timestamp
timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
print('Gathering data...')
# grab humidity data from DHT22 sensor
sensor = 22
pin = 4
humidity, temperature_DHT22 = Adafruit_DHT.read_retry(sensor, pin)
# grab barometric data
sensor = BMP085.BMP085()
temperature_bmp9985 = sensor.read_temperature()
pressure_bmp9985 = (sensor.read_pressure()/100)
# grab outside temperature from ds18b20
f = open('/sys/bus/w1/devices/28-00043c9677ff/w1_slave', 'r')
lines = f.read()
match = re.search('t=(-?[0-9]+)', lines)
temperature_18b20 = (float(match.group(1))/1000)
# grab cpu temperature
cpuTempFile = open( "/sys/class/thermal/thermal_zone0/temp" )
cpu_temp = float(cpuTempFile.read())/1000
cpuTempFile.close()
# calculate aproximate dew point
DewPoint = ((humidity / 100) ** 0.125) * (112 + 0.9 * temperature_18b20) + (0.1 * temperature_18b20) - 112
print('Opening database connection')
# connecting to MySQL database and creating cursor
# all queries are executed by the cursor
db = MySQLdb.connect(host="HOST", user="USER", passwd="PASSWORD", db="DATABASE")
cur = db.cursor()
print('Preparing SQL statement')
sql = (('INSERT INTO `weather_data` (`t_out`, `t_out_wall`, `t_case`, `t_cpu`, `humidity`, `pressure`, `dewpoint`) VALUES ({:.2f}, {:.1f}, {:.2f}, {:.2f}, {:.2f}, {:.0f}, {:.2f});').format(temperature_18b20, temperature_DHT22, temperature_bmp9985, cpu_temp, humidity, pressure_bmp9985, DewPoint))
print('Executing SQL statement')
cur.execute(sql)
print('Commiting SQL statement')
db.commit()
print('Closing database connection')
db.close
print('Acquired data:')
print(timestamp)
print('temperature_18b20 = {:0.2f} °C').format(temperature_18b20)
print('temperature_dht22 = {:0.1f} °C').format(temperature_DHT22)
print('temperature_bmp9985 = {:0.2f} °C').format(temperature_bmp9985)
print('temperature_cpu = {:0.2f} °C').format(cpu_temp)
print('humidity_dht22 = {:0.1f}%').format(humidity)
print('pressure_bmp9985 = {:0.0f} hPa').format(pressure_bmp9985)
print('dew_point = {:.2f} °C').format(DewPoint)
This is the crontab line I use (as root):
# gather weather data and commit to database
* * * * * /usr/local/bin/weatherPi
My questions are:
- What exactly does take up all the RAM?
- Why is the RAM not freed up after executing the script?
- How can I resolve the issue?
Additional info:
I already tried setting a timeout for the weatherPi script I use in cron, so if the script ran longer than 10 seconds, it would be killed with signal 9. This made no difference, whatsoever.
The Pi runs overclocked at Turbo
, but this makes no difference to the crashes (tried several settings).
If any other information is needed, please let me know. I don't know any further on how to debug this issue.
EDIT:
After updating my code like the following the script seems to not close anymore. First tests (with same conditions above) crashed the Pi within an hour.
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# This software is used to gather basic environmennt data
# with the Rapsberry Pi Model B. This software was sepecifically
# designed for one single system
import os
import sys
import re
import Adafruit_DHT
import Adafruit_BMP.BMP085 as BMP085
import MySQLdb
import time
# make sure script is run as root
euid = os.geteuid()
if euid != 0:
print('Script not started as root. Running sudo...')
args = ['sudo', sys.executable] + sys.argv + [os.environ]
# the next line replaces the currently-running process with the sudo
os.execlpe('sudo', *args)
# create timestamp
timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
print('Gathering data...')
# grab humidity data from DHT22 sensor
sensor = 22
pin = 4
humidity, temperature_DHT22 = Adafruit_DHT.read_retry(sensor, pin)
# grab barometric data
sensor = BMP085.BMP085()
temperature_bmp9985 = sensor.read_temperature()
pressure_bmp9985 = (sensor.read_pressure()/100)
# grab outside temperature from ds18b20
f = open('/sys/bus/w1/devices/28-00043c9677ff/w1_slave', 'r')
lines = f.read()
f.close()
match = re.search('t=(-?[0-9]+)', lines)
temperature_18b20 = (float(match.group(1))/1000)
# grab cpu temperature
cpuTempFile = open( "/sys/class/thermal/thermal_zone0/temp" )
cpu_temp = float(cpuTempFile.read())/1000
cpuTempFile.close()
# calculate aproximate dew point
DewPoint = ((humidity / 100) ** 0.125) * (112 + 0.9 * temperature_18b20) + (0.1 * temperature_18b20) - 112
print('Opening database connection')
# connecting to MySQL database and creating cursor
# all queries are executed by the cursor
db = MySQLdb.connect(host="HOST", user="USER", passwd="PASSWORD", db="DATABASE")
cur = db.cursor()
print('Preparing SQL statement')
sql = (('INSERT INTO `weather_data` (`t_out`, `t_out_wall`, `t_case`, `t_cpu`, `humidity`, `pressure`, `dewpoint`) VALUES ({:.2f}, {:.1f}, {:.2f}, {:.2f}, {:.2f}, {:.0f}, {:.2f});').format(temperature_18b20, temperature_DHT22, temperature_bmp9985, cpu_temp, humidity, pressure_bmp9985, DewPoint))
print('Executing SQL statement')
cur.execute(sql)
print('Commiting SQL statement')
db.commit()
print('Closing database connection')
cur.close()
db.close()
print('Acquired data:')
print(timestamp)
print('temperature_18b20 = {:0.2f} °C').format(temperature_18b20)
print('temperature_dht22 = {:0.1f} °C').format(temperature_DHT22)
print('temperature_bmp9985 = {:0.2f} °C').format(temperature_bmp9985)
print('temperature_cpu = {:0.2f} °C').format(cpu_temp)
print('humidity_dht22 = {:0.1f}%').format(humidity)
print('pressure_bmp9985 = {:0.0f} hPa').format(pressure_bmp9985)
print('dew_point = {:.2f} °C').format(DewPoint)
Asked by tac:
Output of cat /sys/bus/w1/devices/28-00043c9677ff/w1_slave
56 00 55 00 7f ff 0c 10 7b : crc=7b YES
56 00 55 00 7f ff 0c 10 7b t=5375
This is just the temperature reading of the ds18b20 I2C temperature sensor on the bus.
Update 24.03.2016:
After using the suggested fixes from @tac all seemed to work fine for about 24 hours. But suddenly the RPi crashed again with the same kern.log
which indicated that there was a mass of my weatherPi
scripts running.
My guess is that the script starts hanging if the database connection cannot be established. From the Python MySQL docs I found that you can set a timeout for MySQLdb.connect
. I added a 15 second timeout for testing purposes.
MySQLdb.connect(host="HOST", user="USER", passwd="PASSWORD", db="DATABASE", connect_timeout=15)
Another change that I made was to add a killall
to the crontab, to assure that all remaining scripts are stopped before running a new one:
# gather weather data and commit to database
* * * * * killall weatherPi && /usr/local/bin/weatherPi
Of course the connection timeout is currently redundant because of the prefixed killall
. I currently want to see if this helps at all. After some testing of about 48 hours I will remove this command again and try out my connection timeout solution solely
/sys/bus/w1/devices/28-00043c9677ff/w1_slave
? Just a few numbers?