unit DeviceRD; interface uses D2xxUnit, SysUtils, dialogs, Windows, math; //пользовательские типы type bit_array_8 = array[0..7] of byte; //массив из 8 чисел. Используется для байта bit_Array_32 = array[0..31] of byte; //массив из 32 чисел. Используется для 32-битного числа message_Array = array[0..24002] of integer; //массив посылки TMatrix = array [0..4,0..4] of extended; //тип массива //для матрицы 5 на 5 TMes_array = array [0..4] of message_Array; Tbool = array of boolean; TCol = array [0..4] of extended; params_record = record //запись для результатов разбора R:extended; C:extended; g0:extended; g1:extended; g2:extended; g3:extended; U_izm: array [0..2400] of extended; I_izm: array [0..2400] of extended; end; //непосредственно класс устройства type TDevice = class (TObject) private connected :boolean; //существует ли связь с прибором. port_opened :boolean; //открыт ли порт прибора device_name :string; //Название прибора device_serial_no:string; //Серийный номер прибора device_desc :string; //Описание прибора const version = '0.1.4'; //function to_binary(x:integer): bit_array_32; //переводит целое число<256 в двоичное //function add_to_32_binary(x:bit_array_32; start_pos,count:integer; ar:bit_array_32):bit_array_32; //записывает байт в 32-битное число начиная с start_pos //function to_decimal(x:bit_Array_32):extended; //переводит двоичное число в десятичное function Determinant(FirstRow : Integer; Matrica:TMatrix; k:integer; ac:Tbool): extended; function copy_col(Al:TMatrix; Bl:TCol; coll:integer):TMatrix; function det5(A:TMatrix):extended; public message_ : message_Array; got_message : boolean; constructor Create(); destructor Destroy(); function IsConnected:boolean; function IsPortOpened:boolean; function Show_device_name:string; function Show_device_serial_no:string; function Show_device_desc:string; function message_decode(massiv:message_Array):params_record; function Start_waiting(mode:integer):message_Array; // procedure receive; procedure Check_device; procedure Open_device; protected { protected declarations } end; implementation uses device_thread, MainUnit; constructor TDevice.Create; var device_index,i:integer; begin GetFTDeviceCount; FT_Enable_Error_Report := true; connected:=false; Device_Index := 0; //предполагается что устройств всегда будет только одно If FT_Device_Count > 0 then For i:= 1 to FT_Device_Count do Begin GetFTDeviceSerialNo(Device_Index); device_serial_no:=FT_Device_String; GetFTDeviceDescription ( Device_Index ); device_desc:=FT_Device_String; Device_Index := Device_Index + 1; connected:=true; End; end; destructor TDevice.Destroy; begin If port_opened then begin Set_USB_Device_BitMode($ff,0); Purge_USB_Device_In; Purge_USB_Device_Out; Close_USB_Device; end; end; Procedure Tdevice.Check_device; Var PortStatus : FT_Result; device_index,i :integer; begin FT_Enable_Error_Report := true; If Not Connected then Begin Close_USB_Device; // In case device was already open PortStatus := Open_USB_Device; // Try and open device If PortStatus = FT_OK then // Device is Now Present ! Begin Connected := True; // Reset_USB_Device; // warning - this will destroy any pending data. //получаем информацию о приборе device_index:=0; if FT_Device_Count > 0 then For i:= 1 to FT_Device_Count do Begin GetFTDeviceSerialNo(Device_Index ); device_serial_no:=FT_Device_String; GetFTDeviceDescription ( Device_Index ); device_desc:=FT_Device_String; Device_Index := Device_Index + 1; End; End; End else Begin PortStatus := Get_USB_Device_QueueStatus; If PortStatus <> FT_OK then begin // Device has been Unplugged Connected := False; end else End; end; Procedure TDevice.Open_device; begin connected:=false; port_opened:=false; If Open_USB_Device_By_Serial_Number(device_serial_no) = FT_OK then begin connected:=true; //showmessage('1'); Set_USB_Parameters(16384,16384); //размеры буферов FT_Current_Baud:=FT_BAUD_921600; if (not Set_USB_Device_BaudRate = FT_OK) then MessageBox(0, PChar('Ошибка при установки скорости соединения'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); FT_Current_DataBits:=FT_DATA_BITS_8; FT_Current_StopBits:=FT_STOP_BITS_1; FT_Current_Parity:=FT_PARITY_NONE; if (not Set_USB_Device_DataCharacteristics = FT_OK) then MessageBox(0, PChar('Ошибка при установке параметров(Бит,СтопБит,Паритет)'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); if not Set_USB_Device_TimeOuts(5,5) = FT_OK then MessageBox(0, PChar('Ошибка при установке таймаутов'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); if not Set_USB_Device_BitMode($ff,0) = FT_OK then MessageBox(0, PChar('Ошибка при выключении Bit Mode'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); if (not Purge_USB_Device_In = FT_OK) and (Purge_USB_Device_Out = FT_OK) then MessageBox(0, PChar('Ошибка при очистке буферов I/O'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); port_opened:=true; end; end; function TDevice.IsConnected; begin if connected then result:=true else result:=false; end; function TDevice.IsPortOpened; begin if port_opened then result:=true else result:=false; end; function TDevice.Show_device_name; begin result:=device_name; end; function TDevice.Show_device_serial_no; begin result:=device_serial_no; end; function TDevice.Show_device_desc; begin result:=device_desc end; function TDevice.Start_waiting(mode:integer):message_Array; var i:integer; f:Textfile; message_:Message_Array; res_m:params_record; begin if mode=1 then if port_opened then TTH:=device_thread_th.Create(false); if mode=2 then begin assignfile(f, 'message'); reset(f); i:=0; repeat readln(f, message_[i]); inc(i); until EOF(f); closefile(f); //if got_message then //showmessage('Сообщение получено') res_m:=self.message_decode(message_); MainForm.Memo1.Clear; MainForm.Memo1.Visible:=false; for I := 0 to 2400 do MainForm.Memo1.Lines.Add(floattostr(res_m.U_izm[i])); MainForm.Memo1.Lines.SaveToFile('1'); end; end; //разбор посылки function TDevice.message_decode(massiv: message_Array):params_record; const N=2400; //количество замеров тока и напряжения T2=0.00083717036416911; //время в секундах между отсчетами Ki=33554431999999.996; //коэф. пересчета из целочисленных в реальные тока Ku=3355443.2; //коэф. пересчета из целочисленных в реальные напряжения rescale = 1000000; // var k, //текущее значение строчки в массиве измерения i, //счетчик в цикле //значение массива j,j1 ,a1,b1,c1,d1,a2,b2,c2,d2: //счетчики для инициализации integer; bin_volt, //двоичное значение напряжения bin_curr:bit_Array_32; //двоичное значение тока U0, // I0, // Ud0, // Up0 // :Extended; A: TMatrix; B : TCol; Det0:extended; begin ///инициализация переменных //setlength(a,5,5); U0:=0;Ud0:=0; I0:=0; for j:=0 to 4 do begin B[j]:=0; for j1:=0 to 4 do A[j,j1]:=0; end; k:=-9; for i:=0 to N do begin k:=k+10; //разбор блока значений напряжения //вся посылка 5 байт for j:=0 to 31 do bin_volt[j]:=0; a1:=(((((massiv[k] shl 4) and $80) or massiv[k+1]) shl 24) and $FF000000); b1:=(((((massiv[k] shl 5) and $80) or massiv[k+2]) shl 16) and $FFFF0000); c1:=(((((massiv[k] shl 6) and $80) or massiv[k+3]) shl 8) and $FFFFFF00); d1:=(((((massiv[k] shl 7) and $80) or massiv[k+4]) shl 0) and $FFFFFFFF); result.U_izm[i]:=a1+b1+c1+d1; for j:=0 to 31 do bin_curr[j]:=0; a2:=(((((massiv[k+5] shl 4) and $80) or massiv[k+6]) shl 24) and $FF000000); b2:=(((((massiv[k+5] shl 5) and $80) or massiv[k+7]) shl 16) and $FFFF0000); c2:=(((((massiv[k+5] shl 6) and $80) or massiv[k+8]) shl 8) and $FFFFFF00); d2:=(((((massiv[k+5] shl 7) and $80) or massiv[k+9]) shl 0) and $FFFFFFFF); result.I_izm[i]:=a2+b2+c2+d2; //начало нарастания 977 отсчет ///Подсчёт значений R, g0, g1, g2, g3, C силами программы if (i=1000) then Ud0:=a1+b1+c1+d1; if (i=1001) then begin U0:=a1+b1+c1+d1; I0:=a2+b2+c2+d2; end; if ((i>=1002)and(i<=2201)) then begin Up0:=a1+b1+c1+d1; A[0,0]:=A[0,0]+intpower(U0,2); A[0,1]:=A[0,1]+intpower(U0,3); A[0,2]:=A[0,2]+intpower(U0,4); A[0,3]:=A[0,3]+intpower(U0,5); A[1,3]:=A[1,3]+intpower(U0,6); A[2,3]:=A[2,3]+intpower(U0,7); A[3,3]:=A[3,3]+intpower(U0,8); A[0,4]:=A[0,4]+U0*(Up0-Ud0); A[1,4]:=A[1,4]+intpower(U0,2)*(Up0-Ud0); A[2,4]:=A[2,4]+intpower(U0,3)*(Up0-Ud0); A[3,4]:=A[3,4]+intpower(U0,4)*(Up0-Ud0); A[4,4]:=A[4,4]+intpower((Up0-Ud0),2); //приводим к диагональному виду матрицу А A[1,0]:=A[0,1]; A[2,0]:=A[0,2]; A[3,0]:=A[0,3]; A[3,1]:=A[1,3]; A[4,0]:=A[0,4]; A[3,2]:=A[2,3]; A[4,1]:=A[1,4]; A[4,2]:=A[2,4]; A[4,3]:=A[3,4]; //НЕ ПОНЯТНО!!!!!!!!!!!!!!! A[1,1]:=A[0,2]; A[1,2]:=A[0,3]; A[2,1]:=A[0,3]; A[2,2]:=A[1,3]; //формируем столбец В B[0]:=B[0]+I0*U0; B[1]:=B[1]+I0*intpower(U0,2); B[2]:=B[2]+I0*intpower(U0,3); B[3]:=B[3]+I0*intpower(U0,4); B[4]:=B[4]+I0*(Up0-Ud0); I0:=a2+b2+c2+d2; Ud0:=U0; U0:=Up0; end; if i=2393 then begin Det0:=det5(A); showmessage(floattostr(Det0)); result.g0:=det5(copy_col(A,B,0))/Det0*Ku/Ki*rescale; result.g1:=det5(copy_col(A,B,1))/Det0*Ku/Ki*rescale; result.g2:=det5(copy_col(A,B,2))/Det0*Ku/Ki*rescale; result.g3:=det5(copy_col(A,B,3))/Det0*Ku/Ki*rescale; result.C:=det5(copy_col(A,B,4))/Det0*Ku/Ki*rescale; result.R:= rescale/result.g0; end; end; end; //функции работы с числами и байтами {function TDevice.to_binary(x:integer):bit_array_32; var i:integer; begin if x>0 then begin for i:=31 downto 0 do result[i]:=0; i:=31; repeat result[i]:=x mod 2; //остаток от деления на 2 x:=x div 2; dec(i); until (x=0); end else if x=0 then for i:=0 to 31 do result[i]:=0 {else if x<0 then begin result:=to_binary(-x); for i:=7 downto 0 do if result[i]=1 then result[i]:=0 else result[i]:=1; //доп. код. for i:=7 downto 0 do if result[i]=0 then begin result[i]:=1; break; end else result[i]:=0; //скорее всего добавляем 1 к доп. коду??? end; end else //возможное добавление обработки ошибок end; function TDevice.to_decimal(x:bit_Array_32):extended; var i:Integer; begin result:=0; for i:=31 downto 1 do if x[i]=1 then result:=result+ldexp(1,i); if x[0]=1 then result:=result*(-1); end; {function TDevice.add_to_32_binary(x:bit_array_32; start_pos,count:integer; ar:bit_array_32):bit_array_32; var i:integer; begin for i:=1 to count do ar[start_pos-i+1]:=x[8-i]; result:=ar; end; //вычисление определителя произвольной матрицы function TDevice.Determinant(FirstRow : Integer; Matrica:TMatrix; k:integer; ac:Tbool) : extended; Массив ActiveCols будем использовать для обозначения "вычеркнутых" колонок FirstRow указывает на первую строку массива, с которой начинается матрица, рассматриваемая на текущем шаге. Строки вычеркиваем последовательно var i : Integer; Odd : Boolean; begin //setLength(Matrica, n-1,n-1); if ac=nil then begin setlength(ac,k); for I:=0 to k-1 do ac[i]:=true; end; Result:=0; Odd:=true; for i:=0 to k-1 do // пробегаем по всем элементам текущей строки begin if NOT ac[i] then Continue; // если колонка вычеркнута, то пропускаем // если первая строка равна размерности матрицы, значит у нас остался один единственный элемент (матрица 1х1). Этот элемент и будет детерминантом. if FirstRow = k-1 then begin Result:=Matrica[FirstRow,i]; Exit; end; ac[i]:=false; // вычеркиваем текущий столбец if Odd then если позиция нечетная, то к результату прибавляем произведение элемента на дополниетльный минор Result:=Result+Matrica[FirstRow,i]*Determinant((FirstRow+1), Matrica, k,ac) else если позиция четная, то вычитаем Result:=Result-Matrica[FirstRow,i]*Determinant(FirstRow+1, Matrica, k,ac); ac[i]:=true; // восстанавливаем вычеркнутый стобец Odd:=NOT Odd; // меняем четность end; end; } //копирование столбца В в матрицу А в колонку col function TDevice.copy_col(Al:TMatrix; Bl:TCol; coll:integer):TMatrix; var i:integer; begin for I := 0 to 4 do Al[i,coll]:=Bl[i]; result:=Al; end; function TDevice.det5(A:TMatrix):extended; function det4(A11,A12,A13,A14,A21,A22,A23,A24,A31,A32,A33,A34,A41,A42,A43,A44:extended):extended; function det3(A11,A12,A13,A21,A22,A23,A31,A32,A33:extended):extended; function det2(A11,A12,A21,A22:extended):extended; begin result:=A11*A22-A12*A21; end; begin result:=A11*det2(A22,A23,A32,A33)-A12*det2(A21,A23,A31,A33)+A13*det2(A21,A22,A31,A32); end; begin result:=A11*det3(A22,A23,A24,A32,A33,A34,A42,A43,A44)- A12*det3(A21,A23,A24,A31,A33,A34,A41,A43,A44)+ A13*det3(A21,A22,A24,A31,A32,A34,A41,A42,A44)- A14*det3(A21,A22,A23,A31,A32,A33,A41,A42,A43); end; begin result:=A[0,0]*det4(A[1,1],A[1,2],A[1,3],A[1,4],A[2,1],A[2,2],A[2,3],A[2,4],A[3,1],A[3,2],A[3,3],A[3,4],A[4,1],A[4,2],A[4,3],A[4,4])- A[0,1]*det4(A[1,0],A[1,2],A[1,3],A[1,4],A[2,0],A[2,2],A[2,3],A[2,4],A[3,0],A[3,2],A[3,3],A[3,4],A[4,0],A[4,2],A[4,3],A[4,4])+ A[0,2]*det4(A[1,0],A[1,1],A[1,3],A[1,4],A[2,0],A[2,1],A[2,3],A[2,4],A[3,0],A[3,1],A[3,3],A[3,4],A[4,0],A[4,1],A[4,3],A[4,4])- A[0,3]*det4(A[1,0],A[1,1],A[1,2],A[1,4],A[2,0],A[2,1],A[2,2],A[2,4],A[3,0],A[3,1],A[3,2],A[3,4],A[4,0],A[4,1],A[4,2],A[4,4])+ A[0,4]*det4(A[1,0],A[1,1],A[1,2],A[1,3],A[2,0],A[2,1],A[2,2],A[2,3],A[3,0],A[3,1],A[3,2],A[3,3],A[4,0],A[4,1],A[4,2],A[4,3]); end; end.