domaci automatizace

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
antrac1t
Příspěvky: 7
Registrován: 08 zář 2019, 12:21
Reputation: 0

domaci automatizace

Příspěvek od antrac1t » 08 zář 2019, 12:40

Zdravím,
před nedávnem jsem se spustil do vyroby ridici desky pro ovladani domu, predevsim bojleru a topeni (pro zacatek). Pri navrhu desky jsem se rozhodl pouzi arduino nano a ENC28J60 ethernet (coz nyni vim ze nebyla dobra volba pro usetreni mista na pcb). Pri zapojeni prvnich cidel a rele vse fungovalo bez problemu (prozatim teplotni cidla ds18b20, ktera jsou pripojena kazde zvlast na vlastni port a vytvarim z nich multibus). Bohuzel jakmile jsem prekrocil 5te teplotni cidlo tak retezeni cidel nejak prestalo fungovat, i kdyz vyuziti pameti se nijak nezmenilo. Pri vyprintovani vysledku na serial vzdy dostanu pouze prazdnou hodnotu. Vytvarim vetsi retezec pro GET metodu, atributy jsou pripraveny pro budouci cidla. Proto bych Vas chtel pozadat o radu v cem muze byt problem. Jestli vyuzit jiny datovy typ nez string?

Dekuji

retezeni hodnot z cidel pro get String

Kód: Vybrat vše

for (int i = 0; i < oneWireCount; i++) {
    sensor[i].requestTemperatures();
    postData = postData + "Zarizeni_ID_" + i + "=" + i + "&Atribut_" + i + "=1 & Hodnota_" + i + "=" + sensor[i].getTempCByIndex(0);
  }

ovladaci deska
Obrázek

kod

Kód: Vybrat vše

//Ethernet
#include <UIPEthernet.h>
byte mac[] = { 0x94, 0xE7, 0xF2, 0xF1, 0x44, 0x0A };
EthernetClient client;
char server[] = "server";
IPAddress ip(10, 0, 0, 19);
IPAddress dns2(10, 0, 0, 138);
IPAddress gateway(10, 0, 0, 138);
IPAddress subnet(255, 255, 255, 0);
//temperatures
//------------------------------------------------------
#include <OneWire.h>
#include <DallasTemperature.h>
//bojler vrsek, bojler spodek, aku nadrz,obyvak termostat,
OneWire ds18x20[] = { 7, 8, 6, 5, 9 };
const int oneWireCount = sizeof(ds18x20) / sizeof(OneWire);
DallasTemperature sensor[oneWireCount];

int  Getinterval = 3000; 
unsigned long GetMethodTime; 
String postData;
String tempData;
//PCF
//------------------------------------------------------
#include "PCF8574.h"
#include <Wire.h>
PCF8574 pcf(0x20);
PCF8574 pcf2(0x21);
PCF8574 pcf3(0x22);
PCF8574 pcf4(0x23);
int DeviceString[10];
int DeviceIncrement;
int StatusString[10];
uint8_t ValveString[10];
//------------------------------------------------------
//topeni kohouty
//RadiatoryON,AkuNadryON,AkuNadryON,KuchyneON
//RadiatoryOFF,AkuNadryOFF,KoupelnaON,KuchyneOFF
const byte EndSwitchON[4] = {0, 2, 4, 6};
const byte EndSwitchOFF[4] = {1, 3, 5, 7};

void setup() {
  Serial.begin(9600);
  //ethernet
  Ethernet.begin(mac, ip, dns2, gateway, subnet);
  Serial.println(Ethernet.localIP());
  Serial.println(Ethernet.subnetMask());
  Serial.println(Ethernet.gatewayIP());
  Serial.println(Ethernet.dnsServerIP());

//dallas teplomery
  DeviceAddress deviceAddress;
  for (int i = 0; i < oneWireCount; i++) {
    sensor[i].setOneWire(&ds18x20[i]);
    sensor[i].begin();
    if (sensor[i].getAddress(deviceAddress, 0)) sensor[i].setResolution(deviceAddress, 12);
  }

  //pcf
  pcf.begin();
  pcf2.begin();
  pcf3.begin();
  pcf4.begin();
}

void loop() {
  if (millis() > GetMethodTime + Getinterval) {
    getTemps();
    sendGET();
    GetMethodTime = millis();
  }
  //Valve();
}

