pezi / dart_periphery

dart_periphery is a Dart port of the native c-periphery library
BSD 3-Clause "New" or "Revised" License
36 stars 9 forks source link

Can you add one-wire driver? #2

Closed tsuiwade closed 2 years ago

tsuiwade commented 3 years ago

Nice contribution! Thanks!

Can you add one-wire driver?

I had used IO to simulate the time sequence, and the result is very unstable.

Please give me your precious advice!

pezi commented 3 years ago

Hi!

For the most SoCs, Raspberry Pi and Armbian based. The one-wire integrations inside the device tree works well.

Raspberry Pi https://pinout.xyz/pinout/1_wire# Armbian example: https://forum.armbian.com/topic/17383-bananapi-m1-with-armbian-2102-one-wire-temperature-sensor-and-tv-output/?tab=comments#comment-121649) For Armbian the integration of the one-interface is probably more tricky - you must google to get one-wire running on your board.

Therefore the question -

tsuiwade commented 3 years ago

Hi! I'm new in Raspberry Pi and dart.I may not be able to realize dht22 sensor based on one-wire protocol. So I'm glad to see your dart peripherals sharing on GitHub, but unfortunately, there is no one wire peripheral. I'm sorry that I can't find dart implementation of one-wire on the Internet. So I dare to ask if you have the relevant inventory code. Thank you all the same!

pezi commented 3 years ago

Hi!

One-write device tree integration means, that the sensor can be read as a simple file.

See this more elaborated documentation for accessing the DHT22 sensor

cat /sys/bus/w1/devices/28-00000674869d/w1_slave

At this point you can accress the acutal value of the sensor.

alt text

And with Dart you can read the value in this way:

 import 'dart:io';
 ...
 var cmd = File('/sys/bus/w1/devices/28-00000674869d/w1_slave').readAsBytesSync();
 var s2 = s1.substring(s1.indexOf('t=') + 2);
 var v = double.parse(s2.substring(0, 2) + '.' + s2.substring(2));

Not tested!

tsuiwade commented 3 years ago

Thank you very much for your nice answer!

I had read the information you provided me.

document provides DS18B20 which is also a one-wire device.

I have set up W1 by tutorial, But in / sys / bus / W1 / devices , there is only W1_ bus_ Master1 folder, no slave folder, my raspberry pie doesn't recognize my sensor.

So I have seen more information , do w1.h / w1_family.h provide the driver of dht22?

Can the sensor be read without setting the timing?

Thank you very much all the same!

pezi commented 3 years ago

Sorry - I am wrong, I wrote DHT22, I mean DS18B20. DS18B20 is a one-wire device. DHT22 is GPIO based sensor - years ago, I wrote a Java/JNI bridge to access this native C DHT22 library.

https://github.com/adafruit/Adafruit_Python_DHT/tree/master/source/Raspberry_Pi_2

The Java/Native Lib bridge worked, but this sensor is disappointing - sometimes many retries were necessary to get valid results, looking at the C code - the programming is very time sensitive. dart_periphery supports MMIO as the C-library. Probably you can port the C code, but perhaps you run into irresolvable timing problems - or you use this native code via Dart FFI mechansim - probably the fastest and the simpelst method.

But if possible, I would change the sensor - e.g BME280

But perhaps this more simple code can be ported to Dart https://github.com/nebulx29/dht22/blob/master/dht22.c

tsuiwade commented 3 years ago

Thank you very much for your guidance!

I may not have the concept of these at present.

I'd better change to other sensors at present.

After I have a concept of C interface, I will go back to this issue and try again.

Thank you!!!

pezi commented 3 years ago

If you a little patient, at the weekend I have time to try to port this code https://github.com/nebulx29/dht22/blob/master/dht22.c to Dart.

tsuiwade commented 3 years ago

Thanks a bunch! 😊 😊 😊

pezi commented 3 years ago

DHT22/11 Code is ported, but I must find the DHT22 sensor for a real HW test.

// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// https://github.com/nebulx29/dht22/blob/master/dht22.c
// https://stackoverflow.com/questions/41120541/dht22-sensor-pi4j-java
//

// import '../gpio.dart';
import 'package:dart_periphery/dart_periphery.dart';
import 'dart:io';

const int MAX_TIMINGS = 85;

/// [DHT22] measured data: temperature and humidity.
class DHT22result {
  final bool isValid;

  /// temperature in °C
  final double temperature;

  /// relative humidity %
  final double humidity;

  DHT22result(this.temperature, this.humidity) : isValid = true;
  DHT22result.invalid()
      : temperature = -1,
        humidity = -1,
        isValid = false;

  @override
  String toString() =>
      'DHT22result [isValid=$isValid,temperature=$temperature, humidity=$humidity]';

  /// Returns a [DHT22result] as a JSON string. [fractionDigits] controls the number fraction digits.
  String toJSON([int fractionDigits = 2]) {
    return '{"temperature":"${temperature.toStringAsFixed(fractionDigits)}","humidity":"${humidity.toStringAsFixed(fractionDigits)}"';
  }
}

class DHT22 {
  int pin;
  GPIO gpio;

  DHT22(this.pin) : gpio = GPIO(pin, GPIOdirection.GPIO_DIR_OUT);

  DHT22result getValues() {
    var lastState = true;
    var dht22_dat = List<int>.filled(5, 0);
    var j = 0;
    gpio.setGPIOdirection(GPIOdirection.GPIO_DIR_OUT);
    gpio.write(false);
    sleep(Duration(milliseconds: 18));
    gpio.write(false);
    gpio.setGPIOdirection(GPIOdirection.GPIO_DIR_IN);
    for (var i = 0; i < MAX_TIMINGS; i++) {
      var counter = 0;
      while (gpio.read() == lastState) {
        counter++;
        sleep(Duration(microseconds: 1));
        if (counter == 255) {
          break;
        }
      }

      lastState = gpio.read();

      if (counter == 255) {
        break;
      }

      // ignore first 3 transitions
      if (i >= 4 && i % 2 == 0) {
        // shove each bit into the storage bytes
        dht22_dat[j >> 3] <<= 1;
        if (counter > 16) {
          dht22_dat[j >> 3] |= 1;
        }
        j++;
      }
    }
    if (j >= 40 && checkParity(dht22_dat)) {
      var humidity = ((dht22_dat[0] << 8) + dht22_dat[1]) / 10;

      if (humidity > 100) {
        humidity = dht22_dat[0].toDouble();
      }
      var temperature = (((dht22_dat[2] & 0x7F) << 8) + dht22_dat[3]) / 10;
      if (temperature > 125) {
        temperature = dht22_dat[2].toDouble(); // for DHT11
      }
      if (dht22_dat[2] & 0x80 != 0) {
        temperature = -temperature; // for DHT11
      }
      return DHT22result(temperature, humidity);
    }
    return DHT22result.invalid();
  }

  bool checkParity(List<int> dht22_dat) {
    return dht22_dat[4] ==
        (dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3] & 0xFF);
  }
}

void main() {
  var dht22 = DHT22(3);
  for (var i = 0; i < 5; ++i) {
    print(dht22.getValues());
    sleep(Duration(seconds: 5));
  }
}
tsuiwade commented 3 years ago

When I see your timely reply and help, I feel very happy and grateful!

I tested your code immediately. But, only DHT22result [isValid=false,temperature=-1.0, humidity=-1.0] .

I guess I didn't get the GPIO pin wrong.

I just realized that there is such a convenient way to convert the existing C code into dart code. I also tested your recommended project https://github.com/nebulx29/dht22 . The results show that there is no problem with my existing sensors

C code relies on the traditional . And your code depends on 'dart:io' and 'package:dart_periphery/dart_periphery.dart'. Thank you for your ideas. I think I can draw inferences from one instance.

But is the failure of this code due to the features of dart language?

pezi commented 3 years ago

I found my DHT11 senor - but neither the original C code nor the ported Dart code works.

But the Python code for this sensor works - this code uses also a C lib. I must take a closer look at this code.

tsuiwade commented 3 years ago

It's really a tough problem.

For me, C code and Python code works.

Maybe I can only cheer for you behind your back. 🤦‍♂️🤦‍♂️🤦‍♂️

I'm not in a hurry. If you are interested, you can have a look at it when you are free.

pezi commented 3 years ago

I found my DHT22 and tried to port C code, which works, to Dart - GPIO or MMIO access - but the all these attempts failed - timing problems prevented reading the correct bit sequence from the sensor.

GoRadioGo commented 3 years ago

Yes, you would likely have to do it using existing w1-gpio device driver. See https://pinout.xyz/pinout/1_wire This driver would handle the timing problems.

I was able to do dynamic overlay loading and it would recognize my device (DS28E10) using shell commands. But I haven't yet figured out the specifics of the how to access it properly. It would read the ID ... but next steps were not so clear.

Seems each DSxxx device may have slightly different file operations that are possible. I'm learning ...