
Это тема поддержки статьи: Самодельная метеостанция на esp8266. Оставляйте здесь свои комментарии и вопросы.
Повідомлення відредагував RUS_D: 04 грудень 2016 - 22:36
| Тема | Форум | Написано | Дата | 
|---|---|---|---|
 
								
 
 
 
 
  | 
 
								
 
 
 
 
 
  | 
				
					
				
Это тема поддержки статьи: Самодельная метеостанция на esp8266. Оставляйте здесь свои комментарии и вопросы.
Повідомлення відредагував RUS_D: 04 грудень 2016 - 22:36
				
					
				Вывод датчиков прямо тут на сайте ![]()
 
Повідомлення відредагував RUS_D: 06 жовтень 2020 - 22:41
				
					
				
				
					
				
				
					
				
				
					
				
				
					
				
				
					
				Выложу программу для ARDUINO если кто надумает повторить
В ней отсуствует только код ля дозиметра (можно встроить тот что выше выложен)
 
//--- One-wire
//
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire); //DS18B20
DeviceAddress Thermometer1 = { //второй термометр
0x28, 0x00, 0x54, 0xB6, 0x04, 0x00, 0x00, 0x92
};
DeviceAddress Thermometer3 = { // улица
0x28, 0xFF, 0x56, 0xCB, 0x6A, 0x14, 0x03, 0x16
};
//--- One-wire
//
#define chclient 1 // номер клиента 1...
#define timeoutper 400 // таймаут запросов от сервера.
#define timesend 300 // интервал отправки данных,для обычных датчиков можно установить время выше.
#include <SPI.h>
#include "DHT.h"
DHT dht;
#include "nRF24L01.h"
#include "RF24.h"
unsigned long time1=0;
unsigned long time2=0;
#define RELE_1 6 //
#define RELE_2 7
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
//
// 0 -прием , 1 -передача
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL,0xF0F0F0F0D2LL};
//
// структура принятых данных.МЕНЯТЬ НЕЛЬЗЯ
typedef struct{
byte identifier;
byte val1;
byte val2;
byte val3;
byte val4;
}
nf0;
nf0 servernf;
// структура отправляемых данных.Изменяемые данные.Размер структуры должен быть не больше 32 байт !
typedef struct{
byte identifier;// номер передатчика.МЕНЯТЬ НЕЛЬЗЯ
int temperature_Sensor;// передаём температуру.
int Humidity_Sensor;// передаём влажность
int temperature1_Sensor;// передаём температуру.
int Analog;
//int Analog;
unsigned int Error_Message; // счетчик ошибок
unsigned long count;// счетчик передач для контроля качества канала
// boolean test_data;
}
nf1;
nf1 clientnf;
/* ************************************** */
void setup() {
Serial.begin(9600);
dht.setup(3); // DHT датчик на пине 3
pinMode(RELE_1, OUTPUT);
pinMode(RELE_2, OUTPUT);
radio.begin();
delay(2);
// выбор скорости
// radio.setDataRate(RF24_250KBPS);
radio.setDataRate(RF24_1MBPS);
// radio.setDataRate(RF24_2MBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setChannel(100); //тут установка канала
radio.setCRCLength(RF24_CRC_16);
radio.setAutoAck(false); // выключить аппаратное потверждение
radio.setRetries(15,15);
radio.openReadingPipe(1,pipes[0]); // Открываем канал приема
radio.openWritingPipe(pipes[1]); // Открываем канал передачи
clientnf.identifier = chclient;
sensors.begin();
//sensors.setResolution(Thermometer1, 10); //второй термометр
sensors.setResolution(Thermometer3, 10);
}
byte errorstate;
void loop() {
sensors.requestTemperatures(); // опрос датчика температуры улица
// для чтения сенсоров
if ((millis()-time1) >= 1000) { // обновляем сенсоры раз в секунду (1000млс)
// тут будут опросы сенсоров
clientnf.temperature_Sensor = dht.getTemperature()*10;
clientnf.Humidity_Sensor = dht.getHumidity()*10;
clientnf.temperature1_Sensor = sensors.getTempC(Thermometer3)*10; // опрос датчика температуры улица
clientnf.Analog=analogRead(0); //пример передачи int данных
//clientnf.Analog1=analogRead(1); //пример передачи int данных
//clientnf.Analog2=analogRead(2); //пример передачи int данных
//clientnf.Analog3=analogRead(3); //пример передачи int данных
//Serial.print(" C "); Serial.println(clientnf.temperature1_Sensor/10);
time1 = millis();
}
//**************************************************************/
if ((millis() - time2) >= timesend || errorstate !=0) {
if (clientnf.count <= 2147483646) clientnf.count++; // счетчик передач для контроля качества канала
else clientnf.count = 0;
radio.stopListening();
bool ok = radio.write( &clientnf, sizeof(clientnf) );
radio.startListening();
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > timeoutper ) timeout = true;
if ( timeout ) {
// счетчик ошибок
clientnf.Error_Message++;
errorstate++; // счетчик ошибок для повтора
}
else {
radio.read( &servernf, sizeof(servernf) );
errorstate=0;
}
if (errorstate>=50) errorstate=0; // не более 3 попыток для повтора
//************************************************************************************************/
if (servernf.identifier == chclient) { // выполнение команд с сервера,если данные предназначены для этого клиента:
// val1= 10 -значит дергаем пинами, val2 - номер пина, val3 - состояние пина
// не забудте установить режим OUTPUT для нужных пинов.
// nRF-USB write 1 10 7 1 1 - что значит установить на 7 выводе логический уровень 1
if (servernf.val1==10) digitalWrite(servernf.val2,servernf.val3);
// val1= 11 -значит управляем ШИМ пинами, val2 - номер пина, val3 - уровень 0..255.
// не забудте установить режим OUTPUT для нужных пинов.
// ШИМ возможен только на некоторых пинах !!
if (servernf.val1==11) analogWrite(servernf.val2,servernf.val3);
}
time2 = millis();
}
} // конец loop
В настройке сервера у казать Data structure: THTAL
Счетчик можно закоментить в скетче, тогда данные будут так - THTA
				
					
				
				
					
				Обновленный вид на метеостанцию в смартфоне (спецпрограмма) - могу поглядеть что делается дома с любой точки мира.
				
					
				Обновлю тему по случаю приезда печатной платы ![]()
