DYI инструкция по сбору домашней метеостанции.
Нам понадобиться:
- Arduino — 1 шт.
- OLDE экран - 1шт.
- Датчик давления BMP085 - 1 шт.
- Датчик температуры и влажности DHT22 - 1 шт.
- Беспроводной датчик температуры и влажности Oregon THGN132N - 1 шт. (для измерения показаний на улице)
- Приемник на 433МГц — 1 шт.
- Свободное время - от 60 минут.
- Не очень кривые руки - 2 шт.
Схема подключения элементов:
И собранный прототип:
Scetch
/*
MODULE..........ARDUINO
GND.............GND
VCC.............3.3V
D0 (CLK)........D13
D1 (DATA).......D11
RST (RESET).....D10
DC..............D9
CS (SS).........D8
*/
#include
#include "HCuOLED.h"
#include "SPI.h"
#include "DHT.h"
#include
#define DHTPIN 3
#define DHTTYPE DHT22
#define CS_DI 8
#define DC_DI 9
#define RST_DI 10
//#define DISABLE_DEBUG // если нужен вывод в Serial - закомментируйте эту строчку
HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI);
BMP085 dps = BMP085();
DHT dht(DHTPIN, DHTTYPE);
long temp3 = 0, Pressure = 0, Altitude = 0;
// переменные для хранения значений
// 0 - THGN132N на "1 канале"
// 1 - THGN132N на "2 канале"
// температура
float t[2];
// влажность
byte h[2];
// батарейка
byte b[2];
unsigned long ledNow = 0;
long previousMillis = 0;
// Oregon V2 decoder added - Dominique Pierre
// New code to decode OOK signals from weather sensors, etc.
// 2010-04-11 http://opensource.org/licenses/mit-license.php
// $Id: ookDecoder.pde 5331 2010-04-17 10:45:17Z jcw $
class DecodeOOK {
protected:
byte total_bits, bits, flip, state, pos, data[25];
virtual char decode (word width) =0;
public:
enum {
UNKNOWN, T0, T1, T2, T3, OK, DONE };
DecodeOOK () {
resetDecoder();
}
bool nextPulse (word width) {
if (state != DONE)
switch (decode(width)) {
case -1:
resetDecoder();
break;
case 1:
done();
break;
}
return isDone();
}
bool isDone () const {
return state == DONE;
}
const byte* getData (byte& count) const {
count = pos;
return data;
}
void resetDecoder () {
total_bits = bits = pos = flip = 0;
state = UNKNOWN;
}
// add one bit to the packet data buffer
virtual void gotBit (char value) {
total_bits++;
byte *ptr = data + pos;
*ptr = (*ptr >> 1) | (value << 7);
if (++bits >= 8) {
bits = 0;
if (++pos >= sizeof data) {
resetDecoder();
return;
}
}
state = OK;
}
// store a bit using Manchester encoding
void manchester (char value) {
flip ^= value; // manchester code, long pulse flips the bit
gotBit(flip);
}
// move bits to the front so that all the bits are aligned to the end
void alignTail (byte max =0) {
// align bits
if (bits != 0) {
data[pos] >>= 8 - bits;
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] >> bits) | (data[i+1] << (8 - bits));
bits = 0;
}
// optionally shift bytes down if there are too many of 'em
if (max > 0 && pos > max) {
byte n = pos - max;
pos = max;
for (byte i = 0; i < pos; ++i)
data[i] = data[i+n];
}
}
void reverseBits () {
for (byte i = 0; i < pos; ++i) {
byte b = data[i];
for (byte j = 0; j < 8; ++j) {
data[i] = (data[i] << 1) | (b & 1);
b >>= 1;
}
}
}
void reverseNibbles () {
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] << 4) | (data[i] >> 4);
}
void done () {
while (bits)
gotBit(0); // padding
state = DONE;
}
};
// 433 MHz decoders
class OregonDecoderV2 :
public DecodeOOK {
public:
OregonDecoderV2() {
}
// add one bit to the packet data buffer
virtual void gotBit (char value) {
if(!(total_bits & 0x01))
{
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
}
total_bits++;
pos = total_bits >> 4;
if (pos >= sizeof data) {
resetDecoder();
return;
}
state = OK;
}
virtual char decode (word width) {
if (200 <= width && width < 1200) {
byte w = width >= 700;
switch (state) {
case UNKNOWN:
if (w != 0) {
// Long pulse
++flip;
}
else if (32 <= flip) {
// Short pulse, start bit
flip = 0;
state = T0;
}
else {
// Reset decoder
return -1;
}
break;
case OK:
if (w == 0) {
// Short pulse
state = T0;
}
else {
// Long pulse
manchester(1);
}
break;
case T0:
if (w == 0) {
// Second short pulse
manchester(0);
}
else {
// Reset decoder
return -1;
}
break;
}
}
else {
return -1;
}
return total_bits == 160 ? 1: 0;
}
};
OregonDecoderV2 orscV2;
volatile word pulse;
void ext_int_1(void) {
static word last;
pulse = micros() - last;
last += pulse;
}
void reportSerial (const char* s, class DecodeOOK& decoder) {
byte pos;
const byte* data = decoder.getData(pos);
#ifndef DISABLE_DEBUG
Serial.print(s);
Serial.print(' ');
for (byte i = 0; i < pos; ++i) {
Serial.print(data[i] >> 4, HEX);
Serial.print(data[i] & 0x0F, HEX);
}
Serial.println();
#endif
dps.getPressure(&Pressure);
dps.getAltitude(&Altitude);
//dps.getTemperature(&temp3);
float hi = dht.readHumidity();
float ti = dht.readTemperature();
if(data[0] == 0x1A && data[1] == 0x2D)
{
HCuOLED.Erase(0,0,128,64);
HCuOLED.SetFont(LCDLarge_24pt );
HCuOLED.Cursor(0,0);
HCuOLED.Print(temperatureO(data), 3, 0);
HCuOLED.Cursor(60,0);
HCuOLED.Print(humidityO(data), 3, 0);
HCuOLED.SetFont(Terminal_8pt);
HCuOLED.Cursor(44,0);
HCuOLED.Print("o");
HCuOLED.Cursor(20,44);
HCuOLED.Print("o");
HCuOLED.Cursor(62,49);
HCuOLED.Print("%");
HCuOLED.Cursor(110,49);
HCuOLED.Print("mm");
if (battery(data) <= 15) {
HCuOLED.Cursor(120,0);
HCuOLED.Print("b");
}
HCuOLED.SetFont(MedProp_11pt);
HCuOLED.Cursor(-20,45);
HCuOLED.Print(ti, 4, 0);
HCuOLED.Cursor(98,12);
HCuOLED.Print("%");
HCuOLED.Cursor(23,45);
HCuOLED.Print(hi, 4, 0);
HCuOLED.Cursor(82,45);
HCuOLED.Print(Pressure/133.3, 3, 0);
HCuOLED.Refresh();
// используем только 2 датчика THGN132N на 1 и 2 канале
if (channel(data) > 0 && channel(data) < 4){
t[channel(data)-1]=temperatureO(data);
h[channel(data)-1]=humidityO(data);
b[channel(data)-1]=battery(data);
}
}
decoder.resetDecoder();
}
void setup()
{
#ifndef DISABLE_DEBUG
Serial.begin(115200);
#endif
HCuOLED.Reset();
analogReference(INTERNAL);
Wire.begin();
dht.begin();
delay(2000);
dps.init(MODE_ULTRA_HIGHRES, 25000, true); // 250 метрov над уровнем моря
pinMode(2, INPUT); // D2 - RF-модуль
digitalWrite(2, 1); // включим подтягивающий резистор
attachInterrupt(0, ext_int_1, CHANGE);
}
void loop() {
unsigned long currentMillis = millis();
noInterrupts();
word p = pulse;
pulse = 0;
interrupts();
if (p != 0) {
if (orscV2.nextPulse(p)) {
reportSerial("OSV2", orscV2);
}
}
if(currentMillis - previousMillis > 180000) {
previousMillis = currentMillis;
HCuOLED.Erase(0,0,128,34);
HCuOLED.SetFont(MedProp_11pt);
HCuOLED.Cursor(30,12);
HCuOLED.Print("no signal");
HCuOLED.Refresh();
}
}
float temperatureO(const byte* data)
{
int sign = (data[6]&0x8) ? -1 : 1;
float tempO = ((data[5]&0xF0) >> 4)*10 + (data[5]&0xF) + (float)(((data[4]&0xF0) >> 4) / 10.0);
return sign * tempO;
}
byte humidityO(const byte* data)
{
return (data[7]&0xF) * 10 + ((data[6]&0xF0) >> 4);
}
byte battery(const byte* data)
{
return (data[4] & 0x4) ? 10 : 90;
}
byte channel(const byte* data)
{
byte channel;
switch (data[2])
{
case 0x10:
channel = 1;
break;
case 0x20:
channel = 2;
break;
case 0x40:
channel = 3;
break;
}
return channel;
}
скетч неправильный, со всеми библиотеками выдает кучу ошибок при компеляции...
ОтветитьУдалитьпытаюсь залить в ардуино нано, безуспешно, не могу понять как у вас работает...
ОтветитьУдалитьне работает
ОтветитьУдалить