void getTemps() {
  postData = "";
  for (int i = 0; i < oneWireCount; i++) {
    sensor[i].requestTemperatures();
    postData = postData + "Zarizeni_ID_" + i + "=" + i + "&Atribut_" + i + "=1 & Hodnota_" + i + "=" + sensor[i].getTempCByIndex(0);
  }
  Serial.println(postData);
}

void Valve() {
  for (int i = 0; i < 10; i++) {
    if (ValveString[i] != 0) {
      switch (StatusString[i]) {
        case 0:
          if (pcf4.readButton(EndSwitchOFF[ValveString[i - 1]]) == true ) {
            pcf.write(ValveString[i],  1);
          }
          else
          {
            pcf.write(ValveString[i],  0);
          }
          break;
        case 1:
          if (pcf4.readButton(EndSwitchON[ValveString[i - 1] ]) == true ) {
            pcf.write(ValveString[i],  1);
          }
          else
          {
            pcf.write(ValveString[i],  0);
          }
          break;
      }
    }
  }
}

void sendGET() {
  if (client.connect(server, 80)) {  //starts client connection, checks for connection
    Serial.println(F("connected"));
    client.print(F("GET adresa));
    client.println(F(" HTTP / 1.1")); //download text
    client.println(F("Content - Type: application / x - www - form - urlencoded"));
    client.println(F("Host: server"));
    client.println(F("Connection: close"));  //close 1.1 persistent connection
    client.print(F("Content - Length: "));
    client.println(postData.length());
    client.println();
    client.print(postData);
    delay(10);

  }
  else {
    Serial.println(F("connection failed"));
    return;
  }
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      //Serial.println(F(" >>> Client Timeout !"));
      client.stop();
      return;
    }
  }
  DeviceIncrement = 0;
  while (client.connected() && !client.available()) delay(50); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char m = client.read(); //gets byte from ethernet buffer
    // d - device
    // v - valve device
    // s - status
    if (m == '#') {
      char n =  client.read();
      if (n == 'd') {
        DeviceString[DeviceIncrement] = client.readStringUntil('*').toInt();
        DeviceIncrement = DeviceIncrement + 1;
      }
      //      if (n == 'v') {
      //        ValveString[DeviceIncrement - 1] = client.readStringUntil('*').toInt();
      //        DeviceIncrement = DeviceIncrement + 1;
      //      }
      if (n == 's') {
        StatusString[DeviceIncrement - 1] = client.readStringUntil('*').toInt();
        if (StatusString[DeviceIncrement - 1] == 0) {
          if (DeviceString[DeviceIncrement - 1] <= 7) {
            pcf.write(DeviceString[DeviceIncrement - 1],  1);
          }
          else
          {
            pcf2.write(DeviceString[DeviceIncrement - 8],  1);
          }
        }
        else {
          if (DeviceString[DeviceIncrement - 1] <= 7) {
            pcf.write(DeviceString[DeviceIncrement - 1],  0);
          }
          else {
            pcf2.write(DeviceString[DeviceIncrement - 8],  0);
          }
        }
      }
    }
  }
  client.stop();
}

KamilV
Příspěvky: 479
Registrován: 03 dub 2018, 15:27
Reputation: 0
Bydliště: Olomouc

Re: domaci automatizace

Příspěvek od KamilV » 08 zář 2019, 14:15

Printni si i oneWireCount, vykoná se ten cyklus vůbec někdy?
Jinak je dobrým zvykem psát konstatny velkými písmeny, takto to vypadá, že funkce závisí na nějaké globální prom.

antrac1t
Příspěvky: 7
Registrován: 08 zář 2019, 12:21
Reputation: 0

Re: domaci automatizace

Příspěvek od antrac1t » 08 zář 2019, 15:05

pod oneWireCount se nabinduje pocet ds18b20 a cykly bezi bez sebemensiho problemu.

antrac1t
Příspěvky: 7
Registrován: 08 zář 2019, 12:21
Reputation: 0

Re: domaci automatizace

Příspěvek od antrac1t » 08 zář 2019, 17:13

jen ted jsem si vsiml co se deje kdyz se bindujou ty teplomery (5 kousku by se melo nahrat). Vidno ze se prvni 3 priradi do stringu bez problemu ale 4 nejak smazne predesle data a zacina od znova (viz obr)

ps ted to testuji na jinem arduinu a ethernetu kde nejsou pripojeny cidla, proto ty -127

Obrázek

