Потеря данных СОМ порта

Subscriber
Offline
Зарегистрирован: 31.08.2014

Доброго времени суток!

Есть задача чтения потока данных, поступающих из СОМ-порта.

Данные сохраняются в файлы размером не более 1 МБ. При этом, чтобы имена файлов не повторялись, при формировании их имени осуществляется привязка к внутреннему времени, формируемому платой с микросхемой DS1302.

Имя файла ММДДЧЧММ.dat (месяц-дата-часы-минуты).

Программа нормально компилируется. Файлы с данными пишутся.

Но это прелюдия.

Основная проблема состоит в том, что при чтении потока происходит потеря байт.

Дело в том, что в поток внедрены метки, повторяющиеся через 6 байт (6 байт - длина кадра, информационной последовательности). По ним можно отследить пропуски кадров.

Я вижу, что записываются 16-17 кадров (96-112 байт), потом идет пропуск до 32-34 кадров (192-204 байт).

Потом данные опять записываются. Потом опять пропуск.

Кодприведен ниже:

#include <WProgram.h>
#include <Wire.h>
#include <SD.h>
#include <stdio.h>
#include <DS1302.h>

const int chipSelect = 4; // On the Ethernet Shield, CS is pin 4
long volume=0; // Размер файла с данными
boolean flag = true; // Разрешение формирования нового имени файла
int incomingByte = 0;   // переменная для хранения байта данных, 
                        //принятых по последовательному интерфейсу
File dataFile;
char * szNewFileName;
char data[100];
char massive[100];
int i=0;
//Исходные данные времени для имени файла  
String HR;    //Часы
String MIN;   //Минуты
String DATE;  //День (число)
String MTH;   //Месяц

// Предустановка микросхемы DS1302 chip
// Init the DS1302 (2->5, 3->6, 4->7)
DS1302 rtc(5, 6, 7);

// Init a Time-data structure
Time t;

void setup() {
 
  Serial.begin(9600);     // открываем последовательный порт
                                // задаем скорость передачи данных 9600 бод
 
  Serial.print("Initializing SD card..."); // ВЫВОД ИНФОРМАЦИИ ОБ ИНИЦИАЛИЗАЦИИ КАРТЫ ПАМЯТИ
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:

  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) 
  {
   Serial.println("Card failed, or not present"); // ВЫВОД ИНФОРМАЦИИ ОБ ИНИЦИАЛИЗАЦИИ КАРТЫ ПАМЯТИ
    // don't do anything more:
    return;
  }
  Serial.println("card initialized."); // ВЫВОД ИНФОРМАЦИИ ОБ ИНИЦИАЛИЗАЦИИ КАРТЫ ПАМЯТИ
  
}
 
void loop() {

  if (flag==true)
{
// Get data from the DS1302
  t = rtc.getTime();
  
//ФОРМИРУЕМ ИМЯ ФАЙЛА  
if (t.min < 10)
MIN = "0" + String(t.min, DEC);
else
MIN = String(t.min, DEC);

if (t.hour < 10)
HR = "0" + String(t.hour, DEC);
else
HR = String(t.hour, DEC);

if (t.date < 10)
DATE = "0" + String(t.date, DEC);
else
DATE = String(t.date, DEC);

if (t.mon < 10)
MTH = "0" + String(t.mon, DEC);
else
MTH = String(t.mon, DEC);

String stroke = MTH+DATE+HR+MIN+".wg";

char charVar[12];
stroke.toCharArray(charVar, 12);
char new_data[12];
strcpy(new_data,charVar);
szNewFileName = new_data;

flag=false; 
}  
// отправляем данные только после их получения:
if (Serial.available() > 0) 
{
dataFile = SD.open(szNewFileName, FILE_WRITE);
volume = dataFile.size();
 if (volume<1000000) 
{
  // считываем принятый байт:
Serial.readBytes((char*)data,100);
//Записываем данные в файл
dataFile.write(data,sizeof(data));
}
else
{flag=true;}
dataFile.close();
}
}  

Использую Arduino UNO. Скорость входного потока - 9600 кб/с.

Подключал источник данных к компу, там проблем нет.

Не могу понять: то ли идет переполнение буфера, то ли нужно выставлять правильно таймеры.

Может кто подскажет: это затык по железу (что, на мой взгляд, маловероятно) либо корявый код?

P.S.: Размер буфера варьировал. Не помогло.

Radjah
Offline
Зарегистрирован: 06.08.2014

С какой частотой твои "кадры" идут. Чую, что ардуина тупо не успевает всё записать.

Попробуй вместо if (Serial.available() > 0) сделать while, чтобы выбрать все данные из порта и не тягать лишний раз код по формированию имени файла.