SD.open == 0

Тема в разделе "Arduino & Shields", создана пользователем snake32, 25 май 2014.

  1. snake32

    snake32 Нерд

    Доброго времени.
    Подключил к уно SD и NFC shields. По отдельности всё работает, но вместе - не хочет.
    Хочу записывать ID карты на флешку.
    Код (Text):
    #include "defcard.h"
    #include <SPI.h>
    #include <PN532_SPI.h>
    #include "PN532.h"
    #include <LiquidCrystal.h>
    #include <SD.h>

    #define USED_SERIAL

    // RS, E, DB5, DB6, DB7, DB8
    LiquidCrystal lcd(2, 3, 6, 7, 8, 9);

    const int SD_pin = 4;
    const int NFC_pin = 10;
    int lastSelect_pin = -1;

    const int init_delay = 2000;

    char basename[] = "base.dat";
    //boolean busy = false;
    boolean rec_mode = false;

    PN532_SPI pn532spi( SPI, NFC_pin );
    PN532 nfc( pn532spi );

    void selectDevice(int pin, boolean init = false )
    {
      if( lastSelect_pin == pin )
        return;
      lastSelect_pin = pin;
     
      if( pin == SD_pin )
      {
        digitalWrite( NFC_pin, HIGH );
        digitalWrite( SD_pin, LOW );
        if( init )
        {
          if(!SD.begin( SD_pin ))
          {
            printLCD( 0, 1, "SD Failed");
            while(1);// halt;
          }
        }
      }
       
      if( pin == NFC_pin )
      {
        digitalWrite( SD_pin, HIGH );
        digitalWrite( NFC_pin, LOW );
        if( init )
        {
          nfc.begin();
          uint32_t versiondata = nfc.getFirmwareVersion();
          if( !versiondata )
          {
            printLCD( 0, 1, "NFC Failed");//Didn't find PN53x board
            while (1); // halt
          }
          nfc.SAMConfig();
        }
      }
         
      #ifdef USED_SERIAL
        Serial.print( "selectDevice: " );
        if( pin == SD_pin )
          Serial.println("SD");
        else
          Serial.println("NFC");
      #endif
    }

    void printLCD( int x, int y, String str )
    {
      lcd.setCursor( x, y );
      lcd.print( str );
      #ifdef USED_SERIAL
        Serial.println( str );
      #endif
    }

    void RWFile( char * filename )
    {
      File file = SD.open( filename, FILE_WRITE );
      if( file )
      {
        file.println("test");
        file.close();
        printLCD(0,1,"file ok");
      }else
        printLCD(0,1,"file error");
    }

    void setup()
    {
      lcd.begin(16, 2);
      #ifdef USED_SERIAL
        Serial.begin( 9600 );
      #endif
      pinMode( SD_pin, OUTPUT );
      pinMode( NFC_pin, OUTPUT );
     
      printLCD( 1, 0, "Initialization");
     
      selectDevice( SD_pin, true );
      printLCD( 0, 1, "SD Ready");
      RWFile("setup.txt"); // ЭТА Ф-ИЯ НОРМАЛЬНО РАБОТАЕТ
         
      delay( init_delay );
     
      selectDevice( NFC_pin, true );
      printLCD( 0, 1, "NFC Ready");
      delay( init_delay );
     
      printLCD( 0, 1, "Finish");
      delay( init_delay );
      lcd.clear();
    }


    void loop(void)
    {
     
        printLCD( 0, 0, "Present the card");
        printLCD( 0, 1, "                ");
       
        CARD card;
        memset( &card, 0, sizeof(card) );

        selectDevice( NFC_pin );
        if( nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, card.id, &card.len) )
        {
          String s;
          for( int i=0; i<8; i++ )
            s += String( card.id[i], HEX );
          s.toUpperCase();
         
          printLCD( 0,0, s );
         
          //s = String( card.len, DEC );
          //printLCD( 0,1, s );
         
          selectDevice( SD_pin );
          RWFile("loop.txt"); // А ЗДЕСЬ - НЕТ. SD.open == false
        }
        delay( 2000 );
    }
    В коде выполняется одна и та же ф-ия записи на SD 2 раза( в setup и в loop )
    RWFile("setup.txt");
    RWFile("loop.txt");
    соответсвенно.
    setup - пишет
    loop - нет.
    Видимо влияет как-то настройка NFC.
    Вопрос: что нужно сделать чтобы после настройки NFC работала SD?
     
  2. NR55RU

    NR55RU Гик

    Дабы избежать гаданий на кофейной гуще, проще закомментировать код связанный с NFC и проверить записи в loop.txt, и сразу разобраться в вопросе какой код вносит баги. :)

    Я с библиотекой SD не знаком, но предположу что функции SD.begin() производят инициализацию требуемых пинов в нужные режимы для работы.
    SD по своему а NFC по своему, соответственно вызов NFC.begin() перенастраивает их.
    Таким образом перед записью в loop.txt вам надо вызвать функцию выбора со вторым параметров TRUE чтобы SD снова произвела инициализацию.
    Попробуйте :)
     
    snake32 нравится это.
  3. snake32

    snake32 Нерд

    Вроде работает:
    Код (Text):
    #include "defcard.h"
    #include <SPI.h>
    #include <PN532_SPI.h>
    #include "PN532.h"
    #include <LiquidCrystal.h>
    #include <SD.h>

    #define USED_SERIAL

    // RS, E, DB5, DB6, DB7, DB8
    LiquidCrystal lcd(2, 3, 6, 7, 8, 9);

    const int SD_pin = 4;
    const int NFC_pin = 10;
    int lastSelect_pin = -1;

    const int init_delay = 2000;

    char basename[] = "base.dat";
    //boolean busy = false;
    boolean rec_mode = false;

    PN532_SPI pn532spi( SPI, NFC_pin );
    PN532 nfc( pn532spi );

    void selectDevice(int pin, boolean init = false )
    {
      if( lastSelect_pin == pin )
        return;
      lastSelect_pin = pin;
     
      if( pin == SD_pin )
      {
        digitalWrite( NFC_pin, HIGH );
        digitalWrite( SD_pin, LOW );
       
        if( !SD.begin( SD_pin ) && init )
        {
            printLCD( 0, 1, "SD Failed");
            while(1);// halt;
        }
      }
       
      if( pin == NFC_pin )
      {
        digitalWrite( SD_pin, HIGH );
        digitalWrite( NFC_pin, LOW );
       
        nfc.begin();
        if( init )
        {
            uint32_t versiondata = nfc.getFirmwareVersion();
            if( !versiondata )
            {
              printLCD( 0, 1, "NFC Failed");//Didn't find PN53x board
              while (1); // halt
            }
        }
        nfc.SAMConfig();
      }
         
      #ifdef USED_SERIAL
        Serial.print( "selectDevice: " );
        if( pin == SD_pin )
          Serial.println("SD");
        else
          Serial.println("NFC");
      #endif
    }

    void printLCD( int x, int y, String str )
    {
      lcd.setCursor( x, y );
      lcd.print( str );
      #ifdef USED_SERIAL
        Serial.println( str );
      #endif
    }

    void RWFile( char * filename )
    {
      File file = SD.open( filename, FILE_WRITE );
      if( file )
      {
        file.println("test");
        file.close();
        printLCD(0,1,"file ok");
      }else
        printLCD(0,1,"file error");
    }

    void setup()
    {
      lcd.begin(16, 2);
      #ifdef USED_SERIAL
        Serial.begin( 9600 );
      #endif
      pinMode( SD_pin, OUTPUT );
      pinMode( NFC_pin, OUTPUT );
     
      printLCD( 1, 0, "Initialization");
     
      selectDevice( NFC_pin, true );
      printLCD( 0, 1, "NFC Ready");
      delay( init_delay );
     
      selectDevice( SD_pin, true );
      printLCD( 0, 1, "SD Ready");
      RWFile("setup.txt");
      delay( init_delay );
     
      printLCD( 0, 1, "Finish");
      delay( init_delay );
      lcd.clear();
    }


    void loop(void)
    {
     
        printLCD( 0, 0, "Present the card");
        printLCD( 0, 1, "                ");
       
        CARD card;
        memset( &card, 0, sizeof(card) );

        selectDevice( NFC_pin );
        if( nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, card.id, &card.len) )
        {
          String s;
          for( int i=0; i<8; i++ )
            s += String( card.id[i], HEX );
          s.toUpperCase();
         
          printLCD( 0,0, s );
         
          //s = String( card.len, DEC );
          //printLCD( 0,1, s );
         
          selectDevice( SD_pin );
          RWFile("loop.txt");
        }
        delay( 2000 );
    }
    Спасибо!
     
  4. Megakoteyka

    Megakoteyka Оракул Модератор

    Не обязательно дергать вручную chip select для SD - библиотека делает это сама когда нужно.
    Там есть функции:
    Код (Text):
    void Sd2Card::chipSelectHigh(void) {
      digitalWrite(chipSelectPin_, HIGH);
    }
    void Sd2Card::chipSelectLow(void) {
      digitalWrite(chipSelectPin_, LOW);
    }
    Насчет nfc не скажу, не смотрел. Но по логике тоже должна. Возможно, библиотеки просто настраивают SPI на разные режимы работы, тогда достаточно оставить только begin в функции выбора устройства, а строчки
    Код (Text):
        digitalWrite( NFC_pin, HIGH );
        digitalWrite( SD_pin, LOW );
     
    и
    Код (Text):
        digitalWrite( SD_pin, HIGH );
        digitalWrite( NFC_pin, LOW );
    можно убрать. Попробуйте, может получится маленько код сократить.
     
  5. snake32

    snake32 Нерд

    >> Не обязательно дергать вручную

    Дёргать всё равно придётся(через метод chipSelect или на прямую digitalWrite) так как одновременно общаться по SPI более чем с одним устройством не получится.
     
  6. Megakoteyka

    Megakoteyka Оракул Модератор

    Когда я ковырялся во внутренностях библиотеки SD, видел, что она сама вызывает функции chipSelectHigh и chipSelectLow, когда это необходимо. Если руки дойдут, попробую одновременно с двумя картами поработать, посмотрю, насколько необходимо вручную выбирать чип.