Files
rpi-sensors/main.go
Daniel Ledda 07b870ef00 finding a bug
2020-10-31 16:11:01 +01:00

121 lines
2.6 KiB
Go

package main
import (
"fmt"
"errors"
"github.com/warthog618/gpio"
"math"
"time"
)
const Timeout = math.MaxInt32
const TimeoutErrInitial string = "timed out waiting for sensor's initial %s reading"
var oneSecondInCycles = (func() int {
result := cyclesInAMillisecond()
for i := 0; i < 100; i++ {
result += cyclesInAMillisecond()
}
fmt.Printf("cycles %v", result)
return result / 100
})()
func cyclesInAMillisecond() int {
count := 0
start := time.Now().UnixNano()
for {
count++
if time.Now().UnixNano() - start >= 1000000 {
break
}
}
return count
}
func main() {
err := gpio.Open()
if err != nil {
panic(err)
}
defer gpio.Close()
pin := gpio.NewPin(gpio.GPIO4)
dhtData, err := readDataFromDHT(pin)
if err != nil {
fmt.Println(fmt.Sprintf("Bad read! Reason: %s!", err.Error()))
} else {
fmt.Println(convertToRhAndTemp(dhtData))
}
}
func readDataFromDHT(pin *gpio.Pin) ([5]byte, error) {
// Setup
pin.PullUp()
time.Sleep(time.Second)
// Send start signal
pin.Low()
pin.Output()
time.Sleep(1100 * time.Microsecond)
pin.Input()
time.Sleep(30 * time.Microsecond)
// Wait for high low signal
cyclesLo := cyclesForReading(pin, gpio.Low)
if cyclesLo == Timeout {
return [5]byte{}, errors.New(fmt.Sprintf(TimeoutErrInitial, "low"))
}
cyclesHi := cyclesForReading(pin, gpio.High)
if cyclesHi == Timeout {
return [5]byte{}, errors.New(fmt.Sprintf(TimeoutErrInitial, "high"))
}
pulsesAsCycles := readPulsesAsCycles(pin)
fmt.Printf("lo %v, hi %v", cyclesLo, cyclesHi)
receivedInput, err := storeCycleCountsAsBinarySequence(&pulsesAsCycles)
if err != nil {
return [5]byte{}, err
}
return receivedInput, nil
}
func cyclesForReading(pin *gpio.Pin, level gpio.Level) int {
count := 0
for pin.Read() == level {
count++
if count >= oneSecondInCycles {
return Timeout
}
}
return count
}
func readPulsesAsCycles(pin *gpio.Pin) [80]int {
cycles := [80]int{}
for i := 0; i < 80; i += 2 {
cycles[i] = cyclesForReading(pin, gpio.Low)
cycles[i + 1] = cyclesForReading(pin, gpio.High)
}
return cycles
}
func storeCycleCountsAsBinarySequence(cycles *[80]int) ([5]byte, error) {
data := [5]byte{}
for i := 0; i < 40; i++ {
lowCycles := cycles[2 * i]
highCycles := cycles[2 * i + 1]
if (lowCycles == Timeout) || (highCycles == Timeout) {
return [5]byte{}, errors.New("timed out waiting for sensor pulse")
}
data[i / 8] <<= 1
if highCycles > lowCycles {
data[i / 8] |= 1
}
}
return data, nil
}
func convertToRhAndTemp(data [5]byte) (float32, float32) {
rh := float32(data[0]) + float32(int(data[1]) << 4)
temp := float32(data[2]) + float32(int(data[3]) << 4)
return rh/10, temp/10
}