Skocz do zawartości

Połączenie dwóch esp8266 do pomiaru temperatur


Pomocna odpowiedź

(edytowany)

w. g. wersji @jaro44 else się nigdy nie wykona... 

5 minut temu, jaro44 napisał:

musiałem podejrzeć

wkleiłeś wersję ethanak, w której else się wykona... 

Edytowano przez SOYER

@SOYER przypominam wersję z błędem:

if (zlecenie)
  {
    if (millis() - ostatnio > 750)
    {
      termometr[0] = DS18B20.getTempC(t1)*100;
      termometr[1] = DS18B20.getTempC(t2)*100;
      zlecenie = false;
    }
      else
      {
        if (millis() - ostatnio > 5000)
        {
           DS18B20.requestTemperatures();
           ostatnio = millis();
        }
      }
  }
  
  

Traktujmy to jako zabawę (no, powiedzmy "zabawę edukacyjną")

Wcale nie proste, nie odpowiedziałes na pytanie "co się stanie".

Przy okazji - kto znajdzie jeszcze jeden mój błąd (efekt pisania kodu przed właściwą porcją kawy)?

Nikt prawidłowo na razie nie odpowiedział - a szukanie błędów to 90% zajęć programisty...

Ktoś kiedyś powiedział, że przeciętny programista robi jeden błąd na 7 linii programu... coś w tym jest 🙂

Najpierw mój błąd:

oprócz DS18B20.requestTemperatures() należy ustawić zlecenie na true. Ale nawet gdyby...

Wskutek błędu całość znalazła się w bloku "if (zlecenie)". Ponieważ na początku zlecenie jest równe true, program bardzo grzecznie poczeka 750 milisekund, odczyta wartości termometrów i zmieni wartość zlecenia na false.

Ponieważ od tej chwili zlecenie jest równe false, blok w if(zlecenie) nie wykona się nigdy.

Wracam do roboty 😞

(edytowany)

to swoją drogą, mnie zastanawia dlaczego to się w ogóle wykona chociaż raz, skoro ostatno=millis() macie w pętli głównej nad if-em korzystającym z ostatni=millis() ... 

A to co napisałeś teraz ethanak to myślałem, że dopiero do tego dojdziecie w nauce, iż ten if wykona się, póki co, tylko raz... 

Edytowano przez SOYER
(edytowany)

mam nadzieję, że teraz jest już ok

//ESP8266 server

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include <OneWire.h>
#include <DallasTemperature.h>

#define TESTY 1

#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

const char* ssid = "xxx";
const char* password = "yyy";

WiFiUDP Udp;
  unsigned int localUdpPort = 12345;
  char packetBuffer[255];
  int termometr[4];

  DeviceAddress t1 = { 0x28, 0xfb, 0x50, 0x79, 0xA2, 0x00, 0x03, 0x61 }; // - adres DS18B20 - 1
  DeviceAddress t2 = { 0x28, 0x44, 0x2B, 0x79, 0xA2, 0x00, 0x03, 0x5F }; // - adres DS18B20 - 2

void setup()
{
  Serial.begin(115200);
  Serial.println();

  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
    WiFi.config(IPAddress(192, 168, 1, 102), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("connected");

  Udp.begin(localUdpPort);
  DS18B20.begin();
  DS18B20.requestTemperatures();
}

void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize>0)
  {
    #ifdef TESTY
      Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    #endif
    int len = Udp.read(packetBuffer, packetSize);
    packetBuffer[len] = 0;
    #ifdef TESTY
    Serial.printf("UDP packet contents: %s\n", packetBuffer);
    #endif

  
    if (packetBuffer[0] == 'T' && packetBuffer[0] >='1' && packetBuffer[1] <= '2')
    {
      int indeks = packetBuffer[1] - '1' + 2;
      termometr[indeks] = atoi(packetBuffer+2);
    }
  }

  static bool zlecenie = true;
  static uint32_t ostatnio = millis();

  if (zlecenie)
  {
    if (millis() - ostatnio > 750)
    {
      termometr[0] = DS18B20.getTempC(t1)*100;
      termometr[1] = DS18B20.getTempC(t2)*100;
      zlecenie = false;
    }
  }
      else
      {
        if (millis() - ostatnio > 5000)
        {
           DS18B20.requestTemperatures();
           zlecenie = true;
           ostatnio = millis();
        }
      }

  
  static uint32_t ostatnio2 = millis();
  if (millis() - ostatnio2 > 5000)
  {
    ostatnio2 = millis();
    printf("%d %d %d %d\n", termometr[0], termometr[1], termometr[2], termometr[3]);
  }
}

 

Edytowano przez jaro44
2 godziny temu, SOYER napisał:

to swoją drogą, mnie zastanawia dlaczego to się w ogóle wykona chociaż raz, skoro ostatno=millis() macie w pętli głównej nad if-em korzystającym z ostatni=millis() ... 

Dopiero się uczę, ale to jest chyba jasne, że to jest dyrektywa static tylko do inicjalizacji zmiennej i po wykonaniu if nie jest już ona inicjalizowana tylko zachowuje ostatni wpis.

(edytowany)

Jak tylko znajdziesz wolną chwilę to bardzo proszę o instrukcje co następnie.

Wspominałeś coś o wyświetlaczu, więc go zainstalowałem:

//ESP8266 server

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include <OneWire.h>
#include <DallasTemperature.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define TESTY 1