Все было разобрано, запаяно на новую плату и запущено в работу...
Временно собранный модуль 
  все никак не вызреет у меня корпус для метеостанции ![]()
				
					
				Обновлю тему.
Проект пересобран на печатной плате. Присутствует дистанционное (интернет) управление реле.
Также есть управление по планировщику заданий, термостат и много другого.
				
					
				
				
					
				
				
					
				Ну после марта 2016г.
Скетч не правился - вот последний
 
/*
Код мониторинга электропотребления и трансляции
данных на сервер
*/
//------------ Измерение напряжения / тока -------------- //
int numberOfSamples = 500;
//Установка датчиков тока и напряжения
int inPinV = A0;
int inPinI = 1;
// Коэффициенты для калибровки выводимых значений
// Подбираются опытным путем сверяясь с эталонным прибором
double VCAL = 13.0; // для напряжения
double ICAL = 0.21; // для тока
double PHASECAL = 2.3; // для мощности
//*************************************************************************
double V_RATIO = 50.5 / 1024 * VCAL;
double I_RATIO = (long double) 15.15 * 5 / 1024 * ICAL;
//Образцы переменных
int lastSampleV,lastSampleI,sampleV,sampleI;
//Переменные для фильтров
double lastFilteredV, lastFilteredI, filteredV, filteredI;
double filterTemp;
//Сюда сохраняем калибровочное значение фазы мгновенного напряжения
double shiftedV;
//Расчет переменной для мощности
double sqI,sqV,instP,sumI,sumV,sumP;
//Полезные значения переменных
double realPower,
apparentPower,
apparentPower1,
powerFactor,
Vrms,
Irms;
//------------ Измерение радиации -------------- //
#include <SPI.h>
#define LOG_PERIOD 300000//34280  //Logging period in milliseconds, recommended value 15000-60000.
//#define MAX_PERIOD 60000  //Maximum logging period without modifying this sketch
unsigned long counts;     //variable for GM Tube events
unsigned long cpm;        //variable for CPM
//unsigned int multiplier;  //variable for calculation CPM in this sketch
unsigned long previousMillis;  //variable for time measurement
//------------ Измерение радиации -------------- //
//--- One-wire ----------------------------------------------------------- //
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire); //DS18B20
DeviceAddress Thermometer1 = {  0x28, 0x00, 0x54, 0xB6, 0x04, 0x00, 0x00, 0x92 };
DeviceAddress Thermometer3 = {   0x28, 0xFF, 0x56, 0xCB, 0x6A, 0x14, 0x03, 0x16 };  // улица
//--- One-wire ----------------------------------------------------------- //
#define chclient 1 // номер клиента 1...
#define timeoutper 400 // таймаут запросов от сервера.
#define timesend 1000 // интервал отправки данных,для обычных датчиков можно установить время выше.
#include <SPI.h>
#include "DHT.h"
DHT dht;
#include "nRF24L01.h"
#include "RF24.h"
unsigned long time1=0;
unsigned long time2=0;
#define RELE_1 6 //
#define RELE_2 7
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
//
// 0 -прием , 1 -передача
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL,0xF0F0F0F0D2LL};
//
// структура принятых данных.МЕНЯТЬ НЕЛЬЗЯ
typedef struct{
byte identifier;
byte val1;
byte val2;
byte val3;
byte val4;
}
nf0;
nf0 servernf;
// структура отправляемых данных.Изменяемые данные.Размер структуры должен быть не больше 32 байт !
typedef struct{
byte identifier;// номер передатчика.МЕНЯТЬ НЕЛЬЗЯ
int temperature_Sensor;// передаём температуру.
int Humidity_Sensor;// передаём влажность
// float Humidity_Sensor;// передаём влажность
int temperature1_Sensor;// передаём температуру.
 int Analog;
 int Analog1;
 int Analog2;
//int Analog2;
//int Analog3;
unsigned int Error_Message; // счетчик ошибок
unsigned long count;// счетчик передач для контроля качества канала
  boolean test_data;
}
nf1;
nf1 clientnf;
void setup() {
//Serial.begin(9600);
dht.setup(3); // DHT датчик на пине 3
pinMode(4, OUTPUT);
pinMode(RELE_1, OUTPUT);
pinMode(RELE_2, OUTPUT);
radio.begin();
delay(2);
// выбор скорости
// radio.setDataRate(RF24_250KBPS);
radio.setDataRate(RF24_1MBPS);
// radio.setDataRate(RF24_2MBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setChannel(100); //тут установка канала
radio.setCRCLength(RF24_CRC_16);
radio.setAutoAck(false); // выключить аппаратное потверждение
// radio.enableDynamicPayloads(); // разрешить Dynamic Payloads
// radio.enableAckPayload(); // разрешить AckPayload
radio.setRetries(15,15);
radio.openReadingPipe(1,pipes[0]); // Открываем канал приема
radio.openWritingPipe(pipes[1]); // Открываем канал передачи
clientnf.identifier = chclient;
 sensors.begin();
 sensors.setResolution(Thermometer1, 10);
 sensors.setResolution(Thermometer3, 10);
 
//датчик радиации
 counts = 0;
  cpm = 0;
 // multiplier = MAX_PERIOD / LOG_PERIOD;      //calculating multiplier, depend on your log period
  attachInterrupt(0, tube_impulse, FALLING); //define external interrupts 
//датчик радиации
}
byte errorstate;
void loop() {
// измерение радиации
    unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > LOG_PERIOD){
    previousMillis = currentMillis;
   //cpm = counts * multiplier;
    cpm = (counts*35)/300;
 //  Serial.print(cpm); Serial.println(" - mlr/h");
//Serial.print(currentMillis); Serial.println(" currentMillis");    
       counts = 0;
  }
