################################################################################ # # # This file is part of the Buildbotics firmware. # # # # Copyright (c) 2015 - 2018, Buildbotics LLC # # All rights reserved. # # # # This file ("the software") is free software: you can redistribute it # # and/or modify it under the terms of the GNU General Public License, # # version 2 as published by the Free Software Foundation. You should # # have received a copy of the GNU General Public License, version 2 # # along with the software. If not, see . # # # # The software is distributed in the hope that it will be useful, but # # WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # # Lesser General Public License for more details. # # # # You should have received a copy of the GNU Lesser General Public # # License along with the software. If not, see # # . # # # # For information regarding this software email: # # "Joseph Coffland" # # # ################################################################################ import time def read_temp(): with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f: return round(int(f.read()) / 1000) def set_max_freq(freq): filename = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq' with open(filename, 'w') as f: f.write('%d\n' % freq) class MonitorTemp(object): def __init__(self, app): self.app = app self.ctrl = app.get_ctrl() self.log = self.ctrl.log.get('Mon') self.ioloop = self.ctrl.ioloop self.last_temp_warn = 0 self.temp_thresh = 80 self.min_temp = 60 self.max_temp = 80 self.min_freq = 600000 self.max_freq = 1200000 self.low_camera_temp = 75 self.high_camera_temp = 80 self.callback() # Scale max CPU based on temperature def scale_cpu(self, temp): if temp < self.min_temp: cpu_freq = self.max_freq elif self.max_temp < temp: cpu_freq = self.min_freq else: r = 1 - float(temp - self.min_temp) / \ (self.max_temp - self.min_temp) cpu_freq = self.min_freq + (self.max_freq - self.min_freq) * r set_max_freq(cpu_freq) def update_camera(self, temp): if self.app.camera is None: return # Disable camera if temp too high if temp < self.low_camera_temp: self.app.camera.set_overtemp(False) elif self.high_camera_temp < temp: self.app.camera.set_overtemp(True) def log_warnings(self, temp): # Reset temperature warning threshold after timeout if time.time() < self.last_temp_warn + 60: self.temp_thresh = 80 if self.temp_thresh < temp: self.last_temp_warn = time.time() self.temp_thresh = temp self.log.info('Hot RaspberryPi at %d°C' % temp) def callback(self): try: temp = read_temp() self.ctrl.state.set('rpi_temp', temp) self.scale_cpu(temp) self.update_camera(temp) self.log_warnings(temp) except: self.log.exception('Internal error: Temperature status') self.ioloop.call_later(5, self.callback)