cleanup
This commit is contained in:
parent
01f5651377
commit
a58f3e8b5f
7
Makefile
Normal file
7
Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
build:
|
||||
go build main.go
|
||||
run:
|
||||
go run main.go
|
||||
clean:
|
||||
rm -rf test.db main
|
||||
|
@ -1,14 +1,16 @@
|
||||
[TH7]
|
||||
port = 9090
|
||||
logfreq = 60
|
||||
debug = true
|
||||
|
||||
[DB]
|
||||
type = "sqlite3"
|
||||
path = "test.db"
|
||||
freq = 60
|
||||
|
||||
[Channel_2]
|
||||
type = 'N'
|
||||
unit = 'C'
|
||||
filter.samples = 20
|
||||
|
||||
[Channel_3]
|
||||
type = 'T'
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"th7/data/config"
|
||||
"th7/data/temperature"
|
||||
"th7/data/thermocouple"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
@ -28,12 +27,6 @@ var (
|
||||
"T": thermocouple.T,
|
||||
"UV": thermocouple.None,
|
||||
}
|
||||
temperatureUnits = map[string]temperature.Unit{
|
||||
"C": temperature.C,
|
||||
"F": temperature.F,
|
||||
"K": temperature.K,
|
||||
"UV": temperature.None,
|
||||
}
|
||||
)
|
||||
|
||||
func getThermocoupleType(t string) (thermocouple.Type, error) {
|
||||
@ -45,15 +38,6 @@ func getThermocoupleType(t string) (thermocouple.Type, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func getTemperatureUnit(u string) (temperature.Unit, error) {
|
||||
u = strings.ToUpper(u)
|
||||
if val, ok := temperatureUnits[u]; ok {
|
||||
return val, nil
|
||||
} else {
|
||||
return temperature.None, ErrConfigBadTemperatureUnit
|
||||
}
|
||||
}
|
||||
|
||||
func Load() (config.Config, error) {
|
||||
|
||||
var cfg config.Config
|
||||
@ -71,14 +55,14 @@ func Load() (config.Config, error) {
|
||||
v.SetDefault("TH7.port", 8080)
|
||||
v.SetDefault("TH7.cache", true)
|
||||
v.SetDefault("TH7.LED", true)
|
||||
v.SetDefault("TH7.logfreq", 60)
|
||||
v.SetDefault("TH7.debug", false)
|
||||
v.SetDefault("TH7.nolog", false)
|
||||
v.SetDefault("DB.freq", 60)
|
||||
|
||||
cfg.Board.Port = v.GetInt("TH7.port")
|
||||
cfg.Board.Cache = v.GetBool("TH7.cache")
|
||||
cfg.Board.Led = v.GetBool("TH7.LED")
|
||||
cfg.Board.Logfreq = v.GetInt("TH7.logfreq")
|
||||
cfg.Board.Logfreq = v.GetInt("DB.freq")
|
||||
cfg.Board.Debug = v.GetBool("TH7.debug")
|
||||
cfg.Board.NoLogging = v.GetBool("TH7.nolog")
|
||||
|
||||
@ -91,11 +75,12 @@ func Load() (config.Config, error) {
|
||||
v.SetDefault(head+".gain", 106.8)
|
||||
v.SetDefault(head+".offset", 0.0)
|
||||
v.SetDefault(head+".unit", "UV")
|
||||
// filter settings
|
||||
v.SetDefault(head+".filter.samples", 50)
|
||||
}
|
||||
|
||||
for i := 1; i < 8; i++ {
|
||||
var c config.Channel
|
||||
var unit temperature.Unit
|
||||
var tc thermocouple.Type
|
||||
var head = fmt.Sprintf("Channel_%d", i)
|
||||
|
||||
@ -114,16 +99,7 @@ func Load() (config.Config, error) {
|
||||
}
|
||||
c.Thermo = tc
|
||||
|
||||
if tc == thermocouple.None {
|
||||
unit = temperature.None
|
||||
} else {
|
||||
unit, err = getTemperatureUnit(v.GetString(head + ".unit"))
|
||||
if err != nil {
|
||||
fmt.Printf("%s.unit=%s\n", head, v.GetString(head+".unit"))
|
||||
return cfg, err
|
||||
}
|
||||
}
|
||||
c.Unit = unit
|
||||
c.Filter.SampleSize = v.GetInt(head+".filter.samples")
|
||||
|
||||
cfg.Channels = append(cfg.Channels, c)
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package th7
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
temp_data "th7/data/temperature"
|
||||
"th7/temperature"
|
||||
thermo_data "th7/data/thermocouple"
|
||||
"th7/filter"
|
||||
"th7/thermocouple"
|
||||
"time"
|
||||
)
|
||||
@ -15,22 +15,11 @@ const (
|
||||
DurWaitRestart = 1000 * time.Millisecond
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO: configurable global or per-channel sample
|
||||
Samples = 50
|
||||
)
|
||||
|
||||
// TODO: per-channel configurable filter(-stages)
|
||||
func alphaBetaFilter(arr []float64, init float64) float64 {
|
||||
|
||||
value := init
|
||||
for i := range arr {
|
||||
gain := 1.0 / (float64(i + 1))
|
||||
value += (gain*arr[i] - value)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// Continuously sample each configured channel, apply filter, and save result
|
||||
// in a mutex controlled shared data object, that can be accessed at any time
|
||||
// by a web-request or similar.
|
||||
func startCacheService(t *TH7Adapter) {
|
||||
|
||||
data := t.data
|
||||
@ -39,7 +28,7 @@ func startCacheService(t *TH7Adapter) {
|
||||
|
||||
// init
|
||||
for i := range samples {
|
||||
samples[i] = make([]float64, Samples)
|
||||
samples[i] = make([]float64, t.cfg.Channels[i].Filter.SampleSize)
|
||||
}
|
||||
|
||||
duroffset := time.Duration(0) * time.Millisecond
|
||||
@ -48,18 +37,16 @@ func startCacheService(t *TH7Adapter) {
|
||||
|
||||
timer_start := time.Now()
|
||||
|
||||
for i := 0; i < Samples; i++ {
|
||||
for channel := range t.cfg.Channels {
|
||||
|
||||
// update Table
|
||||
channel_id := t.cfg.Channels[channel].Id
|
||||
channel_gain := t.cfg.Channels[channel].Gain
|
||||
|
||||
for i:=0; i<t.cfg.Channels[channel].Filter.SampleSize; i++ {
|
||||
// update vref table
|
||||
t.pcbPort.UpdateTable()
|
||||
|
||||
for k := range t.cfg.Channels {
|
||||
channel_id := t.cfg.Channels[k].Id
|
||||
channel_gain := t.cfg.Channels[k].Gain
|
||||
|
||||
val := t.pcbPort.ReadChannel(channel_id, channel_gain)
|
||||
|
||||
samples[k][i] = val
|
||||
measurement := t.pcbPort.ReadChannel(channel_id, channel_gain)
|
||||
samples[channel][i] = measurement
|
||||
time.Sleep(DurWaitBetweenSample)
|
||||
}
|
||||
time.Sleep(DurWaitBetweenChannel)
|
||||
@ -67,44 +54,38 @@ func startCacheService(t *TH7Adapter) {
|
||||
|
||||
// do alpha~beta on each channel,
|
||||
// putting the value in
|
||||
|
||||
// TODO: in config have different types.
|
||||
for i := range samples {
|
||||
data[i].Value = alphaBetaFilter(samples[i], data[i].Value)
|
||||
data[i].Value = filter.AlphaBetaFilter(samples[i], data[i].Value)
|
||||
}
|
||||
|
||||
// read pcb temp and apply CJC
|
||||
// the board temperature wont noticeably change for the ~300 ms of sampling
|
||||
// at least compared to the TC error.
|
||||
// so only reading pcb temp and applying cjc after this duration
|
||||
// probably wont affect the readings.
|
||||
pcb_temperature := t.pcbPort.ReadPCBTemp()
|
||||
|
||||
for k := range t.cfg.Channels {
|
||||
|
||||
tc := t.cfg.Channels[k].Thermo
|
||||
data[k].Unit = t.cfg.Channels[k].Unit
|
||||
thermo_type := t.cfg.Channels[k].Thermo
|
||||
data[k].Id = t.cfg.Channels[k].Id
|
||||
|
||||
// if we can apply CJC with this configuration ...
|
||||
if thermocouple.WithinTemperatureRange(tc, pcb_temperature) {
|
||||
|
||||
cjc_uv, err := thermocouple.UV(tc, pcb_temperature)
|
||||
if thermocouple.WithinTemperatureRange(thermo_type, pcb_temperature) {
|
||||
cjc_uv, err := thermocouple.UV(thermo_type, pcb_temperature)
|
||||
if err != nil {
|
||||
log.Println("Error doing CJC", err)
|
||||
cjc_uv = 0.0
|
||||
}
|
||||
|
||||
data[k].Value += cjc_uv
|
||||
|
||||
}
|
||||
// CJC can not be applied
|
||||
// board temp out of range for specified thermocouple type
|
||||
// perhaps just subtract board temperature? dont know
|
||||
//fmt.Println("No valid CJC for Channel", t.cfg.Channels[k].Id)
|
||||
|
||||
// if the temperature unit is "None", it is probably for UV only.
|
||||
// if the thermocouple unit is "None", it is for UV only.
|
||||
// so do not convert it to a value using t/c polys
|
||||
if data[k].Unit != temp_data.None {
|
||||
new_value_c, err := thermocouple.C(tc, data[k].Value)
|
||||
if t.cfg.Channels[k].Thermo != thermo_data.None {
|
||||
new_value_c, err := thermocouple.C(thermo_type, data[k].Value)
|
||||
if err != nil {
|
||||
log.Println("Error converting UV to C", t.cfg.Channels[k].Id, data[k].Value)
|
||||
new_value_c = data[k].Value
|
||||
@ -112,21 +93,7 @@ func startCacheService(t *TH7Adapter) {
|
||||
|
||||
data[k].Value = new_value_c
|
||||
|
||||
// It is celsius by default
|
||||
switch data[k].Unit {
|
||||
|
||||
case temp_data.F:
|
||||
data[k].Value = temperature.F(temp_data.C, data[k].Value)
|
||||
|
||||
case temp_data.K:
|
||||
data[k].Value = temperature.K(temp_data.C, data[k].Value)
|
||||
|
||||
}
|
||||
|
||||
// temp conv if any is applied ... add offset
|
||||
// offset is specified in the same temperature unit
|
||||
// as is specified for the channel
|
||||
// ie if unit = F then the offset counts in unit F also.
|
||||
data[k].Value += t.cfg.Channels[k].Offset
|
||||
|
||||
}
|
||||
@ -149,7 +116,12 @@ func startCacheService(t *TH7Adapter) {
|
||||
|
||||
elapsed := time.Since(timer_start)
|
||||
|
||||
fmt.Printf("updated %d channels, %d samples each (total=%d) dur=%s\n", len(samples), Samples, len(samples)*Samples, elapsed)
|
||||
total_sample_size := 0
|
||||
for k := range t.cfg.Channels {
|
||||
total_sample_size += t.cfg.Channels[k].Filter.SampleSize
|
||||
}
|
||||
|
||||
fmt.Printf("updated %d channels. %d samples. dur=%s\n", len(t.cfg.Channels), total_sample_size, elapsed)
|
||||
|
||||
if elapsed >= (DurWaitRestart + duroffset) {
|
||||
fmt.Println("timer overrun, adding 100ms")
|
||||
|
@ -1,16 +1,19 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"th7/data/temperature"
|
||||
"th7/data/thermocouple"
|
||||
)
|
||||
|
||||
type Filter struct {
|
||||
SampleSize int `json:"sample_size"`
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
Id int `json:"id"`
|
||||
Thermo thermocouple.Type `json:"thermocouple"`
|
||||
Gain float64 `json:"gain"`
|
||||
Offset float64 `json:"offset"`
|
||||
Unit temperature.Unit `json:"unit"`
|
||||
Filter Filter `json:"filter"`
|
||||
}
|
||||
|
||||
type TH7 struct {
|
||||
|
@ -1,11 +1,9 @@
|
||||
package core
|
||||
|
||||
import "th7/data/temperature"
|
||||
|
||||
type Channel struct {
|
||||
Id int `json:"id"`
|
||||
Value float64 `json:"value"`
|
||||
Unit temperature.Unit `json:"unit"`
|
||||
}
|
||||
|
||||
type Ratio struct {
|
||||
|
@ -1,10 +0,0 @@
|
||||
package temperature
|
||||
|
||||
type Unit int
|
||||
|
||||
const (
|
||||
None Unit = iota // None is UV
|
||||
K
|
||||
C
|
||||
F
|
||||
)
|
@ -19,7 +19,7 @@ func (d *DummyAdapter) Close() {
|
||||
func (d *DummyAdapter) Save(channels []core.Channel) error {
|
||||
fmt.Println("=======================================")
|
||||
for _, val := range channels {
|
||||
fmt.Printf("Saved: id=%d, unit=%d, value=%g\n", val.Id, val.Unit, val.Value)
|
||||
fmt.Printf("Saved: id=%d, value=%g\n", val.Id, val.Value)
|
||||
}
|
||||
fmt.Println("=======================================")
|
||||
return nil
|
||||
|
12
filter/filter.go
Normal file
12
filter/filter.go
Normal file
@ -0,0 +1,12 @@
|
||||
package filter
|
||||
|
||||
|
||||
func AlphaBetaFilter(arr []float64, init float64) float64 {
|
||||
|
||||
value := init
|
||||
for i := range arr {
|
||||
gain := 1.0 / (float64(i + 1))
|
||||
value += (gain*arr[i] - value)
|
||||
}
|
||||
return value
|
||||
}
|
3
main.go
3
main.go
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
@ -34,8 +33,6 @@ func main() {
|
||||
log.Fatalf("Error loading config: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(config)
|
||||
|
||||
pcbPort, err = pcb.NewAdapter(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Fatal error: %v\n", err)
|
||||
|
@ -2,7 +2,9 @@ package pcb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"th7/data/pcb"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DummyAdapter struct {
|
||||
@ -10,6 +12,7 @@ type DummyAdapter struct {
|
||||
}
|
||||
|
||||
func NewDummyAdapter() (*DummyAdapter, error) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return &DummyAdapter{}, nil
|
||||
}
|
||||
|
||||
@ -29,7 +32,7 @@ func (d *DummyAdapter) GetTable() pcb.Table {
|
||||
}
|
||||
|
||||
func (d *DummyAdapter) ReadChannel(id int, gain float64) float64 {
|
||||
return -9000.0
|
||||
return -9000.0 * rand.Float64()
|
||||
}
|
||||
|
||||
func (d *DummyAdapter) ReadPCBTemp() float64 {
|
||||
|
@ -1,68 +0,0 @@
|
||||
package temperature
|
||||
|
||||
import (
|
||||
"th7/data/temperature"
|
||||
)
|
||||
|
||||
func c_to_k(val float64) float64 {
|
||||
return val + 273.15
|
||||
}
|
||||
|
||||
func c_to_f(val float64) float64 {
|
||||
return (val * 9 / 5) + 32.0
|
||||
}
|
||||
|
||||
func f_to_c(val float64) float64 {
|
||||
return (val - 32.0) * 5 / 9
|
||||
}
|
||||
|
||||
func f_to_k(val float64) float64 {
|
||||
return (val-32.0)*5/9 + 273.15
|
||||
}
|
||||
|
||||
func k_to_c(val float64) float64 {
|
||||
return val - 273.15
|
||||
}
|
||||
|
||||
func k_to_f(val float64) float64 {
|
||||
return (val-273.15)*9/5 + 32.0
|
||||
}
|
||||
|
||||
func C(unit temperature.Unit, value float64) float64 {
|
||||
switch unit {
|
||||
case temperature.C:
|
||||
return value
|
||||
case temperature.F:
|
||||
return c_to_f(value)
|
||||
case temperature.K:
|
||||
return c_to_k(value)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func F(unit temperature.Unit, value float64) float64 {
|
||||
switch unit {
|
||||
case temperature.F:
|
||||
return value
|
||||
case temperature.C:
|
||||
return f_to_c(value)
|
||||
case temperature.K:
|
||||
return f_to_k(value)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func K(unit temperature.Unit, value float64) float64 {
|
||||
switch unit {
|
||||
case temperature.K:
|
||||
return value
|
||||
case temperature.F:
|
||||
return k_to_f(value)
|
||||
case temperature.C:
|
||||
return k_to_c(value)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
@ -95,8 +95,10 @@ func NewGinAdapter(corePort ports.CorePort, port int) *GinAdapter {
|
||||
adapter.corePort = corePort
|
||||
adapter.port = port
|
||||
|
||||
adapter.router = gin.Default()
|
||||
//adapter.router = gin.Default()
|
||||
adapter.router = gin.New()
|
||||
|
||||
// API
|
||||
adapter.router.GET("/ratio", adapter.RatioHandler)
|
||||
adapter.router.GET("/channels", adapter.ChannelsHandler)
|
||||
adapter.router.GET("/channel/:id", adapter.ChannelByIDHandler)
|
||||
|
Loading…
Reference in New Issue
Block a user