Odczyt danych z karty SD

Ogólne rozmowy na temat Arduino (i jemu podobnych).
ODPOWIEDZ
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 03:32

Poczytaj o readString, readStringUntil, readBytes, readBytesUntil bo na razie powtarzasz to co jest w standardowej bibliotece.
Pamiętaj, że File dziedziczy po Stream i tam szukaj wszystkich fajnych funkcji do czytania (nie tylko z karty, ale ogólnie ze wszystkiego z czego da sę czytać). Tutaj masz opis klasy.

BTW w programie masz niedoróbki następujące:
a) polegasz radośnie na automatycznej inicjalizacji zmiennych zerami ("i" i "input"). Uważaj, bo to nie zawsze działa;
b) po co za każdym odczytem cyfry wykonujesz atoi , jeśli za chwilę czytasz następną cyfrę i nadpisujesz wynik?

A w ogóle to Stream ma jeszcze taką fajną funkcję jak parseInt - może lepiej od razu ją zastosować zamiast bawić się w samodzielne pisanie parserów?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 10:38

Co to ogarniać?
Nie mam pod ręką Arduino więc sprawdź sam czy zadziała:

Kod: Zaznacz cały

  plik = SD.open("costam.txt");
  czas=plik.parseInt();
  plik.close();
Ot i cała filozofia...
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 11:04

A po co chcesz czytać ten plik za każdy obiegiem pętli? Zapisujesz coś tam za każdym obrotem czy co?
Coś mi się zdaje, że chcesz czytać z karty coś, co powinieneś mieć albo w RAMIE albo w EEPROM-ie...
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 11:41

Dobra, w setup() to nie działa czy co?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 13:03

Jak rozumiem nie szukasz już innego hobby :)
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 14:11

Ne powinieneś!!!
Poza tym... Hm... Orzechy w majtkach to mu się bardziej z męską bielizną kojarzą... Dawaj ten problem bo zaczyna być ciekawie!
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
Slawek
Starszy majsterkowicz
Posty: 449
Rejestracja: 29 mar 2015, 15:05

Re: Odczyt danych z karty SD

Post autor: Slawek » 13 sie 2017, 14:56

Proponuję abyś umieścił ten kawałek kodu w :

setup() {
// kod
}
bo inaczej będzie to wykonywać non stop a operacje I/O są dość czasochłonne w tym przypadku. Skoro masz zmieniać nastawę czasu na karcie, to i tak musisz ją wyciągnąć a wiec musisz wyłączyć arduino, wtedy po włączeniu wykona się to raz i po temacie.

Pozdr
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 15:18

Do odczytu treści z SD masz readString/readBytes. Do odczytu wiersza masz readStringUntil/readBytesUntil. Ponieważ readString* zwraca (jak wskazuje nazwa) właśnue String, dalsza obróbka (konkatencja, wyświetlanie itp.) jest już trywialna.
Gorzej z wczytanuem n-tego wiersza. Ale tu problem można bardzo prosto rozwiązać - wczytujesz ze streama po jednym znaku, liczysz znaki końca linii i zatrzymujesz się po osiągnięciu konkretnej ilości - a potem readStringUntil i masz n-ty wiersz wczytany.
Co do analizy zawartości owego wiersza - pamiętaj, że obróbka stringów w C/C++ nie jest tym, do czego owe języki zostały stworzone. Owszem, istnieją funkcje klasyfikacji znaków (isalpha, isalnum, isdigit itd.), nawet straszliwie fujasta i przez wszystkich zakazana funkcja tokenizera (strtok) - ale niestety, tu musisz sobie radzić sam.
Prosty przykład: strip (wycięcie białych znaków z początku/końca napisu). Spróbuj od takiej prostej rzeczy zacząć. Jeśli to zrobisz, potem jest z górki:
Jeśli napis zawiera same cyfry to pewnie jest liczbą;
Jeśli napis zawiera (po zestripowaniu) jakikolwiek biały znak (np. spację) to jest to kilka wyrazów.
I tak dalej...
Zapoznaj się z funkcjami z avr-libc (bo na Wiringowych Stringach przy ilości pamięci w Arduino daleko nie zajedziesz).
Aha, nie będę pisał o tym, jakie rozwiązania mamy w firmie na serwerach, bo nie o to pytałeś ;)
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
Slawek
Starszy majsterkowicz
Posty: 449
Rejestracja: 29 mar 2015, 15:05

