lednerg

pcb.py for Super Kuma 9000 fan and LED control

May 30th, 2018
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.65 KB | None | 0 0
  1. #!/usr/bin/python3 -u
  2. #Copyright 2017 Michael Kirsch
  3.  
  4. #Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
  5. #to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  6. # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  7. #The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  8.  
  9. #Fan and LED portions by @ThisSteveGuy (June 12, 2018)
  10.  
  11. import http.server
  12. import configparser
  13. import time
  14. import os
  15. import RPi.GPIO as GPIO
  16. import subprocess
  17. from configparser import SafeConfigParser
  18. from enum import Enum
  19.  
  20. pcb_components={"LED":7,"FAN":8,"RESET":3,"POWER":5,"CHECK_PCB":10}
  21.  
  22. class path():
  23.     kintaro_folder = "/opt/kintaro/"
  24.     start_folder = "start/"
  25.     intro_video = kintaro_folder + start_folder + "intro.mp4"
  26.     config_file = kintaro_folder + start_folder + "kintaro.config"
  27.     temp_command = 'vcgencmd measure_temp'
  28.  
  29. class vars():
  30.     fan_hysteresis = 5
  31.  # The fan curve has three points: high mid low. Each has a temperature (celsius) and a fan speed (percent).
  32.     temp_high = 70      #   fan curve
  33.     fan_high = 100      #           o
  34.     temp_mid = 65       #         /
  35.     fan_mid = 75        #       o
  36.     temp_low = 60       #     /
  37.     fan_low = 60        #   o
  38.     led_max_bright = 35
  39.     reset_hold_short = 100
  40.     reset_hold_long = 500
  41.     debounce_time = 0.1
  42.     counter_time = 0.01
  43.  
  44. GPIO.setmode(GPIO.BOARD) #Use the same layout as the pins
  45. GPIO.setup(pcb_components["LED"], GPIO.OUT) #LED Output
  46. pled = GPIO.PWM(pcb_components["LED"], 60) #For LED dimming. This number is in Hz. Adjust "led_max_bright" above instead of this.
  47. GPIO.setup(pcb_components["FAN"], GPIO.OUT) #FAN Output
  48. pfan = GPIO.PWM(pcb_components["FAN"], 30) #Fan PWM. This is in Hz. I've had no issues with 30.
  49. GPIO.setup(pcb_components["POWER"], GPIO.IN)  #set pin as input
  50. GPIO.setup(pcb_components["RESET"], GPIO.IN, pull_up_down=GPIO.PUD_UP) #set pin as input and switch on internal pull up resistor
  51. GPIO.setup(pcb_components["CHECK_PCB"], GPIO.IN, pull_up_down=GPIO.PUD_UP)
  52.  
  53. def temp(): #returns the gpu temoperature
  54.     res = os.popen(path.temp_command).readline()
  55.     return float((res.replace("temp=", "").replace("'C\n", "")))
  56.  
  57. curLED = 100 #for keeping track of current LED brightness, edit "led_max_bright" above instead
  58. def ledChange(newLED,speed):
  59.     global curLED
  60.     while (newLED != curLED):
  61.          #speed is a decimal which describes how long it takes the LED to go from one brightness level to the next.
  62.         if speed == 0: speed = 1 #a speed of 0 would mean the LED never changes, so we turn it to a 1 (an instant change).
  63.         curLED = curLED * (1-speed) + newLED * speed #this makes for a smooth transition between brightness levels.
  64.         if (abs(curLED-newLED) <= 1): curLED = newLED #close enough to desired brightness level? Then switch over to it.
  65.         pled.start(curLED) #this is when the change to the actual LED brightness is applied. 0-100, & decimals are okay.
  66.         if speed < 1: time.sleep(0.02) #tiny pause between changing brightness levels, otherwise it'd be too quick.
  67.  
  68. class led:  #class to control the led
  69.     #I should just overhaul this whole part. For now, toggle and blink are used to keep things similar
  70.     #  with the code from before. I've made it so one can customize the speed and brightness of blinks if they want.
  71.     def toggle(status,speed):
  72.     #a status of 0 or 1 behaves like an on/off switch. Any other value, and it gets passed on as a brightness value.
  73.         if status == 0:
  74.             ledChange(0,speed)
  75.         elif status == 1:
  76.     #This is where the max brightness setting is actually applied.
  77.             ledChange(vars.led_max_bright,speed)
  78.         else:
  79.     #we could ignore the max brightness here if we wanted.
  80.             ledChange(status,speed)
  81.  
  82.     def blink(amount,interval,speed,brightness): #blink the led
  83.   #amount = number of blinks; interval = time between blinks; speed = slowness of blinks; brightness = optional (2-100)
  84.         for x in range(amount):
  85.             if brightness > 0:
  86.                 led.toggle(brightness,speed)
  87.             else:
  88.                 led.toggle(0,speed)
  89.             time.sleep(interval)
  90.             led.toggle(1,speed)
  91.             time.sleep(interval)
  92.  
  93. def return_config_bool(searchterm):
  94.     Config = configparser.ConfigParser()
  95.     Config.read(path.config_file)  # read the configfile
  96.     return Config.getboolean("Boot", searchterm)
  97.  
  98. def fan(speed):
  99.     pfan.start(speed)
  100.  
  101. #this is just initializing variables. Change the fan curve above instead.
  102. curTemp = 50   #Current Temperature. We hold onto this value because we're using it in a filter.
  103. topTemp = 0    #Top Temperature. Keeps track of temp increases, used to apply hysteresis.
  104. botTemp = 100  #Bottom Temperature. As the fan cools things down, this keeps track of how cool it's gotten.
  105. oldFan = 0     #keeps track of what the fan speed was after the last time we ran this function
  106. def fancontrol():
  107.     global curTemp
  108.     global topTemp
  109.     global botTemp
  110.     global oldFan
  111.     curTemp = curTemp * .4 + temp() * .6 #Applies a slight low pass filter to temperature readings, minimizes errors
  112.     if botTemp >= curTemp:
  113.       #if the temperature has been going down, then record it...
  114.         botTemp = curTemp
  115.       #...and lower the point at which the fan will speed up again.
  116.         topTemp = curTemp + vars.fan_hysteresis
  117.     elif topTemp <= curTemp:
  118.       #if the temp's been getting hot, then record it...
  119.         topTemp = curTemp
  120.       #...and raise the level at which we will decrease the fan speed again.
  121.         botTemp = curTemp - vars.fan_hysteresis
  122.           #This applies the "fan curve". You could do several if elif lines like this to make more points on the curve.
  123.     if topTemp > vars.temp_mid: #"topTemp" here means the current temp after hysteresis has been applied to it.
  124.         #maps the range of temperatures to the range of fan speeds from the "fan curve". This part is from mid to high.
  125.         newFAN = (topTemp-vars.temp_mid+.01)/(vars.temp_high-vars.temp_mid) * (vars.fan_high-vars.fan_mid) + vars.fan_mid
  126.     elif topTemp > vars.temp_low:
  127.         #and this part is from low to mid.
  128.         newFAN = (topTemp-vars.temp_low+.01)/(vars.temp_mid-vars.temp_low) * (vars.fan_mid-vars.fan_low) + vars.fan_low
  129.     else:
  130.         newFAN = 0 #if we're below the fan curve, then turn off the fan
  131.         if oldFan != 0: led.blink(3,0,.1,0) #if the fan's going off, we'll do 3 long, slow blinks.
  132.     fan(newFAN) #this is the line that actually changes the fan speed. 0-100 only, decimals are okay.
  133.     if (oldFan == 0) and (newFAN > 0): led.blink(5,.15,1,100) #we'll do 5 quick blinks if the fan is going on.
  134.     oldFan = newFAN #keep track of how this function ended so we can do the blinks (that's all oldFan is used for)
  135.  
  136. if return_config_bool("video"):
  137.     os.system("omxplayer " + path.intro_video + " &") #start the bootvideo on start
  138.  
  139. def toggle(toggle_this):  #change one of the values in the config file
  140.     parser = configparser.ConfigParser()
  141.     parser.read(path.config_file)
  142.     if return_config_bool(toggle_this):
  143.         parser.set('Boot', toggle_this, "False")
  144.         fan(0)
  145.     else:
  146.         parser.set('Boot', toggle_this, "True")
  147.     with open(path.config_file, "w+") as configfile:
  148.         parser.write(configfile)
  149.  
  150. def Falling_Power(channel):
  151.     time.sleep(vars.debounce_time) #debounce
  152.     if (GPIO.input(pcb_components["POWER"]) == GPIO.HIGH) and GPIO.input(pcb_components["CHECK_PCB"]) == GPIO.LOW:  # shutdown funktion if the powerswitch is toggled
  153.         led.toggle(0,1)
  154.         fan(0)
  155.         os.system("sudo shutdown -h now")
  156.  
  157. def Falling_Reset(channel):
  158.     if (GPIO.input(pcb_components["RESET"]) == GPIO.LOW):  # reset function
  159.         reset_counter = 0  # counter for the time funktion
  160.         time.sleep(vars.debounce_time)  # debounce time
  161.         while (GPIO.input(pcb_components["RESET"]) == GPIO.LOW):  # while the button is hold the counter counts up
  162.             reset_counter = reset_counter + 1
  163.             time.sleep(vars.counter_time)
  164.         if reset_counter > vars.reset_hold_short:  # check if its hold more that one second
  165.             if reset_counter <= vars.reset_hold_long:  # if you hold it less than 5 sec it will toggle the fan
  166.                 toggle("fan")
  167.                 led.blink(1,.333,.2,0)
  168.             if reset_counter > vars.reset_hold_long:  # if you hold it more than 5 seconds if will toggle the bootupvideo
  169.                 toggle("video")
  170.                 led.blink(5,.1,0,0)
  171.         else:
  172.             os.system("killall emulationstation")
  173.             time.sleep(5)
  174.             os.system("sudo reboot")
  175.  
  176. def PCB_Pull(channel):
  177.     GPIO.cleanup()
  178.  
  179. if (GPIO.input(pcb_components["POWER"]) == GPIO.HIGH) and GPIO.input(pcb_components["CHECK_PCB"]) == GPIO.LOW:
  180.     os.system("sudo shutdown -h now")
  181.  
  182. GPIO.add_event_detect(pcb_components["CHECK_PCB"],GPIO.RISING,callback=PCB_Pull)
  183.  
  184. time.sleep(1)
  185.  
  186. if return_config_bool("pcb") and GPIO.input(pcb_components["CHECK_PCB"])==GPIO.LOW: #check if there is an pcb and if there is then attach the interrupts
  187.     led.toggle(1,1)
  188.     GPIO.add_event_detect(pcb_components["RESET"], GPIO.FALLING, callback=Falling_Reset)
  189.     GPIO.add_event_detect(pcb_components["POWER"], GPIO.FALLING, callback=Falling_Power)
  190.  
  191.     #check for interrupts :D
  192. while True:
  193.     time.sleep(5)
  194.     led.toggle(1,1)
  195.     if return_config_bool("fan"): #check if the fan is activated in the config
  196.         fancontrol()
Advertisement
Add Comment
Please, Sign In to add comment