Форум программистов, компьютерный форум, киберфорум
Arduino
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23

Потеря байт при записи данных из СОМ порта на SD карту

27.03.2015, 09:08. Показов 3766. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Есть задача прочитать поток данных, поступающих из СОМ-порта.
Данные сохраняются в файлы размером не более 1 МБ. При этом, чтобы имена файлов не повторялись, при формировании их имени осуществляется привязка к внутреннему времени, формируемому платой с микросхемой DS1302.
Имя файла ММДДЧЧММ.dat (месяц-дата-часы-минуты).
Программа нормально компилируется. Файлы с данными пишутся.

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

Я вижу, что записываются 16-17 кадров (96-102 байт), потом идет пропуск до 32-34 кадров (150-160 байт).
Потом данные опять записываются. Потом опять пропуск.
Код скетча приведен ниже:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#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();
}
}
Подключал источник данных к компу, там проблем нет.
Не могу понять: то ли идет переполнение буфера, то ли нужно выставлять правильно таймеры.

P.S.: Размер буфера варьировал. Не помогло.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.03.2015, 09:08
Ответы с готовыми решениями:

Поиск последовательности байт в массиве, приходящем из СОМ-порта
Ещё раз здравствуйте. Из последовательного порта приходит несколько ненужных байт каждые 2-3 секунды, затем в определённое время следует...

Преобразование последовательности из 4 байт в вещественное число при считывании данных с COM порта
Добрый день, уважаемые форумчане! При считывании данных c COM-порта я получаю массив из 9 байт: 0х10, 0х04, 0х04, 0хAC, 0x09, 0x42,...

График данных СОМ-порта
Доброго времени суток! Подниму еще раз избитую тему, но не могу найти подробный материал (желательно с исходниками). Переделал под...

14
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
27.03.2015, 11:43
Лучший ответ Сообщение было отмечено raxp как решение

Решение

Цитата Сообщение от New_Subscriber Посмотреть сообщение
считываем принятый байт Serial.readBytes((char*)data,100);
это больше похоже на 100 байт
Цитата Сообщение от New_Subscriber Посмотреть сообщение
dataFile.write(data,sizeof(data));
пишите в файл блок данных размером в количество полученных байт, а не размером в буфер - буфер мог быть и не заполнен
0
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23
27.03.2015, 14:46  [ТС]
vxg
У меня ж вроде стоит

Code
1
2
//Записываем данные в файл
dataFile.write(data,sizeof(data));
По идее он должен записывать фактически принятое количество байт.
Или я что-то недопонимаю?
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
27.03.2015, 16:53
Цитата Сообщение от New_Subscriber Посмотреть сообщение
Или я что-то недопонимаю?
sizeof(data) вернет размер буфера (всегда одно и то же число 100), а вот dataFile.write(...) возвращает сколько байт фактически прочиталось в буфер
1
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23
28.03.2015, 09:49  [ТС]
vxg
Большое спасибо за подсказку.
Увеличил объем массива со 100 до 256
Code
1
byte data[256];
Проблема вроде ушла
P.S.: Тип данных изменил, т.к. принимаю численные значения. Хотя, как понял, конкретно для моей задачи это не критично.
0
 Аватар для dimape
0 / 0 / 0
Регистрация: 29.03.2015
Сообщений: 7
29.03.2015, 16:42
я всегда когда пишу, делаю массив побольше, чтобы таких проблем не возникало)
0
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23
29.03.2015, 21:33  [ТС]
dimape
Я уже сталкивался с подобной проблемой ранее, когда делал аналогичную прогу в MFC.
Просто давно это было, вот и забыл
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
30.03.2015, 09:20
Цитата Сообщение от New_Subscriber Посмотреть сообщение
Проблема вроде ушла
проблема уйдет когда будет написано
C++
1
dataFile.write(data,Serial.readBytes((char*)data,sizeof(data)));
однако помните что некоторые пакеты может разорвать (разнести куски в разные файлы)
1
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23
30.03.2015, 14:23  [ТС]
vxg
ОК, спасибо.
Потеря 1-2 пакетов не смертельна.
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
30.03.2015, 14:24
Цитата Сообщение от vxg Посмотреть сообщение
проблема уйдет когда будет написано
Код C++
1
dataFile.write(data,Serial.readBytes((ch ar*)data,sizeof(data)));
да ну никуда не уйдет проблема, ну что вы . Для безопасной трансляции данных между двумя очередями нужно использовать FIFO-буфер, и не факт что только один. Все операции копирования и записи тоже занимают время, соответственно, должны выполняться асинхронно. А раз асинхронно - значит со своими собственными буферами данных.
У вас UART имеет свой собственный RX FIFO, который получает данные от приемника и отдает их функцией readBytes. Но! Что в момент вызова readBytes скопирует данные в некий буфер (в вашем варианте это вообще не сработает), а затем отдаст этот буфер на выполнение функции записи. Пока происходит запись, система UART'а должна иметь возможность принимать данные в уже освобожденный буфер, свой. Иначе произойдут коллизии.
0
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23
30.03.2015, 21:12  [ТС]
И как тогда выкрутиться?
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
31.03.2015, 09:20
Цитата Сообщение от Voland_ Посмотреть сообщение
да ну никуда не уйдет проблема, ну что вы
...и тут произошел краткий экскурс в строение вселенной...
проблема уйдет. поверьте. вызов Serial.readBytes скопирует байты в количестве меньшем или равном sizeof(data) из того самого первого страшного места о котором вы говорите в буфер, а вызов dataFile.write скопирует полученные байты из буфера в то самое второе страшное место о котором вы говорите. и пусть они там себе живут. я свечку не держал, но с вероятностью 100% могу утверждать что во время вызовов Serial.readBytes и dataFile.write никаких движений в тех самых страшных местах не происходит ибо это разрушит целостность данных и вообще помножит на ноль саму суть вызовов этих функций. как вариант - пока выполняются вызовы данные накапливаются в тех самых страшных местах, если будет переполнение вызов просто вернет ошибку или просто вышвырнет "лишние" данные - это зависит от реализации
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
31.03.2015, 09:39
я с ардуино не работал, могу дать только общие рекомендации.
1) Можно пытаться увеличить буфер RX для UART'а.
2) Возможно, не успевает контроллер. Увеличить частоту, если это возможно.
3) Проверить SD-карту. Поверьте, не все карты одинаково быстро пишут. Форматировать карту с увеличенным размером кластера.
4) Написать код на сях. Будет намного оптимальнее, т.к. тогда писать в файл можно будет напрямую, без промежуточных операций, которые в данной задаче только отнимают время.

Добавлено через 18 минут
Цитата Сообщение от vxg Посмотреть сообщение
...и тут произошел краткий экскурс в строение вселенной...
ах ну все правильно вы говорите. Виноват.
Теперь главное чтобы все это успевало крутиться.
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
31.03.2015, 11:54
Цитата Сообщение от Voland_ Посмотреть сообщение
Теперь главное чтобы все это успевало крутиться.
согласен - если мы захотим пропихнуть непропихуемое за наносекунду, то будут проблемы и на стороне COM и на стороне SD. я думаю ошибка ТС была в неверном указании размеров записываемых данных ибо они реально неверные
0
0 / 0 / 0
Регистрация: 27.05.2013
Сообщений: 23
31.03.2015, 13:13  [ТС]
Проверил первые записанные файлы (писали с три дня).
Потерь вроде нет (даже при переходе из файла в файл).
Похоже, что, действительно, увеличение размера массива данных data помогло
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.03.2015, 13:13
Помогаю со студенческими работами здесь

Прием данных с СОМ-порта
В общем надо мне написать программу для передачи и приема хотя бы текста через последовательный порт. Нашел пару исходников программ в...

Распознавание данных из СОМ-порта
Хелпаните с лабой комрады. Собственно само задание: составить программу считывания данных из СОМ-порта, генерируемых манипулятором Мышь....

Чтение и обработка данных из СОМ порта
Добрый день! Есть программа для работы с внешним устройством через СОМ порт. Данные у меня она отправляет на ура, а вот с чтением у меня...

Потеря данных при многопоточной записи в файл
Приветствую. Есть программа, которая одновременно из нескольких потоков пишет данные в один файл. В каждом потоке есть метод, с помощью...

Драйвер чтения данных из СОМ-порта(Ассемблер)
Доброго времени суток,может завалялся у кого драйвер DOS на ассемблере под COM-порт(без разницы на какой,очень нужна простейшая основа...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru