Čtení hodnot z SD karty

herdsman
Příspěvky: 11
Registrován: 29 srp 2022, 21:22
Reputation: 0

Čtení hodnot z SD karty

Příspěvek od herdsman » 20 zář 2022, 19:48

Ahoj všem,
v mém začátečnickém bastlení jsem narazil na problém s čtením čísel z SD karty tak, že jí pak můžu používat jako proměnou. (Doufám, že to říkám dobře :D )
Cílem je do SD karty zapsat hodnotu například "10" do souboru "test.txt" a následně si umět hodnotu načíst jako například int, abych s ní mohl počítat (přičíst třeba 10) a přeuložit zpět novou hodnotu na SD kartu.
Tímto způsobem chci ošetřit to, aby si arduino pamatovalo hodnotu proměnné i po odpojení od proudu.

Předem všem děkuji za nápovědu. :)

herdsman
Příspěvky: 11
Registrován: 29 srp 2022, 21:22
Reputation: 0

Re: Čtení hodnot z SD karty

Příspěvek od herdsman » 20 zář 2022, 20:39

Teď se mi povedlo zpatlat toto a jako funguje to... ale načítání dat z karty je hodně pomalé...
takže i tak prosím prosím o nějaký názor a radu. :)

Kód: Vybrat vše

#include <SPI.h>
#include <SD.h>


File myFile1;
File myFile2;

String data1;
String data2;

int vysledek;
int cislo_1;
int cislo_2;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
  }

  Serial.print("Načítám SD Kartu...");

  if (!SD.begin(10)) {
    Serial.println("Načítání selhalo!");
    while (1);
  }
  Serial.println("Načítání bylo úspěšné");

  myFile1 = SD.open("cislo1.txt", FILE_READ);
  if (myFile1) {
    if ( myFile1.available()) {
      data1 = myFile1.readString();
      Serial.println(data1);
    }
    myFile1.close();
  } else {
    Serial.println("Nepodařilo se....");
  }

  myFile2 = SD.open("cislo2.txt", FILE_READ);
  if (myFile2) {
    if ( myFile2.available()) {
      data2 = myFile2.readString();
      Serial.println(data2);
    }
    myFile2.close();
  } else {
    Serial.println("Nepodařilo se....");
  }
cislo_1=data1.toInt();
cislo_2=data2.toInt();
vysledek = cislo_1 + cislo_2;
Serial.println(vysledek);
}

void loop() {
  // nothing happens after setup
}

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

Re: Čtení hodnot z SD karty

Příspěvek od martinius96 » 20 zář 2022, 21:57

Tak na polovicu aktuálneho času sa dostaneš, ak budeš mať obe čísla v jednom súbore a vyčítaš ich naraz a vyparsuješ si ich samostatne. Môžeš tam použiť nejaký oddelovač, napr. ; teda čísla budeš mať vo formáte 123;456. Parsing urobíš napr. cez funkciu strtok(). Môžeš si to skúsiť odmerať cez millis(), aká je výkonnosť s dvomi súbormi a s jedným + koľko ms zaberie samotný parsing dvoch čísel.

Ak budú obe čísla v jednom súbore a tie vyparsuješ, takto bude stále rýchlejšie, ako otvárať ďalší súbor a čítať z neho. Rýchlejšie načítanie z SD karty by sa dalo zrealizovať aj zvýšením hodinového signálu SPI zbernice, ktorú knižnica SD používa.

Čítanie dvoch čísel z dvoch súborov:
Obrázek

Čítanie dvoch čísel z jedného súboru s oddelovačom ; + parsing čísel:
Obrázek

Ako vidíš, parsing nezabral ani jednu milisekundu... Takže stále sme o 1004 ms rýchlejší ako v predchádzajúcom príklade, kedy sme načítavali 2 čísla z dvoch súborov.

herdsman
Příspěvky: 11
Registrován: 29 srp 2022, 21:22
Reputation: 0

Re: Čtení hodnot z SD karty

Příspěvek od herdsman » 20 zář 2022, 23:02

Okej tomu rozumím, v projektu budu potřebovat pracovat například s 20 takovými čísli, což znamená úsporu třeba 19x. To je určitě přínosem. snažil jsem se podívat na návod, jak funkci strtok() využít, a musím říct, nejsem z toho úplně chytrý. :D
Neznáš nějaké místo, kde je to nějak srozumitelně popsané pro začátečníka ?
Abych to dokázal napsat...

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

Re: Čtení hodnot z SD karty

Příspěvek od martinius96 » 21 zář 2022, 00:38

Nie je to tak zložité, stačí určiť terminátor - znak podľa ktorého sa bude robiť parsing, String previesť na pole znakov (buffer) na ktoré ide použiť funkcia strtok(). Tým je parser v podstate hotový. Potom už len treba pretypovať získanú hodnotu na INT, ktorú vieš vypísať a zároveň sa uloží aj do poĺa na daný index 0 až 19, teda celkovo získaš 20 prvkov.

Vzoro má program pripravené prázdne 20 prvkové pole integerov, kde ich zapisuješ pri parsingu jeden po druhom.
Funkcia strtok() prechádza pole znakov zľava doprava. Urobil som to čo najjednoduchšie na pochopenie. Dal som terminátor ; aj za posledné číslo v pôvodnej reprezentácii, šlo by to s jednou úpravou v programe použiť aj bez neho, ale takto to zbehne v cykle, program je kratší.

Môžeš si daný program vyskúšať priamo v simulátore Wokwi: https://wokwi.com/projects/343359507599983186.
Taktiež simulátor podporuje aj modul SD karty a knižnicu SD, teda aj celý projekt si môžeš zostaviť tam bez nutnosti zapisovať do tvojej fyzickej SD karty, kým si program odladíš, aby si si ju zbytočne mnoho krát neprepísal.

