Skocz do zawartości

Połączenie dwóch esp8266 do pomiaru temperatur


jaro44

Pomocna odpowiedź

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

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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 🙂

Link do komentarza
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 😞

Link do komentarza
Share on other sites

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
Link do komentarza
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
Link do komentarza
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.

Link do komentarza
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
Link do komentarza
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
Link do komentarza
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

 

Link do komentarza
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)

Link do komentarza
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!

Anonim
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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.