Метеостанция с внутренним и внешним датчиком (нужна помощь в доведении скетча до ума)

В сети множество подобных проектов, но не все мне подходят.
Я нашел у иностранца проект подходящий под мои требования, а именно внешний датчик температуры и влажности передающий сигнал по радиоканалу (433Мгц), с приемником показывающим и внутренние данные с возможностью кнопкой переключаться между ними.
Проект был собран и заработал сразу. Но т.к. видать это был всего лишь проект, то в результате тестирования вылезли недочеты программы( А именно при пропадании питания внешнего датчика на дисплее продолжают отображаться его последние данные. (иногда это приводило к зависанию приемника).
Данная связка планируется на дачу для контроля показаний в курятнике.
И еще в проекте используется OLED дисплей, а мне бы хотелось переделать на 1602, чтобы было покрупнее, т.к. в маленьком OLED без очков фиг чего увидишь((((
Передатчик

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
#include <DHT_U.h>

#define DHTPIN 3 
#define DHTTYPE    DHT22
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;

char temp[7];
char umid[7];

void setup() {
  
  // Передатчик подключен к Arduino Pin #10  
  mySwitch.enableTransmit(10);
  dht.begin();
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);
  delayMS = sensor.min_delay / 1000;
  
}

void loop() {
  delay(delayMS);
  // Получите температурное событие и выведите его значение.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  }
  else {
    mySwitch.send(int(event.temperature*10),24);
  }
  delay(delayMS);
  // Получите событие влажности и выведите его значение.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println(F("Error reading humidity!"));
  }
  else {
    mySwitch.send(int(event.relative_humidity*10),25);
  }
  
  delay(2000);
}

Приемник

#include <RCSwitch.h>
#include <DHT_U.h>
#include <U8glib.h>
#include <OneButton.h>

#define DHTPIN 3
#define DHTTYPE DHT11

RCSwitch mySwitch = RCSwitch();

U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);

DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;

OneButton button(A1, true);

int tmp;
int EstInt=0; // Если 0, то отображается внутренняя температура, а если 1, то внешняя температура
char temp[7];
char umid[7];
char tempe[7];
char umide[7];
//float flt = 2.75;

void setup() {
Serial.begin(9600);
mySwitch.enableReceive(0); // Приемник при прерывании 0 => that is pin #2
u8g.setColorIndex(1);

// button.attachClick(click);
button.attachLongPressStop(longPressStop);

dht.begin();
// Распечатайте сведения о датчике температуры.
sensor_t sensor;
dht.temperature().getSensor(&sensor);
Serial.println(F(“------------------------------------”));
Serial.println(F(“Temperature Sensor”));
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F(“C”));
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F(“C”));
Serial.print (F(“Resolution: “)); Serial.print(sensor.resolution); Serial.println(F(“C”));
Serial.println(F(”------------------------------------”));
// Распечатайте сведения о датчике влажности.
dht.humidity().getSensor(&sensor);
Serial.println(F(“Humidity Sensor”));
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
Serial.print (F(“Unique ID: “)); Serial.println(sensor.sensor_id);
Serial.print (F(“Max Value: “)); Serial.print(sensor.max_value); Serial.println(F(”%”));
Serial.print (F(“Min Value: “)); Serial.print(sensor.min_value); Serial.println(F(”%”));
Serial.print (F(“Resolution: “)); Serial.print(sensor.resolution); Serial.println(F(”%”));
Serial.println(F(”------------------------------------”));
// Установите задержку между показаниями датчика на основе сведений о датчике.
delayMS = sensor.min_delay / 1000;
}

void loop() {
button.tick();
if (mySwitch.available()) {
tmp = mySwitch.getReceivedValue();
if (mySwitch.getReceivedBitlength() == 24) {
Serial.print("External Temperature: ");
dtostrf(float(tmp)/10, 2, 1, tempe);
Serial.print(tempe);
Serial.println(“C”);
tempe[4]=byte(0xb0);
tempe[5]=‘C’;
tempe[6]=‘\0’;
}
else {
Serial.print(“External Humidity: “);
dtostrf(float(tmp)/10, 2, 1, umide);
Serial.print(umide);
Serial.println(”%”);
umide[4]=’ ‘;
umide[5]=’%‘;
umide[6]=’\0’;
}
mySwitch.resetAvailable();
}
delay(delayMS);
// Получите температурное событие и выведите его значение.
sensors_event_t event;
dht.temperature().getEvent(&event);
if (isnan(event.temperature)) {
Serial.println(F(“Error reading temperature!”));
}
else {
Serial.print(F("Internal Temperature: "));
Serial.print(event.temperature);
Serial.println(F(“C”));
dtostrf(event.temperature, 2, 1, temp);
temp[4]=byte(0xb0);
temp[5]=‘C’;
temp[6]=‘\0’;
}
// Получите событие влажности и выведите его значение.
dht.humidity().getEvent(&event);
if (isnan(event.relative_humidity)) {
Serial.println(F(“Error reading humidity!”));
}
else {
Serial.print(F(“Internal Humidity: “));
Serial.print(event.relative_humidity);
Serial.println(F(”%”));
dtostrf(event.relative_humidity, 2, 1, umid);
umid[4]=’ ‘;
umid[5]=’%‘;
umid[6]=’\0’;
}
if (EstInt==0) {
u8g.firstPage();
do {
draw(“In Temp:”, 0, 14);
draw(temp, 70, 14);
draw(“In Humi:”, 0, 32);
draw(umid, 70, 32);
} while( u8g.nextPage() );
}
else {
u8g.firstPage();
do {
draw(“Ex Temp:”, 0, 14);
draw(tempe, 70, 14);
draw(“Ex Humi:”, 0, 32);
draw(umide, 70, 32);
} while( u8g.nextPage() );
}
}