Kód: Vybrat vše

//20 cisel v SD karte nacitanych ako String oddelenych terminatorom ;
String values = "111;222;333;444;555;666;777;888;999;100;200;300;400;500;600;700;800;900;110;210;";
const char terminator[] = ";"; //oddelovaci znak (terminator) pre rozdelenie Stringu
int numbers[20] = {}; //prazdne pole cisel s velkostou 30 prvkov pre 30 cisel parsovanych zo Stringu
char* num; //smernik, vrati hodnotu na adrese v pamäti
String num_string; //String ktory textovu hodnotu cisla prevedie na INT
void setup() {
  Serial.begin(9600);
  unsigned char str[values.length() + 1];
  values.toCharArray(str, values.length());
  num = strtok(str, terminator);
  num_string = String(num);
  numbers[0] = num_string.toInt();
  Serial.print("1. prvok v poli numbers: ");
  Serial.println(numbers[0]); //vypis prveho prvku pola numbers (nultý index)
  for(int i=1; i<20; i++){
    num = strtok(NULL, terminator);
    num_string = String(num);
    numbers[i] = num_string.toInt();
    Serial.print(i+1);
    Serial.print(". prvok v poli numbers: ");
    Serial.println(numbers[i]); //vypis i-teho prvku pola numbers, ktore sa inkrementuje 1 až 19
  }
}

void loop() {
}

Očakávaný výstup na UART:
K jednotlivým hodnotám kdekoľvek v programe pristúpiš cez numbers[0] až numbers[19] pre prvé až 20-te číslo.
Obrázek

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Čtení hodnot z SD karty

Příspěvek od AstroMiK » 21 zář 2022, 07:13

Jen k zamyšlení:

Nestačila by na tu požadovanou funkci vnitřní EEPROM?

Opakované zápisy na jedno místo tu kartu poškozují podobně jako opakované zápisy do EEPROM,
ale pro EEPROM nepotřebuješ žádný další hardwér.

Vyčítání EEPROM by se pak obešlo bez jakéhokoliv parsování - vyčítalo by se konkrétní číslo z přesně dané adresy.

ondraN
Příspěvky: 932
Registrován: 08 srp 2019, 20:01
Reputation: 0

Re: Čtení hodnot z SD karty

Příspěvek od ondraN » 21 zář 2022, 09:22

AstroMiK píše:
21 zář 2022, 07:13
............

Opakované zápisy na jedno místo tu kartu poškozují podobně jako opakované zápisy do EEPROM,
............
To už dávno není pravda. Každá SD karta má kontrolér, který si řídí zápisy do buněk tak, aby byly rovnoměrně rozprostřené. Je to interní záležitost, kterou user nepostřehne.

Pro zrychlení práce s kartou je dobré používat blokové zápisy z/do bufferu v RAM kontroléru.

herdsman
Příspěvky: 11
Registrován: 29 srp 2022, 21:22
Reputation: 0

Re: Čtení hodnot z SD karty

Příspěvek od herdsman » 21 zář 2022, 14:04

@martinius96
Děkuji moc za super kódisko :) jak budu u PC tak vyzkouším.

Pro všechny ostatní. EEPROM jsem nechtěl využít, jelikož přepis dat bude probíhat dejme tomu každých 5 vteřin, takže bych ho hodně rychle odčoudil.
Proto jsem chtěl zvolit SD kartu, kde jsem čekal, že tento problém nebude.

Když to vezmu takto, stačilo by mi, kdyby zápis na SD kartu probíhal jenom třeba na zmáčknutí tlačítka, ale tím bych neošetřil situaci, kdy po určité době práce někdo omylem vytáhne přívod proudu a systém prostě vypne a tím se okamžitě ztratí data.

Takže kdyby šel udělat scénář:
zapnu arduino -> načtou se data z SD -> arduino pracuje s proměnnými -> pokud chci můžu v průběhu data uložit na SD -> dám příkaz pro vypnutí a data se uloží na SD (pak mohu vypojit z proudu) a poslední záchytný bod, když v průběhu někdo vyškubne přísun proudu, systém dokáže dopracovat poslední úkony, uložit data a vypne se... To by byl svět nádherný :D ale to by v tom asi musel být nějaký náhradní zdroj jako třeba baterky a vůbec nevím jestli takováto blbina je možná :D

ondraN
Příspěvky: 932
Registrován: 08 srp 2019, 20:01
Reputation: 0

Re: Čtení hodnot z SD karty

Příspěvek od ondraN » 21 zář 2022, 14:32

Samozřejmě, že to jde takto udělat. Ale je to o fous složitější a chce to už nějaké zkušenosti s HW i SW. Taky na zálohování dat můžeš použít externí paměť FRAM, EERAM nebo RAM se záložní baterkou.
Taky pokud není požadavek na čtení i na jiném zařízení (při použití SD), tak si můžeš udělat strukturu s potřebnými proměnnými a zálohovat a číst jako jeden blok, bez jakýchkoli úprav.
Naposledy upravil(a) ondraN dne 21 zář 2022, 14:37, celkem upraveno 1 x.

Uživatelský avatar
kiRRow
Příspěvky: 1152
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Čtení hodnot z SD karty

Příspěvek od kiRRow » 21 zář 2022, 14:37

EERAM ... Je to SRAM + EEPROM dohromady ... normálně zapisuješ do sériové RAM, při výpadku proudu se data sama přepíšou do vnitřní EEPROM. Po obnově napájení se zase překopírují do SRAM

Odpovědět

Kdo je online

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