This is a follow up to my prior response...
On Thu, 31 Mar 2016 00:16:28 -0700 (PDT), Sumit Bhut
<
smb...@gmail.com> declaimed the following:
>Hi, Dennis Lee Bieber
>
>Thanks for the valuable effort but i am unaware of the python language and
>hence it would be really appreciable if you could provide me your help in
>C/C++ language only.
Python may not have been fast enough for the toggling -- combined with
the fact that time.clock() seemed to have a granularity of 0.01 seconds (or
10 milliseconds) which would make it difficult to tell how long the time
was between transitions.
I attempted to generate something in C++ which took hours. For some
reason I can't seem to find a GPIO pin that was actually toggling when
under an oscilloscope. Even when manually setting the pin value using the
echo 1 > /sys/class/gpio/gpio#/value
from a command line. I could read back the 1 (or 0) value, but never found
a level change on the 'scope -- the pin was either tied high, or tied to
ground.
My last version is showing some activity, but is still failing, as
shown (I'm wondering if usleep() has some obscenely large granularity on
the BBB, because it took 53 seconds to go from "beginning measurement" to
the first timeout error on the first byte, sixth bit):
debian@beaglebone:~$ sudo ./DHT11
Beginning measurement pass
Timeout counting bit length 0 5
***** Error while reading sensor
Beginning measurement pass
Timeout counting bit length 0 6
***** Error while reading sensor
Beginning measurement pass
Timeout counting bit length 0 5
***** Error while reading sensor
Beginning measurement pass
Even worst case (all 1 bits) the entire data read (40 bits @ 120 uSec
each) is less than 5 msec, and the 20 msec wake up brings the total to
around <30 msec... So where did the other 53000 msec delay come from?
debian@beaglebone:~$ date && sudo ./DHT11
Sat Apr 2 21:25:45 EDT 2016
Beginning measurement pass
Timeout counting bit length 0 3
***** Error while reading sensor
Beginning measurement pass
Timeout counting bit length 0 4
***** Error while reading sensor
Beginning measurement pass
^Cdebian@beaglebone:~$ date
Sat Apr 2 21:27:37 EDT 2016
debian@beaglebone:~$
Based upon where it is timing out, the code must be seeing some
toggling of the signal coming in, or it is reading atmospheric noise; as it
gets past the bus available, wake up response, and a couple of data bits --
all actions that require seeing a LOW then HIGH sequence.
Maybe next weekend I'll have time to convert the deprecated usleep()
into current POSIX nano_sleep(). In the meantime, my code follows. Compile
with
g++ -o DHT11 DHT11.cpp -std=c++0x
-=-=-=-=-=-
/*
* DHT11.cpp Simple Humidity and Temperature Sensor
* April 2, 2016 Dennis L Bieber
*
* This file defines (and uses) a class to read DHT11 sensors
* on the BeagleBone Black
*
* Minimal error checking is performed, timeout testing is done
* using cpu-hog polling loops
*
* As I've not done C++ in 15 years, there will be some construct
* that may not be "proper"
*
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <unistd.h>
using namespace std;
enum /*class*/ Direction { OUT, IN };
enum /*class*/ PinState { LOW, HIGH };
struct TimeOutError {};
struct CheckSumError {};
struct DHTError {};
class DHT11
{
int pinNum;
long timeOutuSec;
char pinDirPath[200];
char pinDataPath[200];
public:
DHT11(int pin, int timeOut);
~DHT11();
void readDegC(float &humidity, float &temperature);
void readDegF(float &humidity, float &temperature);
private:
void read(float &humidity, float &temperature);
void setDir(Direction dir);
void writePin(PinState value);
PinState readPin();
};
DHT11::DHT11(int pin, int timeOut)
{
FILE *exportCtl;
// save pin number and timeout values
// (though pin number may only be used here)
pinNum = pin;
timeOutuSec = timeOut * 1000; // msec -> microsec
// export the pin for later access
exportCtl = fopen("/sys/class/gpio/export", "w");
fprintf(exportCtl, "%d", pinNum);
fclose(exportCtl);
// set up the pinData and pinDirCtl paths
sprintf(pinDataPath, "/sys/class/gpio/gpio%d/value", pinNum);
sprintf(pinDirPath, "/sys/class/gpio/gpio%d/direction", pinNum);
}
DHT11::~DHT11()
{
FILE *exportCtl;
// unexport the pin for cleanup
exportCtl = fopen("/sys/class/gpio/unexport", "w");
fprintf(exportCtl, "%d", pinNum);
fclose(exportCtl);
}
void DHT11::setDir(Direction dir)
{
FILE *pinDirCtl;
pinDirCtl = fopen(pinDirPath, "w");
fprintf(pinDirCtl, (IN == dir) ? "in" : "out");
fclose(pinDirCtl);
}
void DHT11::writePin(PinState value)
{
FILE *pinData;
pinData = fopen(pinDataPath, "w");
fprintf(pinData, "%d", (HIGH == value) ? 1 : 0);
fclose(pinData);
}
PinState DHT11::readPin()
{
int pinValue;
FILE *pinData;
pinData = fopen(pinDataPath, "r");
fscanf(pinData, "%d", &pinValue);
fclose(pinData);
return (1 == pinValue) ? HIGH : LOW;
}
void DHT11::read(float &humidity, float &temperature)
{
char data[5] = {0, 0, 0, 0, 0};
int toCnt;
cout << "Beginning measurement pass" << endl;
// ensure bus is high (no device is pulling it down)
setDir(IN);
toCnt = 0;
try
{
while (LOW == readPin())
{
toCnt++;
if (toCnt > timeOutuSec)
throw TimeOutError {};
usleep(1);
}
}
catch (TimeOutError)
{
cout << endl << "Timeout waiting for bus available" << endl;
throw DHTError {};
}
// send wake up signal; spec gives minimum of 18msec
setDir(OUT);
writePin(LOW);
usleep(20 * 1000); // deprecated, should use nano_sleep
writePin(HIGH);
setDir(IN);
// wait for response start
toCnt = 0;
try
{
while (HIGH == readPin())
{
toCnt++;
if (toCnt > timeOutuSec)
throw TimeOutError {};
usleep(1);
}
}
catch (TimeOutError)
{
cout << endl << "Timeout waiting for response start" << endl;
throw DHTError {};
}
// wait for response indicator end
toCnt = 0;
try
{
while (LOW == readPin())
{
toCnt++;
if (toCnt > timeOutuSec)
throw TimeOutError {};
usleep(1);
}
}
catch (TimeOutError)
{
cout << endl << "Timeout waiting for response indicator end" <<
endl;
throw DHTError {};
}
// wait for first data bit start
toCnt = 0;
try
{
while (HIGH == readPin())
{
toCnt++;
if (toCnt > timeOutuSec)
throw TimeOutError {};
usleep(1);
}
}
catch (TimeOutError)
{
cout << endl << "Timeout waiting for first bit start" << endl;
throw DHTError {};
}
// loop over 5 data bytes
for (int i = 0; i < 5; i++)
{
// loop over 8 bits per byte
for (int b = 0; b < 8; b++)
{
// wait for actual bit start
toCnt = 0;
try
{
while (LOW == readPin())
{
toCnt++;
if (toCnt > timeOutuSec)
throw TimeOutError {};
usleep(1);
}
}
catch (TimeOutError)
{
cout << endl << "Timeout waiting for actual data bit " << i
<< " " << b << endl;
throw DHTError {};
}
// accumulate microseconds for duration of bit
// until start of next bit signal
toCnt = 0;
try
{
while (HIGH == readPin())
{
toCnt++;
if (toCnt > timeOutuSec)
throw TimeOutError {};
usleep(1);
}
}
catch (TimeOutError)
{
cout << endl << "Timeout counting bit length " << i << " "
<< b << endl;
throw DHTError {};
}
// determine short or long (0 or 1)
if (toCnt > 45)
data[i] = (data[i] << 1) + 1;
else
data[i] = (data[i] << 1) + 0;
}
}
// checksum computation
if ((data[0] + data[1] + data[2] + data[3]) % 256 != data[4])
throw CheckSumError {};
humidity = (float) data[0] + ((float) data[1] / 10.0);
temperature = (float) data[2] + ((float) data[3] / 10.0);
}
void DHT11::readDegC(float &humidity, float &temperature)
{
// reports are that one should read twice as the first
// read contains stale data
read(humidity, temperature);
read(humidity, temperature);
}
void DHT11::readDegF(float &humidity, float &temperature)
{
readDegC(humidity, temperature);
// convert degC to degF
temperature = (temperature * 9.0) / 5.0 + 32.0;
}
int main(int argc, char *argv[])
{
DHT11 mySensor = DHT11{48, 200}; // P9_15, 200mSec time-out
float humidity;
float temperature;
try
{
while (1)
{
try
{
mySensor.readDegF(humidity, temperature);
cout << "Humidity: " << humidity << "%\t"
<< "Temperature: " << temperature << " degF" << endl;
sleep(5);
}
catch (CheckSumError)
{
cout << endl << "***** Checksum mismatch" << endl << endl;
}
catch (DHTError)
{
cout << endl << "***** Error while reading sensor" << endl
<< endl;
}
}
}
catch (...)
{
// Any exception should take this route
cout << endl << "***** Something failed, I won't tell you what" <<
endl << endl;
}
return (0);
}
-=-=-=-=-=-