// измерение радиации //
  
// для чтения сенсоров
if ((millis()-time1) >= 1000) { // обновляем сенсоры раз в секунду (1000млс)
sensors.requestTemperatures(); // опрос датчика температуры улица
// тут будут опросы сенсоров
//float tempC = sensors.getTempC(Thermometer3); // опрос датчика температуры улица
clientnf.temperature_Sensor = dht.getTemperature()*10;
clientnf.Humidity_Sensor = dht.getHumidity()*10-10;
clientnf.temperature1_Sensor = sensors.getTempC(Thermometer3)*10;
clientnf.Analog=Vrms; //передача напряжения
clientnf.Analog1=Irms; //пример передачи int данных
clientnf.Analog2=cpm; //радиация
//clientnf.Analog3=analogRead(3); //пример передачи int данных
//Serial.println (clientnf.Analog);
//Serial.println (clientnf.Analog1);
//Serial.print(clientnf.Analog2);Serial.println("_mlr");
//Serial.println(clientnf.temperature1_Sensor/10); 
//------------ Измерение напряжения / тока -------------- //
//Serial.println(temp);
for (int n=0; n<numberOfSamples; n++) // цикл крутится 3000 раз
{
//Используется для удаления смещения 2,5в
lastSampleV=sampleV;
lastSampleI=sampleI;
//Читаем с пинов текущее значение U и I
sampleV = analogRead(inPinV);
sampleI = analogRead(inPinI);
// Используется для удаления смещения 2,5в
lastFilteredV = filteredV;
lastFilteredI = filteredI;
//Цифровой фильтр для удаления постоянного смещения 2,5 в
filteredV = 0.996*(lastFilteredV+sampleV-lastSampleV);
filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);
//Тут калибруем фазу
shiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);
//Среднеквадратический метод расчета напряжения
//1) square voltage values
sqV= filteredV * filteredV;
//2) Суммируем
sumV += sqV;
// Среднеквадратический метод расчета тока
//1) square current values
sqI = filteredI * filteredI;
//2) Суммируем
sumI += sqI;
//Мгновенная мощность
instP = shiftedV * filteredI;
//Суммируем
sumP +=instP;
}
//Расчет корня из среднего напряжения и тока (rms)
Vrms = V_RATIO*sqrt(sumV / numberOfSamples); 
Irms = I_RATIO*sqrt(sumI / numberOfSamples); 
//Расчет величины мощности
//realPower = V_RATIO*I_RATIO*sumP / numberOfSamples;
apparentPower = (Vrms * Irms)/1000; // значение в Киловатах
apparentPower1 = (Vrms * Irms); // значение в Ваттах
powerFactor = realPower / apparentPower;
//Сброс накопленных значений
sumV = 0;
sumI = 0;
sumP = 0;
// устанавливаем курсор в 0-ом столбце, 1 строка (начинается с 0):
//Serial.println(Vrms);
//lcd.setCursor (0, 0);
//lcd.print ("U=");
//lcd.setCursor (2, 0);
//lcd.print (Vrms);
//lcd.setCursor (0, 2);
//lcd.print ("I=");
//lcd.setCursor (2, 2);
//lcd.print (Irms);
//lcd.print(sampleI);
//lcd.setCursor (0, 2);
//lcd.print ("P=");
//lcd.setCursor (2, 2);
//lcd.print(apparentPower);
//lcd.setCursor (6, 2);
//lcd.print ("kW");
//------------ Измерение напряжения / тока -------------- //
time1 = millis();
}
//************************************************************************************************/
if ((millis() - time2) >= timesend || errorstate !=0) {
if (clientnf.count <= 2147483646) clientnf.count++; // счетчик передач для контроля качества канала
else clientnf.count = 0;
radio.stopListening();
bool ok = radio.write( &clientnf, sizeof(clientnf) );
radio.startListening();
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > timeoutper ) timeout = true;
if ( timeout ) {
// счетчик ошибок
clientnf.Error_Message++;
errorstate++; // счетчик ошибок для повтора
}
else {
radio.read( &servernf, sizeof(servernf) );
errorstate=0;
}
if (errorstate>=50) errorstate=0; // не более 3 попыток для повтора
//************************************************************************************************/
if (servernf.identifier == chclient) { // выполнение команд с сервера,если данные предназначены для этого клиента:
// val1= 10 -значит дергаем пинами, val2 - номер пина, val3 - состояние пина
// не забудте установить режим OUTPUT для нужных пинов.
// nRF-USB write 1 10 7 1 1 - что значит установить на 7 выводе логический уровень 1
if (servernf.val1==10) digitalWrite(servernf.val2,servernf.val3);
// val1= 11 -значит управляем ШИМ пинами, val2 - номер пина, val3 - уровень 0..255.
// не забудте установить режим OUTPUT для нужных пинов.
// ШИМ возможен только на некоторых пинах !!
if (servernf.val1==11) analogWrite(servernf.val2,servernf.val3);
}
time2 = millis();
}
} // конец loop
//////////////////////////////////////////////////
void tube_impulse(){       //subprocedure for capturing events from Geiger Kit
  digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1);              // wait for a second
  digitalWrite(4, LOW);
  counts++;
}
					
					
				
					
				Соединения блока датчиков и основного
конструктор прошивок тут http://wifi-iot.com/
				
					
				Мега проект! Хочу повторить! Буду изучать мат часть да и теоретическую тоже. Спасибо!
Я смог повторить, простой, чей-то проект на народе (BME280/ESP8266), но такой проект это для меня уже фантастика, очень и очень впечатляет и естественно хочу аналогично улучшить на Вашем примере и свою метеостанцию.
				
					
				Метеостанция пересобрана на новом модуле ESP32
Будут добавляться другие датчики - тут ножек для входа выхода хватит..
Если кому интересно буду по мере расширения функционала публиковать тут схемы и код