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; //тип массива TIzm_array = array [0..2400] of integer; //для матрицы 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: TIzm_array; I_izm: TIzm_array; //значения прибора R_e:extended; C_e:extended; g0_e:extended; g1_e:extended; g2_e:extended; g3_e:extended; U_mis: boolean; I_mis: boolean; end; //непосредственно класс устройства type TDevice = class (TObject) private connected :boolean; //существует ли связь с прибором. port_opened :boolean; //открыт ли порт прибора device_name :string; //Название прибора device_serial_no:string; //Серийный номер прибора device_desc :string; //Описание прибора const version = '0.4.4'; function copy_col(Al:TMatrix; Bl:TCol; coll:integer):TMatrix; function det5(A:TMatrix):extended; public message_ : message_Array; constructor Create(); //destructor Destroy(); function IsConnected:boolean; function IsPortOpened:boolean; function Close1: 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; function TDevice.Close1:boolean; begin Set_USB_Device_BitMode($ff,0); if Close_USB_device = FT_OK then result:=true else result:=false; FT_Handle:=0; end; 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 else //Close_USB_Device; 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 If Open_USB_Device = 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; var i,device_Index:integer; begin connected:=false; port_opened:=false; 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; 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 else MessageBox(0, PChar('Ошибка при открытии устройства. Проверьте подключение'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); end; function TDevice.Start_waiting(mode:integer):message_Array; begin if mode=1 then if port_opened then TTH:=device_thread_th.Create(true); if mode=2 then if port_opened then TTH.Resume; end; //разбор посылки function TDevice.message_decode(massiv: message_Array):params_record; const N=2400; //количество замеров тока и напряжения T2=0.00083717036416911; //время в секундах между отсчетами Ki=33554431999999.996; //коэф. пересчета из целочисленных в реальные тока Ku=3355443.2; //коэф. пересчета из целочисленных в реальные напряжения var k, //текущее значение строчки в массиве измерения i, //счетчик в цикле drei, a1,b1,c1,d1,a2,b2,c2,d2: //временные переменные для составных частей посылки integer; U0, // I0, // Ud0, // Up0, Det0 :Extended; A: TMatrix; B: TCol; j: Integer; begin ///инициализация переменных //setlength(a,5,5); U0:=0;Ud0:=0; I0:=0; k:=-9; for I:= 0 to 4 do begin B[i]:=0; for j:= 0 to 4 do A[i,j]:=0; end; result.U_mis:=false; result.I_mis:=false;; for i:=0 to N do begin k:=k+10; //разбор блока значений напряжения //вся посылка 5 байт 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; 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=2390 then begin Det0:=det5(A); result.g0:=det5(copy_col(A,B,0))/Det0*Ku/Ki; result.g1:=det5(copy_col(A,B,1))/Det0*Ku/Ki*Ku; result.g2:=det5(copy_col(A,B,2))/Det0*Ku/Ki*Ku*Ku; result.g3:=det5(copy_col(A,B,3))/Det0*Ku/Ki*Ku*Ku*Ku; result.C:=det5(copy_col(A,B,4))/Det0*Ku/Ki*T2; result.R:= 1/result.g0; end; //2392 - байт ошибки //канал U-выход за диапазон измерения //канал I - отпустили электрод if i=2392 then begin if a1+b1+c1+d1<>0 then result.U_mis:=true; if a2+b2+c2+d2<>0 then result.I_mis:=true; end; if i>=2393 then begin drei:=round(result.I_izm[i]-round(result.I_izm[i]/intpower(2,24))*intpower(2,24)-1023); if i=2393 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.R_e:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.R_e:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; if i=2394 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.g0_e:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g0_e:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; if i=2395 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.g1_e:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g1_e:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; if i=2396 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.g2_e:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g2_e:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; if i=2397 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.g3_e:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g3_e:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; if i=2398 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.C_e:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.C_e:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; end; 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; //копирование столбца В в матрицу А в колонку 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; //определитель матрицы 5х5 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.