• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Problem z odczytem/zapisem na/z karty SD
#1
Hej, mam pewien problem. Pisałam dość prosty, lecz rozbudowany program na Leonardo. Miał on wyświetlać menu, i zależnie od naciśniętej opcji,umożliwiać rysowanie (i na karcie sd zapisywac współrzędne naciśniecia), zapisywać na karcie sd, w pliku napis testowy, lub odczytywać z karty sd i wyświetlac na ekraniku tekst zapisany w pliku.

Na arduino Leonardo wszystko pięknie działało, ale niestety brak miejsca zmusił mnie do zakupu zamiennika arduino Mega 2560. Wszystko podpięłam dobrze, ale niestety pojawił się problem z zapisem/odczytem z/na karte sd (biblioteka SD.h). Czy ktoś jest mi w stanie pomóc?

Płytka: RobotDyn MEGA CH340/A Tmega 2560
   
Biblioteka: SD.h
Wyświetlacz (z portem na karte SD): TJCTM24024-SPI ( 2.4". 240x 320)
   

Podłączenie:
 T_IRQ -> 7
 T_DO -> 6
 T_DIN -> 5 
 T_CS -> 4
 T_CLK -> 3
 MISO -> 50
 MOSI > 51
 LED > 5v
 SCK > 52
 D/C > 46
 RST > 48
 CS > 53 
 SD_SCK > 22

(ICSP)
SD_MISO > 1
SD_MOSI > 4
SD_CS > 3

Ps. Obawiam się że może to być kwestia źle zdefiniowanych pinów, ale nie wiem jak sobie z tym poradzić przy tej bibliotece 

Ps2. Funkcja guz() jest przezemnie napisana, i po prostu wyświetla guziczek w odpowiednim miejscu na ekranie
   

Kod:
#include "SD.h"

#include "Adafruit_ILI9341.h" 

#include "URTouch.h"          



#define TFT_DC 46             

#define TFT_CS 53           

#define TFT_RST 48

#define TFT_MISO 50       

#define TFT_MOSI 51         

#define TFT_CLK 52          


Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);


#define T_CLK 3              

#define T_CS 4                

#define T_DIN 5              

#define T_DOUT 6             

#define T_IRQ 7  




File myFile;

URTouch ts(T_CLK, T_CS, T_DIN, T_DOUT, T_IRQ);


[...]


void zczytajPiksele(int x, int y)

{

        myFile.print(x);

        myFile.print(",");

        myFile.print(y);

        myFile.print(";  ");

        myFile.println();

}


void wyswietlSD()

{

  int x,y;

      tft.setTextSize(1);

      tft.setTextColor(ILI9341_BLACK);  

      tft.setCursor(10,80);

      tft.print("wywołano funkcje wyswietl");

      

    SD.begin(22);

    myFile = SD.open("kord.txt");

    if (myFile) 

    {

      tft.setCursor(10,20);

     tft.println("kord.txt:");

      while (myFile.available()) 

      {

        tft.write(myFile.read());

      }

      myFile.close();

    } 

    else 

    {

       tft.setCursor(10,20);

      tft.println("error opening kordynaty.txt");

    }


}


void zapisz()

{

      tft.setTextSize(1);

      tft.setTextColor(ILI9341_BLACK);  

      tft.setCursor(10,80);

      tft.print("wywołano funkcje zapisz");

      tft.setCursor(10,18);

      tft.print("Initializing SD card...");

      SD.begin(22);

      /*if (!SD.begin(22)) 

      {

        tft.println("initialization failed!");

        return;

      }*/

      tft.println("initialization done.");

      myFile = SD.open("test.txt", FILE_WRITE);

      tft.setCursor(10,28);

      if (myFile) 

      {

        tft.print("Writing to test.txt...");

        myFile.println("testing 1, 2, 3.");

        myFile.close();

        tft.setCursor(10,38);

        tft.println("done.");  //Wysyłanie i wyświetlanie koordynat   178 lin  

      } 

      else 

      {

        tft.println("error opening test.txt");

      }

}

[...]


void rysowanie()

{

     int x, y;

      

      tft.setTextSize(1);

      tft.setTextColor(ILI9341_BLACK);  

      tft.setCursor(10,10);

      tft.print("Naciśnięto pierwszy przycisk. Rysowanie");

      guz(240,190,80,50,2,270,210,"BACK");

      //SD.begin(22);

      //myFile = SD.open("kord.txt", FILE_WRITE);

      while(!(x>240&&y>190&&x<320&&y<240))

      {

        ts.read();                      

        x = ts.getX();                 

        y = ts.getY();  

        x += 13;                      

        y += 4;                       

        int radius = 2;               

        tft.fillCircle(x, y, radius, ILI9341_BLACK);

        //zczytajPiksele(x,y);

      }

      //myFile.close();

}


void przyc2()

{

      int x,y;

      

      tft.setTextSize(1);

      tft.setTextColor(ILI9341_BLACK);  

      tft.setCursor(10,10);

      tft.print("Naciśnięto Drugi przycisk");

      guz(240,190,80,50,2,270,210,"BACK");

       zapisz();

      

      while(!(x>240&&y>190&&x<320&&y<240))

      {

        ts.read();                      

        x = ts.getX();                 

        y = ts.getY(); 

      }

     

      

}


void przyc3()

{

      int x,y;

      tft.setTextSize(1);

      tft.setTextColor(ILI9341_BLACK);  

      tft.setCursor(10,10);

      tft.print("Naciśnięto trzeci przycisk");

     guz(240,190,80,50,2,270,210,"BACK");

      wyswietlSD();

      while(!(x>240&&y>190&&x<320&&y<240))

      {ts.read();                      

        x = ts.getX();                 

        y = ts.getY(); 

      }

      

      

}

[...]

Void setup(){

  tft.begin();                     

  tft.setRotation(1);           

 

  ts.InitTouch();                   

  ts.setPrecision(PREC_MEDIUM);

  tft.fillScreen(ILI9341_BLACK);


  guz(0,0,320,80,3,100,40,"rysowanie");

  guz(0,81,160,80,2,40,100,"tesZap");

  guz(161,81,160,80,2,220,100,"wysw");

  guz(0,161,80,65,1,40,190,"nFol");

  

  tft.setTextColor(ILI9341_GREEN);  

  tft.setTextSize(2);

  tft.setCursor(20,220);           

  tft.print("By Kinga Snuszka");

}

 

void loop()

