Puffer, hogyan??

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

Sziasztok!
A problémám az lenne, hogy figelnem kellene 2db relé kimenetét (nyit,tnyit), aminek a kimeneteit 24VDC-vel mérik.
Tehát mikor zárt a kimenet, akkor 0V, amikor nyitott, akkor 24V. A bemeneteken(2,3 digitális) látom is egy osztóval a működést.
A relék nem kapcsolgatnak gyorsan, viszont előfordulhat az egyszerre váltás is. Ez valószínüleg nem okoz gondot.
Naplózni kell az állapotváltozásokat SD kártyára, emellett a naplózott adatoknak elérhetőnek kell lennie Weben is bármikor.
Elérkeztünk a problémámhoz:
- Amikor az egyik átvált, és utána közvetlen a másik is,( gondolom azon időn belül, amíg a naplózás folyik ) akkor az elsőt sokszor kiírja, be, ki, be ,ki...
- A naplózás ideje alatt nem foglalkozik a változásokkal? Vagy igen? Nem értem.
- Amikor bezár a relé, azt azonnal jelzi a program, amikor kinyit akkor mindig késik 1-2 másodpercet.
Tudom, ez így elég zavaros, de nem tudtam jobban megfogalmazni a problémát. Kérdésekkel megoldjuk.
Arra gondoltam, hogy a naplózást valahogy el kell különíteni, és valamilyen pufferbe gyűjteni az adatokat, valós időben, csak nem tudom hogyan kell. Nem találtam hasonló megoldást a neten.
A hardware:
Arduino uno+ethernet panel SD foglalattal.

ide rakom az egész kódot, legyetek szívesek segítsetek!

Kód: Egész kijelölése

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <TimeLib.h>
#include <EthernetUdp.h>


#define FILE_NAME_LEN  20
// HTTP request type
#define HTTP_invalid   0
#define HTTP_GET       1
#define HTTP_POST      2

// file types
#define FT_HTML       0
#define FT_ICON       1
#define FT_CSS        2
#define FT_JAVASCRIPT 3
#define FT_JPG        4
#define FT_PNG        5
#define FT_GIF        6
#define FT_TEXT       7
#define FT_INVALID    8
#define PIN_ETH_SPI   10 // pin used for Ethernet chip SPI chip select

const int Nyit = 2;
const int tNyit = 3;
const int timeZone = 2;
const byte ip[] = { 192, 168, 1, 230 };
const byte gateway[] = { 192, 168, 1, 254 };
const byte subnet[] = { 255, 255, 255, 0 };
const byte dns[] = { 8, 8, 8, 8 };
IPAddress timeServer(81, 0, 124, 253);
const byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };



boolean NyitAllapot, NyitAllapotOld;
boolean tNyitAllapot, tNyitAllapotOld;
String IrNyit, IrtNyit;
EthernetServer server(80);
EthernetUDP Udp;
unsigned int localPort = 8888;
File logFile;


void setup() {
  // deselect Ethernet chip on SPI bus
  pinMode(PIN_ETH_SPI, OUTPUT);
  digitalWrite(PIN_ETH_SPI, HIGH);

  Serial.begin(115200);       // for debugging
  Serial.println(F("Start!"));
  if (!SD.begin(4)) {
    Serial.println(F("SD card initialization failed."));
    return;  // SD card initialization failed
  }

  Ethernet.begin((uint8_t*)mac, ip, dns, gateway, subnet);
  Udp.begin(localPort);

  Serial.print(F("Ip: "));
  Serial.println(Ethernet.localIP());
  Serial.print(F("Mask: "));
  Serial.println(Ethernet.subnetMask());
  Serial.print(F("GW: "));
  Serial.println(Ethernet.gatewayIP());
  Serial.print(F("DNS: "));
  Serial.println(Ethernet.dnsServerIP());

  server.begin();
  Serial.println(F("waiting for sync"));
  setSyncProvider(getNtpTime);
  Serial.println(F("Start listening for pins."));
  logFile = SD.open("log.txt", FILE_WRITE);
  if (logFile) {
    logFile.print(year()); logFile.print("."); logFile.print(month()); logFile.print("."); logFile.print(day()); logFile.print(". ");
    if (hour() < 10) logFile.print('0'); logFile.print(hour()); logFile.print(":");
    if (minute() < 10) logFile.print('0'); logFile.print(minute()); logFile.print(":");
    if (second() < 10) logFile.print('0');
    logFile.print(second());

    logFile.println(F(" : ***START!***"));
    logFile.close();
  }

  NyitAllapot = digitalRead(Nyit);
  tNyitAllapot = digitalRead(tNyit);

  if (NyitAllapot) {
    IrNyit = "24V";
  }
  else {
    IrNyit = "Zárt";
  }
  if (tNyitAllapot) {
    IrtNyit = "24V";
  }
  else {
    IrtNyit = "Zárt";
  }
  NyitAllapotOld = !NyitAllapot;
  tNyitAllapotOld = !tNyitAllapot;
}

void loop() {

  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (ServiceClient(&client)) {
        Serial.println(F("Received request from client and finished responding."));  // received request from client and finished responding
        break;
      }
    }  // while (client.connected())
    delay(1);
    client.stop();
  }

  LogData();
}

void LogData(void) {

  boolean ir;

  NyitAllapot = digitalRead(Nyit);
  tNyitAllapot = digitalRead(tNyit);
  ir = false;

  if ( !NyitAllapot == NyitAllapotOld ) {
    ir = true;
    if (NyitAllapot) {
      IrNyit = "24V";
    }
    else {
      IrNyit = "Zárt";
    }
    NyitAllapotOld = NyitAllapot;
  }

  if ( !tNyitAllapot == tNyitAllapotOld) {
    ir = true;
    if (tNyitAllapot) {
      IrtNyit = "24V";
    }
    else {
      IrtNyit = "Zárt";
    }
    tNyitAllapotOld = tNyitAllapot;
  }

  if (ir) {
    logFile = SD.open("log.txt", FILE_WRITE);
    if (logFile) {
      logFile.print(year()); logFile.print(F(".")); logFile.print(month()); logFile.print(F(".")); logFile.print(day()); logFile.print(F(". "));
      if (hour() < 10) logFile.print('0'); logFile.print(hour()); logFile.print(F(":"));
      if (minute() < 10) logFile.print('0'); logFile.print(minute()); logFile.print(F(":"));
      if (second() < 10) logFile.print('0'); logFile.print(second());
      logFile.print(F(" - Nyitás: ")); logFile.print(IrNyit);
      logFile.print(F(" - tNyitás: ")); logFile.println(IrtNyit);
      logFile.close();
    }
    Serial.print(year()); Serial.print(F(".")); Serial.print(month()); Serial.print(F(".")); Serial.print(day()); Serial.print(F(". "));
    if (hour() < 10) Serial.print('0'); Serial.print(hour()); Serial.print(F(":"));
    if (minute() < 10) Serial.print('0'); Serial.print(minute()); Serial.print(F(":"));
    if (second() < 10) Serial.print('0'); Serial.print(second());
    Serial.print(F(" - Nyitás: ")); Serial.print(IrNyit);
    Serial.print(F(" - tNyitás: ")); Serial.println(IrtNyit);
  }
}


bool ServiceClient(EthernetClient *client)
{
  static boolean currentLineIsBlank = true;
  char cl_char;
  File webFile;
  // file name from request including path + 1 of null terminator
  char file_name[FILE_NAME_LEN + 1] = {0};  // requested file name
  char http_req_type = 0;
  char req_file_type = FT_INVALID;
  const char *file_types[] = {"text/html", "image/x-icon", "text/css", "application/javascript", "image/jpeg", "image/png", "image/gif", "text/plain"};

  static char req_line_1[40] = {0};  // stores the first line of the HTTP request
  static unsigned char req_line_index = 0;
  static bool got_line_1 = false;

  if (client->available()) {   // client data available to read
    cl_char = client->read();

    if ((req_line_index < 39) && (got_line_1 == false)) {
      if ((cl_char != '\r') && (cl_char != '\n')) {
        req_line_1[req_line_index] = cl_char;
        req_line_index++;
      }
      else {
        got_line_1 = true;
        req_line_1[39] = 0;
      }
    }

    if ((cl_char == '\n') && currentLineIsBlank) {
      // get HTTP request type, file name and file extension type index
      http_req_type = GetRequestedHttpResource(req_line_1, file_name, &req_file_type);
      if (http_req_type == HTTP_GET) {         // HTTP GET request
        if (req_file_type < FT_INVALID) {      // valid file type
          webFile = SD.open(file_name);        // open requested file
          if (webFile) {
            // send a standard http response header
            client->println(F("HTTP/1.1 200 OK"));
            client->print(F("Content-Type: "));
            client->println(file_types[req_file_type]);
            client->println(F("Connection: close"));
            client->println();
            Serial.println(F("Send web page.")); // send web page
            while (webFile.available()) {
              int num_bytes_read;
              char byte_buffer[64];
              // get bytes from requested file
              num_bytes_read = webFile.read(byte_buffer, 64);
              // send the file bytes to the client
              client->write(byte_buffer, num_bytes_read);
            }
            webFile.close();
          }
          else {
            Serial.println(F("Failed to open file.")); // failed to open file
          }
        }
        else {
          // invalid file type
        }
      }
      else if (http_req_type == HTTP_POST) {
        Serial.println(F("A POST HTTP request was received.")); // a POST HTTP request was received
      }
      else {
        Serial.println(F("Unsupported HTTP request received!")); // unsupported HTTP request received
      }
      req_line_1[0] = 0;
      req_line_index = 0;
      got_line_1 = false;
      Serial.println(F("Finished sending response and web page.")); // finished sending response and web page
      return 1;
    }
    if (cl_char == '\n') {
      currentLineIsBlank = true;
    }
    else if (cl_char != '\r') {
      currentLineIsBlank = false;
    }
  }  // if (client.available())
  return 0;
}

// extract file name from first line of HTTP request
char GetRequestedHttpResource(char *req_line, char *file_name, char *file_type)
{
  char request_type = HTTP_invalid;  // 1 = GET, 2 = POST. 0 = invalid
  char *str_token;

  *file_type = FT_INVALID;

  str_token =  strtok(req_line, " ");    // get the request type
  if (strcmp(str_token, "GET") == 0) {
    request_type = HTTP_GET;
    str_token =  strtok(NULL, " ");      // get the file name
    if (strcmp(str_token, "/") == 0) {
      strcpy(file_name, "index.htm");
      *file_type = FT_HTML;
    }
    else if (strlen(str_token) <= FILE_NAME_LEN) {
      // file name is within allowed length
      strcpy(file_name, str_token);
      // get the file extension
      str_token = strtok(str_token, ".");
      str_token = strtok(NULL, ".");

      if      (strcmp(str_token, "htm") == 0) {
        *file_type = 0;
      }
      else if (strcmp(str_token, "ico") == 0) {
        *file_type = 1;
      }
      else if (strcmp(str_token, "css") == 0) {
        *file_type = 2;
      }
      else if (strcmp(str_token, "js")  == 0) {
        *file_type = 3;
      }
      else if (strcmp(str_token, "jpg") == 0) {
        *file_type = 4;
      }
      else if (strcmp(str_token, "png") == 0) {
        *file_type = 5;
      }
      else if (strcmp(str_token, "gif") == 0) {
        *file_type = 6;
      }
      else if (strcmp(str_token, "txt") == 0) {
        *file_type = 7;
      }
      else {
        *file_type = 8;
      }
    }
    else {
      // file name too long
    }
  }
  else if (strcmp(str_token, "POST") == 0) {
    request_type = HTTP_POST;
  }

  return request_type;
}


/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

