Created
May 5, 2020 10:17
-
-
Save Ummon/255f16fd2e5a9e39710d018bf0f27678 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Author: [email protected] | |
* libbcm2835 documentation: http://www.airspayce.com/mikem/bcm2835/index.html | |
*/ | |
#include <bcm2835.h> | |
#include <iostream> | |
#include <ctime> | |
using namespace std; | |
const auto pin = RPI_GPIO_P1_07; | |
const double temperatureMax = 60; | |
const double temperatureMin = -20; | |
const double humidityMax = 100; | |
const double humidityMin = 0; | |
class ReadException {}; | |
inline uint64_t timeFrom(clock_t t) | |
{ | |
return uint64_t(clock() - t) / (CLOCKS_PER_SEC / 1000 / 1000); | |
} | |
void sync(uint64_t timeout, bool toUp) | |
{ | |
auto last = bcm2835_gpio_lev(pin); | |
bool synced = false; | |
clock_t t = clock(); | |
while (!synced && timeFrom(t) < timeout) | |
{ | |
auto current = bcm2835_gpio_lev(pin); | |
synced = toUp ? (last == LOW && current == HIGH) : (last == HIGH && current == LOW); | |
last = current; | |
} | |
if (!synced) | |
{ | |
// uint64_t delta = timeFrom(t); | |
// cout << "Unable to sync " << (toUp ? "up" : "down") << " Time: " << delta << endl; | |
throw ReadException(); | |
} | |
} | |
inline void syncToUp(long timeout) | |
{ | |
sync(timeout, true); | |
} | |
inline void syncToDown(long timeout) | |
{ | |
sync(timeout, false); | |
} | |
bool readNextBit() | |
{ | |
syncToUp(300); // Should be 50 us. | |
clock_t t = clock(); | |
syncToDown(300); // Should be 70 us. | |
return timeFrom(t) > 50; | |
} | |
uint8_t readNextByte() | |
{ | |
uint8_t result = 0; | |
for (int i = 0; i < 8; i++) | |
if (readNextBit()) | |
result |= (1 << (7 - i)); | |
return result; | |
} | |
extern "C" | |
bool init() | |
{ | |
if (!bcm2835_init()) | |
{ | |
cerr << "Unable to init the BCM 2835" << endl; | |
return false; | |
} | |
return true; | |
} | |
extern "C" | |
void getHumidityAndTemperature(double& h, double& t) | |
{ | |
bool dataOK = false; | |
while (!dataOK) | |
{ | |
try | |
{ | |
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); | |
bcm2835_gpio_write(pin, LOW); | |
bcm2835_delayMicroseconds(30000); // 30 ms. | |
bcm2835_gpio_write(pin, HIGH); | |
bcm2835_delayMicroseconds(30); | |
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); | |
syncToUp(200); // Should be 80 us. | |
syncToDown(200); // Should be 80 us. | |
int rh1 = readNextByte(); | |
int rh2 = readNextByte(); | |
int t1 = readNextByte(); | |
int t2 = readNextByte(); | |
int checksum = readNextByte(); | |
if (((rh1 + rh2 + t1 + t2) & 0xFF) != checksum) | |
throw ReadException(); | |
h = double((rh1 << 8) | rh2) / 10.0; | |
t = double(((t1 & 0x7F) << 8) | t2) / 10.0; | |
if (t1 & 0x80) | |
t *= -1.0; | |
if (h >= humidityMin && h <= humidityMax && t >= temperatureMin && t <= temperatureMax) | |
{ | |
dataOK = true; | |
} | |
} | |
catch(ReadException ex) | |
{ | |
cerr << "Read error, retrying ..." << endl; | |
} | |
if (!dataOK) | |
bcm2835_delay(2000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment