Skocz do zawartości
jaro44

Połączenie dwóch esp8266 do pomiaru temperatur

Pomocna odpowiedź

Witam,

Ze względu na nadmiar czasu, chęć nauki na stare lata i rozwinięcie zainteresowań z młodych lat  w planach mam zbudowanie własnoręcznie coś "ala" inteligentny dom.

W planach automatyczne sterowanie akwarium, oświetleniem zewnętrznym, stacja pogody i pomiar temperatur oraz może system alarmowy.

Naukę zaczynam od ESP8266 (na razie zakupiłem 5 szt nodemcu v3 wyświetlacz oled 0,96 i 5 szt czyjników temperatury ds18b20).

Termometr z jednego nodemcu i oled już działa ok, oprócz wyświetlacza temperaturę mogę sprawdzać online przez aplikację termik4temp na smartfonie.

Po wielogodzinnych walkach nie mogę sobie poradzić z połączeniem kolejnego nodemcu przez wifi aby mieś temperaturę zewnętrzną zarówno na wyświetlaczu oled jak i w aplikacji termik4temp.

Może ktoś by mnie naprowadził jak to najrozsądniej rozwiązać.

 

Udostępnij ten post


Link to post
Share on other sites

Najpierw pokaż co do tej pory zrobiłeś, bo połączyć ESP-ki ze sobą można na kilka sposobów.

Udostępnij ten post


Link to post
Share on other sites
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display;

// tutaj musimy ustawić adres ip esp8266 oraz wprowadzić inne dane naszej sieci
// po tym zabiegu będziemy mieć na stałe przypisany adres ip w module ESP8266
// USTAWIENIA PONIŻEJ TO USTAWIENIA MOJEJ SIECI 

IPAddress ip(192, 168, 10, 101);
IPAddress gateway(192, 168, 10, 1);
IPAddress subnet(255, 255, 255, 0);

const char* ssid = "xxxxx";// tutaj wprowadzamy nazwę naszej sieci WiFI
const char* password = "yyyyy";// tutaj hasło sieci

void wifi_init(){
WiFi.config(ip, gateway, subnet);
delay(100);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println();
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(200);
}
Serial.println();
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Fail connecting");
delay(5000);
ESP.restart();
}
Serial.print(" OK ");
Serial.print("Module IP: ");
Serial.println(WiFi.localIP());
}

#define ONE_WIRE_BUS D4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float temp;

// W ten sposób przypisujemy adresy czujników wcześniej odczytane,niestety tak to narazie trzeba wykonać
// 28442b79a200035f
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

WiFiUDP Udp;
unsigned int localUdpPort = 26845; // local port to listen on
char incomingPacket[255]; // buffer for incoming packets
char replyPacekt[] = "Dokonano pomiaru temperatur :-)"; // a reply string to send back

void setup(void)
{
// start serial port
Serial.begin(115200);
Serial.println();
wifi_init();
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");

Udp.begin(localUdpPort);
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);

// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC);
// init done

display.display(); // show splashscreen
delay(2000);
display.clearDisplay();   // clears the screen and buffer
// Start up the library
// draw a single pixel
//display.drawPixel(10, 10, WHITE);
//display.display();
//delay(2000);
//display.clearDisplay();  
sensors.begin();

Udp.beginPacket("192.168.10.102", 26846);

}

void loop(void)
{ 
int packetSize = Udp.parsePacket();
if (packetSize)
{
// receive incoming UDP packets

sensors.requestTemperatures();
Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
int len = Udp.read(incomingPacket, 255);
if (len > 0)
{
incomingPacket[len] = 0;
sensors.requestTemperatures();
delay(2000);
}
Serial.printf("UDP packet contents: %s\n", incomingPacket);

float temp1;
temp1 = sensors.getTempC(t1);
String Pomiar1;
Pomiar1=String(temp1, 2);
Serial.println(Pomiar1);

//float temp2;
temp1 = sensors.getTempC(t2);
String Pomiar2;
Pomiar2=String(temp1, 2);
Serial.println(Pomiar2);

Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());


String tempp1 ;

tempp1 += "n1=";
tempp1 += Pomiar1;
tempp1 += "x";
tempp1 += "n2=";
tempp1 += Pomiar2;
tempp1 += "x";

Udp.println(tempp1); 

Udp.endPacket();
}

float temp1;
temp1 = sensors.getTempC(t1);

float temp2;
temp2 = sensors.getTempC(t2);

delay(2000);
display.clearDisplay();   // clears the screen and buffer 
// text display tests
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Temperatura w salonie");
display.setTextSize(4,3);
display.setTextColor(WHITE);
display.setCursor(8,10);
display.print(temp1, 1);
display.setTextSize(2,1);
display.println(" O");
display.display();
delay(2000);
display.clearDisplay();
}

Na razie mam tyle, próbowałem spiąć pomiar z drugiego esp po udp, ale niestety bez pozytywnego skutku.

 

DSC_0002.JPG

Udostępnij ten post


Link to post
Share on other sites

Przede wszystkim: czy ESP ustawia sobie ten adres IP który mu kazałeś? Bo prawidłowa kolejność wykonania powinna być mode -> begin -> config, a nie config -> mode -> begin.

 

Udostępnij ten post


Link to post
Share on other sites

przypisuje, ale mam na routerze ustawione statyczne ip po mac, więc może dlatego

Udostępnij ten post


Link to post
Share on other sites

To może teraz opiszesz, jak ma działać ten program i gdzie tu jest miejsce na odbiór danych z drugiego ESP.

Poza tym zrób jakieś formatowanie kodu bo bez wcięć to się fatalnie czyta...

 

Udostępnij ten post


Link to post
Share on other sites

próbowałem robić drugi esp jako serwer udp, a do tego dopisywałem odbiór pakietu,

ale nic mi nie wychodziło, więc czyściłem do tego momentu.

Z pisaniem kodu dopiero zaczynam, więc estetyka na razie poszła na drugi plan.

Potrzebuję raczej sugestii jak to w moim zastosowaniu zrobić najlepiej.

W sieci znalazłem wiele informacji, ale raczej zastosowaniem jednego esp i wielu czujników.

U mnie to nie wchodzi w grę, bo nie mam możliwości wyjęcia czujnika po kablu na zewnątrz.

Udostępnij ten post


Link to post
Share on other sites

Spróbuj zrobić na razie prosty program:

Pomiń na razie czujniki, wyświetlania, skup się na samym połączeniu ESP.

Niech jeden ESP (serwer) słucha sobie cały czas na porcie X.

Niech drugi (a potem trzeci, czwarty i tak dalej) wysyła mu na ten port jakiś string, np:

  • litera 'T' (czyli temperatura)
  • numer czujnika (od 1 do ile ich tych ESP tam masz)
  • odczytana temperatura (na razie zastąp to jakąś wartością losową)

Czyli wysłany napis będzie czymś w rodzaju "T123" (temperatura na czujniku pierwszym 23 stopnie). Niech to wysyłanie odbywa się powiedzmy co 10 sekund (docelowo po podłączeniu czujników co minutę bo nie ma sensu częściej).

Na razie zrób tak, aby pierwszy ESP tylko:

  • wypisywał na serialu odebrany string
  • wrzucał do jakiejś tablicy odebrane wartości (tzn. do każdej komórki z tablicy wartość z odpowiedniego czujnika)
  • wypisywał na serialu temperatury z tablicy

Może być?

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

ok, dzięki

będę walczył i informował o efektach

rozumiem że chodzi o serwer i client udp?

Edytowano przez jaro44

Udostępnij ten post


Link to post
Share on other sites

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

 

Zrób to osobno UDP potrafi nie dotrzeć zgubić się, wiec dane wysyłaj co ileś tam sekund...  A drugim przechwytuj i wyświetlaj... 

Udostępnij ten post


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

rozumiem że chodzi o serwer i client udp?

Oczywiście.

I na razie nie rób nic więcej dopóki to nie będzie działać bezawaryjnie.

Udostępnij ten post


Link to post
Share on other sites

udp client:

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

const char* ssid     = "xxxxx";
const char* password = "yyyyy";

// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp;


void setup() {
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  
  Udp.beginPacket("192.168.1.102", 12345);
  
}

void loop() {

    Udp.write("hello\r\n");

    Udp.endPacket();
        
    Serial.println("hello sent to UDP server");
    
  delay(5000);
}

udp server:

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

const char* ssid     = "xxxxx";
const char* password = "yyyyy";

WiFiUDP UDPTestServer;
unsigned int UDPPort = 12345;

const int packetSize = 16;
byte packetBuffer[packetSize];

void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
  WiFi.config(IPAddress(192, 168, 10, 102), IPAddress(192, 168, 10, 1), IPAddress(255, 255, 255, 0));
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected"); 
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  UDPTestServer.begin(UDPPort);
 
}

int value = 0;

void loop() {
   handleUDPServer();
   delay(1);
}

void handleUDPServer() {
  int cb = UDPTestServer.parsePacket();
  if (cb) {
    UDPTestServer.read(packetBuffer, packetSize);
    String myData = "";
    for(int i = 0; i < packetSize; i++) {
      myData += (char)packetBuffer[i];
    }
    Serial.println(myData);
  }
}

Podstawowe połączenie uzyskałem, teraz czas na zainstalowanie do clienta czujnika ds18b20

i próba wysłania temperatury do servera 🙂

Jeśli coś zrobiłem nie tak na tym etapie, to proszę o sugestie

Udostępnij ten post


Link to post
Share on other sites

Nie używaj String bo się któregoś dnia natniesz!

Poza tym wcale nie jest tam potrzebny, wystarczy coś takiego:

int cb = UDPTestServer.parsePacket();
  if (cb) { // w cb jest ilość odebranych bajtów
    UDPTestServer.read(packetBuffer, packetSize);
    packetBuffer[cb] = 0 ; // dodajemy brakujące zero
    Serial.println(packetBuffer); // i wypisujemy na wyjściu
  }

Ale ale... miałeś coś zrobić, tzn. wysłać konkretny string a nie "hello", odebrać go, stwierdzić kto go wysłał i co oznacza i zapisać do tablicy wyniki... jakoś tego nie widzę, a bez tego dalej nie pójdziemy!

A przy okazji: udp.beginPacket musisz dać za każdym razem kiedy wysyłasz pakiet, czyli ma być w kliencie:

Udp.beginPacket(IP,PORT);
Udp.write(tocotrzeba);
Udp.endPacket();

 

Udostępnij ten post


Link to post
Share on other sites
3 godziny temu, ethanak napisał:

Nie używaj String bo się któregoś dnia natniesz!

3 godziny temu, ethanak napisał:

Ale ale... miałeś coś zrobić, tzn. wysłać konkretny string a nie "hello", odebrać go, stwierdzić kto go wysłał i co oznacza i zapisać do tablicy wyniki... jakoś tego nie widzę, a bez tego dalej nie pójdziemy!

Nie bardzo rozumiem, to mam nie używać string i wysłać string?

próbuję z tym:

3 godziny temu, ethanak napisał:


int cb = UDPTestServer.parsePacket();
  if (cb) { // w cb jest ilość odebranych bajtów
    UDPTestServer.read(packetBuffer, packetSize);
    packetBuffer[cb] = 0 ; // dodajemy brakujące zero
    Serial.println(packetBuffer); // i wypisujemy na wyjściu
  }

ale kompletnie nic mi nie wychodzi, chyba jednak jestem juz za stary na naukę 😞

 

Udostępnij ten post


Link to post
Share on other sites

Bo to trochę terminologicznie zagmatwane...

Termin "string" (z małej litery) oznacza po prostu ciąg (łańcuch) znaków. Z reguły reprezentowany w postaci fragmentu pamięci (np. tablicy) zawierającego owe znaki i zakończonego bajtem zero.

Termin "String" (z wielkiej litery) to klasa (lub - w zależności od kontekstu - obiekt tej klasy) która może przechowywać napisy (łańcuchy) dowolnej (no, powiedzmy) długości, a także oferuje różne ciekawe możliwości łączenia, konwersji, podstawiania i w ogóle cudów i wianków na napisach. Niestety - z uwagi na niewielkie ilości pamięci w mikrokontrolerach nieuważne/nieumiejętne stosowanie tej klasy może (nie musi) prowadzić do nieoczekiwanych "zacięć" programu. Szczególnie odczuwalne jest to w programach działających non stop, gdzie wystąpienie błędu pt. "aplikacja zawiesza mi się po dwóch miesiącach działania i odebraniu konkretnego ciągu znaków" może być raczej frustrujące.

Dlatego nie pochwalam używania String (klasy) w tego typu programach do przechowywania stringów (czyli ciągów literek).

Teraz dalej: co nie wychodzi w przytoczonym fragmencie? Nie odbiera komunikatów? Nie wypisuje co odebrał? Jeśli nie odbiera, to czy ktoś taki komunikat wysłał i jak?

A co do wieku... tu już parę osób kwękało że są starzy i zgrzybiali a potem się okazywało, że mogą tym starszym po piwo biegać 🙂

To co, próbujesz dalej czy się poddajesz?

 

  • Lubię! 1

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