https://github.com/github0013/rpi-dht J'ai essayé de gemme
$ gem install rpi-dht
J'ai essayé d'utiliser [dht-sensor-ffi] 1, mais lorsque je l'ai utilisé pendant longtemps, j'ai eu une erreur et je n'ai pas pu comprendre ce qui n'allait pas.
Je n'ai pas d'autre choix que de créer moi-même la bibliothèque (je ne peux pas écrire C). avec rubis
Tout d'abord, DHT est «Communication à bus unique (ONE-WIRE)». Donc je pense que [GPIO4] 4 est ça.
--3.3v / 5v comme un plus pour Raspberry Pi ――De moins au moins de Raspberry Pi --Ligne de données vers [GPIO4] 4 de Raspberry Pi
[Fiche technique DHT11] 2 [Fiche technique DHT22] 3


Il n'y a pas de différence le 22/11 jusqu'à ce que les données finales soient prises. Le flux est comme ça
HIGH / LOW coule à chaque instant (en microsecondes), et vous devez le lire (donc c'est dur pour ruby ...).

Notez que ce n'est pas simplement HIGH = 1 et LOW = 0. Après que LOW dure environ 50us, il est jugé si HIGH dure plus de 50us (= 1) ou non (= 0) (c'est donc strict pour le rubis ...).
Par exemple, si vous le prenez avec Time.now.to_f lors de l'acquisition de données, ce processus prendra probablement beaucoup de temps et les données circuleront en premier. Pour cette raison, les données ont d'abord été sauvegardées successivement, et le nombre moyen de fois que LOW a continué après cela a été sauvegardé, et il a été jugé si HIGH était supérieur ou inférieur à la moyenne.
Organiser 40 bits en octets 8 bits,
Diviser en.
Octet supérieur d'humidité + Octet inférieur d'humidité + Octet supérieur de température + Octet inférieur de température == parité
Vérifier avec.
Octet supérieur d'humidité + octet inférieur d'humidité + octet supérieur de température + octet inférieur de température
00000001 + 00000001 + 00000001 + 00000001 # => 00000100
Si la parité est 00000100, c'est OK
La précision étant faible, l'octet inférieur est toujours «00000000», vous pouvez donc l'ignorer. Simplement
L'humidité et la température sont exprimées en 2 octets.
Exemple:
2 octets de «0000001000001111» (527) en supposant une humidité de 52,7%, divisé par 10 à 52,7%
2 octets de 0000000100000111 (263) en supposant que l'humidité est de 26,3 ℃, et en divisant cela par 10, cela donne 26,3 ℃
Par conséquent, la valeur correcte ne peut être obtenue que si l'octet supérieur est décalé de 8 bits et ajouté à l'octet inférieur.
Exemple
  humidity = ((humidity_high << 8) + humidity_low) / 10.to_f
De plus, seulement dans le cas de la température, le moins peut être exprimé. Cela dépend du fait que le bit de température de poids fort commence par 1. Par conséquent, il est nécessaire de supprimer le premier bit après avoir confirmé si le premier bit est 1.
  is_negative = temp_high & 0b10000000
  temp_high &= 0b01111111
Le dernier calcul est le même que l'exemple d'humidité ci-dessus.
La question de savoir si les données circulant en microsecondes peuvent être obtenues avec précision (que le contrôle de parité réussisse ou non) dépend du degré de congestion du traitement à ce moment-là, de sorte que l'on ne sait pas si les données peuvent être obtenues de manière fiable à chaque fois avec un seul appel. .. Par conséquent, il est nécessaire de l'exécuter plusieurs fois jusqu'à ce que les données puissent être obtenues. En fait, [dht-sensor-ffi] 1 vaut également [50 essais] 5 par défaut.
Classe DHTBase
require "rpi_gpio"
RPi::GPIO.set_numbering :bcm #Spécifiez la broche par un numéro basé sur bcm
class DHTBase
  CLEAR_SIGNALS = 500 / 1000.to_f # ms
  START_SIGNAL = 1 / 1000.to_f # ms
  VALID_BYTE_SIZE = 5 # humidity_high, humidity_low, temp_high, temp_low, parity
  BITS_IN_BYTE = 8
  HUMIDITY_PRECISION = 10.to_f
  TEMPERATURE_PRECISION = 10.to_f
  ENOUGH_TO_CAPTURE_COUNT = 1000 #Nombre de fois où des données suffisantes peuvent être obtenues (environ)
  class << self
    def read(pin)
      dht = new(pin)
      dht.send_start_signal
      dht.collect_response_bits
      dht.convert
    end
  end
  def initialize(pin)
    @pin = pin
  end
  def send_start_signal
    RPi::GPIO.setup pin, as: :output
    RPi::GPIO.set_high pin
    sleep(CLEAR_SIGNALS)
    RPi::GPIO.set_low pin
    sleep(START_SIGNAL)
  end
  def collect_response_bits
    RPi::GPIO.setup pin, as: :input, pull: :up
    @bits = ENOUGH_TO_CAPTURE_COUNT.times.collect { RPi::GPIO.high?(pin) }
    release
    break_into_byte_strings
    check_parity!
  end
  private
  attr_reader :pin, :bits, :byte_strings
  def release
    RPi::GPIO.clean_up pin
  end
  def break_by_high_or_low
    # HIGH = true
    # LOW = false
    # [false, false, false, ...]
    # [true, true, true, ...]
    #Résumer comme
    last_value = :not_yet
    bits.slice_before do |value|
      (last_value != value).tap { |not_same| last_value = value if not_same }
    end.to_a
  end
  def break_into_byte_strings
    #Pour cette raison, inverser et vrai du bas/Après avoir créé une fausse paire de tableaux
    #5 octets de données sont préparés pour chaque 8 bits.
    # ture/Fausse paire de tableaux = 0 ou 1 bit
    #C'est 5 octets, 40 bits=80 séquences
    # [false, false, false, ...]
    # [true, true, true, ...]
    # [false, false, false, ...]
    # [true, true, true, ...]
    # [false, false, false, ...]
    # [true, true, true, ...]
    # ...
    # ...
    # ...
    #La fin se termine toujours par une série de faux et une longue série de vrais, et ce ne sont pas des données, alors ne les utilisez pas
    # [false, false, false, ...]
    # [true, true, true, true, true, true, true, true, true, ...]
    end_part, *low_high_pairs = break_by_high_or_low.reverse.each_slice(2).to_a
    # low_high_pairs = [
    #   ture /fausse paire de tableaux=1 bit
    #1 octet pour 8 éléments
    #   [
    #     [[true, true ...], [false, false ...]],  1
    #     [[true, true ...], [false, false ...]],  2
    #     [[true, true ...], [false, false ...]],  3
    #     [[true, true ...], [false, false ...]],  4
    #     [[true, true ...], [false, false ...]],  5
    #     [[true, true ...], [false, false ...]],  6
    #     [[true, true ...], [false, false ...]],  7
    #     [[true, true ...], [false, false ...]],  8
    #   ]
    #   ...
    #5 octets au total
    # ]
    #Premier vrai pour le signal de réponse/J'ai un faux tableau mais je n'ai pas besoin de le lire
    #Je prends seulement les 5 derniers
    valid_bytes =
      low_high_pairs.reverse.each_slice(8).to_a.last(VALID_BYTE_SIZE).select do |pair|
        pair.all? { |x| x.is_a?(Array) }
      end
    unless valid_bytes.size == VALID_BYTE_SIZE
      raise "not valid byte set (#{valid_bytes.size}bytes, should be #{
              VALID_BYTE_SIZE
            }bytes)"
    end
    valid_bytes.each do |byte|
      unless byte.size == BITS_IN_BYTE
        raise "not a byte (#{byte.size}bits, should be #{BITS_IN_BYTE}bits)"
      end
    end
    all_falses = valid_bytes.collect { |byte| byte.collect(&:last) }.flatten(1) #Aplatir du tableau d'octets en bits dans les octets
    average_false_count = all_falses.sum(&:size) / all_falses.size.to_f
    #Jugez si c'est 1 ou 0 en comparant avec le nombre de vrais éléments en fonction du nombre de fausses consécutives équivalentes à 50us en moyenne.
    @byte_strings =
      valid_bytes.collect do |byte|
        byte.collect { |trues, _| average_false_count <= trues.size ? 1 : 0 }.join
      end
  end
  def bytes
    byte_strings.collect { |x| x.to_i(2) }
  end
  def check_parity!
    humidity_high, humidity_low, temp_high, temp_low, parity = bytes
    unless (humidity_high + humidity_low + temp_high + temp_low) == parity
      raise "parity check failed"
    end
  end
end
Classe DHT11
class DHT11 < DHTBase
  def convert
    humidity_high, _, temp_high, _, _ = bytes
    humidity = humidity_high
    temperature = temp_high #Vous ne devriez pas connaître la température négative
    { humidity: humidity, temperature: temperature }
  end
end
Classe DHT22
class DHT22 < DHTBase
  def convert
    humidity_high, humidity_low, temp_high, temp_low, _ = bytes
    is_negative = 0 < (temp_high & 0b10000000)
    temp_high &= 0b01111111
    humidity = ((humidity_high << 8) + humidity_low) / HUMIDITY_PRECISION
    temperature = ((temp_high << 8) + temp_low) / TEMPERATURE_PRECISION
    temperature *= -1 if is_negative
    { humidity: humidity, temperature: temperature }
  end
end
Exemple d'exécution
100.times do
  begin
    p DHT22.read(4)
    break
  rescue => exception
    p exception
    puts exception.backtrace.first(10).join("\n")
    sleep 0.1
  end
end
        Recommended Posts