Kód: Vybrat vše

  postData = "";
  for (int i = 0; i < oneWireCount; i++) {
    sensor[i].requestTemperatures();
    postData = postData + sensor[i].getTempCByIndex(0);
    Serial.println(postData);
  }
  

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: domaci automatizace

Příspěvek od pavel1tu » 08 zář 2019, 17:21

Přehodnoť celkový návrh HW - pokud to chceš rozšiřovat.
My mám ecentrálu na DUE, v každé místnosti po 485 máme vlastní modul postavený na ATMega.

ds18b20 - mi fungují i 10ks na 30m vedení ;) ale musíš je pak adresovat + nepoužívám parazitní napájení.
Já si vyčtu po jenom adresy, očísluji si je a pak vím která adresa kde přesně je.
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Reputation: 0
Bydliště: Poprad
Kontaktovat uživatele:

Re: domaci automatizace

Příspěvek od martinius96 » 08 zář 2019, 19:16

Vždy pred čítaním hodnôt (po vyžiadaní - requeste) som používal 750ms-1000ms delay, aby dáta "stihli" prísť na zbernicu.
A ty vyžiadaš dáta, okamžite ich chceš získať a zase ich vyžiadaš.... Takto to nebude spoľahlivo fungovať.
Hľadal by som efektívnejší zápis, napr, vyžiadaj dáta, počkaj, a potom cyklus.

antrac1t
Příspěvky: 7
Registrován: 08 zář 2019, 12:21
Reputation: 0

Re: domaci automatizace

Příspěvek od antrac1t » 08 zář 2019, 19:42

martinius96 píše:
08 zář 2019, 19:16
Vždy pred čítaním hodnôt (po vyžiadaní - requeste) som používal 750ms-1000ms delay, aby dáta "stihli" prísť na zbernicu.
A ty vyžiadaš dáta, okamžite ich chceš získať a zase ich vyžiadaš.... Takto to nebude spoľahlivo fungovať.
Hľadal by som efektívnejší zápis, napr, vyžiadaj dáta, počkaj, a potom cyklus.
upravil jsem kod dle tvojich instrukci a musim kostatovat ze problem vyresen :), tohle me fakt nenapadlo :lol: . Dekuji vsem za prispevky a pomoc

Kód: Vybrat vše

void getTemps() {
  postData = "";
  for (uint8_t i = 0; i < oneWireCount; i++) {
    sensor[i].requestTemperatures();
    delay(100);
    postData = postData + sensor[i].getTempCByIndex(0);
    Serial.println(postData);
    delay(30);
  }
}

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Reputation: 0
Bydliště: Poprad
Kontaktovat uživatele:

Re: domaci automatizace

Příspěvek od martinius96 » 08 zář 2019, 21:54

8-) to som rád.
Kedysi som tu publikoval aj jednoduchý "tester", ktorý vypíše jednotlivé teploty pre senzory na základe indexu.
https://www.arduino-forum.cz/viewtopic.php?t=152
Ups, už som si všimol, že máš viacero zberníc a iba 0-tý index.

antrac1t
Příspěvky: 7
Registrován: 08 zář 2019, 12:21
Reputation: 0

Re: domaci automatizace

Příspěvek od antrac1t » 09 zář 2019, 09:35

jj, mam kazdej sensor na vlastnim pinu. Jinak vcera jsem odzkousel print raw hodnot z cidel, kde pridani delay fungovalo, ale jakmile upravim kod zpet na a pridam 6te cidlo, tak kod opet nefunguje.

Kód: Vybrat vše

   postData = postData + "Zarizeni_ID_" + i + "=" + i + "&Atribut_" + i + "=1 & Hodnota_" + i + "=" + sensor[i].getTempCByIndex(0);
pri mensim hranim kodu jsem si vsiml, ze kdyz zakomentuji Get metodu na pripojeni k internetu tak vse funguje spravne, takze vidno ze i kdyz vyuziti pameti je 85% tak s tim budu muset neco udelat.

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: domaci automatizace

Příspěvek od pavel1tu » 09 zář 2019, 11:34

U toho sendGET(); se na konci čeká na odpověď serveru, že data zpracoval.
Tam záleží jak složitě v tom PHP souboru zpracováváš data, popřípadě jak dlouho trvá zápis do databáze - když to mám doma na BananaPi jsou to max. stovky ms, pokud to posílám na FREE hosting, klidně i 2s (ukládám 12 hodnot).
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 15 hostů