Re: Odczyt danych z karty SD

Post autor: Slawek » 13 sie 2017, 15:36

Jak nie chcesz się bawić w tworzenie samemu, to poniżej masz kod, który działa w ten sposób, że w pliku settings.txt w kolejnych wierszach masz np. następujące dane :

[exINT=15]
[exFloat=1.12345]
[exBoolean=1]
[exLong=2123456789]

Następnie zawartość pliku linia po linii jest wczytywana i rozpoznawana po nazwie a następnie przypisywana odpowiadająca jej wartość czyli np. dla exFloat 1.12345. Nieważna jest kolejność i ilość wierszy. W ten sposób możesz sobie sobie zdefiniować więcej zmiennych i przypisać do nich wartości w pliku.
 #include <SPI.h>
 #include <SD.h>
 
File myFile;

String plik = "settings.txt";

 
 int exINT = 15;
 float exFloat = 1.12345;
 boolean exBoolean = true;
 long exLong = 2123456789;
 
 void setup()
 {

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

 
 Serial.print("Initializing SD card...");
 
 pinMode(10, OUTPUT);
 if (!SD.begin(4)) {
 Serial.println("initialization failed!");
 return;
 }
 Serial.println("initialization done.");
 writeSDSettings();
 readSDSettings();
 
 
 Serial.println("In RAM Memory");
 Serial.print("exINT=");
 Serial.println(exINT);
 Serial.print("exFloat=");
 Serial.println(exFloat,10);
 Serial.print("exBoolean=");
 Serial.println(exBoolean);
 Serial.print("exLong=");
 Serial.println(exLong);
 
 }
 
 void loop()
 {
 }
 
 
 
 
 
 void readSDSettings(){
 
 char character;
 String settingName;
 String settingValue;
   
   myFile = SD.open(plik);
   if (myFile) {
   while (myFile.available()) {
   character = myFile.read();
   while((myFile.available()) && (character != '[')){
   character = myFile.read();
   }
   character = myFile.read();
   while((myFile.available()) && (character != '=')){
   settingName = settingName + character;
   character = myFile.read();
   }
   character = myFile.read();
   while((myFile.available()) && (character != ']')){
   settingValue = settingValue + character;
   character = myFile.read();
   }
   if(character == ']'){
   
   
   Serial.print("Name:");
   Serial.println(settingName);
   Serial.print("Value :");
   Serial.println(settingValue);
   
   
   applySetting(settingName,settingValue);
   settingName = "";
   settingValue = "";
   }
   }
   myFile.close();
   } else {
   Serial.println("error opening settings.txt");
   }
 }
 
 

 
 void applySetting(String settingName, String settingValue) {
 
   if(settingName == "exINT") {
   exINT=settingValue.toInt();
   }
   if(settingName == "exFloat") {
   exFloat=toFloat(settingValue);
   }
   if(settingName == "exBoolean") {
   exBoolean=toBoolean(settingValue);
   }
   if(settingName == "exLong") {
   exLong=toLong(settingValue);
   }
 }
 
 
 
 
 float toFloat(String settingValue){
 
   char floatbuf[settingValue.length()+1];
   settingValue.toCharArray(floatbuf, sizeof(floatbuf));
   float f = atof(floatbuf);
   return f;
 }


 
 long toLong(String settingValue){
 
   char longbuf[settingValue.length()+1];
   settingValue.toCharArray(longbuf, sizeof(longbuf));
   long l = atol(longbuf);
   return l;
 }

 
 boolean toBoolean(String settingValue) {

   if(settingValue.toInt()==1){
   return true;
   } else {
   return false;
   }
 }
 
 
  
