При повторном вставлении SD карта не определяеться.

AmateurFF
Offline
Зарегистрирован: 02.02.2015

Плата MEGA 2560. Подключены дисплей 12862B V2.0, часы DS1302, клавиатура и считыватель SD карт от LC STUDIO.

Программа имеет два файла CSBoiler.ino и CSBoiler.h. Отлаживается на Microsoft Visual Studio 2015.

Файл CSBoiler.ino.

#include "CSBoiler.h"

void setup()

{

  /* add setup code here */

       u8g.setRot180();

       initSD();

       Serial.begin(115200);

}

void loop()

{

  

  /* add main program code here */

       switch (wait4event())

       {

       case eDisp:

             draw();

             break;

       case eSDwr:

             writeLog();

             break;

       case eKeyP:

             break;

       default:

             break;

       }

}

Файл CSBoiler.h

// CSBoiler.h



#ifndef _CSBOILER_h

#define _CSBOILER_h



#if defined(ARDUINO) && ARDUINO >= 100

       #include "arduino.h"

#else

       #include "WProgram.h"

#endif





#include <U8glib.h>

#include <DS1302.h>

#include <Keypad.h>

#include <SPI.h>

#include <SD.h>



#define Tic  200

#define RTic  10





#define      eNone         0

#define      eTerm         1

#define      eVent         2

#define      eDisp         3

#define      eSDwr         8

#define      eKeyP         4





void printTime(void);



struct CSData

{

       uint16_t yyyy;

       uint8_t mm;

       uint8_t dd;

       uint8_t hh;

       uint8_t nn;

       uint8_t ss;

       char temp1[10];

       char temp2[10];

       char temp3[10];

       char temp4[10];

       uint16_t dtBegn;

       uint16_t dtTemp;

       uint16_t dtDisp;

       uint16_t dtKeyp;

       uint16_t dtSDwr;

};

struct CSData csd = { 2016,02,04, 23,30,44, "88.0","89.3","84.7", "70.6", 55,120,300 };



/*****************************************************************************/

// Настройка клавиатуры

const byte ROWS = 4; //four rows

const byte COLS = 4; //four columns

                                   //define the cymbols on the buttons of the keypads

char hexaKeys[ROWS][COLS] = {

       { '9', '#', '3', '6' },

       { 'C', 'D', 'A', 'B' },

       { '7', '*', '1', '4' },

       { '8', '0', '2', '5' }

};



byte rowPins[ROWS] = { 29, 28, 27, 26 }; //connect to the row pinouts of the keypad

byte colPins[COLS] = { 25, 24, 23, 22 }; //connect to the column pinouts of the keypad

                                                                    //initialize an instance of class NewKeypad

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

/*****************************************************************************/

const int csLCD = A7;

const int enLCD = A6;

const int rwLCD = A5;

//U8GLIB_ST7920_128X64_4X u8g(18, 16, 17);     // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17

U8GLIB_ST7920_128X64_4X u8g(csLCD);

/*****************************************************************************/

// Часы

const int kCePin = A2;  // Chip Enable

const int kIoPin = A1;  // Input/Output

const int kSclkPin = A0;  // Serial Clock

char inKey;



// Create a DS1302 object.

DS1302 rtc(kCePin, kIoPin, kSclkPin);

Time t(2016, 2, 4, 22, 15, 0, Time::kThursday);

/*****************************************************************************/

// SD Card

const int csSD = 48;

boolean errSD;

void initSD(void) {

       Serial.println("Init");

       pinMode(SS, OUTPUT);

       pinMode(csSD, OUTPUT);

       pinMode(csLCD, OUTPUT);

       digitalWrite(SS, HIGH);

       digitalWrite(csSD, HIGH);

       digitalWrite(csLCD, HIGH);

       errSD = !SD.begin(csSD);

       Serial.print("errSD=");

       Serial.println(errSD);

       if (errSD)

             return;

       printTime();

       char fname[10];

       snprintf(fname, sizeof(fname), "%02d_%02d.txt",

             csd.dd, csd.hh);

       uint16_t tmp = millis();

       File dataFile = SD.open(fname, FILE_WRITE);

       if (dataFile) {

             dataFile.println("Begin ---------------------------------------------------------------");

             dataFile.close();

       }

       else

       {

             errSD = true;

       }

       csd.dtSDwr = (uint16_t)millis() - tmp;

return;

}

/*****************************************************************************/

/*****************************************************************************/

/*****************************************************************************/

uint8_t wait4event(void) {

             uint32_t numTic = millis();

             if ((numTic % Tic) == 0) {

                    csd.dtBegn = (uint16_t)millis();

                    return (uint8_t)((numTic / Tic) % RTic);

             }

       if (numTic % Tic < Tic - 10) {

             csd.dtKeyp = -(uint16_t)millis();

             customKeypad.getKey();

             csd.dtKeyp += (uint16_t)millis();

             return eKeyP;

       }

       return eNone;

 }



/*****************************************************************************/

/*****************************************************************************/

void printTime() {

       // Get the current time and date from the chip.

       t = rtc.time();

       csd.yyyy = t.yr; csd.mm = t.mon; csd.dd = t.date;

       csd.hh = t.hr; csd.nn = t.min; csd.ss = t.sec;

       // Name the day of the week.

       // Format the time and date and insert into the temporary buffer.

       char buf[50];

       snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",

             t.yr, t.mon, t.date,

             t.hr, t.min, t.sec);

       // Print the formatted string to serial so we can see the time.

       u8g.setFont(u8g_font_courB08);

       u8g.drawStr(7, 8, buf);

}

/*****************************************************************************/

void printErrors(void) {

       if (errSD) {

             u8g.setFont(u8g_font_courB08);

             u8g.drawStr( 1, 63, "SD!");

       }

}

/*****************************************************************************/

void draw(void){

       csd.dtDisp = -(uint16_t)millis();

       u8g.firstPage();

       do {

             printTime();

             printErrors();

       } while (u8g.nextPage());

       pinMode(csLCD, OUTPUT);

       digitalWrite(csLCD, HIGH);

       csd.dtDisp += (uint16_t)millis();

}

/*****************************************************************************/

void writeLog(void) {

       uint16_t tmp = millis();

       Serial.println("writeLog");

       Serial.print("errSD=");

       Serial.println(errSD);

       if (errSD) {

             initSD();

             Serial.println("ReInit");

             Serial.print("errSD=");

             Serial.println(errSD);

       }

             if(errSD) return;

       char fname[10];

       snprintf(fname, sizeof(fname), "%02d_%02d.txt",

             csd.dd, csd.hh);

       File logFile = SD.open(fname, FILE_WRITE);

       int num;

       // if the file is available, write to it:

       if (logFile) {

             char dstr[200];

             snprintf(dstr, sizeof(dstr), "%02d:%02d:%02d %s %s %s %s %04d %04d %04d %04d %04d",

                    csd.hh, csd.nn, csd.ss,

                    csd.temp1, csd.temp2, csd.temp3, csd.temp4,

                    csd.dtBegn, csd.dtTemp, csd.dtDisp, csd.dtKeyp, csd.dtSDwr);

             num = logFile.println(dstr);

             Serial.print("NumWrite=");

             Serial.println(num);

             logFile.close();

             }

             else

                    errSD = true;

       if(num == 0)

             errSD = true;

//     logFile = SD.open(fname, FILE_READ);

       csd.dtSDwr = (uint16_t)millis() - tmp;

}

Если карта вставлена то при запуске все работает, за исключением «муссора» на экране. По вопросу «муссора» создал тему в Аппаратных вопросах «При работе по SPI SD карта «мусорит» дисплей ST7920_128X64. Как побороть?».

А теперь софтовая проблема №1: Если карту вынуть во время работы то программа это определяет и выводит сообщение на дисплей. Если ее повторно вставить то она не переинициализируется и не работает. Все время стоит флаг ошибки errSD = true.

Отладочная информация:

Opening port
Port open
writeLog
errSD=0
NumWrite=55
writeLog
errSD=0
NumWrite=55
/// Вынул карту
writeLog
errSD=0
/// Дальше сколько раз не вставляй/вынимай карту, она не работает
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
Port closed

Если карта вынута при запуске то при вставлении она инициализируется, но после вынимания и повторного вставления она не переинициализируется.
Opening port
Port open
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
/// Вставил карту
Init
errSD=0
ReInit
errSD=0
NumWrite=55
writeLog
errSD=0
NumWrite=55
writeLog
errSD=0
NumWrite=56
/// Вынул карту
writeLog
errSD=0
writeLog
errSD=1
/// Дальше сколько раз не вставляй/вынимай карту, она не работает
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
writeLog
errSD=1
Init
errSD=1
ReInit
errSD=1
Port closed

Как заставить карту работать нормально? Это ошибка библиотеки SD?

AmateurFF
Offline
Зарегистрирован: 02.02.2015

Второй вопрос возник по анализу записываемой в карту информации, а именно времени работы подпрограмм. 

Вот фрагмент такого файла:

Begin ---------------------------------------------------------------
12:28:25 88.0 89.3 84.7 70.6 1600 0120 0787 0000 0235
12:28:26 88.0 89.3 84.7 70.6 3600 0120 0049 0000 0179
12:28:28 88.0 89.3 84.7 70.6 5600 0120 0048 0000 0017
12:28:30 88.0 89.3 84.7 70.6 7600 0120 0048 0001 0017
12:28:32 88.0 89.3 84.7 70.6 9600 0120 0048 0000 0017
12:28:34 88.0 89.3 84.7 70.6 11600 0120 0048 0000 0017
12:28:36 88.0 89.3 84.7 70.6 13600 0120 0048 0000 0018
12:28:38 88.0 89.3 84.7 70.6 15600 0120 0048 0000 0025
12:28:40 88.0 89.3 84.7 70.6 17600 0120 0048 0000 0026
12:28:42 88.0 89.3 84.7 70.6 19600 0120 0049 0000 0176
12:28:44 88.0 89.3 84.7 70.6 21600 0120 0048 0000 0017
12:28:46 88.0 89.3 84.7 70.6 23600 0120 0048 0000 0017
12:28:48 88.0 89.3 84.7 70.6 25600 0120 0048 0000 0017
12:28:50 88.0 89.3 84.7 70.6 27600 0120 0048 0001 0017
12:28:52 88.0 89.3 84.7 70.6 29600 0120 0048 0000 0018
12:28:54 88.0 89.3 84.7 70.6 31600 0120 0048 0000 0018
12:28:56 88.0 89.3 84.7 70.6 -31936 0120 0048 0000 0018
12:28:58 88.0 89.3 84.7 70.6 -29936 0120 0049 0000 0025
12:29:00 88.0 89.3 84.7 70.6 -27936 0120 0048 0000 0020
12:29:02 88.0 89.3 84.7 70.6 -25936 0120 0048 0000 0176
12:29:04 88.0 89.3 84.7 70.6 -23936 0120 0048 0000 0017
12:29:06 88.0 89.3 84.7 70.6 -21936 0120 0048 0000 0017
12:29:08 88.0 89.3 84.7 70.6 -19936 0120 0048 0000 0018
12:29:10 88.0 89.3 84.7 70.6 -17936 0120 0048 0000 0018
12:29:12 88.0 89.3 84.7 70.6 -15936 0120 0048 0000 0018
12:29:14 88.0 89.3 84.7 70.6 -13936 0120 0049 0000 0017
12:29:16 88.0 89.3 84.7 70.6 -11936 0120 0048 0002 0017
12:29:18 88.0 89.3 84.7 70.6 -9936 0120 0048 0000 0029
12:29:20 88.0 89.3 84.7 70.6 -7936 0120 0048 0000 0174
12:29:22 88.0 89.3 84.7 70.6 -5936 0120 0048 0000 0017
12:29:24 88.0 89.3 84.7 70.6 -3936 0120 0048 0000 0018
12:29:26 88.0 89.3 84.7 70.6 -1936 0120 0048 0000 0018
12:29:28 88.0 89.3 84.7 70.6 0064 0120 0048 0000 0018
12:29:30 88.0 89.3 84.7 70.6 2064 0120 0049 0000 0017
12:29:32 88.0 89.3 84.7 70.6 4064 0120 0048 0000 0017
12:29:34 88.0 89.3 84.7 70.6 6064 0120 0048 0000 0017
12:29:36 88.0 89.3 84.7 70.6 8064 0120 0048 0000 0021
12:29:38 88.0 89.3 84.7 70.6 10064 0120 0048 0001 0181
12:29:40 88.0 89.3 84.7 70.6 12064 0120 0048 0000 0018
12:29:42 88.0 89.3 84.7 70.6 14064 0120 0048 0000 0018
12:29:44 88.0 89.3 84.7 70.6 16064 0120 0048 0000 0018

Из него видно, что вывод на LCD занимает 48-49 мс, опрос клавиатуры меньше 1 мс, а вот с записью в SD карту происходят чудеса.

Как правило строка 55-56 символов пишется 17-18 мс (последняя колонка), но периодически бывает резкое увеличение времени записи - больше 174 мс. Чем это объяснить. Как с этим бороться?

AmateurFF
Offline
Зарегистрирован: 02.02.2015

Имел ли кто опыт работы с SD? Определяется ли у вас карта при повторном вставлении? М.б. какую-то другую библиотеку надо подключить?