Professional Documents
Culture Documents
MS8229 part2
Author tasosPublished on October 8, 2012
Making DMM
In this third and last article of this series we will add two libraries in our Lazarus project and the event handling.
The compiled project can be found at TrustFm Opens in a new window website.
We are going to use the synaser library (part of synapse Opens in a new window) for the serial communication and the
PlotPanel Opens in a new windowin order to plot our real time graph.
For synaser we are going to add only the "synaser.pas" file into our project.
For the PlotPanel we need to add the "plotpanel.pas" file into our project.
More informations for synaser can be found here Opens in a new window and for PlotPanel here Opens in a new
window
?
1
uses
2 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
3 ExtCtrls, ComCtrls, Spin, Buttons,
4 //Serial
5 Synaser,
6 //Plot
Plotpanel;
7
?
1
procedure TFormMain.Disconnect();
2begin
3 BlockSerial.Purge;
4 BlockSerial.Free;
5 IsConnected := false;
StatusBar.Panels.Items[0].Text:='Status : DISCONNECTED';
6end;
7
Then if the segment number is 1 we are good to go and we read the rest 13 bytes byte by byte using
BlockSerial.RecvByte.
If the segment is between 2 and 14 then we need to ignore 14-segment number bytes in order to find the starting byte
(segment 1).
?
procedure TFormMain.GetCode();
1 var TempByte: byte;
2 segment: integer;
3 i:integer;
4 ignorebytes:integer;
begin
5 if (BlockSerial.LastError <> 0) then Exit;
6 if BlockSerial.CanRead(Timeout) then begin
7
8 TempByte := BlockSerial.RecvByte(Timeout);
9 segment := TempByte shr 4; //XXXXYYYY->0000XXXX get the segment number
10 if segment = 1 then begin
My_Multimeter.Code.Value[0] := TempByte;
11 for i:=1 to 13 do begin //read the rest 13 bytes
12 My_Multimeter.Code.Value[i] := BlockSerial.RecvByte(Timeout);
13 end;
14 end else begin
15
if (segment > 1) and (segment <= 14) then begin
16
17 ignorebytes:=14-segment;
18 if ignorebytes>0 then begin
19 for i:=1 to ignorebytes do begin
BlockSerial.RecvByte(Timeout); //ignore 14-segment bytes
20 end;
21 end;
22
23 TempByte := BlockSerial.RecvByte(Timeout); //try again to read the segment 1
24 segment := TempByte shr 4; //XXXXYYYY->0000XXXX get the segment number
if segment = 1 then begin
25 My_Multimeter.Code.Value[0] := TempByte;
26 for i:=1 to 13 do begin //read the rest 13 bytes
27 My_Multimeter.Code.Value[i] := BlockSerial.RecvByte(Timeout);
28 end;
29 end;
30
end;
31
32 end;
33 end;
34end;
35
36
37
38
39
40
41
I hope that this reading method is clear enough. Of course you can use your reading method as well.
Once setting up the synaser we are ready to add a TTimer in our project that :
1) Gets the code (GetCode)
2) Validates the parsed code (IsValidCode Opens in a new window)
3) Parses the status from the code (ParseStatus Opens in a new window)
4) Prints the code into the screen (PrintStatusInLabel)
?
//The timer !
1 procedure TFormMain.TimerTimer(Sender: TObject);
2 var y:double;
3 begin
4 Application.ProcessMessages;
5 GetCode();
StatusBar.Panels.Items[1].Text := 'Code : ' + PrintCode();
6 if IsValidCode then begin
7 StatusBar.Panels.Items[1].Text := StatusBar.Panels.Items[1].Text + ' [valid]';
8 ParseStatus();
9 LabelScreen.Caption := PrintStatusInLabel();
10
11 endStatusBar.Panels.Items[1].Text
else begin
:= StatusBar.Panels.Items[1].Text + ' [invalid]';
12 end;
13
14 FormMain.Refresh;
15
16 //Close the timer and disconnect if IsConnected is false
17 if not IsConnected then begin
Timer.Enabled:=false;
18 Disconnect();
19 end;
20end;
21
22
23
24
?
1
2 //On connect disconnect
3 procedure TFormMain.ButtonConnectDisconnectClick(Sender: TObject);
4 begin
5
6 //Connect
7 if ButtonConnectDisconnect.Caption = 'Connect' then begin
8
Connect(EditPort.Text); //Connect at the port ...
9
10 if IsConnected then begin
11 ButtonConnectDisconnect.Caption:='Disconnect';
12 Timer.Interval:=SpinEditEveryXMs.Value;
13 Timer.Enabled:=true;
end;
14
15 //Disconnect
16 end else if ButtonConnectDisconnect.Caption = 'Disconnect' then begin
17
18 IsConnected := false; //this must stop the timer securely
19 ButtonConnectDisconnect.Caption:='Connect';
20
21 end;
end;
22
23
?
1 function TFormMain.PrintStatusInLabel():string;
2 var stemp:string;
begin
3
4 if My_Multimeter.Status.IsRS232 = true then
5 stemp += ' [RS233] ';
6
7 if My_Multimeter.Status.IsAuto = true then
8 stemp += ' [AUTO] ';
9
10 ifstemp
My_Multimeter.Status.AC_DC_None = AC then
+= ' [AC] '
11 else if My_Multimeter.Status.AC_DC_None = DC then
12 stemp += ' [DC] ';
13
14 stemp += My_Multimeter.Status.ValuePrefix + ' ' + My_Multimeter.Status.UnitPrefix +
15My_Multimeter.Status.UnitValue;
16
stemp += #13#10; //Break line
17
18 if My_Multimeter.Status.IsDiode = true then
19 stemp += ' DIODE ';
20
21 if My_Multimeter.Status.IsSound = true then
22 stemp += ' SOUND ';
23
24 ifstemp
My_Multimeter.Status.IsHold = true then
+= ' HOLD ';
25
26 if My_Multimeter.Status.IsRelative = true then
27 stemp += ' REL ';
28
29 if My_Multimeter.Status.IsBattery = true then
30 stemp += ' BAT ';
31
result := stemp;
32
33end;
34
35
36
37
At this point you should be able to get the readings on your screen (LabelScreen.Caption)
Of course once reading the values you can store them into a ListView / csv file.
You can use your dedicated functions in order to do this job.
This step is really easy to do and it is not explained in this article.
In the next page we will see the plot graph.
PlotPanel Opens in a new window contains a nice demo (TryPlotPanel) so we are based in the official demo example.
We create a new "graph" form .
We add these variables :
?
1public
2 My_PlotPanel: TPlotpanel;
3 Xcur : integer; //Xcur is the current time stamp
4 Xwidth : integer;
?
1 procedure TFormGraph.CreatePanel(Sender: TObject);
begin
2 My_PlotPanel:=Tplotpanel.Create(Self);
3 My_PlotPanel.Top:=8;
4 My_PlotPanel.Left:=8;
5 My_Plotpanel.Width:=462;
My_PlotPanel.Height:=300;
6 My_PlotPanel.Margin:=10;
7 My_PlotPanel.Anchors:=[akTop,akLeft,akBottom,akRight];
8 My_PlotPanel.Color:=clBtnFace;
9 My_PlotPanel.BackColor:=clWhite;
My_PlotPanel.GridColor:=clSilver;
10 My_PlotPanel.PlotPen.Color:=clBlue;
11 My_PlotPanel.PlotPen.Width:=2;
12 My_PlotPanel.XLabel:='Record number';
13 My_PlotPanel.YLabel:='Value';
14end;
15procedure TFormGraph.ClearPanel();
16begin
17 My_PlotPanel.Freeze(True);
18 My_PlotPanel.XMarks:=true;
19 My_PlotPanel.YMarks:=true;
My_PlotPanel.XMarksFont.Color:=clBlack;
20 My_PlotPanel.YMarksFont.Color:=clBlack;
21 My_PlotPanel.XMin:=0;
22 My_PlotPanel.XMax:=Xwidth;
23 My_PlotPanel.YMin:=0;
24 My_PlotPanel.YMax:=10;
My_PlotPanel.XInterval:=1;
25 My_PlotPanel.YInterval:=1;
26 My_PlotPanel.ClearData;
27 My_PlotPanel.Freeze(False);
28end;
29
30
31
32
33
34
Focus your attention at the TryPlotPanel -> TimerPlot tab -> Start/Stop Chart button event
?
1procedure TFormGraph.FormCreate(Sender: TObject);
2begin
3 CreatePanel(nil);
4 ClearPanel();
5end;
?
1 //The timer !
procedure TFormMain.TimerTimer(Sender: TObject);
2 var y:double;
3 begin
4 Application.ProcessMessages;
5 GetCode();
StatusBar.Panels.Items[1].Text := 'Code : ' + PrintCode();
6 if IsValidCode then begin
7 StatusBar.Panels.Items[1].Text := StatusBar.Panels.Items[1].Text + ' [valid]';
8 ParseStatus();
9 LabelScreen.Caption := PrintStatusInLabel();
10
11 //Plot the graph !
if CheckBoxEnableGraph.Checked then begin
12
13 inc(FormGraph.Xcur); //increase the time stamp
14
15 With FormGraph.My_PlotPanel do begin
16 Freeze(True);
17 PlotPen.Width:=2;
PlotMode:=pmLine;
18
19 if TryStrToFloat(My_Multimeter.Status.ValueNoPrefix,y) then begin
20
21 AddXY(FormGraph.Xcur,y); //Plot x,y point
22
23 //Autoscale
24 if FormGraph.CheckBoxAutoscaleY.Checked then begin
if FormGraph.Xcur > 10 then AutoScale(0); //Autoscale x,y
25 end else begin
26 YMax:=FormGraph.SpinEditMaxY.Value;
27 YMin:=FormGraph.SpinEditMixY.Value;
28 end;
29
30 XMin:=FormGraph.Xcur-FormGraph.Xwidth; //Scale X to XWidth
XMax:=FormGraph.Xcur;
31 XInterval:=1;
32 YInterval:=(YMax-YMin)/10;
33
34 end;
35
36 Freeze(False);
end;
37
38 end;
39 end else begin
40 StatusBar.Panels.Items[1].Text := StatusBar.Panels.Items[1].Text + ' [invalid]';
41 end;
42
43 FormMain.Refresh;
44
//Close the timer and disconnect if IsConnected is false
45 if not IsConnected then begin
46 Timer.Enabled:=false;
47 Disconnect();
48 end;
49end;
50
51
52
53
54
55
56
57
We are done !
DMM Data Logger can be downloaded from here Opens in a new window