Ви використовуєте застарілий браузер. Цей та інші сайти можуть відображатися в ньому некоректно. Необхідно оновити браузер або спробувати використовувати https://www.google.com/chrome/
и все же реальный реалтайм только в реальных RTOS, тобишь QNX, VxWorkx и т.д.
красота qnx заключается в том, что ты вообще можешь собрать систему впринципе без планировщика задач, только одну твою прогу (ну с дровами конечно), которая будет работать в максимальном приоритете. тогда правда не будет многозадачности как таковой. в любом случае qnx дает гарантированный отклик, будь то 1мс, или 500нс... счет идет на наносекунды. при условии что можно задействовать Adaptive Partition, который позволяет гарантированно отдавать заданное %-е время процессора/памяти и прочих ресурсов конкретной программе, про работе в многозадачном режиме. ничего сложного в qnx нет, тем более если есть опыт написания под лины. впрочем достаточно знать с++, сокеты, ну и как работать с gcc. единственный минус, что qnx не бесплатна, и в конце концов на готовый продукт придётся покупать лицензию. хотя базовая лицензия на самый минимум порядка 50-7- баксов, что не так уж много.
Пардон. Мой первый вариант не катит. Написал, потестил (самому интересно стало).
Даже привязанный к одному ядру поток TIME_CRITICAL в процессе REALTIME_CLASS_PRIORITY проскакивает интервалы в 1 мс.
И ваще, с виндой дело плохо. ((
PS: Спс BFG-9000, напомнил про Affinity (привязку к ядру).
у меня получилось сделать псевдореальайм под винды в аналогичной задаче, только у меня карт ввода/вывода 3 и комп чистый двухпроцессорный был. Причем делалось это в Делфи, ибо для всех карт под него были библиотеки. Делалось это на таймере, в основе которого был счетчик циклов проца (таймер не мой, сторонний номпонент). Точность времени квантования 1 мс плюс/минус 50 мкс. Вышибается только потоковыми файловыми операциями, а если комп не трогать, вообще работает идеально. На однопроцессорной машине не работало, была та же проблема - пропускал такты
Всем привет)
Наконец-то я добрался до работающего приложения))
Защита магистрерской младшего брата на подходе и пора было закончить эти пляски с бубном)
Итак что получилось:
1.Первоначальные требования по производительности оказались значительно завышены.
2.Целевой алгоритм оказался детерминированным- Т.е он работает независимо от предидущего состояния системы, пропуск отсчетов между блоками по 20 точек совершенно не критичен)
3.Основной модуль--консольное приложение. модуль конфигурации - диалоговое окно . связь по PIPE.
Не судите строго быдлокод — очень спешил..))
Идея с половинками буфера нагло скопипизжена из документации для работы с платой L-Card L783M
Сбор данных идет в отдельном потоке.
Настройки АЦП :
частота дискретизации 400кГц.
считывается блоками по 7 значений(7 каналов ввода.)
интервал между считывания блоков 1 мс.
после считывания 20 блоков--происходит запуск обработчика данных через флаг. С++ код
PHP:
ULONG WINAPI ServiceThread(PVOID /*Context*/)
{
ULONG halfbuffer = IrqStep*pages/2; // Собираем половинками кольцевого буфера
ULONG fl2,fl1 = fl2 = (*sync<=halfbuffer)? 0:1; // Настроили флаги
short *tmp1;
//Процедура копирования половинок бушера в рабочий массив
while(1)
{
while(fl2==fl1) fl2=(*sync<=halfbuffer)? 0:1; // Ждем заполнения половинки буфера
//tmp=fdata+(halfbuffer*i); // Настраиваем указатель в файле
tmp1=data+(halfbuffer*fl1); // Настраиваем указатель в кольцевом буфере
memcpy(data1,tmp1,halfbuffer*sizeof(USHORT));// Записываем данные в файл
fl1=(*sync<=halfbuffer)? 0:1; // Обновляем флаг
HalfBuffer=true;
Sleep(10);
}
complete=1;
// Мы завершили сбор данных
return 0;// Вышли (надо реализовать выход по команде с пользовательской консоли)
}
В фокусе приложение конфигурирования, на заднем сам процесс сбора данных и расчетов.
В main() кроме потока сбора данные запускается 3 потока связи с внешним миром:
PHP:
//Запускаем поток чтения конфигурации
// защиты в пользовательскую консоль
hThread_config_read=CreateThread(0,0x2000,ThreadWaitConfigReadConnect,0,0,&Tid2);
//cout<<"pipe test write"<<endl;
//Запускаем поток записи конфигурации защиты из пользовательской консоли
hThread_config_write=CreateThread(0,0x2000,ThreadWaitConfigWriteConnect,0,0,&Tid2);
//Запускаем поток данных для пользовательской консоли и OPC сервера
hThread_data=CreateThread(0,0x2000,ThreadWaitDataConnect,0,0,&Tid2);
Пример одного из сторожевых потоков для PIPE
PHP:
DWORD WINAPI ThreadWaitDataConnect(LPVOID nParam)
{ float nData[8];
DWORD dwBytesRead;
hNamedPipe_data = CreateNamedPipe ( "\\\\.\\pipe\\pipe_data",PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_WAIT,
10, // максимальное количество экземпляров канала
0, // размер выходного буфера по умолчанию
0, // размер входного буфера по умолчанию
INFINITE, // клиент ждет связь бесконечно долго
NULL // защита по умолчанию
);
/////////////////////////////
if (hNamedPipe_data == INVALID_HANDLE_VALUE)
{
cout<<"NVALID_HANDLE_VALUE"<<endl;
}
///////////////////////////
while(1)
{
if(!ConnectNamedPipe( hNamedPipe_data, NULL ))
{
//cout<<"error"<<endl;
}
//...................................................................
///
//Заполняем nData
///
//...................................................................
if(WriteFile(hNamedPipe_data, &nData,sizeof(nData),&dwBytesRead,NULL))
{
//cout<<"read ok"<<endl;
}
DisconnectNamedPipe(hNamedPipe_data);
FlagConnect_data=FALSE;
}
return 0;
}
Поток основного расчетного алгоритма:
PHP:
DWORD WINAPI ThreadMainAlgoritm(LPVOID nParam)
{
while(1)
{
if(HalfBuffer==true)
{
//Выполняется заполнение массивов и преобразование из кода АЦП в вольты(float)
for(int i=0;i<=19;i++)
{
Ia1[i]=5.0*data[i*7]/2000.0;
Ib1[i]=5.0*data[i*7+1]/2000.0;
Ic1[i]=5.0*data[i*7+2]/2000.0;
Ua1[i]=5.0*data[i*7+3]/2000.0;
Ub1[i]=5.0*data[i*7+4]/2000.0;
Uc1[i]=5.0*data[i*7+5]/2000.0;
F[i]=10*data[i*7+6]/2000.0;
//cout<<Ia1[i]<<endl;
}
//попробуем вызвать основную функцию расчета температуры ротора...
F4();
HalfBuffer=false;
}
}
return 0;
}
Оболочка пользователя интереса совершенно не представляет --там стандартная работа с MFC.
BFG-9000, Sefiroth огромное спасибо за информацию, пригодится в других проектах)
кстати та задача которая мной решалась , в свете новых требований по производительности прекрасно заработает на ATmega 8))
Там в расчетной функции F4() только фильтр Фурье для расчета действующих значений токов и напряжений и функция с чисто алгебраическими вычислениями для расчета температуры ротора.
Кому интересно, могу расказать как написать СВОЙ!! OPC сервер)