Вход

Просмотр полной версии : Библиотека SysLibFile



Serp
08.09.2008, 16:25
Цель: Архиватор для переменной temp. Переменная temp должна сохраняться в файле archive.log каждые 2 секунды.

Проблема: файл не открывается и не дописывается в режиме доступа append. :(


ПЛК100 Р-L
прошивка 2.03
тагет 2.02

Филоненко Владислав
08.09.2008, 16:48
Библиотека поддерживает только режимы r и w. Об этом ясно написано в документации.

Serp
09.09.2008, 09:35
Библиотека поддерживает только режимы r и w. Об этом ясно написано в документации.

Где же эта заветная документация??????!!!!!!
все что нашел syslibfile.pdf, в справочной системе тоже самое. там приведены 4 режима.

Serp
09.09.2008, 15:37
Владислав, ну поделитесь уже документацией, в которой все ясно описано :)

Филоненко Владислав
09.09.2008, 15:59
Спутал с документацией на ядро CoDeSys. Там только 2 режима. И библиотека тоже поддерживает эти 2 режима. Если есть заинтересованность в реализации режима "a", то можно это сделать.
Режим "rw"=="w", а "а" можно сделать переместив после открытия в "w" указатель в файле в конец.

Serp
10.09.2008, 16:31
1. Ограничено ли количество одновременно открытых файлов?
2. В каких случаях требуется закрывать файл?
3. Все ли остальные возможности библиотеки поддержаны?

Филоненко Владислав
10.09.2008, 21:32
1. 5 одновременно открытых файлов.
2. Закрывать надо, если надо удалить/дать доступ из другого места на запись (например через сервисы среды разработки).
3. Да: статистика, перемещение, переименование.

Serp
22.09.2008, 16:39
как избавиться от квадратиков, которыми заполняются пробелы в строках записываемых в файл?

Филоненко Владислав
22.09.2008, 20:49
??? Квадратики? Может это проблема с отображением?
Код пробела - 0х20, и если просмотрщик (например из TotalCommander) в 16-ричном режиме показывает 0х20 - всё в порядке. Если иное - пришлите исходный код и результат.
В библиотеке никаких преобразований с потоком данных не производится.

Serp
23.09.2008, 13:24
Вторая половина файла archive.log создана текущим проектом, а первая тем же проектом, но с не ограниченными по размеру строковыми переменными (половины между словом "температура", это хорошо видно в wordpad):
stTemp: STRING(5);
stParam: STRING(2) := 'T=';
PerevodStr: STRING(1) := '$0A';

1.Вопрос про квадратики :)
2.Не получилось записать в файл переменную типа флоат, возможно ли это?
3.Пришлось написать функцию realformat, ограничивающую количество знаков после запятой, есть ли в кодесис такая встроенная?

Филоненко Владислав
23.09.2008, 16:52
1. Квадратиков не обнаружил :)
2. Если надо бинарное отображение - просто копируете 4 байта из ADR(REAL) в файл.
3. Стандартная библиотека CoDeSys ограничена в возможностях форматирования. Обычно приходится делать решение под себя.

Сергей71
24.09.2008, 08:44
3.Пришлось написать функцию realformat, ограничивающую количество знаков после запятой, есть ли в кодесис такая встроенная?

см. бибиотеку oscаt функция round()

Serp
24.09.2008, 13:13
Вроде разобрался.
После каждой записанной в файл строки автоматически вставляется символ NUL(00).

Как этого избежать?

Филоненко Владислав
24.09.2008, 14:24
Работать не со строками, а с байтовым массивом. Или при передаче строк на запись размер уменьшать на 1.

Serp
25.09.2008, 13:25
Работать не со строками, а с байтовым массивом. Или при передаче строк на запись размер уменьшать на 1.

При уменьшении размера строки обрезаются последние символы. Символ 00 после нее все равно остается. :( А как поместить в байтовый массив символ перевода строки и буквы?

Филоненко Владислав
25.09.2008, 15:58
Можно Ваш проект посмотреть?

Serp
26.09.2008, 09:06
Можно Ваш проект посмотреть?

Да не вопрос :)

На всякий случай прилагаю файл, который у меня пишется в ПЛК. Как можно видеть, после любой строки принудительно записывается комбинация 00(NUL). Она то и не распознается виндой и отображается в виндовских средствах просмотра как квадратик :). Фар рулит :)

з.ы.
Скажу еще на всякий случай (может чего присоветуете :)), что предполагается 5 таких одновременно работающих модулей (архиваторов) (при 5 подключенных объектах) и шестой, включаемый пользователем при опред. условиях.

ПЛК100 Р-L
прошивка 2.03
тагет 2.02

Филоненко Владислав
26.09.2008, 20:27
Вы используете строку как источник данных и берете её размер через sizeof(). При этом sizeof() строки возвращает заданный при объявлении размер + 1 скрытый байт на завершающий ноль.
Нужно использовать либо strlen() для строк переменной длины, либо SIZEOF()-1 для константных строк.

Serp
27.09.2008, 13:43
Большое спасибо Владислав!
все получилось :)

Gerkules
09.06.2009, 15:03
Здравствуйте! сколько ни бьюсь не могу разобраться с библиотекой SysLibFile. скачал проект "test_syslibfile2.rar" и немного изменил программу, всёравно ничего не получается- создаётся пустой файл archive.log и всё. может ктонибудь подсказать что в нём не так???

Gerkules
09.06.2009, 16:15
или мне достаточно будет узнать как можно записывать в архив периодически (ну скажем через секунду) строковую переменную 'slovo'. в данной программе оно записывается только 1 раз. если кто поможет то буду очень благодарен!!!

PROGRAM PLC_PRG
VAR
x:STRING; (*строка для архивирования*)
number: DWORD; (*дескриптор файла*)
dipos: DINT; (*текущая позиция в файле*)
dwSize: DWORD; (*количество записанных байт данных*)
dwSize1: DWORD; (*размер файла*)
END_VAR

(*открываем файл*)
number:=SysFileOpen('arc.log', 'w');
(*создаём строку*)
x:='slovo';
(*Пишем строку в файл*)
dwSize:=SysFileWrite(number,ADR(x),LEN(x));
(*получаем текущую позицию в файле*)
dipos:=SysFileGetPos(number);
(*получаем размер файла в байтах*)
dwSize1:=SysFileGetSize('arc.log');

Филоненко Владислав
09.06.2009, 21:57
см. другой пост. зачем их дублировать?

Gerkules
12.06.2009, 07:16
прошу прощения, думал одно из сообщение не отправилось. скорость интеренета на работе оставляет желать лучшего)

Ollegator
25.11.2009, 14:09
Здравствуйте.
У меня вопрос. Попытался воспользоваться функцией SysFileGetSize
Она работает некорректно, на файл размером в 18 кБ, возвращается непонятное число - 9 с лишнем миллионов.
Нужно вот для чего, у меня ведется архивация с помощью модуля Archiver, на вашем форуме я прочитал, что размер архива не может превышать 32 кБ, практика показала, что это правда (почему -то не указанная в документации). Нужно внести такие изменения в программу, чтобы она проверяла размер архива, и, в случае превышения его размера, скажем, 30 кБ, копировала его в новый файл.
Функция SysFileCopy, кстати, то же работает у меня не корректно, новый файл создается, но он пустой.
Как быть?

Филоненко Владислав
25.11.2009, 17:19
1. Опишите что за ПЛК
2. "неработающий" код в студию.
3. Архиватор - не абсолютное решение, а предназначен для простых задач. Если его функционала не хватает - Вы можете сами написать его улучшенный аналог использую библиотеку SysLibFile.lib

Ollegator
25.11.2009, 17:33
Выложу написанный мной текст программы, который сейчас не работает как надо

PROGRAM Archive
VAR
FileSize: DWORD;
filename: STRING [40];
Files_Name_Array: Files_Name;
fAD,fSize, fileadr: DWORD;
END_VAR
VAR RETAIN
Flag:BOOL;
END_VAR

TYPE Files_Name :
STRUCT
File_Name_Array: ARRAY[1..50] OF STRING[40];
NFile: BYTE;
END_STRUCT
END_TYPE


FileSize:=SysFileGetSize('tenzo_reg.log'); (*Определение размера файла регистратора *)

IF FileSize> 30000 AND (NOT Flag) THEN (*Если размер файла превысел 30 Кбайт, то сохраняем данные в новом файле *)

filename:=CONCAT('reg' , '_');
filename:=CONCAT(filename ,INT_TO_STRING(DT_NOW[3]));
filename:=CONCAT(filename , '_');
filename:=CONCAT(filename ,INT_TO_STRING(DT_NOW[2]));
filename:=CONCAT(filename , '_');
filename:=CONCAT(filename ,INT_TO_STRING(DT_NOW[1]));
filename:=CONCAT(filename , '_');
filename:=CONCAT(filename ,INT_TO_STRING(DT_NOW[4]));
filename:=CONCAT(filename , '_');
filename:=CONCAT(filename ,INT_TO_STRING(DT_NOW[5]));
filename:=CONCAT(filename , '.log');

SysFileCopy(filename,'tenzo_reg.log');

Flag:=TRUE;

fAD:=ADR(Files_Name_Array);
fSize:=SIZEOF(Files_Name_Array);
fileadr:=SysFileOpen('Nfile.txt','r');
SysFileRead(fileadr,fAD,fSize); (*Считываем данные об уже записанных фалах*)
SysFileClose(fileadr);

IF Files_Name_Array.NFile < 50 THEN
Files_Name_Array.NFile:=Files_Name_Array.NFile+1;
ELSE Files_Name_Array.NFile:=1;
END_IF;

SysFileDelete(Files_Name_Array.File_Name_Array[Files_Name_Array.NFile]); (*удаляем старый файл*)

Files_Name_Array.File_Name_Array[Files_Name_Array.NFile]:=filename; (*Записываем в массиы имя нового файла*)

fAD:=ADR(Files_Name_Array);
fSize:=SIZEOF(Files_Name_Array);
fileadr:=SysFileOpen('Nfile.txt','w');
SysFileWrite(fileadr,fAD,fSize); (*Записываем в файл данные об имеющихся файлах регистратора*)

ELSE Flag:=FALSE;
END_IF;


В файле tenso_reg.log ведется архив через модуль Archiver в режиме Shift mode. Нужно его периодически копировать в новый файл.

По факту происходит следующее. FileSize принимает то невероятно большие значения, то становится равным 0, в результате у меня в ПЛК создается куча файлов (за полчаса работы штук 20), все пустые.
Что я делаю неправильно?

ПЛК 150 IM

Ollegator
25.11.2009, 17:46
Эта программа у меня вызывается после каждого сделанного цикла грузоподъемного крана, параметры этого цикла нужно регистрировать, в файле tenzo_reg.log сохраняется информация о 150 - 200 последних циклах, этого недостаточно. Полностью переписывать принцип регистрации, используя SysLibFile неохота, да и время поджимает.

Филоненко Владислав
26.11.2009, 00:41
пришлите весь проект, я его протестирую.
какой у вас плк, версии прошивок, логи загрузки пришлите.

Ollegator
26.11.2009, 12:58
хорошо, сейчас выложу, однако, чтобы протестировать проект, нужно подавать сигналы от датчиков на аналоговые входы плк, у меня для этого стоит другой плк , который имитирует эти сигналы по нужному алгаритму. кроме того, многие уставки вводятся с панели оператора.

Ollegator
26.11.2009, 14:18
плк 150 Im
прошивка 10.5.0

используются все аналоговые входы, на первый и третий подается сигнал с датчика усилия основного подъема (они соединены последовательно, посчитали, что так входы будут работать быстрее), на второй с датчика усилия вспомогательного подъема, на четвертый, с датчика вылета стрелы.

цикл в программе начинается, когда усилие на датчике превышает определенное значение (5 т для основного подъема в этой программе) и регистрируется, если его длительность превышает 15 с.
конец цикла определяется, когда сигнал с датчика становится меньше определенного значения.

я еще прикрепил файл уставок, который надо записать на плк, чтобы не вводить с панели.

вообще, проект не мой, многое в нем мне самому не нравится, но мне его править.

Филоненко Владислав
26.11.2009, 16:11
1. Абсолютно неправильно работает вся система управления архиватором.
Например код
ST_T:=254;
...
ST_T:=255;

выполнятся правильно не будет, т.к. архиватор получает команду только после завершения цикла ПЛК, а любые манипуляции в ходе цикла игнорируются (это ключевая особенность ПЛК как класса).
В результате каждый цикл файл пишется и доступ к файлу, естественно, оказывается заблокированным, т.к. этот файл занят.

Далее:

Одновременно с попыткой управления архиватором происходит еще множественный доступ к файлам

REGISTRATOR_TENZO(....);

WRITE_RETAIN;

Archive;

Эти операции необходимо разнести по времени.

В программе Archive
происходит также одновременный множественный доступ к файловой системе. Этот участок тоже надо разбить на отдельно исполняемые части.
В программе PLC_PRG больша часть событий обрабатывается тоже в 1 цикле - это неправильно.

Ollegator
26.11.2009, 20:07
Спасибо Владислав.
У вас есть простенький пример работы с архиватором по команде?
Что мне необходимо сделать, чтобы добавить очередную запись в файл по событию?
Как я понял, нужно придать соответствующие значения архивируемым переменным, после чего придать переменной Status значение 255 (ST_T:=255 в моей программе), так? И команду "стоп" (ST_T:=254) нужно будет подать в следующем цикле работы ПЛК. Я понял правильно?



Одновременно с попыткой управления архиватором происходит еще множественный доступ к файлам

REGISTRATOR_TENZO(....);

WRITE_RETAIN;

Archive;

Эти операции необходимо разнести по времени.


Ну программа REGISTRATOR_TENZO(....); у меня как раз и управляет архиватором.

WRITE_RETAIN пришлось делать по причине не сохранения ретэйн переменных при перезагрузке. Собственно, если я буду ее вызывать из Task Configuration по событию befor reset, этого будет достаточно, так?

Разнести операции записи в файл нужно по реальному времени, или достаточно будет выполнять их в разных циклах работы ПЛК?



В программе PLC_PRG больша часть событий обрабатывается тоже в 1 цикле - это неправильно.


Если я сделаю основную программу на SFC, разнеся события по разным шагам, то это будет правильно?

Заранее благодарен.

Ollegator
09.12.2009, 13:35
Еще раз здравствуйте.
Все переделал, вроде получилось. Модуль архив - штука не жизнеспособная, была выкинута, сделал через SysLibFile.
Встал вопрос, что делать с переполнением регистратора. Как из файла удалять часть более ранних записей, продолжая добавлять в конец новые данные? Как реализовать "shift mode" средствами SysLibFile?

Филоненко Владислав
09.12.2009, 14:15
очень просто. читаете последнюю половину файла в буфер, создаете новый файл, записываете буфер (не забудьте заголовок добавить к нему), удаляете старый файл, переименовываете.
лучше делить файл не побайтно, а по строкам.

Ollegator
09.12.2009, 18:49
Ага. Буфер должен быть строковой переменной так? я собираюсь удалять треть файла после записи 6000 строк, максимальная длина строки - 100 символов, размер файла тогда может доходить до 600 кБ (100*6000). CoDeSys будет нормально работать со строкой длиной 400 000 ? Или со строковым массивом 4000 Х 100? Или следует считывать и записывать файл построчно? В таком случае, сколько времени это может занять?

Филоненко Владислав
10.12.2009, 11:20
Buffer:Array [0..1024] of byte;
Строки можно делать любой длинны, но работать с ними с помощью строковых функций - только до размера 256 байт.

SergeyNG
23.03.2010, 12:30
Хочу прояснить для себя следующее, т.к. на форуме всё разбросано по разным темам.
Ситуация. Ratain сбрасываются при Reset Original контроллера. Поэтому для комфортной отладки и дальнейшей эксплуатации сохраняю уставки работы системы в файл. Т.е. при изменнении уставок выполняю перезапись данных в файл с заданным именем, а при начале работы программы восстанавливаю из файла. Какая последовательность действий при записи данных в файл верная:

- открыть файл на запись
- записать файл
- закрыть файл

или

- удалить файл
- открыть файл на запись
- записать файл
- закрыть файл

Конкретно интересует в первом случае ФС трёт данные по одному и тому же месту диска или каждый раз использует разные места?
На какой ресурс количества записей можно расчитывать в том и другом случае?
Размер файла укладывается в один блок.

Филоненко Владислав
23.03.2010, 13:34
ресурс одноблоковых записей (первый блок==448 байт!) 300000000 записей.
если размер данных не меняется или только увеличивается - вариант 1 подходит.
если уменьшается - вариант 2.