kstmApp/src/pi_2_dht_read.c
changeset 1 7029db7ac3db
parent 0 bd6bb22c6533
equal deleted inserted replaced
0:bd6bb22c6533 1:7029db7ac3db
    19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20 // SOFTWARE.
    20 // SOFTWARE.
    21 #include <stdbool.h>
    21 #include <stdbool.h>
    22 #include <stdlib.h>
    22 #include <stdlib.h>
    23 
    23 
       
    24 #include "epicsExit.h"
       
    25 #include "epicsThread.h"
       
    26 #include "iocsh.h"
       
    27 
    24 #include "pi_2_dht_read.h"
    28 #include "pi_2_dht_read.h"
    25 #include "pi_2_mmio.h"
    29 #include "pi_2_mmio.h"
    26 
    30 
    27 // This is the only processor specific magic value, the maximum amount of time to
    31 // 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
    32 // spin in a loop before bailing out and considering the read a timeout.  This should
    34 // the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
    38 // the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
    35 // the data afterwards.
    39 // the data afterwards.
    36 #define DHT_PULSES 41
    40 #define DHT_PULSES 41
    37 
    41 
    38 int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) {
    42 int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) {
       
    43 int i;
       
    44 volatile int j;
       
    45 unsigned int defPrio;
       
    46 epicsThreadId threadIdSelf;
       
    47 
    39   // Validate humidity and temperature arguments and set them to zero.
    48   // Validate humidity and temperature arguments and set them to zero.
    40   if (humidity == NULL || temperature == NULL) {
    49   if (humidity == NULL || temperature == NULL) {
    41     return DHT_ERROR_ARGUMENT;
    50     return DHT_ERROR_ARGUMENT;
    42   }
    51   }
    43   *temperature = 0.0f;
    52   *temperature = 0.0f;
    54 
    63 
    55   // Set pin to output.
    64   // Set pin to output.
    56   pi_2_mmio_set_output(pin);
    65   pi_2_mmio_set_output(pin);
    57 
    66 
    58   // Bump up process priority and change scheduler to try to try to make process more 'real time'.
    67   // Bump up process priority and change scheduler to try to try to make process more 'real time'.
    59   set_max_priority();
    68   defPrio = epicsThreadGetPrioritySelf();
       
    69   threadIdSelf = epicsThreadGetIdSelf();
       
    70   epicsThreadSetPriority( threadIdSelf , epicsThreadPriorityHigh);
    60 
    71 
    61   // Set pin high for ~500 milliseconds.
    72   // Set pin high for ~500 milliseconds.
    62   pi_2_mmio_set_high(pin);
    73   pi_2_mmio_set_high(pin);
    63   sleep_milliseconds(500);
    74   sleep_milliseconds(500);
    64 
    75 
    70   busy_wait_milliseconds(20);
    81   busy_wait_milliseconds(20);
    71 
    82 
    72   // Set pin at input.
    83   // Set pin at input.
    73   pi_2_mmio_set_input(pin);
    84   pi_2_mmio_set_input(pin);
    74   // Need a very short delay before reading pins or else value is sometimes still low.
    85   // Need a very short delay before reading pins or else value is sometimes still low.
    75 volatile int i;
    86   for (j = 0; j < 50; ++j) { }
    76   for (i = 0; i < 50; ++i) {
       
    77   }
       
    78 
    87 
    79   // Wait for DHT to pull pin low.
    88   // Wait for DHT to pull pin low.
    80   uint32_t count = 0;
    89   uint32_t count = 0;
    81   while (pi_2_mmio_input(pin)) {
    90   while (pi_2_mmio_input(pin)) {
    82     if (++count >= DHT_MAXCOUNT) {
    91     if (++count >= DHT_MAXCOUNT) {
    83       // Timeout waiting for response.
    92       // Timeout waiting for response.
    84       set_default_priority();
    93       epicsThreadSetPriority( threadIdSelf , defPrio);
    85       return DHT_ERROR_TIMEOUT;
    94       return DHT_ERROR_TIMEOUT;
    86     }
    95     }
    87   }
    96   }
    88 
    97 
    89   // Record pulse widths for the expected result bits.
    98 
    90   int j;
    99  // Record pulse widths for the expected result bits.
    91   for ( j=0; j < DHT_PULSES*2; j+=2) {
   100   for ( i=0; i < DHT_PULSES*2; i+=2) {
    92     // Count how long pin is low and store in pulseCounts[i]
   101     // Count how long pin is low and store in pulseCounts[i]
    93     while (!pi_2_mmio_input(pin)) {
   102     while (!pi_2_mmio_input(pin)) {
    94       if (++pulseCounts[i] >= DHT_MAXCOUNT) {
   103       if (++pulseCounts[i] >= DHT_MAXCOUNT) {
    95         // Timeout waiting for response.
   104         // Timeout waiting for response.
    96         set_default_priority();
   105         epicsThreadSetPriority( threadIdSelf , defPrio);
    97         return DHT_ERROR_TIMEOUT;
   106         return DHT_ERROR_TIMEOUT;
    98       }
   107       }
    99     }
   108     }
   100     // Count how long pin is high and store in pulseCounts[i+1]
   109     // Count how long pin is high and store in pulseCounts[i+1]
   101     while (pi_2_mmio_input(pin)) {
   110     while (pi_2_mmio_input(pin)) {
   102       if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
   111       if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
   103         // Timeout waiting for response.
   112         // Timeout waiting for response.
   104         set_default_priority();
   113         epicsThreadSetPriority( threadIdSelf , defPrio);
   105         return DHT_ERROR_TIMEOUT;
   114         return DHT_ERROR_TIMEOUT;
   106       }
   115       }
   107     }
   116     }
   108   }
   117   }
   109 
   118 
   110   // Done with timing critical code, now interpret the results.
   119   // Done with timing critical code, now interpret the results.
   111 
       
   112   // Drop back to normal priority.
   120   // Drop back to normal priority.
   113   set_default_priority();
   121   // set_default_priority();
       
   122   epicsThreadSetPriority( threadIdSelf , defPrio);
   114 
   123 
   115   // Compute the average low pulse width to use as a 50 microsecond reference threshold.
   124   // 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.
   125   // Ignore the first two readings because they are a constant 80 microsecond pulse.
   117   uint32_t threshold = 0;
   126   uint32_t threshold = 0;
   118   int k;
   127   for (i=2; i < DHT_PULSES*2; i+=2) {
   119   for (k=2; i < DHT_PULSES*2; k+=2) {
   128     threshold += pulseCounts[i];
   120     threshold += pulseCounts[k];
       
   121   }
   129   }
   122   threshold /= DHT_PULSES-1;
   130   threshold /= DHT_PULSES-1;
   123 
   131 
   124   // Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
   132   // 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
   133   // 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.
   134   // then it must be a ~70us 1 pulse.
   127   uint8_t data[5] = {0};
   135   uint8_t data[5] = {0};
   128   int l;
   136   for ( i=3; i < DHT_PULSES*2; i+=2) {
   129   for ( l=3; l < DHT_PULSES*2; l+=2) {
   137     int index = (i-3)/16;
   130     int index = (l-3)/16;
       
   131     data[index] <<= 1;
   138     data[index] <<= 1;
   132     if (pulseCounts[l] >= threshold) {
   139     if (pulseCounts[i] >= threshold) {
   133       // One bit for long pulse.
   140       // One bit for long pulse.
   134       data[index] |= 1;
   141       data[index] |= 1;
   135     }
   142     }
   136     // Else zero bit for short pulse.
   143     // Else zero bit for short pulse.
   137   }
   144   }