#define ONE_WIRE_BUS 2
  OneWire oneWire(ONE_WIRE_BUS);
  DallasTemperature DS18B20(&oneWire);

  Adafruit_SSD1306 display;

  const char* ssid = "xxx";
  const char* password = "yyy";

  WiFiUDP Udp;
  unsigned int localUdpPort = 12345;

  char packetBuffer[255];
  int termometr[4];

  DeviceAddress t1 = { 0x28, 0xfb, 0x50, 0x79, 0xA2, 0x00, 0x03, 0x61 }; // - adres DS18B20 - 1
  DeviceAddress t2 = { 0x28, 0x44, 0x2B, 0x79, 0xA2, 0x00, 0x03, 0x5F }; // - adres DS18B20 - 2

void setup()
{
  Serial.begin(115200);
  Serial.println();

  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  WiFi.config(IPAddress(192, 168, 1, 102), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("connected");

  Udp.begin(localUdpPort);
  DS18B20.begin();
  DS18B20.requestTemperatures();
  display.begin(SSD1306_SWITCHCAPVCC);
  display.display();
}

void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize>0)
  {
    #ifdef TESTY
      Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    #endif
    int len = Udp.read(packetBuffer, packetSize);
    packetBuffer[len] = 0;
    #ifdef TESTY
      Serial.printf("UDP packet contents: %s\n", packetBuffer);
    #endif

  
    if (packetBuffer[0] == 'T' && packetBuffer[0] >='1' && packetBuffer[1] <= '2')
    {
      int indeks = packetBuffer[1] - '1' + 2;
      termometr[indeks] = atoi(packetBuffer+2);
    }
  }

  static bool zlecenie = true;
  static uint32_t ostatnio = millis();

  if (zlecenie)
  {
    if (millis() - ostatnio > 750)
    {
      termometr[0] = DS18B20.getTempC(t1)*100;
      termometr[1] = DS18B20.getTempC(t2)*100;
      zlecenie = false;
    }
  }
      else
      {
        if (millis() - ostatnio > 5000)
        {
           DS18B20.requestTemperatures();
           zlecenie = true;
           ostatnio = millis();
        }
      }

    static uint32_t ostatnio2 = millis();
    if (millis() - ostatnio2 > 5000)
    {
      ostatnio2 = millis();
      printf("%d %d %d %d\n", termometr[0], termometr[1], termometr[2], termometr[3]);
    }
}

 

Edytowano przez jaro44

Dobra - zakładam że to co post wyżej działa (tzn. mierzy temperaturę, odbiera od zdalnego termometru i wypisuje na serialu wyniki).

Zanim zaczniemy bawić się wyświetlaczem, zastanówmy się: czy wyświetlanie co dwie sekundy na pewno ma sens? Czy nie lepiej zrobić tak, żeby wyświetlacz od razu reagował na jakiekolwiek zmiany?

Taki algorytm:
 

czy dane w tablicy się zmieniły?

jeśli tak: wyświetl dane

Niby proste... ale jak stwierdzić, czy dane są zmienione?

Jak słusznie kolega @jaro44 zauważył, konieczne będzie porównanie bieżących wyników z zachowaną kopią poprzednich. Tyle, że w przypadku tablicy wygodniej będzie przechowywać kopię tej właśnie tablicy, niż porównywać nowe dane ze starymi - szczególnie, że nowe dane pochodzą z różnych źródeł i trzeba by było we wszystkich przypadkach umieszczać te porównania w kodzie.

Czyli zróbmy tak: zainicjalizujmy tablicę jakimiś wartościami (np. -12700 - oznaczającą "niepodłączony termometr"), tablicę-kopię pozostawmy wyzerowaną; w tej sytuacji termometr od razu nam wyświetli jakieś wartości oznaczające w tym przypadku "oczekujemy na wartość z czujnika".

Czyli zdeklarujmy sobie dwie globalne tablice:
 

int termometry[4]={12700,12700,12700,12700};
int termometry_kopia[4]; // automatycznie wypełniona zerami

A w funkcji loop() zamiast kodu wyświetlającego co dwie sekundy spróbujmy wstawić coś takiego:

int i;
for (i=0; i<4; i++) {
  if (termometry[i] != termometry_kopia[i]) break; // przerywamy pętlę jeśli mamy nową wartość
}
// teraz jeśli po wyjściu z pętli zmienna kontrolna i jest mniejsza niż 4,
// oznacza to, że dane się zmieniły

if (i < 4) {
  // wyświetlamy na razie na serialu
  printf("%d %d %d %d\n", termometr[0], termometr[1], termometr[2], termometr[3]);
  // 
  for (i=0; i<4; i++) termometry_kopia[i] = termometry[i]; 
}

    

Później w miejsce printf będziemy mogli wstawić cały kod zarządzający wyświetlaczem - ale jeszcze nie teraz!

@jaro44 sprawdź działanie i zastanów się, w jakim przypadku otrzymamy błędne wyniki - ew. zaproponuj jak się tego ustrzec!

  • Lubię! 1
49 minut temu, ethanak napisał:

@jaro44 sprawdź działanie i zastanów się, w jakim przypadku otrzymamy błędne wyniki - ew. zaproponuj jak się tego ustrzec!

działa, musiałem tylko semantykę poprawić (termometry --> termometr)

teraz daj mi chwilę na zastanowienie się nad drugą częścią zadania

 

1 minutę temu, jaro44 napisał:

działa, musiałem tylko semantykę poprawić (termometry --> termometr)

Jasne - pamiętaj, że ja to piszę bezpośrednio w przeglądarce i mam prawo się pomylić (szczególnie jak się programuje w paru językach jednocześnie można dostać kociokwiku np. z true, True i TRUE)

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...