void longPressStop() {
Serial.println(“Button click.”);
u8g.firstPage();
do {
draw(“Please Wait…”, 0, 23);
} while( u8g.nextPage() );

if (EstInt == 0)
EstInt=1;
else
EstInt=0;
}

void draw(char* parola, int posx, int posy) {
// графические команды для перерисовки всего экрана должны быть размещены здесь
u8g.setFont(u8g_font_unifont);
//u8g.setFont(u8g_font_osb21);
u8g.drawStr( posx, posy, parola);
}

Спасибо за помощь.

Пожалуйста, вставьте код правильно, иначе спасибо будет говорить не за что

модули 433МГц сразу выкинь нахрен. И температуру/влажность лучше выводить на ТМ1637

Приемник

#include <RCSwitch.h>
#include <DHT_U.h>
#include <U8glib.h>
#include <OneButton.h>

#define DHTPIN 3 
#define DHTTYPE    DHT11

RCSwitch mySwitch = RCSwitch();

U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);

DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;

OneButton button(A1, true);

int tmp;
int EstInt=0; // Если 0, то отображается внутренняя температура, а если 1, то внешняя температура
char temp[7];
char umid[7];
char tempe[7];
char umide[7];
//float flt = 2.75;

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Приемник при прерывании 0 => that is pin #2
  u8g.setColorIndex(1); 

//  button.attachClick(click);
  button.attachLongPressStop(longPressStop);

  dht.begin();
  // Распечатайте сведения о датчике температуры.
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  Serial.println(F("------------------------------------"));
  Serial.println(F("Temperature Sensor"));
  Serial.print  (F("Sensor Type: ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:  ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:   ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:   ")); Serial.print(sensor.max_value); Serial.println(F("C"));
  Serial.print  (F("Min Value:   ")); Serial.print(sensor.min_value); Serial.println(F("C"));
  Serial.print  (F("Resolution:  ")); Serial.print(sensor.resolution); Serial.println(F("C"));
  Serial.println(F("------------------------------------"));
  // Распечатайте сведения о датчике влажности.
  dht.humidity().getSensor(&sensor);
  Serial.println(F("Humidity Sensor"));
  Serial.print  (F("Sensor Type: ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:  ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:   ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:   ")); Serial.print(sensor.max_value); Serial.println(F("%"));
  Serial.print  (F("Min Value:   ")); Serial.print(sensor.min_value); Serial.println(F("%"));
  Serial.print  (F("Resolution:  ")); Serial.print(sensor.resolution); Serial.println(F("%"));
  Serial.println(F("------------------------------------"));
  // Установите задержку между показаниями датчика на основе сведений о датчике.
  delayMS = sensor.min_delay / 1000;
}