void writeSDSettings() {

   SD.remove(plik);
   myFile = SD.open(plik, FILE_WRITE);
   myFile.print("[");
   myFile.print("exINT=");
   myFile.print(exINT);
   myFile.println("]");
   myFile.print("[");
   myFile.print("exFloat=");
   myFile.print(exFloat,5);
   myFile.println("]");
   myFile.print("[");
   myFile.print("exBoolean=");
   myFile.print(exBoolean);
   myFile.println("]");
   myFile.print("[");
   myFile.print("exLong=");
   myFile.print(exLong);
   myFile.println("]");
   myFile.close();
   Serial.println("Writing done.");
 }
Awatar użytkownika
ethanak
Złota rączka
Posty: 755
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Odczyt danych z karty SD

Post autor: ethanak » 13 sie 2017, 15:49

A co to ma wspólnego z problemem MrLewerence?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
Slawek
Starszy majsterkowicz
Posty: 449
Rejestracja: 29 mar 2015, 15:05

Re: Odczyt danych z karty SD

Post autor: Slawek » 13 sie 2017, 17:38

@MrLewerence spoko, wkleiłem to żebyś się nie męczył z wczytywaniem i obróbką ciągów znaków z pliku, lepiej skupić się na pozostałej części kodu.

Pozdr
Awatar użytkownika
Slawek
Starszy majsterkowicz
Posty: 449
Rejestracja: 29 mar 2015, 15:05

Re: Odczyt danych z karty SD

Post autor: Slawek » 14 sie 2017, 14:07

Tak, przerwie ci działanie danej funkcji lub programu jeżeli dasz to w pętli loop, w tym przypadku wyjdzie z IF.
Z tym, że to powinno być tak :
if(!SD.begin(nr_pin)) {return;}
Awatar użytkownika
Slawek
Starszy majsterkowicz
Posty: 449
Rejestracja: 29 mar 2015, 15:05

Re: Odczyt danych z karty SD

Post autor: Slawek » 15 sie 2017, 08:49

MrLewerence pisze:Z tym pinem to jasne.
Warunek który sprawdza czy karta została zainicjowana jest w void setup, czyli sprawdzone będzie, czy karta jest zainicjowane czy nie, jeśli nie to przestanie jej "szukać" i program jedzie dalej... o to chodzi?


EDIT::

Jakie znaczenie ma długość nazwy pliku txt na karcie?
Plik o nazwie NUMER.txt odczytywany jest prawidłowo;
Plik o nazwie MESSAGE.txt już nie, ale po zmianie nazwy na SMS.txt już jest ok.
Jeżeli jest w setup() to każda instrukcja jest wykonywana tylko raz, zatem ten IF tez tylko raz próbuje zainicjować kartę, jeżeli zakończy się niepowodzeniem (znak ! oznacza zaprzeczenie prawdy) to poprzez return wyjdzie z IF i wykonuje kolejne instrukcje. Problem tylko w takim przypadku jest taki, iż jeżeli inicjowanie karty zakończy się niepowodzeniem, to program idzie dalej, jednak dalsze operacje w pętli loop() na pliku czyli np. odczyt, mogą powodować zawieszenie programu. Stąd, jeżeli zależy Ci na pewnej pracy układu, po niepowodzeniu zainicjowania karty, program powinien się jednak zakończyć lub przejść do jakiejś specjalnej procedury.

Długość nazwy ma znaczenie, najlepiej 8+3 czyli maks osiem znaków nazwy plus 3 rozszerzenia, bez spacji i polskich liter. Pamiętaj o małych i dużych literach.

Pozdr
sargus
Młodszy majsterkowicz
Posty: 1
Rejestracja: 11 kwie 2019, 18:20

Re: Odczyt danych z karty SD

Post autor: sargus » 11 kwie 2019, 18:24

Slawek pisze:
13 sie 2017, 15:36
Jak nie chcesz się bawić w tworzenie samemu, to poniżej masz kod, który działa w ten sposób, że w pliku settings.txt w kolejnych wierszach masz np. następujące dane :

[exINT=15]
[exFloat=1.12345]
[exBoolean=1]
[exLong=2123456789]

Następnie zawartość pliku linia po linii jest wczytywana i rozpoznawana po nazwie a następnie przypisywana odpowiadająca jej wartość czyli np. dla exFloat 1.12345. Nieważna jest kolejność i ilość wierszy. W ten sposób możesz sobie sobie zdefiniować więcej zmiennych i przypisać do nich wartości w pliku.
 #include <SPI.h>
 #include <SD.h>
 
File myFile;

String plik = "settings.txt";

 
 int exINT = 15;
 float exFloat = 1.12345;
 boolean exBoolean = true;
 long exLong = 2123456789;
 
 void setup()
 {

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

 
 Serial.print("Initializing SD card...");
 
 pinMode(10, OUTPUT);
 if (!SD.begin(4)) {
 Serial.println("initialization failed!");
 return;
 }
 Serial.println("initialization done.");
 writeSDSettings();
 readSDSettings();
 
 
 Serial.println("In RAM Memory");
 Serial.print("exINT=");
 Serial.println(exINT);
 Serial.print("exFloat=");
 Serial.println(exFloat,10);
 Serial.print("exBoolean=");
 Serial.println(exBoolean);
 Serial.print("exLong=");
 Serial.println(exLong);
 
 }
 
 void loop()
 {
 }
 
 
 
 
 
 void readSDSettings(){
 
 char character;
 String settingName;
 String settingValue;
   
   myFile = SD.open(plik);
   if (myFile) {
   while (myFile.available()) {
   character = myFile.read();
   while((myFile.available()) && (character != '[')){
   character = myFile.read();
   }
   character = myFile.read();
   while((myFile.available()) && (character != '=')){
   settingName = settingName + character;
   character = myFile.read();
   }
   character = myFile.read();
   while((myFile.available()) && (character != ']')){
   settingValue = settingValue + character;
   character = myFile.read();
   }
   if(character == ']'){
   
   
   Serial.print("Name:");
   Serial.println(settingName);
   Serial.print("Value :");
   Serial.println(settingValue);
   
   
   applySetting(settingName,settingValue);
   settingName = "";
   settingValue = "";
   }
   }
   myFile.close();
   } else {
   Serial.println("error opening settings.txt");
   }
 }
 
 

 
 void applySetting(String settingName, String settingValue) {
 
   if(settingName == "exINT") {
   exINT=settingValue.toInt();
   }
   if(settingName == "exFloat") {
   exFloat=toFloat(settingValue);
   }
   if(settingName == "exBoolean") {
   exBoolean=toBoolean(settingValue);
   }
   if(settingName == "exLong") {
   exLong=toLong(settingValue);
   }
 }
 
 
 
 
 float toFloat(String settingValue){
 
   char floatbuf[settingValue.length()+1];
   settingValue.toCharArray(floatbuf, sizeof(floatbuf));
   float f = atof(floatbuf);
   return f;
 }


 
 long toLong(String settingValue){
 
   char longbuf[settingValue.length()+1];
   settingValue.toCharArray(longbuf, sizeof(longbuf));
   long l = atol(longbuf);
   return l;
 }

 
 boolean toBoolean(String settingValue) {

   if(settingValue.toInt()==1){
   return true;
   } else {
   return false;
   }
 }
 
 
  
void writeSDSettings() {

   SD.remove(plik);
   myFile = SD.open(plik, FILE_WRITE);
   myFile.print("[");
   myFile.print("exINT=");
   myFile.print(exINT);
   myFile.println("]");
   myFile.print("[");
   myFile.print("exFloat=");
   myFile.print(exFloat,5);
   myFile.println("]");
   myFile.print("[");
   myFile.print("exBoolean=");
   myFile.print(exBoolean);
   myFile.println("]");
   myFile.print("[");
   myFile.print("exLong=");
   myFile.print(exLong);
   myFile.println("]");
   myFile.close();
   Serial.println("Writing done.");
 }

mam pytanie a jak odczytać dane w postaci nazw?
powyższe odczytywanie to tylko dane liczbowe i prawdziwe fałszywe.

a ja chciałbym mieć zapisane słowo i je umieścić w zmiennej po czym wyświetlić je na lcd w dalszej części programu.
Proszę o pomoc.
ODPOWIEDZ

Strony partnerskie: