Skocz do zawartości
jaro44

Połączenie dwóch esp8266 do pomiaru temperatur

Pomocna odpowiedź

Przepraszam, ale musiałem pieska wyprowadzić

nie mam jeszcze w tym nodemcu testowym jako server zamontowanego czujnika,

ale myślę, że ja (pewnie nie za dobrze) jakoś tak bym robił:

  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
  termometr[0] = DS18B20.getTempC(t1);
  termometr[1] = DS18B20.getTempC(t2);

zaraz to pospinam i sprawdzę

Udostępnij ten post


Link to post
Share on other sites
6 minut temu, jaro44 napisał:

Przepraszam, ale musiałem pieska wyprowadzić

Ty to masz fajnie... ja nie mam pieska i nie mam co wyprowadzać 😞

7 minut temu, jaro44 napisał:

zaraz to pospinam i sprawdzę

tylko pamiętaj o odczekaniu jakiegoś czasu po request i zrobieniu jakiejś magii, żeby nie czytał temperatury co sekundę (bo to trochę nie ma sensu).

Udostępnij ten post


Link to post
Share on other sites
//ESP8266 server

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

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

#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);
}


void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(packetBuffer, 255);
    packetBuffer[len] = 0;
    Serial.printf("UDP packet contents: %s\n", packetBuffer);
  }
  
  if (packetBuffer[0] == 'T' && packetBuffer[0] >='1' && packetBuffer[1] <= '2') {
	int indeks = packetBuffer[1] - '1' + 2;
    termometr[indeks] = atoi(packetBuffer+2);
  }
  
  DS18B20.requestTemperatures();
  delay(5000);

  termometr[0] = DS18B20.getTempC(t1)*100;
  termometr[1] = DS18B20.getTempC(t2)*100;
  
  static uint32_t ostatnio = millis();
  if (millis() - ostatnio > 2000) {
    ostatnio = millis();
    printf("%d %d %d %d\n", termometr[0], termometr[1], termometr[2], termometr[3]);
  }
}

mam czujnik tylko pod t1, ale wygląda ok:

2175 -12700 2037 0
Received 6 bytes from 192.168.1.103, port 53260
UDP packet contents: T12037
2175 -12700 2037 0
2175 -12700 2037 0
2181 -12700 2037 0
2181 -12700 2037 0
Received 6 bytes from 192.168.1.103, port 53260
UDP packet contents: T12037
2187 -12700 2037 0
2181 -12700 2037 0
2181 -12700 2037 0
2187 -12700 2037 0
2193 -12700 2037 0
Received 6 bytes from 192.168.1.103, port 53260
UDP packet contents: T12037
2193 -12700 2037 0
2193 -12700 2037 0
2193 -12700 2037 0
2193 -12700 2037 0
2193 -12700 2037 0
Received 6 bytes from 192.168.1.103, port 53260
UDP packet contents: T12037
2187 -12700 2037 0

temperatura na t1 trochę skacze ale czujnik mam przy komputerze

Udostępnij ten post


Link to post
Share on other sites

Wszystko jest fajnie, tylko wyskoczyła jedna niemiła sprawa: dopóki nie było termometrów, na serialu program wypisywał sobie ładnie wszystko co 2 sekundy. Teraz... mija siedem, tak? I to w ciągu tych siedmiu sekund układ może zgubić pakiet Udp... coś tu chyba jest nie tak...

Zauważ jedno: co prawda serial wypluwał z siebie wyniki co dwie sekundy - nie było tam żadnego delaya! Magia?

Możesz to jakoś poprawić? W razie czego możesz popatrzeć tutaj: https://forbot.pl/blog/kurs-arduino-ii-wielozadaniowosc-opoznienia-z-millis-id18418

 

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

wdług mnie wciąż jest co 2 s, ale ok postaram się wgłębić w temat i zmienić to

Edit:

ten delay przy wifi też zmienić na milis?

Edytowano przez jaro44

Udostępnij ten post


Link to post
Share on other sites
8 minut temu, jaro44 napisał:

ten delay przy wifi też zmienić na milis?

Nie - tam jest prawidłowo. Tylko w loop nie może być żadnego delay - po prostu żeby nie zgubić pakietu.

10 minut temu, jaro44 napisał:

wdług mnie wciąż jest co 2 s, ale ok postaram się wgłębić w temat i zmienić to

No tak, nie zauważyłem jednego:

odczyt termometrów musi być niezależny (bezpośrednio w loop a nie za jakimś ifem). Poza tym ten fragment który Ci podałem (z wypisywaniem na serial) miał byc na końcu loop, a nie prawie na końcu. Jeden nawias dalej.

Czyli coś takiego:

loop() {
	jeśli odebrano pakiet {
  		rób coś z pakietem
	}
	odczytaj termometry;
	wyświetl wyniki;
}

Jeśli urządzenie ma mieć podłączony wyświetlacz - odczyt termometru nie może być po odebraniu pakietu, bo co się stanie jak np. wyłączysz zdalny termometr albo padnie sieć?

To samo dotyczy wyświetlania.

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

wdług mnie jest ok, ten nawias jest od wyswietlana wyników

tak jest dobrze?:

void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(packetBuffer, 255);
    packetBuffer[len] = 0;
    Serial.printf("UDP packet contents: %s\n", packetBuffer);
  }
  
  if (packetBuffer[0] == 'T' && packetBuffer[0] >='1' && packetBuffer[1] <= '2') {
	int indeks = packetBuffer[1] - '1' + 2; // zaczynany od indeksu 2 bo 0 i 1 to termometry bezpośrednie
    termometr[indeks] = atoi(packetBuffer+2);
  }

  static uint32_t ostatnio = millis();
  if (millis() - ostatnio > 2000) {
    ostatnio = millis();
    DS18B20.requestTemperatures();
  }

  termometr[0] = DS18B20.getTempC(t1)*100;
  termometr[1] = DS18B20.getTempC(t2)*100;
  
  static uint32_t ostatnio2 = millis();
  if (millis() - ostatnio2 > 2000) {
    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

Nie, nie jest dobrze, ale dzisiaj już mam dość monitora - jutro też jest dzień 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

ok, dzięki

ja sobie poczytam, a Tobie dobrej nocy

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
44 minuty temu, ethanak napisał:

Tylko w loop nie może być żadnego delay - po prostu żeby nie zgubić pakietu.

Przepraszam, że się wcinam, ale to zdanie zdaje się rozwiązywać mój problem z gubieniem końcówki transmisji z sim800l. W sumie logiczne, że jeśli jakiś moduł nadaje, a odbiorca wejdzie w delay np. w połowie transmisji to reszty wiadomości nie zobaczy, tak? Nawet jeśli to jakieś "głupie" 20ms...

Edytowano przez SOYER

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

W udp nie ma możliwości by zgubić pakiet tym że odbiorca cobie czeka ...  Po to jest Bufor dopiero po przekroczeniu buforu są kasowane stare na nowe, inaczej mówiąc nastąpi przepełnienie buforu... Wiec jeśli nie wysyła pakiety co 1ms  a co 2s to może spokojnie odbiorca coś inne robić w tym czasie i odczytać można spokojnie nawet po 10s małe treści...  A w esp8266 bufor jest 1024 wiec trochę pomieści... W przypadku ESP nawet dalay jest wskazane w niektórych sytuacjach  bo to nie oznacza dla niego postój "zawieszenie" a w tym czasie zajmuje się komunikacją WIFI bo tak naprawdę ESP nie ma typowej funkcji "delay"... 

 

Komunikacja  z sim800l jest na UART tam też jest bufor do odczytu tylko sporo mniejszy jeżeli uważasz że to przez przepełnienie zwiększ go.... 

Edytowano przez Jarewa

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
1 godzinę temu, Jarewa napisał:

W udp nie ma możliwości by zgubić pakiet tym że odbiorca cobie czeka ...  Po to jest Bufor dopiero po przekroczeniu buforu są kasowane stare

Czyli jest możliwość.

1 godzinę temu, Jarewa napisał:

W przypadku ESP nawet dalay jest wskazane w niektórych sytuacjach 

o właśnie: w niektórych sytuacjach, a tutaj akurat z taką niektórą sytuacją nie mamy do czynienia. A właśnie w ESP8266 funkcja loop() powinna się skończyć jak najszybciej, aby zostawić czas na komunikację WiFi i inne ważne sprawy którymi się ESP w międzyczasie zajmuje.

Mamy natomiast do czynienia z zewnętrzną aplikacją (termik4temp konkretnie), która wysyła pakiet udp i oczekuje odpowiedzi - i jest to przy okazji odpowiedź na Twoje uwagi:
 

Cytat

 

A dlaczego w kodzie połączyłeś odbiór z nadawaniem?

Bo to wygląda tak że dopóki nie dostanie nic po UDP to nic nie wyśle.. 

 

Ano dlatego, że tak to sobie autor owej aplikacji wymyślił i tak to działa...

Gdybyś zadał sobie trudu i sprawdził zobaczyłbyś, że ten kod jest po prostu żywcem przepisany z zamieszczonego przez autora termika kodu na arduinopolska. Owszem - kod jest fatalny, ale skąd kolega wątkotwórca (który się na tym niespecjalnie zna) miałby o tym wiedzieć?

Tak że następnym razem, kolego @Jarewa sprawdź o czym się tu mówi a potem zabieraj głos w obronie delajów i zależności wysyłania pakietów od ich otrzymania. Bo na pewno delay(5000) nie wpłynie pozytywnie na responsywność.

Edytowano przez ethanak
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
9 godzin temu, ethanak napisał:

Nie, nie jest dobrze, ale dzisiaj już mam dość monitora - jutro też jest dzień 🙂

  static uint32_t ostatnio = millis();
  if (millis() - ostatnio > 2000) {
    ostatnio = millis();
    DS18B20.requestTemperatures();
  }

nie wiem czy to dobrze interpretuje:

statyczna "ostatnio" jest równa aktualnemu czasowi stopera,

więc jeśli aktualny stoper minus ostatnio będzie większy od 2000ms

to wykona się pomiar?

Udostępnij ten post


Link to post
Share on other sites
1 godzinę temu, jaro44 napisał:

nie wiem czy to dobrze interpretuje:

Interpretujesz bardzo dobrze, tyle że pomiar co prawda się wykona, ale trzeba jeszcze te wyniki z termometru pobrać. O ile w przypadku wypisywania czegoś na monitorze/serialu wystarczy takie proste sprawdzanie - o tyle odczyt z termometru jest dwufazowy (zlecenie - odczekanie - odczyt).

Czyli mamy coś takiego:

czy zleciliśmy odczyt?
jeśli tak:
   czy minęło 750 milisekund?
   jeśli tak:
        odczyt z termometru
jeśli nie:
   czy minęło 5000 milisekund?
   jeśli tak:
	   zlecamy odczyt
	   zerujemy stoper

Praktycznie musimy wprowadzić tu drugą zmienną - nazwijmy ją np. "zlecenie". Typem niech będzie bool, bo ma przechowywać tylko dwa stany (było/nie było zlecenia):

static bool zlecenie = True; // bo w setup() musimy wydać requestTemperatures()
static uint32_t ostatnio = mllis();

if (zlecenie) {
  if (millis() - ostatnio > 750) { // tyle trzeba czekać przy najwyższej rozdzielczości
    termometr[0] = DS18B20.getTempC(t1)*100;
    termometr[1] = DS18B20.getTempC(t2)*100;
    zlecenie = False; // unieważniamy zlecenie, ale jeszcze nie kasujemy stopera
  }
  else {
    if (millis() - ostatnio > 5000) {
       DS18B20.requestTemperatures();
       ostatnio = millis();
    }
}

Ale ogólnie najważniejsze że rozumiesz o co chodzi, reszta to szczegóły techniczne.

Jest jeszcze jedna sprawa:

if (packetSize)
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(packetBuffer, 255);
    packetBuffer[len] = 0;
    Serial.printf("UDP packet contents: %s\n", packetBuffer);
  }
  
  if (packetBuffer[0] == 'T' && packetBuffer[0] >='1' && packetBuffer[1] <= '2') {
	int indeks = packetBuffer[1] - '1' + 2; // zaczynany od indeksu 2 bo 0 i 1 to termometry bezpośrednie
    termometr[indeks] = atoi(packetBuffer+2);
  }

  

Przypatrz się temu fragmentowi... co jest źle?

W sumie te dwa miejsca wymagają poprawki - jak to zrobisz możemy zająć się wyświetlaczem; może wreszcie coś zacznie nam świecić 🙂

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