Skocz do zawartości
jaro44

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

Udostępnij ten post


Link to post
Share on other sites

@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ą")

Udostępnij ten post


Link to post
Share on other sites

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)?

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@soyer odpowiedział

ten kolejny błąd w tym fragmencie?

Edytowano przez jaro44

Udostępnij ten post


Link to post
Share on other sites

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 🙂

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

poddaje się, nie wiem

Edytowano przez jaro44

Udostępnij ten post


Link to post
Share on other sites

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 😞

Udostępnij ten post


Link to post
Share on other sites
(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

Udostępnij ten post


Link to post
Share on other sites
(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

Udostępnij ten post


Link to post
Share on other sites
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.

Udostępnij ten post


Link to post
Share on other sites
(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

Udostępnij ten post


Link to post
Share on other sites

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

Udostępnij ten post


Link to post
Share on other sites
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

 

Udostępnij ten post


Link to post
Share on other sites
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)

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...