Skocz do zawartości

Dodanie sterowania przekaźnikiem do istniejącego programu


Jackoboo

Pomocna odpowiedź

Witam wszystkich w moim pierwszym poważnym poście na forum.

Chciałbym sobie zrobić sterownik do fotowoltaiki aby odczytywał mi wartość natężenia światła i po przekroczeniu pewnej wartości wysterowywał wyjście ESP.

Projekt oparty na dwóch ESP8266, które łączą się ze sobą za pomocą domowego wifi. Znalazłem parę projektów które mają części kodu mi potrzebne i je połączyłem.

Chyba wyszedł z tego niezły bałagan, ale działa. ESP łączą się ze sobą i jedno za pomocą LCD wyświetla aktualną wartość.

Problem mam z dodaniem sterowania przekaźnikiem. Próbowałem najprostszej rzeczy czyli dodać instrukcję warunkową if na końcu pętli, jednak albo nie działa, albo wyrzuca błąd kompilacji.

Czy mógłby mi ktoś napisać poprawnie kod i powiedzieć co robię źle albo chociaż nakierować na rozwiązanie problemu.

Z góry dzięki wielkie. 

 

#include <SPI.h>
#include <ESP8266WiFi.h>

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);

byte ledPin = 2;
char ssid[] = "XXXX";           
char pass[] = "XXXX"; 

unsigned long askTimer = 0;

IPAddress server(192,168,1,62);       
WiFiClient client;

void setup() {
  pinMode(D0, OUTPUT);
  digitalWrite(D0, HIGH);

  lcd.init();                      
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.println("Naslonecznienie:");
  lcd.setCursor(11,1);
  lcd.println("[LUX]");
  Serial.begin(115200);               
  WiFi.begin(ssid, pass);            
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
/*  Serial.println("Connected to wifi");
  Serial.print("Status: "); Serial.println(WiFi.status());    
  Serial.print("IP: ");     Serial.println(WiFi.localIP());
  Serial.print("Subnet: "); Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: "); Serial.println(WiFi.gatewayIP());
  Serial.print("SSID: "); Serial.println(WiFi.SSID());
  Serial.print("Signal: "); Serial.println(WiFi.RSSI());*/
  pinMode(ledPin, OUTPUT);
}

void loop () {
  lcd.setCursor(0,1);
  client.connect(server, 80);  
  digitalWrite(ledPin, LOW);   
  client.println("Hello server! Are you sleeping?\r");  
  String answer = client.readStringUntil('\r');  
  lcd.println(answer);
  client.flush();
  digitalWrite(ledPin, HIGH);
  delay(2000);                  
}
 

 

Link do komentarza
Share on other sites

18 godzin temu, Jackoboo napisał:

Próbowałem najprostszej rzeczy czyli dodać instrukcję warunkową if na końcu pętli, jednak albo nie działa, albo wyrzuca błąd kompilacji.

 


#include <SPI.h>
#include <ESP8266WiFi.h>

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);

byte ledPin = 2;
char ssid[] = "XXXX";           
char pass[] = "XXXX"; 

unsigned long askTimer = 0;

IPAddress server(192,168,1,62);       
WiFiClient client;

void setup() {
  pinMode(D0, OUTPUT);
  digitalWrite(D0, HIGH);

  lcd.init();                      
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.println("Naslonecznienie:");
  lcd.setCursor(11,1);
  lcd.println("[LUX]");
  Serial.begin(115200);               
  WiFi.begin(ssid, pass);            
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
/*  Serial.println("Connected to wifi");
  Serial.print("Status: "); Serial.println(WiFi.status());    
  Serial.print("IP: ");     Serial.println(WiFi.localIP());
  Serial.print("Subnet: "); Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: "); Serial.println(WiFi.gatewayIP());
  Serial.print("SSID: "); Serial.println(WiFi.SSID());
  Serial.print("Signal: "); Serial.println(WiFi.RSSI());*/
  pinMode(ledPin, OUTPUT);
}

void loop () {
  lcd.setCursor(0,1);
  client.connect(server, 80);  
  digitalWrite(ledPin, LOW);   
  client.println("Hello server! Are you sleeping?\r");  
  String answer = client.readStringUntil('\r');  
  lcd.println(answer);
  client.flush();
  digitalWrite(ledPin, HIGH);
  delay(2000);                  
}
 

 

Pokaz jak ten warunek wyglada i kawalek kodu do odczytu natezenia swiatla

Link do komentarza
Share on other sites

1 godzinę temu, farmaceuta napisał:

Pokaz jak ten warunek wyglada i kawalek kodu do odczytu natezenia swiatla

Masz na myśli drugie ESP do odczytu nat. światła, proszę bardzo:

#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BH1750.h>
#include <Wire.h>



BH1750 lightMeter;

float lux = lightMeter.readLightLevel();


byte ledPin = 2;
char ssid[] = "xxx";               // SSID of your home WiFi
char pass[] = "xxx";               // password of your home WiFi
WiFiServer server(80);                    

IPAddress ip(192, 168, 1, 62);            // IP address of the server
IPAddress gateway(192,168,0,1);           // gateway of your network
IPAddress subnet(255,255,255,0);          // subnet mask of your network

void setup() {
  Serial.begin(115200);    
   Wire.begin();
     lightMeter.begin(); 
 
  WiFi.config(ip, gateway, subnet);       // forces to use the fix IP
  WiFi.begin(ssid, pass);                 // connects to the WiFi router
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  server.begin();                         // starts the server
/*  Serial.println("Connected to wifi");
  Serial.print("Status: "); Serial.println(WiFi.status());  // some parameters from the network
  Serial.print("IP: ");     Serial.println(WiFi.localIP());
  Serial.print("Subnet: "); Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: "); Serial.println(WiFi.gatewayIP());
  Serial.print("SSID: "); Serial.println(WiFi.SSID());
  Serial.print("Signal: "); Serial.println(WiFi.RSSI());
  Serial.print("Networks: "); Serial.println(WiFi.scanNetworks());*/
  pinMode(ledPin, OUTPUT);
}

void loop () {
  WiFiClient client = server.available();
  if (client) {
    if (client.connected()) {
      float lux = lightMeter.readLightLevel();
      digitalWrite(ledPin, LOW);  // to show the communication only (inverted logic)
      Serial.println(".");
      String request = client.readStringUntil('\r');    // receives the message from the client
      Serial.print("From client: "); Serial.println(request);
      Serial.print(lux);
      client.flush();
      client.println(lux); // sends the answer to the client
      digitalWrite(ledPin, HIGH);
    }
    client.stop();                // tarminates the connection with the client
  }
}

 

Oto jedna z prób z instrukcją if :

#include <SPI.h>
#include <ESP8266WiFi.h>

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);



byte ledPin = 2;
char ssid[] = "xxx";           
char pass[] = "xxx"; 




unsigned long askTimer = 0;

IPAddress server(192,168,1,62);       
WiFiClient client;

void setup() {
  pinMode(D0, OUTPUT);
  digitalWrite(D0, LOW);

  lcd.init();                      
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.println("Naslonecznienie:");
  lcd.setCursor(11,1);
  lcd.println("[LUX]");
  Serial.begin(115200);               
  WiFi.begin(ssid, pass);            
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("Connected to wifi");
  Serial.print("Status: "); Serial.println(WiFi.status());    // Network parameters
  Serial.print("IP: ");     Serial.println(WiFi.localIP());
  Serial.print("Subnet: "); Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: "); Serial.println(WiFi.gatewayIP());
  Serial.print("SSID: "); Serial.println(WiFi.SSID());
  Serial.print("Signal: "); Serial.println(WiFi.RSSI());
  pinMode(ledPin, OUTPUT);
}

void loop () {
  lcd.setCursor(0,1);
  client.connect(server, 80);  
  digitalWrite(ledPin, LOW);   
  client.println("Hello server! Are you sleeping?\r");  
  String answer = client.readStringUntil('\r');  
  lcd.println(answer);
  client.flush();
  digitalWrite(ledPin, HIGH);
    
  if ((answer)>=100) 
          { 
            digitalWrite(D0, HIGH);
          }   
           else 
          { 
            digitalWrite(D0, LOW);
          }
   delay(2000);
}

 

 

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

A otrzymujesz ta zmienna answer?? I jaki zakres ona wyswietla?

A nie ma odpowiednikow do odczytu float,int,byte? Bo teraz czytasz String 

client.readStringUntil('\r');  

Szczerze nie wiem czy zadziala (nie rzutowalem nigdy Stringa) ale spruboj moze tak....

if ((float)answer >= 100) 

 

Edytowano przez farmaceuta
  • Lubię! 1
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

String answer ?, string 

if ((answer)>=100) integer, kompilator na pewno wyrzuci błąd, nie porówna bezpośrednio int == string.

  • Lubię! 1
Link do komentarza
Share on other sites

5 godzin temu, farmaceuta napisał:

A otrzymujesz ta zmienna answer?? I jaki zakres ona wyswietla?

ZDJ1.thumb.jpg.5dc848f12af924bb884275e4e6c9e1c4.jpg

 

 

5 godzin temu, farmaceuta napisał:

Szczerze nie wiem czy zadziala (nie rzutowalem nigdy Stringa) ale spruboj moze tak....


if ((float)answer >= 100) 

Niestety błąd.

 

 

5 godzin temu, farmaceuta napisał:

Ok..chyba takie cos pomoze 


string n = "3.4213";
float value = (float)atof(n.c_str());

Dobrze to zrobiłem? Jeżeli tak to dalej błąd.

#include <SPI.h>
#include <ESP8266WiFi.h>

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);



byte ledPin = 2;
char ssid[] = "xxx";           
char pass[] = "xxx"; 

String n = "3.4213";
float value = (float)atof(n.c_str());

unsigned long askTimer = 0;

IPAddress server(192,168,1,62);       
WiFiClient client;

void setup() {
  pinMode(D0, OUTPUT);
  digitalWrite(D0, LOW);

  lcd.init();                      
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.println("Naslonecznienie:");
  lcd.setCursor(11,1);
  lcd.println("[LUX]");
  Serial.begin(115200);               
  WiFi.begin(ssid, pass);            
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  /*
  Serial.println("Connected to wifi");
  Serial.print("Status: "); Serial.println(WiFi.status());    // Network parameters
  Serial.print("IP: ");     Serial.println(WiFi.localIP());
  Serial.print("Subnet: "); Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: "); Serial.println(WiFi.gatewayIP());
  Serial.print("SSID: "); Serial.println(WiFi.SSID());
  Serial.print("Signal: "); Serial.println(WiFi.RSSI());
  pinMode(ledPin, OUTPUT); */
}

void loop () {
  lcd.setCursor(0,1);
  client.connect(server, 80);  
  digitalWrite(ledPin, LOW);   
  client.println("Hello server! Are you sleeping?\r");  
  String answer = client.readStringUntil('\r');  
  lcd.println(answer);
  client.flush();
  digitalWrite(ledPin, HIGH);

   if ((float)answer >= 100) 
          { 
            digitalWrite(D0, HIGH);
          }   
           else 
          { 
            digitalWrite(D0, LOW);
          }

  
              
  delay(2000);        
 
   
}

zdj2.thumb.jpg.cc9e4d8db5eaf846926923008bc89841.jpg

Link do komentarza
Share on other sites