void printDigits(int digits) {
  // utility for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}
vargham
Chipgyilok
Hozzászólások: 308
Csatlakozott: 2014. január 8. szerda, 8:32

Re: Puffer, hogyan??

Hozzászólás Szerző: vargham »

A választott megoldásaid nem alkalmasak a feladathoz.
1. Az SD kártya kezelés rengeteg időt vesz igénybe.
2. A szerver működtetése szintén rengeteg idő.
3. A digitalRead időszükséglete sem elhanyagolható. Realtime alkalmazásoknál érdemes kerülni az Arduino függvények használatát, és inkább közvetlenül kezelni a hardvert.

Javaslatok:
0. Aszinkron működésre van szükséged, használj megszakításokat!
1. Használj pin change interruptot. Arduino függvény nincs rá, de könnyen megérthető.
https://microchipdeveloper.com/8avr:pin ... interrupts
2. Mivel a pin change interrupt a változást figyeli, neked kell lekérdezned a változás irányát. Fentebb írtam, hogy a digitalRead lassú, megszakítás kiszolgáló rutinban (ISR) ne használd. Helyette közvetlenül a regiszterből olvasd ki a bemenet állapotát:
(PINB & (1 << PINB4)) >> PINB4; // Ebben a példában 0 az eredmény, ha Port B Pin 4 alacsony, és 1 ha magas. Az Arduino leírásában benne van, hogy melyik Arduino pin melyik port melyik bitjén van.
Ugyanerre jó az AVR LibC beépített függvényei is: bit_is_set(sfr, bit) és a bit_is_clear(sfr, bit), amik olvashatóbbak.
3. Az ISR-ben csak egy flag-et állítasz, amit a főprogramod dolgoz fel. Tehát ISR-be nem raksz szzerver kezelést, SD kártya írást, de még egy serial printet sem!
3. Még mindig előfordulhat, hogy lefutott ugyan az ISR, de a főprogram még nem dolgozta fel a flag-et. Ha ezt is szeretnéd feldolgozni, akkor az ISR-ben nem flag-et állítasz, hanem egy sort (queue) töltesz fel, amit folyamatosan ürít a főprogram.
4. Ha az ISR futás ideje alatt jönne még egy megszakítás, azt nem fogod tudni detektálni. Ezen a platformon nincsenek egymásba ágyazott megszakítások, se prioritások. Ezért is nagyon fontos az ISR hossza (futás ideje), minél rövidebb, annál kisebb az esélye, hogy közben még egy esemény történjen.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Puffer, hogyan??

Hozzászólás Szerző: Robert »

A megszakítás a kulcs a relé változásához.
A megszakításban amit tesztel:
- melyik relé változott
- időpecsét - szoftverből számolod igaz?
- egy string, abban tárolódik a kiírandó adat.

Ez lefut SD kiírás és Eth kiszolgálás alatt is. A loopban - ha nincs feladat, akkor íratod SD-re.


Igaz nem UNO lapon próbálod? Ott a memória elfogy!


Mennyi a relé meghúzás/elengedés ideje?
Ha 10 sec felett, akkor simán timer INTben nézed, hogy volt-e változás.... Ha volt -> SD kiírást jelző flag bebillent.
http://www.tavir.hu - a gazda :)
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Re: Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

A hardware:
Arduino uno+ethernet panel SD foglalattal.
A húzás ideje kb 2 sec.

"Ha ezt is szeretnéd feldolgozni, akkor az ISR-ben nem flag-et állítasz, hanem egy sort (queue) töltesz fel, amit folyamatosan ürít a főprogram."
Na ezzel lenne gondom, többek közt. Hogyan lehet ezt megvalósítani? mondjuk 1 byte bitjeit mindig tologatom?
Mert ha írni kell egy ilyen metódust, amelyik figyeli, melyik az utolsó írt adat, és utána ír, és figyeli melyik az első írt adat, ezt számon tartja és shiftel, mikor az első kiíródik, az hosszú lenne a megszakításon belül nem?
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Puffer, hogyan??

Hozzászólás Szerző: Robert »

UNO esetén sehogy.
SD: 1200 byte buffer kell neki
Ethernet: 1600-1800 byte.
UNO-ban van 2k...
http://www.tavir.hu - a gazda :)
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Re: Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

Az eth shilden van memória nem?
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Puffer, hogyan??

Hozzászólás Szerző: Robert »

Persze, csak az adatokat küldeni-fogadni kell, mi puffert igényel...
http://www.tavir.hu - a gazda :)
Avatar
aaszabo
Tranzisztorgyógyász
Hozzászólások: 179
Csatlakozott: 2012. január 22. vasárnap, 7:00

Re: Puffer, hogyan??

Hozzászólás Szerző: aaszabo »

A reléknek fizikai jellemzője, hogy mennyi idő alatt zár és nyit. Az időt a vezérlő feszültségének a változási görbéje is befolyásolja.
Pl. ha a vezérlő fesz egy tápról jön, akkor az elengedés lehet lassú, ha a tápfeszültség elmúlása okozza a relé elengedését. A tápban lévő buffer kondi miatt lassabban csökken a feszültség és a relé lassabban mágneseződik le.
De lehet, hogy a relé egyszerűen csak lassan enged el, mert a benne lévő vasmag hiszterézise ilyen.
A bizonytalan működés abból is adódhat, ha az egyik relé vezérli valahogy a másik behúzását, vagy elengedését, vagy hatással van rá valahogy.

Egyet értek az előttem szólóval abban, hogy a feladat túlmutat az eszközön.
Vannak arduinonál erősebb és kétmagos megoldások is elérhető áron( 2-5USD) beépített wifi képességgel és több megás chipen lévő memóriával.
Arduinot és SD kártyát olyan mérési elrendezésben használtam, ahol az arduino ütemezte, hogy mikor kell mérni és volt ideje kényelmesen kiírni az adatokat az SD kártyára.
Egyébként megszakítást használnék, illetve egy időzítő rutint is, ami időnként rákérdez a relékre, hogy biztos abban az állapotban van, mint amiről tud a rendszer.

Ha jó a Chipválasztás, akkor nem kell SD kártya sem, mert van a chippen elég hely. Akár 1-4MByte is.
Ha jól értelmeztem a programot, akkor olvasás után lezárja a fájlt, de nem törli. Így az SD kártya is betelik egyszer.
SD kártyával a megszakításos működés annyiban lehet problémás, ha egyszerre akarja írni is és olvasni is a fájlt a program.
Ekkor kell valami, ami késlelteti azt a folyamatot, ami másodikként esik be.

A következő megoldást javaslom, ha mégis ebben a környezetben kell megoldani a dolgot és a biztos működést is fontos:
  • A memóriában két tömböt definiálnék puffernek. Nem nagyok pár tíz, esetleg pár száz bejegyzést tudnak tárolni.
    Mindig az egyik az elsődleges, amibe a relék megszakításkor beírok és a másik a másodlagos, amiből az SD kártyába írok. Aztán megcserélem őket.
  • A relék megszakításokat generálnak, amik gyorsan beírnak az elsődleges bufferba.
  • A loop ban a következők vannak egymás után:
    1. buffer kezelés.
      Írd ki a buffert ha:
      • tele (közel tele) az elsődleges buffer? - nem szabad megvárni a pont telít, mert lehet, hogy éppen akkor esik be egy írási kérés.
      • régen volt kiírva az elsődleges buffer - mondjuk sok tízezer loop ciklus óta nem volt kiírva. Ez biztosítja, hogy bizonyos késésnél nagyobb ne legyen a tárolásban.
A buffer kiírás úgy kezdődik, hogy megcserélem az elsődleges és másodlagos buffert. Ami az elsődleges volt az most a kiírandó lesz.
A megcserélés csak a hivatkozások megcserélését jelenti (melyiket írja a megszakítás, melyikből írom az SD-t), nem kell másolni.
Így, ha SD írás közben beesik egy megszakítás, azt gond nélkül be tudom írni a másik bufferbe.
Lefut az SD kiírási rutin.
Ki kell üríteni a buffert, amiből a kiírás megtörtént. Ennek a leggyorsabb módja, ha egy mutatót tárolsz ami az aktuális írási pozíciót tárolja. Ezt csak vissza irányítod a buffer elejére. Nem kell a buffer adatokat kinullázni. SD kiíráskor is csak az elejétől eddig a mutatóig kell az adatokat kiírni.
[*]Van webes kérés?
Ha igen ki kell szolgálni.
Mivel a loop soros feldolgozású, ezért ez a kiszolgálás nem akad össze az SD írással.
Annyira azért nem lassú az SD írás, hogy percekig legyen a loopban az SD írással elfoglalva a proci és timeoutra menjen a webes kérés.
[*]mi a relék helyzete?
Ha nem az amiről tudok a megszakítások alapján, akkor írjam be a bufferba a helyzetet, mintha egy megszakítás generálta volna. Ha szükséges megjelölhetem ezt a bejegyzést, hogy megkülönböztessem a megszakítás által generálttól.

Egy gyengéje van ennek a megoldásnak. Ha áramszünet van, akkor az SD-re nem kiírt adatok elvesznek.
Erre egy megoldás lehet, ha van a rendszerben szünetmentes, vagy telepes a táplálás. Illetve a tápfeszt figyeli egy áramkör, ami megszakítást generál és SD kiírást kezdeményez, ha éppen nem az SD kiírás rutin fut. Illetve a lopban a régen volt kiírva a buffer figyeléssel befolyásolhatom a kiírás sűrűségét és így az elveszthető adat mennyiségét.

Nem tudom milyen gyakran kapcsolnak a relék, de a tárolt adatmennyiséget alapul (12byte karakteresen, 6 byte bit vezérelten) véve 5 másodpercenkénti kapcsolgatásnál két relével 1Mbyte adat elég 2,5 napnyi adat tárolásához. Ha 6 byte-on történik a tárolás, akkor 5 nap. Nagyobb chip és magasabb szintű programozói környezetet használva a tárolt adatok tömörítése sem bonyolult feladat. Ez kb. 5-8 szoros adatmennyiséget jelent. Vagyis a 10-20 napnyi adattárolás is lehetséges 1MByte méreten.

Milyen gyakran működnek a relék? Milyen pontosan kell az időt meghatározni, hogy mikor volt egy relé ki/be kapcsolva? Mennyi ideig kell adatot tárolni?

Kiit hosszú lett ez a bejegyzés, de remélem tudtam segíteni.
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Re: Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

Szia!
Nagyon örülök, hogy ilyen terjedelmes választ kanyarintottál nekem, nagyon köszönöm!
Igen, segítettél a puffer technikával kapcsolatban. Nem jutott eszembe a 2 tömb használata. A mutatón már járt a gógyim.
A relék viszont gyors működésűek, de nem gyorsan működtetettek. Szemmel láthatóan ugyanolyan gyorsan elenged, ahogy behúzott, tehat a programom logikájában lehet a gond, de ez mellékesnek bizonyul, hiszen úgyis ujra kell írnom az egészet. A naplózás időtartamának elég legkevesebb 1 nap. Nem kapcsolnak túl gyakran, különösen az egyik leget hogy egy nao alatt csak kétszer vált. A másiknál kb. 30mp átlag számolható. Ezért is nem foglalkoztam egyenlőre az sd file meretkorlattal.
"[*]mi a relék helyzete?"- ez nem tiszta. Nem lehetek biztos benne, hogy a megszakítás mindig ír?
A puffer miatt valószínűleg akkus megoldás lesz.
Hardware ben max arduino mega a lehetőségem. Át is váltok arra, mert már ez a progi is alig fért az unoban nem beszélve az új program nagyobb mem igényéről.
Mégegyszer nagyon köszönöm a segítséget!
Hamarosan nekigyürkőzöm, és megpróbálom valahogy kóddá tenni a leírtakat...
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Re: Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

"SD kártyával a megszakításos működés annyiban lehet problémás, ha egyszerre akarja írni is és olvasni is a fájlt a program."
Az sd kiírást a loop végzi, ahogy a webes kiszolgálást is ,, más esetben pedig nem kell a kártyát olvasni-írni.
A megszakítás az éppen aktuális puffert írogatja.
Vagy nem jól látom?
vargham
Chipgyilok
Hozzászólások: 308
Csatlakozott: 2014. január 8. szerda, 8:32

Re: Puffer, hogyan??

Hozzászólás Szerző: vargham »

"Naplózni kell az állapotváltozásokat SD kártyára"
Ez kötelező? Léteznek egyszerűbb megoldások is.
Például EERAM. SPI-on írod, sima SRAM. De van benne tápfeszültség figyelés, vele egy tokban EEPROM is, és mellette egy kondi. Folyamatosan, akár bájtonként írható. Nem fog elhasználódni, és nem is vesz igénybe sok időt a kommunikáció. Detektálja a tápfeszültség megszűnését, és a kondiban tárolt energiából átírja a RAM tartalmát a ROMba. Bekapcsoláskor pedig automatikusan vissza.
Amúgy ezekre a feladatokra én is nagyobb MCU-t használnék. Miért ragaszkodsz az ATMega 328-hoz? Ennyi pénzért már sokkal újabbakat, erősebbeket lehet kapni.
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Re: Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

Nem ragaszkodom én.
Csak abból kifolyólag, hogy ezek az eszközök biztosítottak a feladat megoldására. Viszont a jövőben valószínűleg beszerzek valami újabb eszközt, ha már olyan olcsóak. Kérlek írj konkrét példákat, milyen eszközökre (MCU stb) gondoltál!?
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Puffer, hogyan??

Hozzászólás Szerző: Robert »

ESP32? ESP8266?
Lehet egyszerűbb sokkal....

A MEGA mindenképp legyen....
http://www.tavir.hu - a gazda :)
fodisoft
Újonc
Újonc
Hozzászólások: 13
Csatlakozott: 2020. március 14. szombat, 13:38

Re: Puffer, hogyan??

Hozzászólás Szerző: fodisoft »

Utána kell néznem, hogy ugyanaz a program fut e rajtuk, mert úgy gondolom igen. A könyvtárakban nem vagyok biztos, viszont ethernetre kell ezek meg wifi modulok.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Puffer, hogyan??

Hozzászólás Szerző: Robert »

Először a MEGA-t próbáldd ki...
http://www.tavir.hu - a gazda :)
Válasz küldése