2026-08-01 Anzeige der 5 Spannungen und Schalten des einen Relais funktioniert
This commit is contained in:
parent
f29a8bbd8d
commit
10ce58541e
5 changed files with 116 additions and 47 deletions
3
build.sh
3
build.sh
|
|
@ -64,7 +64,8 @@ StartLimitIntervalSec=0
|
|||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/bash -c 'for i in {1..10}; do i2cdetect -y 1 | grep -E "^40:" | grep -q -E "\b48\b" && exit 0; echo "warte auf ADS1115..."; sleep 2; done; exit 1'
|
||||
ExecStartPre=/bin/bash -c 'for i in {1..10}; do i2cdetect -y 1 | grep -E "^40:" | grep -q -E "\b48\b" && i2cdetect -y 1 | grep -E "^40:" | grep -q -E "\b49\b" && exit 0; echo "warte auf ADS1115 Module..."; sleep 2; done; exit 1'
|
||||
|
||||
ExecStart=%h/spannung/app/spannung-arm32_7
|
||||
WorkingDirectory=%h/spannung/app
|
||||
User=%u
|
||||
|
|
|
|||
12
config.json
12
config.json
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"web_port": ":8080",
|
||||
"i2c_bus": "/dev/i2c-1",
|
||||
"ads1115_address": 72,
|
||||
"voltage_factor_1": 5.0,
|
||||
"voltage_factor_2": 5.0,
|
||||
"i2c_bus": "1",
|
||||
"ads1115_address_1": 72,
|
||||
"ads1115_address_2": 73,
|
||||
"factor_adc1_ch0": 5.0,
|
||||
"factor_adc1_ch1": 5.0,
|
||||
"factor_adc1_ch2": 1.0,
|
||||
"factor_adc1_ch3": 1.0,
|
||||
"factor_adc2_ch0": 1.0,
|
||||
"relais_pins": [
|
||||
{"id": 1, "name": "Relais 1 (Hauptschalter)", "gpio": "GPIO12"},
|
||||
{"id": 2, "name": "Relais 2 (unbenutzt)", "gpio": "GPIO16"},
|
||||
|
|
|
|||
100
main.go
100
main.go
|
|
@ -7,7 +7,7 @@ import (
|
|||
"os"
|
||||
"sync"
|
||||
|
||||
"spannung/web" // Importiert das neue eigene web-Paket
|
||||
"spannung/web" // Importiert das eigene web-Paket
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/gpio/gpioreg"
|
||||
|
|
@ -18,12 +18,16 @@ import (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
WebPort string `json:"web_port"`
|
||||
I2CBus string `json:"i2c_bus"`
|
||||
ADS1115Address uint16 `json:"ads1115_address"`
|
||||
Factor1 float64 `json:"voltage_factor_1"`
|
||||
Factor2 float64 `json:"voltage_factor_2"`
|
||||
Relais []RelaisConf `json:"relais_pins"`
|
||||
WebPort string `json:"web_port"`
|
||||
I2CBus string `json:"i2c_bus"`
|
||||
ADS1115Address1 uint16 `json:"ads1115_address_1"`
|
||||
ADS1115Address2 uint16 `json:"ads1115_address_2"`
|
||||
FactorAdc1Ch0 float64 `json:"factor_adc1_ch0"`
|
||||
FactorAdc1Ch1 float64 `json:"factor_adc1_ch1"`
|
||||
FactorAdc1Ch2 float64 `json:"factor_adc1_ch2"`
|
||||
FactorAdc1Ch3 float64 `json:"factor_adc1_ch3"`
|
||||
FactorAdc2Ch0 float64 `json:"factor_adc2_ch0"`
|
||||
Relais []RelaisConf `json:"relais_pins"`
|
||||
}
|
||||
|
||||
type RelaisConf struct {
|
||||
|
|
@ -34,13 +38,13 @@ type RelaisConf struct {
|
|||
}
|
||||
|
||||
var (
|
||||
config Config
|
||||
adsDevice *ads1x15.Dev
|
||||
relaisMap = make(map[int]gpio.PinIO)
|
||||
mutex sync.Mutex
|
||||
// Diese Variablen werden durch -ldflags beim Kompilieren befüllt:
|
||||
Version = "Entwicklung"
|
||||
BuildDate = "Unbekannt"
|
||||
config Config
|
||||
adsDevice1 *ads1x15.Dev
|
||||
adsDevice2 *ads1x15.Dev
|
||||
relaisMap = make(map[int]gpio.PinIO)
|
||||
mutex sync.Mutex
|
||||
Version = "Entwicklung"
|
||||
BuildDate = "Unbekannt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
@ -61,12 +65,20 @@ func main() {
|
|||
log.Fatalf("I2C Bus Fehler: %v", err)
|
||||
}
|
||||
|
||||
opts := ads1x15.DefaultOpts
|
||||
opts.I2cAddress = config.ADS1115Address
|
||||
|
||||
adsDevice, err = ads1x15.NewADS1115(bus, &opts)
|
||||
// 1. Ersten ADS1115 initialisieren (z.B. Adresse 72 / 0x48)
|
||||
opts1 := ads1x15.DefaultOpts
|
||||
opts1.I2cAddress = config.ADS1115Address1
|
||||
adsDevice1, err = ads1x15.NewADS1115(bus, &opts1)
|
||||
if err != nil {
|
||||
log.Fatalf("ADS1115 Init fehlgeschlagen: %v", err)
|
||||
log.Fatalf("ADS1115 #1 Init fehlgeschlagen: %v", err)
|
||||
}
|
||||
|
||||
// 2. Zweiten ADS1115 initialisieren (z.B. Adresse 73 / 0x49)
|
||||
opts2 := ads1x15.DefaultOpts
|
||||
opts2.I2cAddress = config.ADS1115Address2
|
||||
adsDevice2, err = ads1x15.NewADS1115(bus, &opts2)
|
||||
if err != nil {
|
||||
log.Fatalf("ADS1115 #2 Init fehlgeschlagen: %v", err)
|
||||
}
|
||||
|
||||
// GPIO-Pins registrieren
|
||||
|
|
@ -85,28 +97,49 @@ func main() {
|
|||
// Instanziierung des Webservers mit Übergabe der Callback-Funktionen
|
||||
server := web.NewServer(config.WebPort, readVoltageCallback, toggleRelaisCallback, getRelaisStateCallback, callbackGetVersion)
|
||||
|
||||
|
||||
fmt.Printf("Webserver gestartet auf Port %s\n", config.WebPort)
|
||||
log.Fatal(server.Start())
|
||||
}
|
||||
|
||||
// Callback: Wird vom Webserver aufgerufen, um Kanäle zu messen
|
||||
// Kanäle 0-3 = ADS1115 Nr. 1 (A0-A3)
|
||||
// Kanal 4 = ADS1115 Nr. 2 (A0)
|
||||
func readVoltageCallback(channel int) float64 {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
var targetDevice *ads1x15.Dev
|
||||
var adsChannel ads1x15.Channel
|
||||
var factor float64
|
||||
|
||||
if channel == 0 {
|
||||
switch channel {
|
||||
case 0:
|
||||
targetDevice = adsDevice1
|
||||
adsChannel = ads1x15.Channel0
|
||||
factor = config.Factor1
|
||||
} else {
|
||||
factor = config.FactorAdc1Ch0
|
||||
case 1:
|
||||
targetDevice = adsDevice1
|
||||
adsChannel = ads1x15.Channel1
|
||||
factor = config.Factor2
|
||||
factor = config.FactorAdc1Ch1
|
||||
case 2:
|
||||
targetDevice = adsDevice1
|
||||
adsChannel = ads1x15.Channel2
|
||||
factor = config.FactorAdc1Ch2
|
||||
case 3:
|
||||
targetDevice = adsDevice1
|
||||
adsChannel = ads1x15.Channel3
|
||||
factor = config.FactorAdc1Ch3
|
||||
case 4:
|
||||
targetDevice = adsDevice2
|
||||
adsChannel = ads1x15.Channel0 // Erster Eingang vom zweiten Chip
|
||||
factor = config.FactorAdc2Ch0
|
||||
|
||||
default:
|
||||
fmt.Printf("Ungültiger Kanal abgefragt: %v\n", channel)
|
||||
return 0.0
|
||||
}
|
||||
|
||||
pin, err := adsDevice.PinForChannel(adsChannel, physic.Volt*4096/1000, 128*physic.Hertz, 0)
|
||||
pin, err := targetDevice.PinForChannel(adsChannel, physic.Volt*4096/1000, 128*physic.Hertz, 0)
|
||||
if err != nil {
|
||||
fmt.Printf("Fehler beim Erzeugen des Pins für Kanal %v: %v\n", channel, err)
|
||||
return 0.0
|
||||
|
|
@ -132,21 +165,24 @@ func toggleRelaisCallback(id int) {
|
|||
return
|
||||
}
|
||||
|
||||
for i, rel := range config.Relais {
|
||||
if rel.ID == id {
|
||||
newState := !rel.State
|
||||
config.Relais[i].State = newState
|
||||
// Direkt über den Index das globale Slice manipulieren
|
||||
for i := range config.Relais {
|
||||
if config.Relais[i].ID == id {
|
||||
// Status sauber invertieren
|
||||
config.Relais[i].State = !config.Relais[i].State
|
||||
|
||||
if newState {
|
||||
pin.Out(gpio.High)
|
||||
// Hardware basierend auf dem neuen, echten Zustand schalten
|
||||
if config.Relais[i].State {
|
||||
pin.Out(gpio.High) // Wenn True -> Pin High
|
||||
} else {
|
||||
pin.Out(gpio.Low)
|
||||
pin.Out(gpio.Low) // Wenn False -> Pin Low
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback: Wird vom Webserver aufgerufen, um den aktuellen UI-Status abzufragen
|
||||
func getRelaisStateCallback() []web.RelaisData {
|
||||
mutex.Lock()
|
||||
|
|
|
|||
|
|
@ -12,10 +12,13 @@ type RelaisData struct {
|
|||
State bool
|
||||
}
|
||||
|
||||
// TemplateData erweitern um Version und Datum
|
||||
// TemplateData erweitert um alle 5 Spannungskanäle
|
||||
type TemplateData struct {
|
||||
V1 float64
|
||||
V2 float64
|
||||
V1 float64 // ADC 1 - Kanal 0
|
||||
V2 float64 // ADC 1 - Kanal 1
|
||||
V3 float64 // ADC 1 - Kanal 2
|
||||
V4 float64 // ADC 1 - Kanal 3
|
||||
V5 float64 // ADC 2 - Kanal 0
|
||||
Relais []RelaisData
|
||||
Version string
|
||||
BuildDate string
|
||||
|
|
@ -26,10 +29,9 @@ type Server struct {
|
|||
readVoltFunc func(channel int) float64
|
||||
toggleFunc func(id int)
|
||||
getRelais func() []RelaisData
|
||||
versionFunc func() (string, string) // Neu hinzugefügt
|
||||
versionFunc func() (string, string)
|
||||
}
|
||||
|
||||
// NewServer um das version-Callback erweitern
|
||||
func NewServer(port string, readVolt func(int) float64, toggle func(int), getRelais func() []RelaisData, getVersion func() (string, string)) *Server {
|
||||
return &Server{
|
||||
port: port,
|
||||
|
|
@ -47,9 +49,13 @@ func (s *Server) Start() error {
|
|||
}
|
||||
|
||||
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||
// Alle 5 Kanäle nacheinander über das Callback einlesen
|
||||
v1 := s.readVoltFunc(0)
|
||||
v2 := s.readVoltFunc(1)
|
||||
ver, date := s.versionFunc() // Version abfragen
|
||||
v3 := s.readVoltFunc(2)
|
||||
v4 := s.readVoltFunc(3)
|
||||
v5 := s.readVoltFunc(4)
|
||||
ver, date := s.versionFunc()
|
||||
|
||||
tmpl, err := template.ParseFiles("web/static/index.html")
|
||||
if err != nil {
|
||||
|
|
@ -60,9 +66,12 @@ func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
|
|||
data := TemplateData{
|
||||
V1: v1,
|
||||
V2: v2,
|
||||
V3: v3,
|
||||
V4: v4,
|
||||
V5: v5,
|
||||
Relais: s.getRelais(),
|
||||
Version: ver, // Daten an Template übergeben
|
||||
BuildDate: date, // Daten an Template übergeben
|
||||
Version: ver,
|
||||
BuildDate: date,
|
||||
}
|
||||
tmpl.Execute(w, data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,15 +22,33 @@
|
|||
<div class="container">
|
||||
<h1>U12V Funkstations-Monitor</h1>
|
||||
|
||||
<!-- Alle 5 Spannungen strikt untereinander -->
|
||||
<div class="card">
|
||||
<h3>Spannungsebene 1</h3>
|
||||
<h3>ADC 1 - Kanal 0</h3>
|
||||
<div class="val">{{printf "%.2f" .V1}} V</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Spannungsebene 2</h3>
|
||||
<h3>ADC 1 - Kanal 1</h3>
|
||||
<div class="val">{{printf "%.2f" .V2}} V</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>ADC 1 - Kanal 2</h3>
|
||||
<div class="val">{{printf "%.2f" .V3}} V</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>ADC 1 - Kanal 3</h3>
|
||||
<div class="val">{{printf "%.2f" .V4}} V</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>ADC 2 - Kanal 0</h3>
|
||||
<div class="val">{{printf "%.2f" .V5}} V</div>
|
||||
</div>
|
||||
|
||||
<!-- Relaissteuerung -->
|
||||
<div class="card">
|
||||
<h3>Relaissteuerung</h3>
|
||||
<div class="grid">
|
||||
|
|
@ -43,6 +61,7 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-nav">
|
||||
Aktualisiert alle 3 Sekunden automatisch<br>
|
||||
<span style="font-size: 0.8em; color: #475569; margin-top: 5px; display: block;">
|
||||
|
|
|
|||
Loading…
Reference in a new issue