Skip to content

Instantly share code, notes, and snippets.

@Ummon
Created May 5, 2020 10:17
Show Gist options
  • Save Ummon/255f16fd2e5a9e39710d018bf0f27678 to your computer and use it in GitHub Desktop.
Save Ummon/255f16fd2e5a9e39710d018bf0f27678 to your computer and use it in GitHub Desktop.
/*
* 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