unit DeviceRD; interface uses D2xxUnit, SysUtils, Dialogs, Windows, math, ExtCtrls, user_types, RDThread; //пользовательские типы type //непосредственно класс устройства TDevice = class (TObject) private connected :boolean; //существует ли связь с прибором. port_opened :boolean; //открыт ли порт прибора device_name :string; //Название прибора device_serial_no:string; //Серийный номер прибора thread: TRDThread; //поток const version = '0.4.4'; function copy_col(Al:TMatrix; Bl:TCol; coll:integer):TMatrix; function det5(A:TMatrix):extended; procedure Set_device_params; procedure Get_device_information; public message_ : message_Array; timer : TTimer; //таймер на подключение прибора procedure TimerTimer(Sender: TObject); constructor Create(); virtual; destructor Destroy(); override; function IsConnected:boolean; function IsPortOpened:boolean; function Show_device_name:string; function Show_device_serial_no:string; //События потока procedure Got_first_message_byte; procedure Got_last_message_byte; function message_decode(massiv:message_Array):params_record; procedure Start_waiting(mode:integer); procedure Open_device; procedure Close_device; procedure Close_thread; protected { protected declarations } end; implementation uses MainUnit, ConstUnit, IzmUnit; constructor TDevice.Create; begin inherited Create; FT_Enable_Error_Report := TRUE; connected := FALSE; port_opened := FALSE; device_name := ''; device_serial_no := ''; //создаем таймер для проверки подключения прибора timer := TTimer.Create(MainForm); timer.Interval := 1000; timer.OnTimer := TimerTimer; TimerTimer(self); timer.Enabled:=false; end; destructor TDevice.Destroy; begin timer.Free; inherited Destroy; end; procedure TDevice.Close_device; begin port_opened := FALSE; Close_USB_device; GetFTDeviceCount; end; procedure TDevice.Close_thread; begin self.thread.Terminate; end; procedure TDevice.TimerTimer(Sender: TObject); begin //получаем количество подключенных устройств, //считаем если их больше 0, то прибор подключен GetFTDeviceCount; if ( FT_Device_Count > 0 ) then begin if ( not connected ) then begin MainForm.new_izm_warning_label.Caption:=devicerd_device_just_connected; connected := true; end; end else begin if connected then begin connected := FALSE; Close_device; end; end; end; procedure TDevice.Set_device_params; begin Set_USB_Parameters(DEVICE_BUFFERS,DEVICE_BUFFERS); //размеры буферов Set_USB_Device_TimeOuts(DEVICE_RED_WRITE_TIMEOUTS,DEVICE_RED_WRITE_TIMEOUTS); FT_Current_Baud:=FT_BAUD_921600; if (not Set_USB_Device_BaudRate = FT_OK) then begin MessageBox(0, PChar('Ошибка при установки скорости соединения'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); end; 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_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 ); end; procedure TDevice.Get_device_information; var device_index: Integer; i: Integer; begin //получаем информацию о приборе device_index := 0; if ( FT_Device_Count > 0 ) then begin for i := 1 to FT_Device_Count do begin GetFTDeviceSerialNo(Device_Index ); device_serial_no:=FT_Device_String; Device_Index := Device_Index + 1; end; end; end; procedure TDevice.Open_device; begin if port_opened then begin Reset_USB_Device; Close_USB_Device; // In case device was already open end; GetFTDeviceCount; if ( FT_Device_Count > 0 ) then begin Get_device_information; if Open_USB_Device_By_Serial_Number( device_serial_no ) = FT_OK then begin Set_device_params; port_opened := TRUE; Reset_USB_Device; // warning - this will destroy any pending data. end end else begin MessageBox(0, PChar('Ошибка при открытии устройства. Проверьте подключение'), PChar('Ошибка устройства'), MB_ICONERROR or MB_OK ); end; end; procedure TDevice.Start_waiting(mode:integer); begin if ( mode = 2 ) then begin // Открываем устройство на чтение self.Open_device; thread := TRDThread.Create ( TRUE ); // запускаем поток self.thread.Resume; end; end; procedure TDevice.Got_first_message_byte; begin // Выводим сообщение о получении данных IzmForm.Izm_condition_label.Caption := MEASURE_GETTING_DATA; // обнуляем прогресс бар получения посылки IzmForm.IzmPB.Position := 0; // запаускаем прогресс бар получения посылки IzmForm.IzmTimer.Enabled := TRUE; end; procedure TDevice.Got_last_message_byte; var decoded_message: params_record; current_point_num: integer; begin Purge_USB_Device_In; Purge_USB_Device_Out; //Вывод сообщения о декодировании посылки IzmForm.Izm_condition_label.Caption := ConstUnit.MEASURE_DECODING_MESSAGE; //декодирование посылки /// Выводим результаты в лист /// Выводим сообщения об ошибках decoded_message := message_decode(thread.message_); IzmForm.incoming_message( decoded_message); //Вывод сообщения о готовности прибора к измерению IzmForm.Izm_condition_label.Caption := MEASURE_DEVICE_READY; IzmForm.IzmPB.Position := 100; IzmForm.IzmTimer.Enabled := FALSE; //Работаем с измрением With IzmForm.measure do begin //номер текущей точки current_point_num := IzmForm.measure.point_values.Get_current_item_index; //увеличиваем счетчики, Inc_total_sent; //showmessage (Get_current_sent); //пишем информацию в класс измерения Write_values( decoded_message ); //пишем информацию в базу Load_values_to_database; //проверяем на переход к новой точке Check_current_sent; if not ( current_point_num = point_values.Get_current_item_index ) then begin IzmForm.Update_controls_After_point_num_change; end; //обновляем компоненты на форме IzmForm.izm_mes_tek_count.Caption := inttostr (Get_current_sent); IzmForm.izm_mes_count.Caption := inttostr (Get_total_sent); end; 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:integer; a1,b1,c1,d1,a2,b2,c2,d2: //временные переменные для составных частей посылки extended; 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; for I := 0 to length(result.I_izm) - 1 do begin result.I_izm[i]:=0; result.U_izm[i]:=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; //result.Usm:=det5(copy_col(A,B,3))/Det0*Ku/Ki*Ku*Ku*Ku; } result.g0_calc:=0; result.g1_calc:=0; result.g2_calc:=0; result.g3_calc:=0; result.C_calc:=0; result.R_calc:= 0; result.Usm_calc:=0; //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_device:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.R_device:=-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_device:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g0_device:=-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_device:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g1_device:=-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_device:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g2_device:=-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_device:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.g3_device:=-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_device:=result.U_izm[i]/intpower(2,30)*intpower(2,drei) else result.C_device:=-1*result.U_izm[i]/intpower(2,30)*intpower(2,drei) end; if i=2399 then begin if round(result.I_izm[i]/intpower(2,24)) mod 2=0 then result.Usm_device:=result.U_izm[i]/Ku else result.Usm_device:=-1*result.U_izm[i]/Ku; 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; //копирование столбца В в матрицу А в колонку 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.