Stránka 1 z 2

domaci automatizace

Napsal: 08 zář 2019, 12:40
od antrac1t
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();
}

Re: domaci automatizace

Napsal: 08 zář 2019, 14:15
od KamilV
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.

Re: domaci automatizace

Napsal: 08 zář 2019, 15:05
od antrac1t
pod oneWireCount se nabinduje pocet ds18b20 a cykly bezi bez sebemensiho problemu.

Re: domaci automatizace

Napsal: 08 zář 2019, 17:13
od antrac1t
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);
  }
  

Re: domaci automatizace

Napsal: 08 zář 2019, 17:21
od pavel1tu
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.

Re: domaci automatizace

Napsal: 08 zář 2019, 19:16
od martinius96
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.

Re: domaci automatizace

Napsal: 08 zář 2019, 19:42
od antrac1t
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);
  }
}

Re: domaci automatizace

Napsal: 08 zář 2019, 21:54
od martinius96
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.

Re: domaci automatizace

Napsal: 09 zář 2019, 09:35
od antrac1t
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.

Re: domaci automatizace

Napsal: 09 zář 2019, 11:34
od pavel1tu
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).