{

  int x, y; 

  String nazFol;

                         

 

  while(ts.dataAvailable())        

  {

    ts.read();    //Wysyłanie i wyświetlanie koordynat   178 lin                

    x = ts.getX();                 

    y = ts.getY();    

    Serial.print(x); Serial.print(','); Serial.println(y);// + " " + Y); 

    if (y<80&&x<320&&x>0&&y>0)

    {

      czysc();

      rysowanie();

      setup();

    }

   

        if(x>0&&y>81&&x<160&&y<160)

        {

          czysc();

          przyc2();

          setup();

        }

        else

        {

          if(x>160&&y>80&&x<320&&y<160)

          {

            czysc();

            przyc3();

            setup();

          }
Z góry dziękuje za pomoc i pozdrawiam
 
Odpowiedź
#2
Na Leonardo też używałaś różnych pinów do SPI? Zwykle wystarcza użyć te same piny MOSI, MISO, SCK i osobne piny CS dla karty i ekranu. No i te piny z ICSP to właśnie te co na 50-52 płytki Arduino MEGA. Stąd właśnie nie można użyć do karty pinu ICSP 3 a do ekranu 53 bo to te same, a maja być różne. Z kolei te które powinny być te same użyłaś różne.
edit:
Aaa, dziewczyna na forum, witamy. Wprowadziłem poprawki w odpowiedź.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
Hmmm, dziwne, bo na Leonardo takie rozwiązanie działało. No dobra, więc jak podłączyc w takim razie i wyświetlacz i czytnik do jednego arduino, jeśli mam tylko jedno wyjście MISO i jedno wyjście MOSI? Bo jezeli po prostu podepnę do tych samych pinów i MISO z wyświetlacza, i MISO z czytnika, to nadal nie działa
 
Odpowiedź
#4
Wlasnie pin ss okresla, z ktorym urzadzeniem chcesz rozmawiac..jak z karta, ustawiasz ss karty, jak z lcd to ss lcd..

Wysłane z mojego SM-G950F przy użyciu Tapatalka
 
Odpowiedź
#5
Trzeba poczytać o SPI, jak wrzucisz w google to znajdziesz nawet wykłady MK na Youtubie, trochę kłuje w uszy ale da się wytrzymać. Pierwszy schemat z google jest np. tu: https://www.digikey.com/en/articles/tech...ot-designs.
Nie ma pewności, że coś takiego zadziała w Twoim konkretnym przypadku, ale co do zasady MOSI, MISO, SCK podłączasz do X urządzeń, poza tym rezerwujesz X pinów CS dla każdego urządzenia i Arduino jako master magistrali SPI decyduje z kim aktualnie gada.
Jak robisz SD.begin(22); to informujesz Arduino, że każda operacja jest robiona na domyślnych pinach SPI - 50,51,52 (w MEGA) a pinem 22 ma przełączać się na obsługę karty.
Jak tworzysz obiekt dla ekranu to też wystarczy Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); - podajesz tylko gdzie będzie pin CS i DC, reszta to domyślne piny SPI płytki i tak je trzeba podpiąć.
Tu masz jeszcze dotyk i obiekt URTouch ts(T_CLK, T_CS, T_DIN, T_DOUT, T_IRQ);. Jak to ma działać również na SPI (nie mam tego ekranu z dotykiem i nie wiem) to podajesz tylko znowu CS i T_IRQ, IRQ powinno być na pinie z przerwaniem INT0 czy który tam jest - co do zasady. Tu przykład z chyba innym dotykiem: https://github.com/adafruit/Adafruit_ILI...hpaint.ino.
Nie ma sensu robić 3 magistral SPI bo i tak masterem jest Arduino, gadać w danej chwili może tylko z jednym. Co najwyżej może zostać poproszony o nawiązanie połączenia przez to IRQ z dotyku. Problem byłby jakbyś chciała gadać z pamięcią na 40MHz, a z dotykiem na 1MHz, ale w MEGA czy innym AVR to nie ma znaczenia, i tak ledwo odrywa się od ziemi. Ale jeśli robisz dwie/trzy magistrale, bo można resztę zrobić na softowych , to przynajmniej nie mieszaj pinów, że raz wykorzystujesz pin 51 do sprzętowej magistrali 1 a za chwilę do softowej 2, bo jak definiujesz piny do SPI to biblioteka może chcieć (a właściwie uzna, że Ty chcesz) zrobić softowy SPI nawet na pinach sprzętowych i to zupełnie w innej funkcji niż oryginalna. No i na softowym SPI to już będzie trzeć o ziemię mocno.
W linku na schemacie znajdziesz też rezystory podciągające do VCC na pinach CS, może być tak, że moduły/shieldy mają je już, a czasami trzeba dodać.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#6
(08-04-2019, 14:58)Kanra napisał(a): Hej, mam pewien problem. Pisałam dość prosty, lecz rozbudowany program
Prosty a skomplikowany? Jakbym Wałęsę słyszał :-)

[quote='Kanra' pid='12413' dateline='1554728295']
na Leonardo. Miał on wyświetlać menu, i zależnie od naciśniętej opcji,umożliwiać rysowanie (i na karcie sd zapisywac współrzędne naciśniecia),
Zły pomysł o ile nie zastosuje sie sprytnych mechanizmów owego zapisu a takich nie masz.
Byłem zmuszony, aby spełnić wymagania PML, aby taka opcja działała ale w jednym zdaniu tego nie da się napisać. Nie sądzę aby były ostre wymagania (jak są pisz na PW) zapisuj pozycję po timeout np 10 sekund.
 
Odpowiedź
#7
Kaczkat : Dzięki za pomoc, postaram sie o tym więcej poczytać i mam nadzieje że zadziała

es2: jako że to projekt na konkurs, to wymagań nie mam wcale. Ma działać. Jeżeli chodzi o czekanie po zarejestrowaniu dotyku, to faktycznie będzie to działało przy guzikach, ale przy rysowaniu, będzie musiało w jakiś sposób sprawdzać czy poprzednie współrzędne są takie same jak obecne, a jeśli tak to je pomijać. Cały czas planuje to zrobić, ale ciągle są pilniejsze problemy

Co do prostego ale rozbudowanego programu, to chodziło mi po prostu o to że działa jak budowa cepa, ale ma mase linijek.... coś jak by przyczepić kilka cepów do czegośco się obraca. Niby w budowie nadal proste, ale duże i rozbudowane.
Co do podobieństwa mojej wypowiedzi do stylu Wałęsy, nie miałam pojęcia, ponieważ gdy doroslam na tyle by coś tam ogarniać z polityki, to Wałęsa już trochę ze sceny politycznej zszedł, ale schlebia mi porównanie do takiego człowieka, nawet jeśli w negatywnym aspekcie Big Grin
 
Odpowiedź
#8
Chyba uporalam sie z tym problemem. Wszystko ładnie zapisuje się na karcie, ale pojawil sie kolejny problem. Po zainicjalizowaniu karty, przestaje działac wyswietlacz (dotyk nadal działa).

Objawia sie to tym, że gdy wybieram opcje rysowania, wyświetla sie to co powinno sie wyświetlić (ze kliknieto przycisk pierwszy i przycisk back). Kiedy zaczynam rysować, współrzędne kliknięcia zapisują się na karcie, ale nie pojawia sie linia na ekranie

Kod:
void zczytajPiksele(int x, int y) //funkcja zapisuje współrzędne kliknięcia do pliku na karcie sd
{
       myFile.print(x );
       myFile.print(" ");
       myFile.print(y );
       myFile.print(" ");
}

void rysowanie()
{
    int x, y;
     
     tft.setTextSize(1);
     tft.setTextColor(ILI9341_BLACK);  
     tft.setCursor(10,10);//ustawia parametry napisu ktory ma byc wyświetlony
     tft.print("Naciśnięto pierwszy przycisk. Rysowanie");
     guz(240,190,80,50,2,270,210,"BACK"); //wywoluje funkcje, która rysuje przycisk opisany jako "back"
     SD.begin(22);
     myFile = SD.open("kord.txt", FILE_WRITE); //otwiera plik do zapisu
     while(!(x>240&&y>190&&x<320&&y<240))
     {
       while(ts.dataAvailable()) //sprawdza czy jest nacisnięty ekran
       {
       ts.read(); //czyta piksele
       tft.print("wykryto ");                    
       x = ts.getX();                
       y = ts.getY();  
       tft.print("xy ");
       x += 13;                      
       y += 4; //zapisuje współrzędne w zmiennuch
       tft.print("narysowano ");
       Serial.print("narysowano");                    
       int radius = 2;              
       tft.fillCircle(x, y, radius, ILI9341_BLACK); //rysuje w podanym miejscu kółko
       

       Serial.print(x); Serial.print(','); Serial.println(y);
       zczytajPiksele(x,y); //wywołuje funkcje zapisujaca do pliku i daje jej x i y
       tft.print("zapisano")  ;
       Serial.print("zapisano");
       }
     }
     myFile.close(); //zamyka plik
}


Pisze tutaj, bo nie chce robic spamu postami
 
Odpowiedź
#9
Takie linijki jak SD.begin(22); robi się raczej tylko raz, czyli w setup. Problem może być taki, że między otwarciem a zamknięciem pliku nie możesz korzystać z ekranu (może być wciąż wysterowany pin CS do SD). Nie powinno tak być, ale biblioteki cudze trzeba poznać w trakcie zabawy, jakie mają niespodzianki. Niestety sama to musisz sprawdzić. Możesz podpiąć ledy+rezystor 1k do pinów CS i obserwować, na które urządzenie "patrzy" w danej chwili Arduino.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#10
Może CS za szybko jest zdejmowane?
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości