kopia lustrzana https://github.com/cyoung/stratux
Merge branch 'master' into ahrs_dev_protocolfun
commit
a0d9a4be25
|
@ -1,11 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/takama/daemon"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
@ -39,14 +40,25 @@ const (
|
|||
name = "fancontrol"
|
||||
description = "cooling fan speed control based on CPU temperature"
|
||||
|
||||
// port which daemon should be listen
|
||||
port = ":9977"
|
||||
// Address on which daemon should be listen.
|
||||
addr = ":9977"
|
||||
)
|
||||
|
||||
type FanControl struct {
|
||||
TempTarget float32
|
||||
TempCurrent float32
|
||||
PWMDutyMin int
|
||||
PWMDutyMax int
|
||||
PWMDutyCurrent int
|
||||
PWMPin int
|
||||
}
|
||||
|
||||
var myFanControl FanControl
|
||||
|
||||
var stdlog, errlog *log.Logger
|
||||
|
||||
func fanControl(pwmDutyMin int, pin int, tempTarget float32) {
|
||||
cPin := C.int(pin)
|
||||
func fanControl() {
|
||||
cPin := C.int(myFanControl.PWMPin)
|
||||
|
||||
C.wiringPiSetup()
|
||||
|
||||
|
@ -58,30 +70,31 @@ func fanControl(pwmDutyMin int, pin int, tempTarget float32) {
|
|||
|
||||
C.pwmSetMode(C.PWM_MODE_MS)
|
||||
C.pinMode(cPin, C.PWM_OUTPUT)
|
||||
C.pwmSetRange(pwmDutyMax)
|
||||
C.pwmSetRange(C.uint(myFanControl.PWMDutyMax))
|
||||
C.pwmSetClock(pwmClockDivisor)
|
||||
C.pwmWrite(cPin, C.int(pwmDutyMin))
|
||||
temp := float32(0.)
|
||||
C.pwmWrite(cPin, C.int(myFanControl.PWMDutyMin))
|
||||
myFanControl.TempCurrent = 0
|
||||
go cpuTempMonitor(func(cpuTemp float32) {
|
||||
if isCPUTempValid(cpuTemp) {
|
||||
temp = cpuTemp
|
||||
myFanControl.TempCurrent = cpuTemp
|
||||
}
|
||||
})
|
||||
pwmDuty := 0
|
||||
|
||||
myFanControl.PWMDutyCurrent = 0
|
||||
|
||||
delay := time.NewTicker(delaySeconds * time.Second)
|
||||
|
||||
for {
|
||||
if temp > (tempTarget + hysteresis) {
|
||||
pwmDuty = iMax(iMin(pwmDutyMax, pwmDuty+1), pwmDutyMin)
|
||||
} else if temp < (tempTarget - hysteresis) {
|
||||
pwmDuty = iMax(pwmDuty-1, 0)
|
||||
if pwmDuty < pwmDutyMin {
|
||||
pwmDuty = 0
|
||||
if myFanControl.TempCurrent > (myFanControl.TempTarget + hysteresis) {
|
||||
myFanControl.PWMDutyCurrent = iMax(iMin(myFanControl.PWMDutyMax, myFanControl.PWMDutyCurrent+1), myFanControl.PWMDutyMin)
|
||||
} else if myFanControl.TempCurrent < (myFanControl.TempTarget - hysteresis) {
|
||||
myFanControl.PWMDutyCurrent = iMax(myFanControl.PWMDutyCurrent-1, 0)
|
||||
if myFanControl.PWMDutyCurrent < myFanControl.PWMDutyMin {
|
||||
myFanControl.PWMDutyCurrent = 0
|
||||
}
|
||||
}
|
||||
//log.Println(temp, " ", pwmDuty)
|
||||
C.pwmWrite(cPin, C.int(pwmDuty))
|
||||
//log.Println(myFanControl.TempCurrent, " ", myFanControl.PWMDutyCurrent)
|
||||
C.pwmWrite(cPin, C.int(myFanControl.PWMDutyCurrent))
|
||||
<-delay.C
|
||||
}
|
||||
|
||||
|
@ -123,7 +136,12 @@ func (service *Service) Manage() (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
go fanControl(*pwmDutyMin, *pin, float32(*tempTarget))
|
||||
myFanControl.TempTarget = float32(*tempTarget)
|
||||
myFanControl.PWMDutyMin = *pwmDutyMin
|
||||
myFanControl.PWMDutyMax = pwmDutyMax
|
||||
myFanControl.PWMPin = *pin
|
||||
|
||||
go fanControl()
|
||||
|
||||
// Set up channel on which to send signal notifications.
|
||||
// We must use a buffered channel or risk missing the signal
|
||||
|
@ -131,55 +149,23 @@ func (service *Service) Manage() (string, error) {
|
|||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)
|
||||
|
||||
// Set up listener for defined host and port
|
||||
listener, err := net.Listen("tcp", port)
|
||||
if err != nil {
|
||||
return "Possibly was a problem with the port binding", err
|
||||
}
|
||||
http.HandleFunc("/", handleStatusRequest)
|
||||
http.ListenAndServe(addr, nil)
|
||||
|
||||
// set up channel on which to send accepted connections
|
||||
listen := make(chan net.Conn, 100)
|
||||
go acceptConnection(listener, listen)
|
||||
|
||||
// loop work cycle with accept connections or interrupt
|
||||
// by system signal
|
||||
// interrupt by system signal
|
||||
for {
|
||||
select {
|
||||
case conn := <-listen:
|
||||
go handleClient(conn)
|
||||
case killSignal := <-interrupt:
|
||||
stdlog.Println("Got signal:", killSignal)
|
||||
stdlog.Println("Stoping listening on ", listener.Addr())
|
||||
listener.Close()
|
||||
if killSignal == os.Interrupt {
|
||||
return "Daemon was interrupted by system signal", nil
|
||||
}
|
||||
return "Daemon was killed", nil
|
||||
killSignal := <-interrupt
|
||||
stdlog.Println("Got signal:", killSignal)
|
||||
if killSignal == os.Interrupt {
|
||||
return "Daemon was interrupted by system signal", nil
|
||||
}
|
||||
return "Daemon was killed", nil
|
||||
}
|
||||
}
|
||||
|
||||
// Accept a client connection and collect it in a channel
|
||||
func acceptConnection(listener net.Listener, listen chan net.Conn) {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
listen <- conn
|
||||
}
|
||||
}
|
||||
|
||||
func handleClient(client net.Conn) {
|
||||
defer client.Close()
|
||||
for {
|
||||
buf := make([]byte, 4096)
|
||||
numbytes, err := client.Read(buf)
|
||||
if numbytes == 0 || err != nil {
|
||||
return
|
||||
}
|
||||
client.Write(buf[:numbytes])
|
||||
}
|
||||
func handleStatusRequest(w http.ResponseWriter, r *http.Request) {
|
||||
statusJSON, _ := json.Marshal(&myFanControl)
|
||||
w.Write(statusJSON)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -689,6 +689,7 @@ func blinkStatusLED() {
|
|||
ledON = !ledON
|
||||
}
|
||||
}
|
||||
|
||||
func heartBeatSender() {
|
||||
timer := time.NewTicker(1 * time.Second)
|
||||
timerMessageStats := time.NewTicker(2 * time.Second)
|
||||
|
@ -700,8 +701,10 @@ func heartBeatSender() {
|
|||
// Blinking when there is a critical system error (and Stratux is still running).
|
||||
|
||||
if len(globalStatus.Errors) == 0 { // Any system errors?
|
||||
// Turn on green ACT LED on the Pi.
|
||||
ioutil.WriteFile("/sys/class/leds/led0/brightness", []byte("1\n"), 0644)
|
||||
if !globalStatus.NightMode { // LED is off by default (/boot/config.txt.)
|
||||
// Turn on green ACT LED on the Pi.
|
||||
ioutil.WriteFile("/sys/class/leds/led0/brightness", []byte("1\n"), 0644)
|
||||
}
|
||||
} else if !ledBlinking {
|
||||
// This assumes that system errors do not disappear until restart.
|
||||
go blinkStatusLED()
|
||||
|
@ -1112,6 +1115,7 @@ type status struct {
|
|||
AHRS_LogFiles_Size int64
|
||||
BMPConnected bool
|
||||
IMUConnected bool
|
||||
NightMode bool // For turning off LEDs.
|
||||
}
|
||||
|
||||
var globalSettings settings
|
||||
|
@ -1237,13 +1241,13 @@ func printStats() {
|
|||
}
|
||||
sensorsOutput := make([]string, 0)
|
||||
if globalSettings.IMU_Sensor_Enabled {
|
||||
sensorsOutput = append(sensorsOutput, fmt.Sprintf("Last IMU read: %s\n", stratuxClock.HumanizeTime(mySituation.AHRSLastAttitudeTime)))
|
||||
sensorsOutput = append(sensorsOutput, fmt.Sprintf("Last IMU read: %s", stratuxClock.HumanizeTime(mySituation.AHRSLastAttitudeTime)))
|
||||
}
|
||||
if globalSettings.BMP_Sensor_Enabled {
|
||||
sensorsOutput = append(sensorsOutput, fmt.Sprintf(" - Last BMP read: %s\n", stratuxClock.HumanizeTime(mySituation.BaroLastMeasurementTime)))
|
||||
sensorsOutput = append(sensorsOutput, fmt.Sprintf("Last BMP read: %s", stratuxClock.HumanizeTime(mySituation.BaroLastMeasurementTime)))
|
||||
}
|
||||
if len(sensorsOutput) > 0 {
|
||||
log.Printf("- " + strings.Join(sensorsOutput, ", "))
|
||||
log.Printf("- " + strings.Join(sensorsOutput, ", ") + "\n")
|
||||
}
|
||||
// Check if we're using more than 95% of the free space. If so, throw a warning (only once).
|
||||
if !diskUsageWarning && usage.Usage() > 0.95 {
|
||||
|
@ -1392,6 +1396,10 @@ func main() {
|
|||
} else { // if not using the FlightBox config, use "normal" log file locations
|
||||
logDirf = logDir
|
||||
}
|
||||
//Merlin: detect presence of /etc/Merlin file.
|
||||
if _, err := os.Stat("/etc/Merlin"); !os.IsNotExist(err) {
|
||||
globalStatus.HardwareBuild = "Merlin"
|
||||
}
|
||||
debugLogf = filepath.Join(logDirf, debugLogFile)
|
||||
dataLogFilef = filepath.Join(logDirf, dataLogFile)
|
||||
//FIXME: All of this should be removed by 08/01/2016.
|
||||
|
|
25
main/gps.go
25
main/gps.go
|
@ -274,6 +274,18 @@ func initGPSSerial() bool {
|
|||
|
||||
p.Write(makeUBXCFG(0x06, 0x24, 36, nav))
|
||||
|
||||
// Turn off "time pulse" (usually drives an LED).
|
||||
tp5 := make([]byte, 32)
|
||||
tp5[4] = 0x32
|
||||
tp5[8] = 0x40
|
||||
tp5[9] = 0x42
|
||||
tp5[10] = 0x0F
|
||||
tp5[12] = 0x40
|
||||
tp5[13] = 0x42
|
||||
tp5[14] = 0x0F
|
||||
tp5[28] = 0xE7
|
||||
p.Write(makeUBXCFG(0x06, 0x31, 32, tp5))
|
||||
|
||||
// GNSS configuration CFG-GNSS for ublox 7 higher, p. 125 (v8)
|
||||
|
||||
// Notes: ublox8 is multi-GNSS capable (simultaneous decoding of GPS and GLONASS, or
|
||||
|
@ -916,11 +928,14 @@ func processNMEALine(l string) (sentenceUsed bool) {
|
|||
tmpSituation.GPSNACp = calculateNACp(tmpSituation.GPSHorizontalAccuracy)
|
||||
|
||||
// field 10 = vertical accuracy, m
|
||||
vAcc, err := strconv.ParseFloat(x[10], 32)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
tmpSituation.GPSVerticalAccuracy = float32(vAcc * 2) // UBX reports 1-sigma variation; we want 95% confidence
|
||||
/*
|
||||
vAcc, err := strconv.ParseFloat(x[10], 32)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
tmpSituation.GPSVerticalAccuracy = float32(vAcc * 2) // UBX reports 1-sigma variation; we want 95% confidence
|
||||
*/
|
||||
tmpSituation.GPSVerticalAccuracy = float32(2.) * tmpSituation.GPSHorizontalAccuracy
|
||||
|
||||
// field 2 = time
|
||||
if len(x[2]) < 8 {
|
||||
|
|
|
@ -484,7 +484,7 @@ func sdrWatcher() {
|
|||
} else if globalSettings.DeveloperMode {
|
||||
// Throw a "critical error" if developer mode is enabled. Alerts the developer that the daemon was restarted (possibly)
|
||||
// unexpectedly.
|
||||
daemonRestartedErr := fmt.Errorf("System uptime %d seconds. Daemon restarted.\n")
|
||||
daemonRestartedErr := fmt.Errorf("System uptime %d seconds. Daemon was restarted.\n", info.Uptime)
|
||||
addSystemError(daemonRestartedErr)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from oled.device import ssd1306, sh1106
|
||||
from oled.render import canvas
|
||||
from luma.core.interface.serial import i2c
|
||||
from luma.oled.device import ssd1306, sh1106
|
||||
from luma.core.render import canvas
|
||||
|
||||
from PIL import ImageDraw, ImageFont, Image
|
||||
|
||||
|
@ -20,7 +21,8 @@ class StratuxScreen():
|
|||
self.pidfile_timeout = 5
|
||||
def run(self):
|
||||
font2 = ImageFont.truetype('/etc/stratux-screen/CnC_Red_Alert.ttf', 12)
|
||||
oled = ssd1306(port=1, address=0x3C)
|
||||
serial = i2c(port=1, address=0x3c)
|
||||
oled = ssd1306(serial)
|
||||
|
||||
with canvas(oled) as draw:
|
||||
logo = Image.open('/etc/stratux-screen/stratux-logo-64x64.bmp')
|
||||
|
|
Ładowanie…
Reference in New Issue