kopia lustrzana https://github.com/cyoung/stratux
Merge remote-tracking branch 'cyoung/ahrs_dev' into ahrs_dev
commit
ea657208c0
23
Makefile
23
Makefile
|
@ -1,21 +1,27 @@
|
|||
|
||||
ifeq "$(CIRCLECI)" "true"
|
||||
BUILDINFO=
|
||||
PLATFORMDEPENDENT=
|
||||
else
|
||||
BUILDINFO=-ldflags "-X main.stratuxVersion=`git describe --tags --abbrev=0` -X main.stratuxBuild=`git log -n 1 --pretty=%H`"
|
||||
LDFLAGS_VERSION=-X main.stratuxVersion=`git describe --tags --abbrev=0` -X main.stratuxBuild=`git log -n 1 --pretty=%H`
|
||||
BUILDINFO=-ldflags "$(LDFLAGS_VERSION)"
|
||||
BUILDINFO_STATIC=-ldflags "-extldflags -static $(LDFLAGS_VERSION)"
|
||||
$(if $(GOROOT),,$(error GOROOT is not set!))
|
||||
PLATFORMDEPENDENT=fancontrol
|
||||
endif
|
||||
|
||||
all:
|
||||
make xdump978
|
||||
make xdump1090
|
||||
make xgen_gdl90
|
||||
make xdump978 xdump1090 xgen_gdl90 $(PLATFORMDEPENDENT)
|
||||
|
||||
xgen_gdl90:
|
||||
go get -t -d -v ./main ./test ./godump978 ./uatparse ./sensors
|
||||
go get -u github.com/westphae/goflying/ahrs
|
||||
go get -u github.com/westphae/goflying/ahrsweb
|
||||
go build $(BUILDINFO) -p 4 main/gen_gdl90.go main/traffic.go main/gps.go main/network.go main/managementinterface.go main/sdr.go main/ping.go main/uibroadcast.go main/monotonic.go main/datalog.go main/equations.go main/sensors.go
|
||||
go build $(BUILDINFO) -p 4 main/gen_gdl90.go main/traffic.go main/gps.go main/network.go main/managementinterface.go main/sdr.go main/ping.go main/uibroadcast.go main/monotonic.go main/datalog.go main/equations.go main/sensors.go main/cputemp.go
|
||||
|
||||
fancontrol:
|
||||
go get -t -d -v ./main
|
||||
go build $(BUILDINFO_STATIC) -p 4 main/fancontrol.go main/equations.go main/cputemp.go
|
||||
|
||||
xdump1090:
|
||||
git submodule update --init
|
||||
|
@ -35,6 +41,10 @@ www:
|
|||
install:
|
||||
cp -f gen_gdl90 /usr/bin/gen_gdl90
|
||||
chmod 755 /usr/bin/gen_gdl90
|
||||
cp -f fancontrol /usr/bin/fancontrol
|
||||
chmod 755 /usr/bin/fancontrol
|
||||
-/usr/bin/fancontrol remove
|
||||
/usr/bin/fancontrol install
|
||||
cp image/10-stratux.rules /etc/udev/rules.d/10-stratux.rules
|
||||
cp image/99-uavionix.rules /etc/udev/rules.d/99-uavionix.rules
|
||||
rm -f /etc/init.d/stratux
|
||||
|
@ -44,11 +54,12 @@ install:
|
|||
chmod 744 /root/stratux-pre-start.sh
|
||||
ln -fs /lib/systemd/system/stratux.service /etc/systemd/system/multi-user.target.wants/stratux.service
|
||||
make www
|
||||
cp -f libdump978.so /usr/lib/libdump978.so
|
||||
cp -f dump1090/dump1090 /usr/bin/
|
||||
cp -f image/hostapd_manager.sh /usr/sbin/
|
||||
cp -f image/stratux-wifi.sh /usr/sbin/
|
||||
|
||||
clean:
|
||||
rm -f gen_gdl90 libdump978.so
|
||||
rm -f gen_gdl90 libdump978.so fancontrol
|
||||
cd dump1090 && make clean
|
||||
cd dump978 && make clean
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# @Author Ryan Dewsbury (helno)
|
||||
#
|
||||
# This script throttles a fan based on CPU temperature.
|
||||
#
|
||||
# It expects a fan that's externally powered, and uses GPIO pin 12 for control.
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
import os
|
||||
|
||||
from daemon import runner
|
||||
|
||||
class FanControl():
|
||||
# Return CPU temperature as float
|
||||
def getCPUtemp(self):
|
||||
cTemp = os.popen('vcgencmd measure_temp').readline()
|
||||
return float(cTemp.replace("temp=","").replace("'C\n",""))
|
||||
|
||||
def __init__(self):
|
||||
self.stdin_path = '/dev/null'
|
||||
self.stdout_path = '/var/log/fancontrol.log'
|
||||
self.stderr_path = '/var/log/fancontrol.log'
|
||||
self.pidfile_path = '/var/run/fancontrol.pid'
|
||||
self.pidfile_timeout = 5
|
||||
def run(self):
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
GPIO.setup(12, GPIO.OUT)
|
||||
GPIO.setwarnings(False)
|
||||
p=GPIO.PWM(12, 1000)
|
||||
PWM = 50
|
||||
while True:
|
||||
CPU_temp = self.getCPUtemp()
|
||||
if CPU_temp > 40.5:
|
||||
PWM = min(max(PWM + 1, 0), 100)
|
||||
p.start(PWM)
|
||||
elif CPU_temp < 39.5:
|
||||
PWM = min(max(PWM - 1, 0), 100)
|
||||
p.start(PWM)
|
||||
time.sleep(5)
|
||||
GPIO.cleanup()
|
||||
|
||||
fancontrol = FanControl()
|
||||
daemon_runner = runner.DaemonRunner(fancontrol)
|
||||
daemon_runner.do_action()
|
|
@ -62,8 +62,14 @@ chmod 755 mnt/usr/sbin/sdr-tool.sh
|
|||
cp -f 99-uavionix.rules mnt/etc/udev/rules.d
|
||||
|
||||
#fan/temp control script
|
||||
cp fancontrol.py mnt/usr/bin/
|
||||
chmod 755 mnt/usr/bin/fancontrol.py
|
||||
#remove old script
|
||||
rm -rf mnt/usr/bin/fancontrol.py
|
||||
#install new program
|
||||
cp ../fancontrol mnt/usr/bin
|
||||
chmod 755 mnt/usr/bin/fancontrol
|
||||
chroot mnt/ /usr/bin/fancontrol remove
|
||||
chroot mnt/ /usr/bin/fancontrol install
|
||||
|
||||
|
||||
#isc-dhcp-server config
|
||||
cp -f isc-dhcp-server mnt/etc/default/isc-dhcp-server
|
||||
|
@ -156,3 +162,5 @@ chroot mnt/ systemctl disable dhcpcd
|
|||
#disable hciuart - interferes with ttyAMA0 as a serial port.
|
||||
chroot mnt/ systemctl disable hciuart
|
||||
|
||||
#clean up for release images.
|
||||
rm -rf mnt/root/stratux mnt/root/go
|
||||
|
|
|
@ -17,9 +17,6 @@ if [ "$_IP" ]; then
|
|||
printf "My IP address is %s\n" "$_IP"
|
||||
fi
|
||||
|
||||
|
||||
/usr/bin/fancontrol.py start
|
||||
/usr/bin/stratux-screen.py start
|
||||
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const invalidCpuTemp = float32(-99.0)
|
||||
|
||||
type CpuTempUpdateFunc func(cpuTemp float32)
|
||||
|
||||
/* cpuTempMonitor() reads the RPi board temperature every second and
|
||||
calls a callback. This is broken out into its own function (run as
|
||||
its own goroutine) because the RPi temperature monitor code is buggy,
|
||||
and often times reading this file hangs quite some time. */
|
||||
|
||||
func cpuTempMonitor(updater CpuTempUpdateFunc) {
|
||||
timer := time.NewTicker(1 * time.Second)
|
||||
for {
|
||||
<-timer.C
|
||||
|
||||
// Update CPUTemp.
|
||||
temp, err := ioutil.ReadFile("/sys/class/thermal/thermal_zone0/temp")
|
||||
tempStr := strings.Trim(string(temp), "\n")
|
||||
t := invalidCpuTemp
|
||||
if err == nil {
|
||||
tInt, err := strconv.Atoi(tempStr)
|
||||
if err == nil {
|
||||
if tInt > 1000 {
|
||||
t = float32(tInt) / float32(1000.0)
|
||||
} else {
|
||||
t = float32(tInt) // case where Temp is returned as simple integer
|
||||
}
|
||||
}
|
||||
}
|
||||
if t >= invalidCpuTemp { // Only update if valid value was obtained.
|
||||
updater(t)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Check if CPU temperature is valid. Assume <= 0 is invalid.
|
||||
func isCPUTempValid(cpuTemp float32) bool {
|
||||
return cpuTemp > 0
|
||||
}
|
|
@ -338,3 +338,18 @@ func CalcAltitude(press float64) (altitude float64) {
|
|||
altitude = 145366.45 * (1.0 - math.Pow(press/1013.25, 0.190284))
|
||||
return
|
||||
}
|
||||
|
||||
// golang only defines min/max for float64. Really.
|
||||
func iMin(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func iMax(x, y int) int {
|
||||
if x > y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/takama/daemon"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// #include <wiringPi.h>
|
||||
// #cgo LDFLAGS: -lwiringPi
|
||||
import "C"
|
||||
|
||||
const (
|
||||
// CPU temperature target, degrees C
|
||||
defaultTempTarget = 50.
|
||||
hysteresis = float32(1.)
|
||||
|
||||
/* This puts our PWM frequency at 19.2 MHz / 128 =
|
||||
/* 150kHz. Higher frequencies will reduce audible switching
|
||||
/* noise but will be less efficient */
|
||||
pwmClockDivisor = 128
|
||||
|
||||
/* Minimum duty cycle is the point below which the fan does
|
||||
/* not spin. This depends on both your fan and the switching
|
||||
/* transistor used. */
|
||||
defaultPwmDutyMin = 20
|
||||
pwmDutyMax = 256
|
||||
|
||||
// how often to update
|
||||
delaySeconds = 2
|
||||
|
||||
// GPIO-1/BCM "18"/Pin 12 on a Raspberry PI 3
|
||||
defaultPin = 1
|
||||
|
||||
// name of the service
|
||||
name = "fancontrol"
|
||||
description = "cooling fan speed control based on CPU temperature"
|
||||
|
||||
// port which daemon should be listen
|
||||
port = ":9977"
|
||||
)
|
||||
|
||||
var stdlog, errlog *log.Logger
|
||||
|
||||
func fanControl(pwmDutyMin int, pin int, tempTarget float32) {
|
||||
cPin := C.int(pin)
|
||||
C.wiringPiSetup()
|
||||
C.pwmSetMode(C.PWM_MODE_BAL)
|
||||
C.pinMode(cPin, C.PWM_OUTPUT)
|
||||
C.pwmSetRange(pwmDutyMax)
|
||||
C.pwmSetClock(pwmClockDivisor)
|
||||
C.pwmWrite(cPin, C.int(pwmDutyMin))
|
||||
temp := float32(0.)
|
||||
go cpuTempMonitor(func(cpuTemp float32) {
|
||||
if isCPUTempValid(cpuTemp) {
|
||||
temp = cpuTemp
|
||||
}
|
||||
})
|
||||
pwmDuty := 0
|
||||
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
|
||||
}
|
||||
}
|
||||
//log.Println(temp, " ", pwmDuty)
|
||||
C.pwmWrite(cPin, C.int(pwmDuty))
|
||||
time.Sleep(delaySeconds * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// Service has embedded daemon
|
||||
type Service struct {
|
||||
daemon.Daemon
|
||||
}
|
||||
|
||||
// Manage by daemon commands or run the daemon
|
||||
func (service *Service) Manage() (string, error) {
|
||||
|
||||
tempTarget := flag.Float64("temp", defaultTempTarget, "Target CPU Temperature, degrees C")
|
||||
pwmDutyMin := flag.Int("minduty", defaultPwmDutyMin, "Minimum PWM duty cycle")
|
||||
pin := flag.Int("pin", defaultPin, "PWM pin (wiringPi numbering)")
|
||||
flag.Parse()
|
||||
|
||||
usage := "Usage: " + name + " install | remove | start | stop | status"
|
||||
// if received any kind of command, do it
|
||||
if flag.NArg() > 0 {
|
||||
command := os.Args[flag.NFlag()+1]
|
||||
switch command {
|
||||
case "install":
|
||||
return service.Install()
|
||||
case "remove":
|
||||
return service.Remove()
|
||||
case "start":
|
||||
return service.Start()
|
||||
case "stop":
|
||||
return service.Stop()
|
||||
case "status":
|
||||
return service.Status()
|
||||
default:
|
||||
return usage, nil
|
||||
}
|
||||
}
|
||||
|
||||
go fanControl(*pwmDutyMin, *pin, float32(*tempTarget))
|
||||
|
||||
// Set up channel on which to send signal notifications.
|
||||
// We must use a buffered channel or risk missing the signal
|
||||
// if we're not ready to receive when the signal is sent.
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
for {
|
||||
buf := make([]byte, 4096)
|
||||
numbytes, err := client.Read(buf)
|
||||
if numbytes == 0 || err != nil {
|
||||
return
|
||||
}
|
||||
client.Write(buf[:numbytes])
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
stdlog = log.New(os.Stdout, "", 0)
|
||||
errlog = log.New(os.Stderr, "", 0)
|
||||
}
|
||||
|
||||
func main() {
|
||||
srv, err := daemon.New(name, description, []string{}...)
|
||||
if err != nil {
|
||||
errlog.Println("Error: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
service := &Service{srv}
|
||||
status, err := service.Manage()
|
||||
if err != nil {
|
||||
errlog.Println(status, "\nError: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(status)
|
||||
}
|
|
@ -457,7 +457,7 @@ func makeStratuxStatus() []byte {
|
|||
}
|
||||
|
||||
// Valid/Enabled: CPU temperature portion.
|
||||
if isCPUTempValid() {
|
||||
if isCPUTempValid(globalStatus.CPUTemp) {
|
||||
msg[13] = msg[13] | (1 << 4)
|
||||
}
|
||||
|
||||
|
@ -753,45 +753,6 @@ func updateMessageStats() {
|
|||
|
||||
}
|
||||
|
||||
// Check if CPU temperature is valid. Assume <= 0 is invalid.
|
||||
func isCPUTempValid() bool {
|
||||
return globalStatus.CPUTemp > 0
|
||||
}
|
||||
|
||||
/*
|
||||
cpuMonitor() reads the RPi board temperature every second and updates it in globalStatus.
|
||||
This is broken out into its own function (run as its own goroutine) because the RPi temperature
|
||||
monitor code is buggy, and often times reading this file hangs quite some time.
|
||||
*/
|
||||
func cpuMonitor() {
|
||||
timer := time.NewTicker(1 * time.Second)
|
||||
for {
|
||||
<-timer.C
|
||||
|
||||
// Update CPUTemp.
|
||||
temp, err := ioutil.ReadFile("/sys/class/thermal/thermal_zone0/temp")
|
||||
tempStr := strings.Trim(string(temp), "\n")
|
||||
t := float32(-99.0)
|
||||
if err == nil {
|
||||
tInt, err := strconv.Atoi(tempStr)
|
||||
if err == nil {
|
||||
if tInt > 1000 {
|
||||
t = float32(tInt) / float32(1000.0)
|
||||
} else {
|
||||
t = float32(tInt) // case where Temp is returned as simple integer
|
||||
}
|
||||
}
|
||||
}
|
||||
if t >= -99.0 { // Only update if valid value was obtained.
|
||||
globalStatus.CPUTemp = t
|
||||
}
|
||||
|
||||
// Update CPULoad.
|
||||
data, err := ioutil.ReadFile("/proc/loadavg")
|
||||
globalStatus.CPULoad = string(data[0:14])
|
||||
}
|
||||
}
|
||||
|
||||
func updateStatus() {
|
||||
if mySituation.GPSFixQuality == 2 {
|
||||
globalStatus.GPS_solution = "GPS + SBAS (WAAS)"
|
||||
|
@ -1528,7 +1489,9 @@ func main() {
|
|||
go printStats()
|
||||
|
||||
// Monitor RPi CPU temp.
|
||||
go cpuMonitor()
|
||||
go cpuTempMonitor(func(cpuTemp float32) {
|
||||
globalStatus.CPUTemp = cpuTemp
|
||||
})
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
|
|
44
main/gps.go
44
main/gps.go
|
@ -330,50 +330,6 @@ func initGPSSerial() bool {
|
|||
p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF1, 0x03, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00})) // Ublox,3
|
||||
p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF1, 0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00})) // Ublox,4
|
||||
|
||||
// Power save mode.
|
||||
|
||||
// UBX-CFG-PM2.
|
||||
pm2 := make([]byte, 44)
|
||||
pm2[0] = 1 // Version.
|
||||
|
||||
// flags.
|
||||
pm2[4] = 0
|
||||
pm2[5] = 0 // ON/OFF mode.
|
||||
pm2[6] = 4 + 8 + 16 // WaitTimeFix+updateRTC+updateEPH.
|
||||
pm2[7] = 32 // extintWake.
|
||||
|
||||
// updatePeriod.
|
||||
pm2[8] = 0
|
||||
pm2[9] = 0
|
||||
pm2[10] = 0x3A // 15000ms.
|
||||
pm2[11] = 0x98
|
||||
|
||||
// searchPeriod.
|
||||
pm2[12] = 0
|
||||
pm2[13] = 0
|
||||
pm2[14] = 0x3A // 15000ms.
|
||||
pm2[15] = 0x98
|
||||
|
||||
// gridOffset.
|
||||
pm2[16] = 0
|
||||
pm2[17] = 0
|
||||
pm2[18] = 0
|
||||
pm2[19] = 0
|
||||
|
||||
// onTime.
|
||||
pm2[20] = 0
|
||||
pm2[21] = 15 // 15s.
|
||||
|
||||
// minAcqTime.
|
||||
pm2[22] = 0
|
||||
pm2[23] = 15 // 15s.
|
||||
|
||||
p.Write(makeUBXCFG(0x06, 0x3B, 44, pm2))
|
||||
|
||||
// UBX-CFG-RXM.
|
||||
|
||||
p.Write(makeUBXCFG(0x06, 0x11, 2, []byte{8, 1})) // Enable.
|
||||
|
||||
// Reconfigure serial port.
|
||||
cfg := make([]byte, 20)
|
||||
cfg[0] = 0x01 // portID.
|
||||
|
|
|
@ -16,6 +16,7 @@ make
|
|||
rm -rf work
|
||||
mkdir -p work/bin
|
||||
cp gen_gdl90 work/bin/
|
||||
cp fancontrol work/bin/
|
||||
cp libdump978.so work/bin/
|
||||
cp linux-mpu9150/libimu.so work/bin/
|
||||
cp __lib__systemd__system__stratux.service work/bin/
|
||||
|
@ -34,8 +35,8 @@ cp image/sdr-tool.sh work/bin/
|
|||
cp image/10-stratux.rules work/bin/
|
||||
cp image/99-uavionix.rules work/bin/
|
||||
cp image/motd work/bin/
|
||||
cp image/fancontrol.py work/bin/
|
||||
cp image/stratux-wifi.sh work/bin/
|
||||
cp image/rc.local work/bin/
|
||||
|
||||
#TODO: librtlsdr.
|
||||
cd work/
|
||||
|
|
|
@ -35,6 +35,9 @@ cp -f sdr-tool.sh /usr/sbin/
|
|||
#boot config
|
||||
cp -f config.txt /boot/config.txt
|
||||
|
||||
#rc.local
|
||||
cp -f rc.local /etc/
|
||||
|
||||
#disable serial console
|
||||
sed -i /boot/cmdline.txt -e "s/console=ttyAMA0,[0-9]\+ //"
|
||||
|
||||
|
@ -56,8 +59,13 @@ cp -f modules.txt /etc/modules
|
|||
cp -f motd /etc/motd
|
||||
|
||||
#fan control utility
|
||||
cp -f fancontrol.py /usr/bin/
|
||||
chmod 755 /usr/bin/fancontrol.py
|
||||
#remove old script
|
||||
rm -f /usr/bin/fancontrol.py
|
||||
#install new program
|
||||
cp -f fancontrol /usr/bin/
|
||||
chmod 755 /usr/bin/fancontrol
|
||||
/usr/bin/fancontrol remove
|
||||
/usr/bin/fancontrol install
|
||||
|
||||
cp -f dump1090 /usr/bin/
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue