• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Pomoc i poprawienie prostego kodu
#1
Dzień dobry,
Może ktoś pomoże poprawić, uprościć moje wypociny aby zaczęły działać jak należy. 
Od początku.
Mam dwa DS18b20, 3 przekaźniki, buzer, lcd 16x2 i arduino nano.
Program powinien robić coś takiego:
Jeżeli temperatura na tempW jest >30 'C to przekaźnik P1 - ON a P2 - OFF
Jeżeli tempG jest > 35 to P3 - ON a jak <=30 to P3 - OFF
Jeżeli temoG >70 to P2 - OFF
Jeżeli tempG >= 80 to Buzer ON i jak tempW > 80 to Buzer ON
Wyświetl na lcd tempG i tempW.
A To moje próby:
Kod:
#include <LiquidCrystal_I2C.h>
byte znak0[8] = { 0b01100, 0b10010, 0b10010, 0b01100, 0b00000, 0b00000, 0b00000, 0b00000 };
byte znak1[8] = { 0b11111, 0b10000, 0b10000, 0b11111, 0b10000, 0b10000, 0b11111, 0b00010 };
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS D7 // Pin OneWire
#define TEMPERATURE_PRECISION 9

int przekaznik1 = D9;
int przekaznik2 = D10;
int przekaznik3 = D11;
int buzer = D2;

// unsigned long czas;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress DS_NR1 = { 0x28, 0x32, 0xFD, 0x48, 0xF6, 0xA8, 0x3C, 0xF2 }; // Tu wpisać adresy czujników
DeviceAddress DS_NR2 = { 0x28, 0x6F, 0x82, 0x95, 0xF0, 0x01, 0x3C, 0x85 };

LiquidCrystal_I2C lcd(0x27,16,2); 
float tempW = 0;
float tempG = 0;

void setup()
{


//  lcd.noBacklight();  //wyłącza podświetlenie
   
  sensors.begin();
  lcd.init();                   
  lcd.backlight();
  lcd.clear();

//unsigned long czas;
// czas = millis();

pinMode(przekaznik1, OUTPUT);      //przekaznik1 jako wyjście
pinMode(przekaznik2, OUTPUT); 
pinMode(przekaznik3, OUTPUT); 
pinMode(buzer, OUTPUT);

digitalWrite(przekaznik1, HIGH);    //stan początkowy przekaznika1 wysoki
digitalWrite(przekaznik2, HIGH);
digitalWrite(przekaznik3, HIGH);
digitalWrite(buzer, LOW);

  sensors.setResolution(DS_NR1, TEMPERATURE_PRECISION);
  sensors.setResolution(DS_NR2, TEMPERATURE_PRECISION);
}

void loop()
{

  sensors.requestTemperatures();
  tempW = sensors.getTempC(DS_NR1);  // pobierz temperaturę po kolei z termometrów
  tempG = sensors.getTempC(DS_NR2);

if(tempW>=30)
{
  digitalWrite(przekaznik3, LOW);
}

if(tempW>70)
{
  digitalWrite(przekaznik2, LOW);
}

if(tempG>=35)
{
  digitalWrite(przekaznik1, LOW);
  digitalWrite(przekaznik2, HIGH);
}

if(tempG<=30)
{
  digitalWrite(przekaznik1, HIGH);
  digitalWrite(przekaznik2, LOW);
}


if((tempG>80) || (tempW>85))
{
    digitalWrite(buzer, HIGH);
}
else
{
  digitalWrite(buzer, LOW);
}

//======================================================

lcd.createChar(0, znak0);
lcd.createChar(1, znak1);
    lcd.setCursor(0,0);
lcd.print("PIEC GAZ: ");
lcd.setCursor(10,0);
    lcd.print(tempG,1);
lcd.print((char)0);
lcd.print("C");

//======================================

    lcd.setCursor(0,1);
lcd.print("PIEC W");
lcd.print((char)1);
lcd.print("G: ");
lcd.setCursor(10,1);
    lcd.print(tempW,1);
lcd.print((char)0);
lcd.print("C");
delay (3000);
}
//=================================


Chciałem też dodać aby jak zostanie włączony przekaźnik to minimum na np. 1 minutę ale mnie przerosło.
 
Odpowiedź
#2
A co nie działa ??
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#3
Zamiast pilnować czasu 1 minuty ustaw sobie histerezy, bo inaczej Ci to będzie dzwonić przekaźnikiem. Jak to jest woda to 2 stopnie spokojnie.
np. float His=2.5; float setpoit=32.5;
Jeżeli tempG jest > 35 to P3 - ON a jak <=30 to P3 - OFF

if(tempG>(setpoint+His) P3on();
else if (tempG<(setpoint-His) P3off();
Czyli uruchomić funkcję włączenia gdy przekroczy 32.5+2.5=35 (można zamienić na >=) i wyłączy dopiero gdy spadnie poniżej 30.

uint8_t Histereza2=2; setpoint2=68.
temoG >70 to P2 - OFF
if(temoG>(setpoint2+Histereza2) P2off() ;
else if (temoG<(setpoint2-Histereza2) P2on(); //chyba że nie ma się już załączyć.

A teraz trzeba połączyć warunki jeśli dwa parametry sterują jednym przekaźnikiem. Czyli z tym tempW jest >30 'C.


DeeSy jeszcze powinieneś zabezpieczyć, jeśli nie jest możliwe osiągnięcie temperatury >=85, oraz mniejszej <=0 to dodaj warunek, że wtedy wszystko OFF (czy może odwrotnie właśnie ON, jeśli to jest bezpieczniejsze) i ma dzwonić buzerem.
Termostatów z DS jest pełno w sieci jako przykłady, wywal delay, użyj millis(), dodaj WDT.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#4
Układ wydawał mi się prosty do ogarnięcia a jednak poległem. Dwa piece. Węglowy i gazowy. Dwie pompy obiegowe. i powinno być tak, że jak w piecu węglowym temperatura wzrośnie do 30-35 stopni to włącza się pompa 1 i wyłącza piec gazowy.  Gdy spadnie lub jest poniżej 30 to włącza piec gazowy wyłącza pompę. Gdy na piecu gazowym temperatura jest powyżej 30-35 stopni włącza pompę 2 gdy spadnie poniżej wyłącza ją. Gdy temperatura na piecu gazowym jest powyżej np. 75-80 wyłącza go a pompa 2 włączona buzer włączony. Gdy na drugim piecu temperatura by była też powyżej np. 85 to włącza buzer i pompę 1. Faktycznie histereza by się przydała aby przekaźniki nie wariowały no i reset gdy się zawiesi. Tego nie przewidziałem. Niby proste a okazało się że nie do końca.
 
Odpowiedź
#5
(25-03-2022, 22:12)Jarewa0606 napisał(a): A co nie działa ??
Niby działa ale nie do końca. Dlatego proszę o pomoc.
 
Odpowiedź
#6
Pochwal się kodem jak zaimplementujesz przedstawione wskazówki. Bo jeśli czekasz, że ktoś to zrobi za Ciebie to trochę potrwa.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#7
Oczywiście że zamieszczę tylko coś mi nie wychodzi. Nadal błędy ale walczę.
 
Odpowiedź
#8
Kod:
#include <avr/wdt.h>
#include <LiquidCrystal_I2C.h>
byte znak0[8] = { 0b01100, 0b10010, 0b10010, 0b01100, 0b00000, 0b00000, 0b00000, 0b00000 };
byte znak1[8] = { 0b11111, 0b10000, 0b10000, 0b11111, 0b10000, 0b10000, 0b11111, 0b00010 };
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS D7 // Pin OneWire
#define TEMPERATURE_PRECISION 9

int przekaznikGaz = D9;
int przekaznikPG = D10;
int przekaznikPW = D11;
int buzer = D4;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress DS_NR1 = { 0x28, 0x32, 0xFD, 0x48, 0xF6, 0xA8, 0x3C, 0xF2 }; // Tu wpisać adresy czujników
DeviceAddress DS_NR2 = { 0x28, 0x6F, 0x82, 0x95, 0xF0, 0x01, 0x3C, 0x85 };

LiquidCrystal_I2C lcd(0x27,16,2); 
float tempW = 0;
float tempG = 0;
float hist = 1.5;
float tG = 31.5;
float tW = 31.5;

void setup()
{
wdt_enable(WDTO_4S);

//  lcd.noBacklight();  //wyłącza podświetlenie
   
  sensors.begin();
  lcd.init();                   
  lcd.backlight();
  lcd.clear();

pinMode(przekaznikGaz, OUTPUT);      //przekaznikGaz jako wyjście
pinMode(przekaznikPG, OUTPUT); 
pinMode(przekaznikPW, OUTPUT); 
pinMode(buzer, OUTPUT);

digitalWrite(przekaznikGaz, HIGH);    //stan początkowy przekaznika1 wysoki
digitalWrite(przekaznikPG, HIGH);
digitalWrite(przekaznikPW, HIGH);
digitalWrite(buzer, LOW);

  sensors.setResolution(DS_NR1, TEMPERATURE_PRECISION);
  sensors.setResolution(DS_NR2, TEMPERATURE_PRECISION);
}

void loop()
{

  sensors.requestTemperatures();
  tempW = sensors.getTempC(DS_NR1);  // pobierz temperaturę po kolei z termometrów
  tempG = sensors.getTempC(DS_NR2);

if(tempW> (tW+hist)) // temperatura większa od  33.0
{
  digitalWrite(przekaznikPW, LOW);
  digitalWrite(przekaznikGaz, HIGH);
}
  else if (tempW< (tW-hist))  // mniejsza od 30.0
  {
  digitalWrite(przekaznikPW, HIGH);
  digitalWrite(przekaznikGaz, LOW);
}

if(tempG>70)
{
  digitalWrite(przekaznikGaz, HIGH);
}

if(tempG> (tG+hist))
{
  digitalWrite(przekaznikPG, LOW);
}
else if (tempG< (tG-hist))
{
  digitalWrite(przekaznikPG, HIGH);
}

if((tempG>80) || (tempW>85))
{
    digitalWrite(buzer, HIGH);
    digitalWrite(przekaznikPG, LOW);
    digitalWrite(przekaznikPW, LOW);
}
else if((tempG<50) || (tempW<60))
{
  digitalWrite(buzer, LOW);
}

//======================================================

lcd.createChar(0, znak0);
lcd.createChar(1, znak1);
lcd.setCursor(0,0);
lcd.print("PIEC GAZ: ");
lcd.setCursor(10,0);
lcd.print(tempG,1);
lcd.print((char)0);
lcd.print("C");

//======================================

lcd.setCursor(0,1);
lcd.print("PIEC W");
lcd.print((char)1);
lcd.print("G: ");
lcd.setCursor(10,1);
lcd.print(tempW,1);
lcd.print((char)0);
lcd.print("C");
delay (3000);

wdt_reset();
}
//=================================

Zamieszczam zgodnie z obietnicą.
Coś takiego spłodziłem. Czy można to jakoś usprawnić, poprawić, zoptymalizować? Czy gdzieś coś zepsułem lub nie zrozumiałem?
I jeszcze pytanie z innej beczki. Czy do takiego układu lepiej zastosować przekaźniki sterowane potencjałem wysokim?
Mam jak widać sterowane niskim. I czy płytka z LGT8G328 może być czy lepiej nie?
 
Odpowiedź
#9
A może ktoś podpowie jak napisać kod awarii. Coś jest nie tak z odczytem z czujników i wtedy np. włączają się przekaźniki pomp a wyłącza piec.
 
Odpowiedź
#10
Zależy o jaki odczyt pytasz?

Jeżeli tylko to czy czujnik istnieje, to akurat dobrze trafiłeś z adresem bo można się zapytać

// finds an address at a given index on the bus
// returns true if the device was found
bool DallasTemperature::getAddress(uint8_t* deviceAddress, uint8_t index) {

uint8_t depth = 0;

_wire->reset_search();

while (depth <= index && _wire->search(deviceAddress)) {
if (depth == index && validAddress(deviceAddress))
return true;
depth++;
}

return false;

}

Jeżeli na błędnym odczycie temperatury samej, przekłamanie to tylko własny algorytm.
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości