Hallo!
Ich habe einen TThread, der während der gesammten Programm-Laufzeit läuft und Daten "sammelt". d.h. er Liest Daten von der Seriellen-Schnittstelle sowie von einem USB-Gerät (über eine DLL). Diese Daten, in meinem Fall Temperaturen sollen dem MainThread zur verfügung gestellt werden.
Bis jetzt habe ich folgenden Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292:
| unit HWUnit;
interface
uses Forms, Classes, RegExpr, SysUtils, AdPort, DateUtils, DFZUnit;
type TempSensor = record romid: String; temp: double; changed: TDateTime; end;
type THWThread = class(TThread) private DataReg: TRegExpr; BufferReg: TRegExpr;
ComPort: TApdComPort; com_buffer: String;
TempSensors: Array[0..11] of TempSensor; Inputs: Array[0..4] of Boolean; Outputs: Array[0..7] of Boolean; ADCs: Array[0..1] of Integer;
SolZae: TDFZaehler; FWWLiter: double;
function GetSolarDurchfluss: double; function GetSolarLiter: double;
function GetWWLiter: double;
function GetInput(Index: Integer): Boolean; function GetTemp(Index: Integer): double; function GetADC(Index: Integer): Integer;
function GetOutput(Index: Integer): Boolean; procedure SetOutput(Index: Integer; Value: Boolean);
procedure ExtractBuffer(const AInputString : string); procedure ExtractData (const AInputString : string); protected procedure Execute; override;
public constructor Create(CreateSuspended: Boolean); destructor Destroy; override;
property Input[Index: Integer]: Boolean read GetInput; property Temp[Index: Integer]: Double read GetTemp; property ADC[Index: Integer]: Integer read GetADC; property Output[Index: Integer]: Boolean read GetOutput write SetOutput;
property SolarDurchfluss: Double read GetSolarDurchfluss; property SolarLiter: Double read GetSolarLiter;
property WWLiter: Double read GetWWLiter; property debg: string read com_buffer;
end;
var HWThread: THWThread;
const DataRegEx = '>(([0-9A-F]{2} ){8}) (.[0-9]{1,}\.[0-9]{4})°C<'; BufferRegEx = '([^<]*)$';
VLH = 0; RLH = 1; P1 = 2; P2 = 3; P3 = 4; P4 = 5; RLS = 6; VLS = 7; WW1 = 8; WW2 = 9; WW3 = 10; WW4 = 11;
implementation
function OpenDevice(CardAddress: Longint): Longint; stdcall; external 'K8055d.dll'; procedure CloseDevice; stdcall; external 'K8055d.dll';
function ReadAnalogChannel(Channel: Longint):Longint; stdcall; external 'K8055d.dll'; procedure ReadAllAnalog(var Data1, Data2: Longint); stdcall; external 'K8055d.dll'; procedure OutputAnalogChannel(Channel: Longint; Data: Longint); stdcall; external 'K8055d.dll'; procedure OutputAllAnalog(Data1: Longint; Data2: Longint); stdcall; external 'K8055d.dll'; procedure ClearAnalogChannel(Channel: Longint); stdcall; external 'K8055d.dll'; procedure ClearAllAnalog; stdcall; external 'K8055d.dll'; procedure SetAnalogChannel(Channel: Longint); stdcall; external 'K8055d.dll'; procedure SetAllAnalog; stdcall; external 'K8055d.dll'; procedure WriteAllDigital(Data: Longint);stdcall; external 'K8055d.dll'; procedure ClearDigitalChannel(Channel: Longint); stdcall; external 'K8055d.dll'; procedure ClearAllDigital; stdcall; external 'K8055d.dll'; procedure SetDigitalChannel(Channel: Longint); stdcall; external 'K8055d.dll'; procedure SetAllDigital; stdcall; external 'K8055d.dll'; function ReadDigitalChannel(Channel: Longint): Boolean; stdcall; external 'K8055d.dll'; function ReadAllDigital: Longint; stdcall; external 'K8055d.dll'; function ReadCounter(CounterNr: Longint): Longint; stdcall; external 'K8055d.dll'; procedure ResetCounter(CounterNr: Longint); stdcall; external 'K8055d.dll'; procedure SetCounterDebounceTime(CounterNr, DebounceTime:Longint); stdcall; external 'K8055d.dll';
constructor THWThread.Create(CreateSuspended: Boolean); var i: Integer; begin OpenDevice(0); DataReg := TRegExpr.Create; DataReg.Expression := DataRegEx;
BufferReg := TRegExpr.Create; BufferReg.Expression := BufferRegEx;
ComPort := TApdComPort.Create(nil); ComPort.Baud := 9600; ComPort.ComNumber := 1; ComPort.Open := True;
SolZae := TDFZaehler.Create; SolZae.DurchflussProImpuls := 10; SolZae.MindestDurchfluss := 1;
TempSensors[VLH].romid := '10 F9 E9 3A 00 08 00 13'; TempSensors[RLH].romid := '10 ED 06 3B 00 08 00 AE'; TempSensors[P1].romid := '10 8B F1 3A 00 08 00 A7'; TempSensors[P2].romid := '10 C2 E0 3A 00 08 00 F5'; TempSensors[P3].romid := '10 07 F6 3A 00 08 00 61'; TempSensors[P4].romid := '10 29 FB 3A 00 08 00 28'; TempSensors[RLS].romid := '10 D7 CA 3A 00 08 00 00'; TempSensors[VLS].romid := '10 C2 F8 3A 00 08 00 B7'; TempSensors[WW1].romid := '10 B2 09 3B 00 08 00 CB'; TempSensors[WW2].romid := '10 6C F6 3A 00 08 00 5A'; TempSensors[WW3].romid := '10 11 50 AA 00 08 00 C6'; TempSensors[WW4].romid := '10 ED 7E AC 00 08 00 9A';
for i := 0 to Length(TempSensors)-1 do begin TempSensors[i].temp := -255; TempSensors[i].changed := Now(); end;
ClearAllAnalog(); ClearAllDigital(); SetCounterDebounceTime(1,250); ResetCounter(1); inherited; end;
destructor THWThread.Destroy; begin ComPort.Open := False; CloseDevice;
DataReg.Free; BufferReg.Free;
SolZae.Free; end;
procedure THWThread.Execute; var data: string; count, i: Integer;
begin
while not Terminated do begin
count := ComPort.InBuffUsed; if count >= 37-length(com_buffer) then begin for i:=1 to count do data := data + ComPort.GetChar; data := com_buffer + data; ExtractData(data); ExtractBuffer(data); end;
ReadAllAnalog(ADCs[0],ADCs[1]);
for i:=0 to Length(Inputs)-1 do Inputs[i] := ReadDigitalChannel(i+1);
if ADCs[0] < 90 then SolZae.Level := false; if ADCs[0] > 100 then SolZae.Level := true;
sleep(10);
end; end;
function THWThread.GetWWLiter: double; begin Result := ReadCounter(1); ResetCounter(1); end;
function THWThread.GetSolarDurchfluss: double; begin Result := SolZae.Durchfluss; end; function THWThread.GetSolarLiter: double; begin Result := SolZae.Liter; end;
function THWThread.GetInput(Index: Integer): Boolean; begin Result := Inputs[Index]; end;
function THWThread.GetADC(Index: Integer): Integer; begin Result := ADCs[Index]; end; function THWThread.GetOutput(Index: Integer): Boolean; begin Result := Outputs[Index]; end; procedure THWThread.SetOutput(Index: Integer; Value: Boolean); begin Outputs[Index] := Value; if Value then SetDigitalChannel(index+1) else ClearDigitalChannel(index+1); end;
procedure THWThread.ExtractData (const AInputString : string); var i: integer; begin if DataReg.Exec (AInputString) then repeat for i:=0 to Length(TempSensors)-1 do begin if TempSensors[i].romid = trim(DataReg.Match[1]) then begin DecimalSeparator := '.'; TempSensors[i].temp := StrToFloat(DataReg.Match[3]); break; end; end; until not DataReg.ExecNext; end;
procedure THWThread.ExtractBuffer(const AInputString : string); begin if BufferReg.Exec (AInputString) then com_buffer := BufferReg.Match[0]; end;
function THWThread.GetTemp(Index: Integer): double; begin result := TempSensors[Index].temp; end;
initialization HWThread := THWThread.Create(false); finalization HWThread.Terminate; HWThread.WaitFor; HWThread.Free; end. |
Man Beachte die property Temp mit GetTemp sowie ExtractData und Execute.
In der Schleife werden ggf. vorhandene Daten vom COM-Port gelesen und an ExtractData übergeben. ExtractData "extrahiert" aus dem empfangenen String die Temperatur und schreibt sie in TempSensors[?].temp.
Aus dem primären Thread greife ich nun zu "willkürlichen" Zeitpunkten auf HWThread.Temp[P1] zu. Dies liefert mir auch werte zurück... jedoch scheit da was nicht hinzuhauen. Ich habe diese Temperaturen minütlich in einer Datenbank gespeichert und daraus ein Diagramm erstellt. (siehe Anhang)
Man kann erkennen, dass die Wert sagen wir "schwingen" und die Amplitude zunimmt. Die am COM-Port empfangenen Daten sind korrekt. Immer wenn diese Schwingung verschwindet habe ich das Programm neu gestartet... im verlauf der Zeit nimmt diese extreme Ausmaße an.
Vermutlich kann ich nicht einfach mit HWThread.Temp[x] aus dem primären Thread auf diese Temperaturen zugreifen. Bitte sagt mir also was ich anders machen muss, damit es funktioniert.
PS.: Bin auch per ICQ zu erreichen
schonma Danke und Tschöö
BiDi