Просмотр полной версии : Библиотека SysLibFile
Цель: Архиватор для переменной temp. Переменная temp должна сохраняться в файле archive.log каждые 2 секунды.
Проблема: файл не открывается и не дописывается в режиме доступа append. :(
ПЛК100 Р-L
прошивка 2.03
тагет 2.02
Филоненко Владислав
08.09.2008, 16:48
Библиотека поддерживает только режимы r и w. Об этом ясно написано в документации.
Библиотека поддерживает только режимы r и w. Об этом ясно написано в документации.
Где же эта заветная документация??????!!!!!!
все что нашел syslibfile.pdf, в справочной системе тоже самое. там приведены 4 режима.
Владислав, ну поделитесь уже документацией, в которой все ясно описано :)
Филоненко Владислав
09.09.2008, 15:59
Спутал с документацией на ядро CoDeSys. Там только 2 режима. И библиотека тоже поддерживает эти 2 режима. Если есть заинтересованность в реализации режима "a", то можно это сделать.
Режим "rw"=="w", а "а" можно сделать переместив после открытия в "w" указатель в файле в конец.
1. Ограничено ли количество одновременно открытых файлов?
2. В каких случаях требуется закрывать файл?
3. Все ли остальные возможности библиотеки поддержаны?
Филоненко Владислав
10.09.2008, 21:32
1. 5 одновременно открытых файлов.
2. Закрывать надо, если надо удалить/дать доступ из другого места на запись (например через сервисы среды разработки).
3. Да: статистика, перемещение, переименование.
как избавиться от квадратиков, которыми заполняются пробелы в строках записываемых в файл?
Филоненко Владислав
22.09.2008, 20:49
??? Квадратики? Может это проблема с отображением?
Код пробела - 0х20, и если просмотрщик (например из TotalCommander) в 16-ричном режиме показывает 0х20 - всё в порядке. Если иное - пришлите исходный код и результат.
В библиотеке никаких преобразований с потоком данных не производится.
Вторая половина файла 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()
Вроде разобрался.
После каждой записанной в файл строки автоматически вставляется символ NUL(00).
Как этого избежать?
Филоненко Владислав
24.09.2008, 14:24
Работать не со строками, а с байтовым массивом. Или при передаче строк на запись размер уменьшать на 1.
Работать не со строками, а с байтовым массивом. Или при передаче строк на запись размер уменьшать на 1.
При уменьшении размера строки обрезаются последние символы. Символ 00 после нее все равно остается. :( А как поместить в байтовый массив символ перевода строки и буквы?
Филоненко Владислав
25.09.2008, 15:58
Можно Ваш проект посмотреть?
Можно Ваш проект посмотреть?
Да не вопрос :)
На всякий случай прилагаю файл, который у меня пишется в ПЛК. Как можно видеть, после любой строки принудительно записывается комбинация 00(NUL). Она то и не распознается виндой и отображается в виндовских средствах просмотра как квадратик :). Фар рулит :)
з.ы.
Скажу еще на всякий случай (может чего присоветуете :)), что предполагается 5 таких одновременно работающих модулей (архиваторов) (при 5 подключенных объектах) и шестой, включаемый пользователем при опред. условиях.
ПЛК100 Р-L
прошивка 2.03
тагет 2.02
Филоненко Владислав
26.09.2008, 20:27
Вы используете строку как источник данных и берете её размер через sizeof(). При этом sizeof() строки возвращает заданный при объявлении размер + 1 скрытый байт на завершающий ноль.
Нужно использовать либо strlen() для строк переменной длины, либо SIZEOF()-1 для константных строк.
Большое спасибо Владислав!
все получилось :)
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.
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot