From d5e9eb31cd0bbdfbc2736fc56a395885bc726ff3 Mon Sep 17 00:00:00 2001 From: Daniel Ledda Date: Sat, 31 Oct 2020 15:08:45 +0100 Subject: [PATCH] First try! --- main.go | 103 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 18 deletions(-) diff --git a/main.go b/main.go index d7ef77d..c6d3e1c 100644 --- a/main.go +++ b/main.go @@ -2,44 +2,111 @@ package main import ( "fmt" + "github.com/pkg/errors" + "github.com/warthog618/gpio" + "math" "os" "os/signal" "syscall" "time" - - "github.com/warthog618/gpio" ) -// Watches GPIO 4 (J8 7) and reports when it changes state. +const Timeout = math.MaxInt32 +const TimeoutErrInitial string = "Timed out waiting for sensor's initial %s reading!" + +var oneSecondInCycles = (func() int { + count := 0 + start := time.Now().Nanosecond() + for { + count++ + if time.Now().Nanosecond() - start >= 1000000 { + break + } + } + return count +})() + func main() { err := gpio.Open() if err != nil { panic(err) } defer gpio.Close() + pinNumber := gpio.GPIO7 pin := gpio.NewPin(pinNumber) - pin.Input() - pin.PullUp() + result, err := readDataFromDHT(pin) + if err != nil { + fmt.Printf("Bad read! Reason: %s", err.Error()) + } else { + fmt.Println(result) + } // capture exit signals to ensure resources are released on exit. quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) defer signal.Stop(quit) - err = pin.Watch(gpio.EdgeBoth, func(pin *gpio.Pin) { - fmt.Printf("Pin %v is %v", pinNumber, pin.Read()) - }) - if err != nil { - panic(err) - } - defer pin.Unwatch() + <-quit +} - // In a real application the main thread would do something useful here. - // But we'll just run for a minute then exit. - fmt.Printf("Watching Pin %v...", pinNumber) - select { - case <-time.After(time.Minute): - case <-quit: +func readDataFromDHT(pin *gpio.Pin) ([4]byte, error) { + receivedInput := [4]byte{0, 0, 0, 0} + // Setup + pin.PullUp() + + // Send start signal + pin.Low() + pin.Output() + time.Sleep(1100 * time.Microsecond) + pin.Input() + pin.PullUp() + time.Sleep(40 * time.Microsecond) + + // Get Data + if cyclesForReading(pin, gpio.Low) == Timeout { + return receivedInput, errors.New(fmt.Sprintf(TimeoutErrInitial, "low")) } + if cyclesForReading(pin, gpio.High) == Timeout { + return receivedInput, errors.New(fmt.Sprintf(TimeoutErrInitial, "high")) + } + + // Store cycle number for each low and high pulse + cycles := [80]int{} + for i := 0; i < 80; i += 2 { + cycles[i] = cyclesForReading(pin, gpio.Low) + cycles[i + 1] = cyclesForReading(pin, gpio.High) + } + + err := storeCycleCountsAsBinarySequence(&receivedInput, &cycles) + if err != nil { + return receivedInput, err + } + + return receivedInput, nil +} + +func storeCycleCountsAsBinarySequence(store *[4]byte, cycles *[80]int) error { + for i := 0; i < 40; i++ { + lowCycles := cycles[2 * i] + highCycles := cycles[2 * i + 1] + if (lowCycles == Timeout) || (highCycles == Timeout) { + return errors.New("Timed out waiting for sensor pulse!") + } + store[i / 8] <<= 1 + if highCycles > lowCycles { + store[i / 8] |= 1 + } + } +} + +func cyclesForReading(pin *gpio.Pin, level gpio.Level) int { + count := 0 + for pin.Read() == level { + count++ + if count >= oneSecondInCycles { + return Timeout + } + } + return count } \ No newline at end of file