kstmApp/src/pi_2_dht_read.c
changeset 0 bd6bb22c6533
child 1 7029db7ac3db
equal deleted inserted replaced
-1:000000000000 0:bd6bb22c6533
       
     1 // Copyright (c) 2014 Adafruit Industries
       
     2 // Author: Tony DiCola
       
     3 
       
     4 // Permission is hereby granted, free of charge, to any person obtaining a copy
       
     5 // of this software and associated documentation files (the "Software"), to deal
       
     6 // in the Software without restriction, including without limitation the rights
       
     7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
     8 // copies of the Software, and to permit persons to whom the Software is
       
     9 // furnished to do so, subject to the following conditions:
       
    10 
       
    11 // The above copyright notice and this permission notice shall be included in all
       
    12 // copies or substantial portions of the Software.
       
    13 
       
    14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       
    17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       
    20 // SOFTWARE.
       
    21 #include <stdbool.h>
       
    22 #include <stdlib.h>
       
    23 
       
    24 #include "pi_2_dht_read.h"
       
    25 #include "pi_2_mmio.h"
       
    26 
       
    27 // This is the only processor specific magic value, the maximum amount of time to
       
    28 // spin in a loop before bailing out and considering the read a timeout.  This should
       
    29 // be a high value, but if you're running on a much faster platform than a Raspberry
       
    30 // Pi or Beaglebone Black then it might need to be increased.
       
    31 #define DHT_MAXCOUNT 32000
       
    32 
       
    33 // Number of bit pulses to expect from the DHT.  Note that this is 41 because
       
    34 // the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
       
    35 // the data afterwards.
       
    36 #define DHT_PULSES 41
       
    37 
       
    38 int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) {
       
    39   // Validate humidity and temperature arguments and set them to zero.
       
    40   if (humidity == NULL || temperature == NULL) {
       
    41     return DHT_ERROR_ARGUMENT;
       
    42   }
       
    43   *temperature = 0.0f;
       
    44   *humidity = 0.0f;
       
    45 
       
    46   // Initialize GPIO library.
       
    47   if (pi_2_mmio_init() < 0) {
       
    48     return DHT_ERROR_GPIO;
       
    49   }
       
    50 
       
    51   // Store the count that each DHT bit pulse is low and high.
       
    52   // Make sure array is initialized to start at zero.
       
    53   int pulseCounts[DHT_PULSES*2] = {0};
       
    54 
       
    55   // Set pin to output.
       
    56   pi_2_mmio_set_output(pin);
       
    57 
       
    58   // Bump up process priority and change scheduler to try to try to make process more 'real time'.
       
    59   set_max_priority();
       
    60 
       
    61   // Set pin high for ~500 milliseconds.
       
    62   pi_2_mmio_set_high(pin);
       
    63   sleep_milliseconds(500);
       
    64 
       
    65   // The next calls are timing critical and care should be taken
       
    66   // to ensure no unnecssary work is done below.
       
    67 
       
    68   // Set pin low for ~20 milliseconds.
       
    69   pi_2_mmio_set_low(pin);
       
    70   busy_wait_milliseconds(20);
       
    71 
       
    72   // Set pin at input.
       
    73   pi_2_mmio_set_input(pin);
       
    74   // Need a very short delay before reading pins or else value is sometimes still low.
       
    75 volatile int i;
       
    76   for (i = 0; i < 50; ++i) {
       
    77   }
       
    78 
       
    79   // Wait for DHT to pull pin low.
       
    80   uint32_t count = 0;
       
    81   while (pi_2_mmio_input(pin)) {
       
    82     if (++count >= DHT_MAXCOUNT) {
       
    83       // Timeout waiting for response.
       
    84       set_default_priority();
       
    85       return DHT_ERROR_TIMEOUT;
       
    86     }
       
    87   }
       
    88 
       
    89   // Record pulse widths for the expected result bits.
       
    90   int j;
       
    91   for ( j=0; j < DHT_PULSES*2; j+=2) {
       
    92     // Count how long pin is low and store in pulseCounts[i]
       
    93     while (!pi_2_mmio_input(pin)) {
       
    94       if (++pulseCounts[i] >= DHT_MAXCOUNT) {
       
    95         // Timeout waiting for response.
       
    96         set_default_priority();
       
    97         return DHT_ERROR_TIMEOUT;
       
    98       }
       
    99     }
       
   100     // Count how long pin is high and store in pulseCounts[i+1]
       
   101     while (pi_2_mmio_input(pin)) {
       
   102       if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
       
   103         // Timeout waiting for response.
       
   104         set_default_priority();
       
   105         return DHT_ERROR_TIMEOUT;
       
   106       }
       
   107     }
       
   108   }
       
   109 
       
   110   // Done with timing critical code, now interpret the results.
       
   111 
       
   112   // Drop back to normal priority.
       
   113   set_default_priority();
       
   114 
       
   115   // Compute the average low pulse width to use as a 50 microsecond reference threshold.
       
   116   // Ignore the first two readings because they are a constant 80 microsecond pulse.
       
   117   uint32_t threshold = 0;
       
   118   int k;
       
   119   for (k=2; i < DHT_PULSES*2; k+=2) {
       
   120     threshold += pulseCounts[k];
       
   121   }
       
   122   threshold /= DHT_PULSES-1;
       
   123 
       
   124   // Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
       
   125   // If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
       
   126   // then it must be a ~70us 1 pulse.
       
   127   uint8_t data[5] = {0};
       
   128   int l;
       
   129   for ( l=3; l < DHT_PULSES*2; l+=2) {
       
   130     int index = (l-3)/16;
       
   131     data[index] <<= 1;
       
   132     if (pulseCounts[l] >= threshold) {
       
   133       // One bit for long pulse.
       
   134       data[index] |= 1;
       
   135     }
       
   136     // Else zero bit for short pulse.
       
   137   }
       
   138 
       
   139   // Useful debug info:
       
   140   //printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]);
       
   141 
       
   142   // Verify checksum of received data.
       
   143   if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
       
   144     if (type == DHT11) {
       
   145       // Get humidity and temp for DHT11 sensor.
       
   146       *humidity = (float)data[0];
       
   147       *temperature = (float)data[2];
       
   148     }
       
   149     else if (type == DHT22) {
       
   150       // Calculate humidity and temp for DHT22 sensor.
       
   151       *humidity = (data[0] * 256 + data[1]) / 10.0f;
       
   152       *temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f;
       
   153       if (data[2] & 0x80) {
       
   154         *temperature *= -1.0f;
       
   155       }
       
   156     }
       
   157     return DHT_SUCCESS;
       
   158   }
       
   159   else {
       
   160     return DHT_ERROR_CHECKSUM;
       
   161   }
       
   162 }