(edytowany)







   
void loop () {
  lcd.setCursor(0,1);
  client.connect(server, 80);  
  digitalWrite(ledPin, LOW);   
  client.println("Hello server! Are you sleeping?\r");  
  String answer = client.readStringUntil('\r'); 
  
float val = (float)atof(answer.c_str());

  lcd.println(val);
  client.flush();
  digitalWrite(ledPin, HIGH);

   if (val >= 100) 
          { 
            digitalWrite(D0, HIGH);
          }   
           else 
          { 
            digitalWrite(D0, LOW);
          }

  

Zle...😜 Spruboj tak jak tu pokazalem (i usun z czesci globalnej te zmienne "n)"

Edytowano przez farmaceuta
  • Pomogłeś! 1
Link do komentarza
Share on other sites

(edytowany)

Ech... a może zamiast tworzyć coś metodą prób i błędów zajrzeć do dokumentacji?

float val = answer.toFloat();

nie zadziała?

Poza tym tam musi być float? Nie wystarczy int? Jak na moje oko wystarczy...

A tak w ogóle jeśli już to raczej strtod a nie atof. No i sprawdzenie czy tam w ogóle była jakaś liczba (errno, sprawdzenie drugiego argumentu strtod/strtol i tak dalej).

 

Edytowano przez ethanak
  • Lubię! 1
Link do komentarza
Share on other sites

7 minut temu, Jackoboo napisał:

@farmaceuta możesz mi jeszcze wytłumaczyć co zmienia ta linijka? Domyślam się, że coś z zamianą string na float 

Cytat..."Funkcja jako argument pobiera liczbę w postaci ciągu znaków ASCII, a następnie zwraca jej wartość w formacie double (format zmiennoprzecinkowy). Argument może poprzedzać dowolna liczba białych znaków (spacje, tabulatory itp.) oraz znak (plus (+) lub minus (-)). Funkcja atof() kończy wczytywać znaki w momencie napotkania jakiegokolwiek znaku, który nie jest cyfrą, kropką bądź znakiem e, bądź E...."

W skrocie, przerabia ciag znakow na liczbe i nie wyrzuca kropki +/- etc jesli sa..(ten pan wyzej duzo lepiej Ci to wyjasni😉 (bo ja z tego nie korzystalem nigdy😜))

  • Lubię! 1
Link do komentarza
Share on other sites

@Jackoboo, żeby procesor mógł porównać dwie wartości, muszą być tego samego typu. W prostych intuicyjnych przypadkach, kompilator umie dokonać konwersji sam, np.

#include <stdio.h>

int main()
{
	double half = 0.5;
	int one = 1;
	if (half < one)
		puts("Oh, the math works!");
}

Wewnętrznie działa to tak, że kompilator dokona konwersji "one" na double w tymczasowej zmiennej i dopiero wtedy porówna z "half". Hasło, do poszukania, to konwersja niejawna albo implicit type conversion.

String nie jest prostym intuicyjnym przypadkiem, bo string przechowuje, co do zasady, tekst. Kompilator miałby tu utrudnione zadanie, bo nie wie w momencie kompilacji, czy ten tekst powinien być liczbą. Ani co zrobić, gdy jednak nie odbierzesz przez sieć liczby. Lub po liczbie będą jakieś dodatkowe litery. Dlatego takich rzeczy automatycznie nie robi. W rękach programisty jest w takim bardziej skomplikowanym przypadku wyrażenie intencji i przemyślenie, jak obsłużyć błędy.

Czyli świadomie zdecydować, w ramach palety sugestii @ethanak, czy używać takich uproszczeń jak atof, stof z C++11 lub toFloat z typu String z Arduino (standardowy typ C++ nazywa się string, małą literą, nie ma w nim toFloat), które ignorują wszelkie błędy i w wypadku, gdy nie znajdą żadnej cyfry, zwrócą po prostu zero czy strtod, strtof (od C99) lub stof z C++11, które pozwalają sprawdzić czy i w którym z kolei znaku wystąpił błąd.

PS Określenie "czy ten tekst powinien być liczbą" jest tu uproszczeniem. Tekst jest zawsze tekstem, więc "3.14" to są cztery bajty odpowiadające kodom kolejnych znaków, co powoduje, że pierwszy bajt nie ma wartości 3, a 51. W ramach dodatkowej rozrywki intelektualnej, możesz poszukać i poczytać o tym, jak są przechowywane w pamięci ciągi znaków, liczby całkowite i liczby z ułamkami (te dwa ostatnie typy też bardzo się od siebie różnią).

Edytowano przez trainee
  • Lubię! 1
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.