void loop() {
  button.tick();
  if (mySwitch.available()) {
    tmp = mySwitch.getReceivedValue();
    if (mySwitch.getReceivedBitlength() == 24) {
      Serial.print("External Temperature: ");
      dtostrf(float(tmp)/10, 2, 1, tempe);
      Serial.print(tempe);
      Serial.println("C");
      tempe[4]=byte(0xb0);
      tempe[5]='C';
      tempe[6]='\0';
      }
    else {
      Serial.print("External Humidity: ");
      dtostrf(float(tmp)/10, 2, 1, umide);
      Serial.print(umide);
      Serial.println("%");
      umide[4]=' ';
      umide[5]='%';
      umide[6]='\0';
      }
    mySwitch.resetAvailable();
  }
  delay(delayMS);
  // Получите температурное событие и выведите его значение.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  }
  else {
    Serial.print(F("Internal Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("C"));
    dtostrf(event.temperature, 2, 1, temp);
    temp[4]=byte(0xb0);
    temp[5]='C';
    temp[6]='\0';
  }
  // Получите событие влажности и выведите его значение.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println(F("Error reading humidity!"));
  }
  else {
    Serial.print(F("Internal Humidity: "));
    Serial.print(event.relative_humidity);
    Serial.println(F("%"));
    dtostrf(event.relative_humidity, 2, 1, umid);
    umid[4]=' ';
    umid[5]='%';
    umid[6]='\0';
  }
  if (EstInt==0) {
    u8g.firstPage();  
    do {
      draw("In Temp:", 0, 14);
      draw(temp, 70, 14);
      draw("In Humi:", 0, 32);
      draw(umid, 70, 32);
    } while( u8g.nextPage() );
  }
  else {
    u8g.firstPage();  
    do {
      draw("Ex Temp:", 0, 14);
      draw(tempe, 70, 14);
      draw("Ex Humi:", 0, 32);
      draw(umide, 70, 32);
    } while( u8g.nextPage() );
  }
}

void longPressStop() {
  Serial.println("Button click.");
  u8g.firstPage();  
  do {
    draw("Please Wait...", 0, 23);
    } while( u8g.nextPage() );

  if (EstInt == 0)
    EstInt=1;
  else
    EstInt=0;
} 

void draw(char* parola, int posx, int posy) {
  // графические команды для перерисовки всего экрана должны быть размещены здесь
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawStr( posx, posy, parola);
}

Значит так и задумано автором. Почему это считается недочётом?

Потому что по логике: есть показания - есть данные на экране, нет показаний - пустота на экране и сразу понятно, что с датчиком что-то не то, а в данном варианте можно до опупения смотреть на (застывшие) показания а в реальности там уже все совсем другое(


Вот утром если бы не влажность можно было бы и не понять что с датчиком что-то не то.

Значит, если в вашей логике нужно сделать иначе, то при каждом удачном сеансе связи запоминаете millis() в переменной lastSuccess. При выводе на экран проверяете разницу между millis() и lastSuccess. Если она больше N, то значит датчик отвалился и на экран нужно выводить фигу. В противном случае - число.

Что взамен?
Спрашиваю, потому как тоже задумал сделать уличный датчик температуры. В принципе, уже сделал, вот только проблема в передатчике. Пробовал FS1000A, но на 5В расстояние передачи маленькое, ему бы 12В, но тогда нужно для остальной схемы понижать напряжение питания, а это лишние потери на преобразовании (тинька спит, а преобразователь всё-равно жрёт). Если же взять SYN115 (ещё не экспериментировал, как у него с дальностью), то ему нужно 3В, что для тиньки норм, но уже для DS18B20 это нижний предел питания.

Смотря какая дальность. В деревне, с минимумом эфирных помех, до 50метров прекрасно подойдёт JDY40 или HC-12. Программирование сводится к минимуму

1 лайк

У мня даччик температуры на Тиньке85 прекрасно себя на балконе чуствует уже 4 года. Питается от лития

У меня тинька, HC-12, DS18B2. Питание от двух AA. Повышалка ничего не жрёт во сне, т.к. она сама питается с пина через транзистор и перед сном я её выключаю. Батареек внешнего модуля хватает на год+

1 лайк

В выходные на даче проверил работоспособность метеостанции. Дальность 433 Мгц передатчика хватило. Скетч автор поправил, все теперь работает по “логике”.

сами не осилили?
Почему сразу к автору не пошли, зачем надо было писать на форум?

Проблема. Есть два ОЛЕД дисплея 0,96 128*64. Внешне немного отличаются друг от друга. Один на этом скетче работает хорошо. При подключении второго идет засветка всех пикселей. Проверял дисплей на другой библиотеке - работает хорошо. Почему-то на этой библиотеке (U8glib) второй дисплей не пашет(
Просто я не сравнил их и напечатал корпус под другой дисплей, а в нем отверстия немного отличаются((


Как его настроить?

Вы вообще предполагает, как пост выглядит со стороны?

Есть две херовины, одна работает так, другая этак. Что делать, куда и какой код написать? (С)

1 лайк

Можно руками, но это опционально.

Практика показывает, что на рынке присутствует несколько похожих моделей, немного отличающихся друг от друга.
С точки зрения программиста это выглядит так: для того, чтобы дисплей начал работать в нужном режиме, на него перед началом работы нужно отправить некоторую последовательность команд. Вот набор этих команд от модели к модели может слегка различаться.
Найдите эту последовательность в той библиотеке, с которой дисплей работает, и перенесите в библиотеку, где дисплей не работает.
Последовательность команд может быть либо записана в массиве, либо непосредственно содержаться в в коде в виде цепочки отдельных команд.

Для начала приложите четкие фото обоих дисплеев с двух сторон - мож кто по фото сразу опознает, в чем разница

Слева - работает (при подаче питания он также загорается полностью и затем выводит информацию)

Ну, Вы ж сами сказали:

Так и используйте “другую библиотеку”. Какие проблемы? Зачем создавать себе трудности и геройски решать. С чем работает, то и используйте.

А вообще, это Вам наука, от вот этих граблей:

Мне, например, не составляет никаких проблем использовать любую библиотек или не использовать никакой, но, тем не менее, пока у меня на макетке не заработает, никаких корпусов я не делаю. А Вы, смелы больно :slight_smile:

1 лайк