package main import ( "errors" "fmt" "github.com/warthog618/gpio" "math" "os" "os/signal" "syscall" "time" ) 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) 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) <-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 } } return nil } func cyclesForReading(pin *gpio.Pin, level gpio.Level) int { count := 0 for pin.Read() == level { count++ if count >= oneSecondInCycles { return Timeout } } return count }