Meningkatkan presisi pembacaan sensor analog dengan metode Trimmed Mean

Sensor-sensor analog dibaca oleh arduino melalui pin analog menggunakan adc. Agar pembacaan adc oleh arduino memiliki presisi yang baik diperlukan perlakuan (treatment) sisi hardware  diantaranya:

  1. Jika impedansi keluaran (output) sensor besar (>10 kΩ) maka perbesar sampling and hold time (s/h) dengan cara mengganti nilai ADCSRA,
  2. Gunakan tegangan referensi yang sesuai dengan tegangan maksimal keluaran sensor menggunakan perintah analogReference(),
  3. Gunakan kabel sependek mungkin antara pin output sensor dan pin adc arduino dan terselubung ground,
  4. Jauhkan kabel dan sensor dari komponen yang bisa menimbulkan interferensi elektromagnetik,
  5. Jika menggunakan tegangan referensi luar, tambakan dengan filter LC,
  6. Pin-pin analog yang tidak digunakan sebaiknya tidak dioperasikan saat proses pembacaan sensor.
  7. Tegangan power supply yang stabil dan terproteksi dari gangguan luar.

Pada sisi software bisa dilakukan peningkatan presisi diataranya menggunakan metode rata-rata seperti Mean, Trimmed Mean, Truncated mean, Winsorizing, Interquartile mean dan sebagainya.

Berikut contoh penggunaan metode Trimmed Mean untuk meningkatkan presisi pembacaan sensor analog :

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
#define faktorTrim        0.2 //20%
#define jumlahSampel      10
 
#define pinSensor         A0
 
int buffer[jumlahSampel], temp, rataRata;
 
void setup() {
  Serial.begin(9600);
  Serial.println(F("Meningkatkan presisi pembacaan sensor analog dengan metode Trimmed Mean"));
  Serial.println(F("https://www.project.semesin.com"));
  Serial.println();
}
 
void loop() {
  for (int i = 0; i < jumlahSampel; i++)
  {
    buffer[i] = analogRead(pinSensor);
    delay(10);
  }
 
  //proses pengurutan (sorting)
  for (int i = 0; i < jumlahSampel - 1; i++)
  {
    for (int j = i + 1; j < jumlahSampel; j++)
    {
      if (buffer[i] > buffer[j])
      {
        temp = buffer[i];
        buffer[i] = buffer[j];
        buffer[j] = temp;
      }
    }
  }
 
  //rata-rata (trimmed mean)
  rataRata = 0;
  for (int i = jumlahSampel * faktorTrim; i < jumlahSampel * (1 - faktorTrim); i++)
  {
    rataRata += buffer[i];
  }
 
  rataRata /= jumlahSampel * (1- (faktorTrim*2));
 
  Serial.print("sensor = ");
  Serial.println(rataRata);
 
  delay(500);
}

Media pembelajaran polygon berbasis Delphi

Poligon adalah geometri dengan banyak sudut seperti segitiga, segi empat dan nonagon dan lainnya. poligon terdiri atas beberapa titik atau vertex yang terhubung menjadi sebuah bentuk geometri. Poligon memiliki penamaan khusus sesuai jumlah sudutnya.

Poligon merupakan geometri yang dapat dikembangkan secara luas sehingga digunakan di berbagai bidang.

Untuk memudahkan mengenal atau memperkenalkan polygon, salah satu media yang bisa digunakan adalah pc/laptop. Fitur dasar seperti create dan modify adalah sebagai langkah awal  untuk membangun sebuah media pembelajaran geometri. Selanjutnya  bisa dikembangkan menjadi lebih fungsional sesuai kebutuhan pengembangannya.

Screenshoot media pembelajaran polygin menggunakan delphi :

Kode delphi pengembangan media belajar geometri polygon :

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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Buttons, Grids;
 
type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Image1: TImage;
    GroupBox1: TGroupBox;
    GroupBox3: TGroupBox;
    GroupBox2: TGroupBox;
    LabelPosisi: TLabel;
    ButtonClose: TButton;
    LabelVertex: TLabel;
    GroupBox4: TGroupBox;
    StringGrid1: TStringGrid;
    ButtonDelete: TButton;
    ButtonDraw: TButton;
    ButtonEdit: TButton;
    ButtonInsert: TButton;
    ButtonClear: TButton;
    ButtonSave: TButton;
    ButtonOpen: TButton;
    Label1: TLabel;
    procedure ButtonDrawClick(Sender: TObject);
    procedure ButtonEditClick(Sender: TObject);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Image1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ButtonCloseClick(Sender: TObject);
    procedure ButtonSaveClick(Sender: TObject);
    procedure ButtonLoadClick(Sender: TObject);
    procedure refreshCanvas();
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure ButtonDeleteClick(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure ButtonInsertClick(Sender: TObject);
    procedure ButtonClearClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
type Point = record
 X : integer;
 Y : integer;
end;
 
var
  Form1: TForm1;
  modeOperasi : integer;
  posisi : Point;
  tinggiCanvas : integer;
  startPolygon : boolean;
  polygon : array[0..20] of Point;
  polygonCount : integer;
  editIndex : integer;
 
const
  modeIdle = 0;
  modeDraw = 1;
  modeEdit = 3;
  modeInsert = 4;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.refreshCanvas();
var
  i : integer;
begin
  StringGrid1.RowCount := polygonCount + 1;
 
  i := 0;
  while true do
  begin
    if polygon[i].X = -1 then
      break;
    StringGrid1.Cells[0,i+1] := inttostr(i+1);
    StringGrid1.Cells[1,i+1] := inttostr(polygon[i].X);
    StringGrid1.Cells[2,i+1] := inttostr(polygon[i].Y);
 
    if i = 0 then
    begin
      image1.Canvas.rectangle(0,0,image1.width-1, image1.height-1);
      image1.Canvas.MoveTo(polygon[0].X, tinggiCanvas - polygon[0].Y);
    end
    else
    begin
      if (modeOperasi = modeInsert) and (editIndex = i) then
      begin
        Image1.Canvas.Pen.Color := clRed;
      end
      else
      begin
        Image1.Canvas.Pen.Color := clBlack;
      end;
      image1.Canvas.LineTo(polygon[i].X, tinggiCanvas - polygon[i].Y);
    end;
 
    i := i + 1;
    if i = 20 then
      break;
 
  end;
 
   if modeOperasi = modeEdit then
   begin
    image1.Canvas.Rectangle(polygon[editIndex].X-5, tinggiCanvas - polygon[editIndex].Y - 5,
      polygon[editIndex].X+5, tinggiCanvas - polygon[editIndex].Y + 5);
   end;
 
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.Cells[0,0] := 'No';
  StringGrid1.Cells[1,0] := 'X';
  StringGrid1.Cells[2,0] := 'Y';
end;
 
 
procedure TForm1.FormResize(Sender: TObject);
begin
  tinggiCanvas := Image1.Height;
 
end;
 
procedure TForm1.ButtonDrawClick(Sender: TObject);
begin
  buttonDraw.Font.Style := [fsBold];
  ButtonEdit.Font.Style := [];
  ButtonInsert.Font.Style := [];
 
  modeOperasi := modeDraw;
  startPolygon := true;
  polygonCount := 0;
  polygon[polygonCount].X := -1;
 
  refreshCanvas();
end;
 
procedure TForm1.ButtonCloseClick(Sender: TObject);
begin
 
  if (modeOperasi = modeDraw) and (polygonCount > 1) then
  begin
    polygon[polygonCount] := polygon[0];
    polygonCount := polygonCount + 1;
 
    polygon[polygonCount].X := -1;
 
    LabelVertex.Caption := 'Vertex ' + inttostr(polygonCount);
 
    refreshCanvas();
 
    buttonDraw.Font.Style := [];
    ButtonEdit.Font.Style := [];
    ButtonInsert.Font.Style := [];
    modeOperasi := modeIdle;
  end;
 
end;
 
procedure TForm1.ButtonEditClick(Sender: TObject);
begin
  buttonDraw.Font.Style := [];
  ButtonEdit.Font.Style := [fsBold];
  ButtonInsert.Font.Style := [];
  modeOperasi := modeEdit;
  editIndex := 1;
  refreshCanvas();
end;
 
procedure TForm1.ButtonInsertClick(Sender: TObject);
begin
  buttonDraw.Font.Style := [];
  ButtonEdit.Font.Style := [];
  ButtonInsert.Font.Style := [fsBold];
  modeOperasi := modeInsert;
  editIndex := 1;
  refreshCanvas();
end;
 
 
procedure TForm1.ButtonClearClick(Sender: TObject);
begin
  polygonCount := 0;
  polygon[polygonCount].X := -1;
 
  refreshCanvas();
end;
 
procedure TForm1.ButtonDeleteClick(Sender: TObject);
var
  i : integer;
begin
  if editIndex <> 0 then
  begin
    for i := editIndex to polygonCount do
    begin
      polygon[i].X := polygon[i+1].X;
      polygon[i].Y := polygon[i+1].Y;
    end;
    polygonCount := polygonCount - 1;
    refreshCanvas();
  end;
end;
 
 
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  posisi.X := X;
  posisi.Y := tinggiCanvas - Y;
  LabelPosisi.Caption := 'Posisi ' + inttostr(posisi.X) + ', ' + inttostr(posisi.Y);
end;
 
procedure TForm1.Image1Click(Sender: TObject);
var
  i : integer;
begin
  if (modeOperasi = modeDraw) and (polygonCount < 20) then
  begin
    polygon[polygonCount].X := posisi.X;
    polygon[polygonCount].Y := posisi.Y;
    polygonCount := polygonCount + 1;
    polygon[polygonCount].X := -1;
    LabelVertex.Caption := 'Vertex ' + inttostr(polygonCount);
 
    refreshCanvas();
  end
  else if (modeOperasi = modeEdit) and (editIndex > 0)then
  begin
    if (editIndex = 1) or (editIndex = polygonCount-1) then
    begin
      polygon[1].X := posisi.X;
      polygon[1].Y := posisi.Y;
      polygon[polygonCount-1].X := posisi.X;
      polygon[polygonCount-1].Y := posisi.Y;
    end
    else if (editIndex > 0) then
    begin
      polygon[editIndex].X := posisi.X;
      polygon[editIndex].Y := posisi.Y;
 
    end;
 
    refreshCanvas();
  end
  else if (modeOperasi = modeInsert) and (editIndex > 0) and (polygonCount < 20) then
  begin
    for i := polygonCount downto editIndex do
    begin
      polygon[i+1].X := polygon[i].X;
      polygon[i+1].Y := polygon[i].Y;
    end;
    polygon[editIndex].X := posisi.X;
    polygon[editIndex].Y := posisi.Y;
    polygonCount := polygonCount + 1;
    refreshCanvas();
 end;
 
end;
 
 
procedure TForm1.ButtonSaveClick(Sender: TObject);
var
  Stream: TStream;
begin
  Stream:= TFileStream.Create('polygon.bin', fmCreate);
  Stream.WriteBuffer(polygonCount, SizeOf(integer));
  Stream.WriteBuffer(polygon, (polygonCount+1) * SizeOf(Point));
  Stream.Free;
end;
 
procedure TForm1.ButtonLoadClick(Sender: TObject);
var
  Stream: TStream;
begin
  Stream:= TFileStream.Create('polygon.bin', fmOpenRead);
  Stream.ReadBuffer(polygonCount, SizeOf(integer));
  Stream.ReadBuffer(polygon, (polygonCount+1) * SizeOf(Point));
  Stream.Free;
 
  refreshCanvas();
  LabelVertex.Caption := 'Vertex ' + inttostr(polygonCount);
 
end;
 
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
begin
  editIndex := ARow - 1;
  refreshCanvas();
end;
 
end.

code lengkap media pengajaran geometri poligon:
library :

simulasi Gerak lurus berubah beraturan (GLBB) – Gerak jatuh bebas menggunakan arduino

Gerak lurus berubah beraturan (GLBB) adalah gerak lurus yang percepatannya tetap, artinya kecepatannya berubah beraturan. terdapat beberapa jenis GLBB yaitu :

  1. Gerak vertikal ke atas
  2. Gerak jatuh bebas
  3. Gerak vertikal ke bawah

untuk keperluan simulasi gerak lurus berubah beraturan diperlukan peralatan sebagai berikut :

  1. Arduino uno
  2. 3x sensor obstacle
  3. sensor ultrasonic
  4. Tombol

Dengan tata letak seperti berikut:

Skema simulasi GLBB menggunakan arduino:

sketch/koding simulasi gerak lurus berubah beraturan berbasis arduino:

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
#define tinggiSensorBawah   10//cm
 
#define pinTombolMulai      A0
 
#define pinSensorA          8
#define pinSensorB          9
#define pinSensorC          10
 
#include <Ultrasonic.h>
 
Ultrasonic ultrasonic(3, 2);
 
uint16_t nomor;
 
void setup() {
  pinMode(pinTombolMulai, INPUT_PULLUP);
 
  pinMode(pinSensorA, INPUT_PULLUP);
  pinMode(pinSensorB, INPUT_PULLUP);
  pinMode(pinSensorC, INPUT_PULLUP);
 
  Serial.begin(9600);
  Serial.println("Gerak Lurus Berubah Beraturan");
  Serial.println("https://www.project.semesin.com");
 
  Serial.println();
  Serial.println("Gerak Lurus Berubah Beraturan (jatuh bebas)");
  Serial.println("No\tJarak (cm)\tWaktu (s)\tPercepatan (cm/s2)");
 
}
 
void loop() {
 
  if (!digitalRead(pinTombolMulai))
  {
    delay(50);
    if (!digitalRead(pinTombolMulai))
    {
      while (!digitalRead(pinTombolMulai));
 
      uint16_t tinggi = 1.0 * ultrasonic.read() - tinggiSensorBawah;
      float jarakSensor = 1.0 * tinggi / 2;
 
      unsigned long waktuA, waktuB, waktuC;
      bool mulaiDiTitikA, mulaiDiTitikC = false;
      while (1)
      {
        if (!digitalRead(pinSensorA))
        {
          waktuA = micros();
          mulaiDiTitikA = true;
          break;
        }
        if (!digitalRead(pinSensorC))
        {
          waktuC = micros();
          mulaiDiTitikC = true;
          break;
        }
      }
 
      while (digitalRead(pinSensorB));
      waktuB = micros();
 
      while (1)
      {
        if (!digitalRead(pinSensorA))
        {
          waktuA = micros();
          break;
        }
        if (!digitalRead(pinSensorC))
        {
          waktuC = micros();
          break;
        }
      }
 
      float waktu_ac = abs(1.0 * waktuC - waktuA) / 1000000;//detik
      float waktu_ab = abs(1.0 * waktuB - waktuA) / 1000000;//detik
      float waktu_bc = abs(1.0 * waktuC - waktuB) / 1000000;//detik
 
      float kecepatan_ab = 0.5 * jarakSensor / waktu_ab;//cm/s
      float kecepatan_cb = 0.5 * jarakSensor / waktu_ab;//cm/s
      float kecepatan_bc = 0.5 * jarakSensor / waktu_bc;//cm/s
 
      float percepatan;
      if (mulaiDiTitikA)
      {
        percepatan = (1.0 * kecepatan_bc - kecepatan_ab) / waktu_bc;//cm/s2
      }
      if (mulaiDiTitikC)
      {
        percepatan = (1.0 * kecepatan_ab - kecepatan_bc) / waktu_ab;//cm/s2
      }
 
      char buffer[200];
      char strWaktu_ac[10];
      char strPercepatan[10];
 
      dtostrf(waktu_ac, 8, 2, strWaktu_ac);
      dtostrf(percepatan, 8, 2, strPercepatan);
 
      sprintf(buffer, "%d\t%d\t\t%s\t%s", nomor, tinggi, strWaktu_ac, strPercepatan);
      Serial.println(buffer);
      nomor++;
 
    }
  }
}

Library:

Kalkulator online persamaan garis lurus antara dua titik

Menghitung persamaan garis linear dengan rumus :

masukkan nilai (x1, y1), (x2, y2) dan nilai x jika ingin mencari nilai y pada titik x tersebut pada kotak berikut :

[WPcalc id=1]

 

Persamaan garis lurus adalah garis dalam bentuk matematis berpangkat satu. Persamaan umumnya adalah :

y = mx + c

dimana m = gradien dan c = konstanta.

Gradien adalah kemiringan dari suatu garis dan konstanta adalah ketinggian garis pada x = 0.

Konversi sistem bilangan biner ke BCD

Bilangan biner adalah angka berbasis 2 yang hanya memiliki numerik ‘0’ dan ‘1’. Dalam ilmu komputer satu numerik bilangan biner disebut “bit”, apabila bilangan ini dikelompokkan kedalam 8 bit disebut dengan byte, Satu byte bisa menyimpan kombinasi hingga 2^8 atau 256 kombinasi.

Dalam ilmu komputer juga dikenal bilangan hex (hexadesimal) yaitu angka berbasis 16 dengan numerik 0-9 dan A-F, bilangan ini merepresentasikan 4-bit bilangan biner (binary number).

Bilangan biner atau bilangan hex juga bilangan byte umum digunakan dalam perhitungan digital dan komputer, namun bilangan ini sulit dicerna oleh manusia yang menggunakan bilangan desimal (basis 10),

Bilangan BCD (binary coded decimal) adalah bilangan hex dalam bentuk desimal yang lebih familier dan bisa terbaca oleh manusia dalam bentuk desimal.

byte 8-bit binary ke BCD

1
2
3
4
5
//max hex 0x63 / bcd 0x99
uint8_t Convert_IntToBCD(uint8_t DecimalValue)
{
    return DecimalValue + 6 * (DecimalValue / 10);
}

atau

1
2
3
4
5
6
7
8
9
10
11
12
13
//max hex 0x63 / bcd 0x99
uint8_t Convert_IntToBCD(uint8_t DecimalValue)
{
    uint8_t MSB = 0;
    uint8_t LSB = DecimalValue;
 
    while (LSB >= 10)
    {
        LSB -= 10;
        MSB += 0x10;
    }
    return MSB + LSB;
}

word 16-bit binary ke BCD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//max hex 0x270F / bcd 0x9999
uint16_t Convert_IntToBCD16(uint16_t DecimalValue)
{
    uint16_t returnValue = 0;
    //uint16_t LSB_L = DecimalValue;
 
    while (DecimalValue >= 1000)
    {
        DecimalValue -= 1000;
        returnValue += 0x1000;
    }
    while (DecimalValue >= 100)
    {
        DecimalValue -= 100;
        returnValue += 0x0100;
    }
    while (DecimalValue >= 10)
    {
        DecimalValue -= 10;
        returnValue += 0x0010;
    }
    return returnValue + DecimalValue;
}

integer 32-bit binary ke BCD

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
//max hex 0x5F5E0FF / bcd 0x99999999
uint32_t Convert_IntToBCD32(uint32_t DecimalValue)
{
    uint32_t returnValue = 0;
    //uint32_t LSB_L = DecimalValue;
 
    while (DecimalValue >= 10000000L)
    {
        DecimalValue -= 10000000L;
        returnValue += 0x10000000;
    }
    while (DecimalValue >= 1000000L)
    {
        DecimalValue -= 1000000L;
        returnValue += 0x01000000;
    }
    while (DecimalValue >= 100000L)
    {
        DecimalValue -= 100000L;
        returnValue += 0x00100000;
    }
    while (DecimalValue >= 10000)
    {
        DecimalValue -= 10000;
        returnValue += 0x00010000;
    }
    while (DecimalValue >= 1000L)
    {
        DecimalValue -= 1000L;
        returnValue += 0x00001000;
    }
    while (DecimalValue >= 100)
    {
        DecimalValue -= 100;
        returnValue += 0x00000100;
    }
    while (DecimalValue >= 10)
    {
        DecimalValue -= 10;
        returnValue += 0x00000010;
    }
    return returnValue + DecimalValue;
}

Perhitungan regresi linear menggunakan arduino

Statistik regresi linear berfungsi mencari nilai trend suatu variabel terhadap pengaruh variabel lainnya. Fungsi regresi linear berupa persamaan grafis yang menyatakan perbedaan nilai dalam rentang/interval tertentu sehingga bisa dianalisis sebagai akibat dari perbedaan variabel input (variabel masukan/ variabel bebas/independen).

Jika diketahui variabel X1..Xn yang mempengaruhi variabel Y1..Yn maka persamaan regresi linear umum/sederhana adalah:

dimana m adalah gradien (kemiringan) dan b adalah konstanta.

source code regresi linear arduino:

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
struct sample
{
  byte waktu;
  float data;
};
 
void setup() {
  Serial.begin(9600);
  Serial.println("Statistik regresi linear dengan Arduino");
  Serial.println("https://www.project.semesin.com/");
  Serial.println();
}
 
void loop() {
  sample Pengukuran[] = {
    {1, 21.2},
    {2, 28.5},
    {3, 42.3},
    {4, 53.9},
    {5, 57.1},
    {6, 70.2},
    {7, 79.9},
    {8, 89.2},
    {9, 101.6},
    {10, 112.4},
  };
 
  float m;
  float b;
 
  regresiLinear(Pengukuran, 10, &m, &b);
 
  Serial.print("m = ");
  Serial.println(m);
  Serial.print("b = ");
  Serial.println(b);
  Serial.print("Prediksi waktu ke-11 = ");
  Serial.println(m * 11 + b);
 
  while (1);
}
 
void regresiLinear(sample *sampling, byte jumlahSampling, float *m, float *b)
{
  byte jumlahWaktu = 0;
  float jumlahData = 0.0;
  uint32_t jumlahDataWaktu = 0;
  uint32_t jumlahWaktu2 = 0;
  float jumlahData2 = 0.0;
  for (byte i = 0; i < jumlahSampling; i++)
  {
    jumlahWaktu += sampling[i].waktu;
    jumlahData += sampling[i].data;
    jumlahDataWaktu += (sampling[i].waktu * sampling[i].data);
    jumlahWaktu2 +=  (sampling[i].waktu *  sampling[i].waktu);
    jumlahData2 +=  (sampling[i].data *  sampling[i].data);
  }
  *m = (jumlahSampling * jumlahDataWaktu) - (jumlahWaktu * jumlahData);
  *m /= (jumlahSampling * jumlahWaktu2) - (jumlahWaktu * jumlahWaktu);
 
  *b = (jumlahWaktu2 * jumlahData) - (jumlahWaktu * jumlahDataWaktu);
  *b /= (jumlahSampling * jumlahWaktu2) - (jumlahWaktu * jumlahWaktu);
}

contoh keluaran serial monitor:

Statistik nilai mean, median dan modus menggunakan arduino

Pembacaan nilai analog arduino sering memberikan hasil dengan simpangan dari nilai yang seharusnya. Untuk mengurangi kesalahan ini kita bisa mengambil nilai rata-rata dari beberapa sample. ada beberapa metode untuk mencari nilai pendekatan pembacaan sensor ini yaitu:

Mean (nilai rata-rata)

adalah nilai tengah dari kelompok data yaitu dengan menjumlahkan seluruh data individu dan kemudian membaginya dengan jumlah individu tersebut.

dalam sketch arduino nilai mean dituliskan:

1
2
3
4
5
6
7
8
9
10
11
float Sampel[] = {75.2, 82.0, 83.7, 74.4, 80.1, 85.5, 82.0, 80.1};
byte jumlahSampel = sizeof(Sampel) / sizeof(Sampel[0]);
 
float jumlah = 0;
for (int i = 0; i < jumlahSampel; i++)
{
  jumlah += Sampel[i];
}
float mean = jumlah / jumlahSampel;
Serial.print("mean = ");
Serial.println(mean);

Median (nilai tengah)

adalah nilai yang letaknya ditengah-tengah dari data yang telah diurutkan dari yang terkecil.

contoh penggunaan median pada arduino:

1
2
3
4
5
6
7
8
9
10
11
12
float Sampel[] = {75.2, 82.0, 83.7, 74.4, 80.1, 85.5, 82.0, 80.1};
byte jumlahSampel = sizeof(Sampel) / sizeof(Sampel[0]);
 
urutkanSampel(Sampel, jumlahSampel);
float median = Sampel[(byte)(jumlahSampel / 2)];
if (!(jumlahSampel % 2))
{
  median += Sampel[(byte)(jumlahSampel / 2) - 1];
  median /= 2;
}
Serial.print("median = ");
Serial.println(median);

Modus (Data paling sering)

Adalah data yang paling sering muncul (frekuensi tertinggi) dan tidak ada yang sama dengan frekuensi tersebut.

Contoh penggunaan mean, median dan modus pada arduino:

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
void setup() {
  Serial.begin(9600);
  Serial.println("Mean, media, modus dengan Arduino");
  Serial.println("https://www.project.semesin.com/");
  Serial.println();
}
 
void loop() {
  float Sampel[] = {75.2, 82.0, 83.7, 74.4, 80.1, 85.5, 82.0, 80.1};
 
  byte jumlahSampel = sizeof(Sampel) / sizeof(Sampel[0]);
  float jumlah = 0;
  for (int i = 0; i < jumlahSampel; i++)
  {
    jumlah += Sampel[i];
  }
  float mean = jumlah / jumlahSampel;
  Serial.print("mean = ");
  Serial.println(mean);
 
  urutkanSampel(Sampel, jumlahSampel);
  float median = Sampel[(byte)(jumlahSampel / 2)];
  if (!(jumlahSampel % 2))
  {
    median += Sampel[(byte)(jumlahSampel / 2) - 1];
    median /= 2;
  }
  Serial.print("median = ");
  Serial.println(median);
 
  float modus;
  Serial.print("modus = ");
  if(cariModus(Sampel, jumlahSampel, &modus))
  {
    Serial.println(modus);
  }
  else
  {
    Serial.println("tidak ada");
  }
   
  while (1);
}
 
void urutkanSampel(float *dataArray, byte jumlahData)
{
  byte i = 0;
  for (byte i = 0; i < jumlahData; i++)
  {
    byte k;
    for (byte j = 1; j < jumlahData; j++)
    {
      if (dataArray[j - 1] > dataArray[j])
      {
        float temp = dataArray[j - 1];
        dataArray[j - 1] = dataArray[j];
        dataArray[j] = temp;
      }
    }
  }
}
bool cariModus(float *dataArray, byte jumlahData, float *modus)
{
  byte frekuensi;
  float frekuensiData;
  byte frekuensiMax = 0;
  byte frekuensiMaxCount = 0;
  *modus = 0;
  for (byte i = 0; i < jumlahData; ++i)
  {
    frekuensi = 0;
    for (byte j = 0; j < jumlahData; j++)
    {
      if (dataArray[i] == dataArray[j])
      {
        frekuensi++;
      }
    }
    if(frekuensiMax < frekuensi)
    {
      frekuensiMax = frekuensi;
      frekuensiData = dataArray[i];
      *modus = dataArray[i];
      frekuensiMaxCount = 0;
    }
    else if((frekuensiMax == frekuensi) && (frekuensiData != dataArray[i]))
    {
      frekuensiMaxCount++;
    }
  }
  if(!frekuensiMaxCount)
  {
    return true;
  }
  return false;
}

Prediksi Extrapolation dengan Arduino

Ekstrapolasi (Extrapolation) adalah proses matematis untuk memprediksi nilai yang akan datang berdasarkan keterkaitan matematis dari nilai-nilai sebelumnya.

Dalam contoh ini akan diprediksi nilai sinus 60° dari deret sinusional sin-0, 10, 20, 30, 40, 50. Pendekatan yang digunakan adalah linear dan polynomial (quadratic, cubic, quartic dan quintic), menggunakan operasi matrik. Formula matematis ini dikerjakan dengan bantuan arduino Uno.

dan hasilnya adalah:

  • Seharusnya (sinus(60) * 1000) = 866.02
  • Linear Extrapolation = 889.34
  • Polynomial Extrapolation (quadratic)= 869.84
  • Polynomial Extrapolation (cubic) = 865.54
  • Polynomial Extrapolation (quartic) = 904.61
  • Polynomial Extrapolation (quintic) = 866.39

Berikut sketch/koding ekstra polasi arduino:

Link download library MatrixMath

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
#include <MatrixMath.h>
 
float dataSinus[] = {0.0, 173.64, 342.02, 500.00, 642.78, 766.06};// -- 866.02
 
void setup() {
  Serial.begin(9600);
  Serial.println("Prediksi Extrapolation dengan Arduino");
  Serial.println("https://www.project.semesin.com/");
  Serial.println();
 
  byte indexTerakhir = sizeof(dataSinus) / sizeof(float) - 1;
 
  Serial.print("Seharusnya (sinus(60) * 1000) = ");
  Serial.println(866.02);
 
  float prediksi;
  prediksi = linearExtrapolation(dataSinus[indexTerakhir], dataSinus[indexTerakhir - 1]);
  Serial.print("Linear Extrapolation = ");
  Serial.println(prediksi);
   
  prediksi = polynomialExtrapolationQuadratic(dataSinus[indexTerakhir], dataSinus[indexTerakhir - 1], dataSinus[indexTerakhir - 2]);
  Serial.print("Polynomial Extrapolation (quadratic)= ");
  Serial.println(prediksi);
 
  prediksi = polynomialExtrapolationCubic(
    dataSinus[indexTerakhir],
    dataSinus[indexTerakhir - 1],
    dataSinus[indexTerakhir - 2],
    dataSinus[indexTerakhir - 3]);
  Serial.print("Polynomial Extrapolation (cubic) = ");
  Serial.println(prediksi);
 
  prediksi = polynomialExtrapolationQuartic(
    dataSinus[indexTerakhir],
    dataSinus[indexTerakhir - 1],
    dataSinus[indexTerakhir - 2],
    dataSinus[indexTerakhir - 3],
    dataSinus[indexTerakhir - 4]);
  Serial.print("Polynomial Extrapolation (quartic) = ");
  Serial.println(prediksi);
 
  prediksi = polynomialExtrapolationQuintic(
    dataSinus[indexTerakhir],
    dataSinus[indexTerakhir - 1],
    dataSinus[indexTerakhir - 2],
    dataSinus[indexTerakhir - 3],
    dataSinus[indexTerakhir - 4],
    dataSinus[indexTerakhir - 5]);
  Serial.print("Polynomial Extrapolation (quintic) = ");
  Serial.println(prediksi);
 
  while (1);
}
 
void loop() {
 
}
 
float linearExtrapolation(float dataN, float dataNminus1)
{
  return dataNminus1 + (2 * (dataN - dataNminus1));
}
float polynomialExtrapolationQuadratic(float dataN, float dataNminus1, float dataNminus2)
{
  float A[3][3] = {{1.0, 0.0, 0.0},
    {1.0, 1.0, 1.0},
    {1.0, 2.0, 4.0}
  };
  float B[3] = {dataNminus2, dataNminus1, dataN};
  float C[3];
 
  Matrix.Invert((float*)A, 3);
  Matrix.Multiply((float*)A, (float*)B, 3, 3, 1, (float*)C);
 
  return(C[0] + (C[1] * 3.0) + (C[2] * 9.0));
}
 
float polynomialExtrapolationCubic(float dataN, float dataNminus1, float dataNminus2, float dataNminus3)
{
  float A[4][4] = {
    {1.0, 0.0, 0.0, 0.0},
    {1.0, 1.0, 1.0, 1.0},
    {1.0, 2.0, 4.0, 8.0},
    {1.0, 3.0, 9.0, 27.0}
  };
  float B[4] = {dataNminus3, dataNminus2, dataNminus1, dataN};
  float C[4];
 
  Matrix.Invert((float*)A, 4);
  Matrix.Multiply((float*)A, (float*)B, 4, 4, 1, (float*)C);
 
  return(C[0] + (C[1] * 4.0) + (C[2] * 16.0) + (C[3] * 64.0));
}
 
float polynomialExtrapolationQuartic(float dataN, float dataNminus1, float dataNminus2, float dataNminus3, float dataNminus4)
{
  float A[5][5] = {
    {1.0, 0.0, 0.0, 0.0, 0.0},
    {1.0, 1.0, 1.0, 1.0, 1.0},
    {1.0, 2.0, 4.0, 8.0, 16.0},
    {1.0, 3.0, 9.0, 27.0, 81.0},
    {1.0, 4.0, 8.0, 64.0, 256.0}
  };
  float B[5] = {dataNminus4, dataNminus3, dataNminus2, dataNminus1, dataN};
  float C[5];
 
  Matrix.Invert((float*)A, 5);
  Matrix.Multiply((float*)A, (float*)B, 5, 5, 1, (float*)C);
 
  return(C[0] + (C[1] * 5.0) + (C[2] * 25.0) + (C[3] * 125.0) + (C[4] * 625.0));
}
 
float polynomialExtrapolationQuintic(float dataN, float dataNminus1, float dataNminus2, float dataNminus3, float dataNminus4, float dataNminus5)
{
  float A[6][6] = {
    {1.0, 0.0, 0.0, 0.0, 0.0, 0.0},
    {1.0, 1.0, 1.0, 1.0, 1.0, 1.0},
    {1.0, 2.0, 4.0, 8.0, 16.0, 32.0},
    {1.0, 3.0, 9.0, 27.0, 81.0, 243.0},
    {1.0, 4.0, 8.0, 64.0, 256.0, 1024.0},
    {1.0, 5.0, 25.0, 125.0, 625.0, 3125.0}
  };
  float B[6] = {dataNminus5, dataNminus4, dataNminus3, dataNminus2, dataNminus1, dataN};
  float C[6];
 
  Matrix.Invert((float*)A, 6);
  Matrix.Multiply((float*)A, (float*)B, 6, 6, 1, (float*)C);
 
  return(C[0] + (C[1] * 6.0) + (C[2] * 36.0) + (C[3] * 216.0) + (C[4] * 1296.0) + (C[5] * 7776.0));
}

hasil Serial monitor:

Linear-feedback shift register (LFSR) dengan arduino

LFSR (linear-feedback shift register) adalah metode matematis untuk menghasilkan sebuah bilangan yang linear dengan bilangan sebelumnya.

Fungsi matematis ini digunakan sebagai:

  1. menghasilkan bilangan acak (random generator)
  2. Menghasilkan bilangan tersusun yang berulang sehingga bisa dimanfaatkan sebagai pembangkit suara gangguan (noise) seperti di tv/radio dengan siaran acak ketika tidak siaran.

sketch/program arduino LFSR:

metode Fibonacci

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
uint16_t LFSRBuffer;
 
void setup() {
  Serial.begin(9600);
  Serial.println("LFSR metode Fibonacci");
  Serial.println("https://www.project.semesin.com");
   
  uint16_t nilaiAwal = analogRead(0);
  LFSRFibonacci(nilaiAwal);
  //LFSRFibonacci(100);
}
 
void loop() {
  uint16_t bilanganLFSR = LFSRFibonacci();
  Serial.println(bilanganLFSR);
 
  delay(1000);
}
 
void LFSRFibonacci(uint16_t nilaiAwal)
{
  LFSRBuffer = nilaiAwal;
}
 
uint16_t LFSRFibonacci()
{
    uint16_t bit;
     
    bit  = ((LFSRBuffer >> 0) ^ (LFSRBuffer >> 2) ^ (LFSRBuffer >> 3) ^ (LFSRBuffer >> 5)) & 1;
    LFSRBuffer =  (LFSRBuffer >> 1) | (bit << 15);
    return LFSRBuffer;
}

metode Galois

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
uint16_t LFSRBuffer;
 
void setup() {
  Serial.begin(9600);
  Serial.println("LFSR metode Galois");
  Serial.println("https://www.project.semesin.com");
   
  uint16_t nilaiAwal = analogRead(0);
  LFSRGalois(nilaiAwal);
  //LFSRGalois(100);
}
 
void loop() {
  uint16_t bilanganLFSR = LFSRGalois();
  Serial.println(bilanganLFSR);
 
  delay(1000);
}
 
void LFSRGalois(uint16_t nilaiAwal)
{
  LFSRBuffer = nilaiAwal;
}
 
uint16_t LFSRGalois()
{
    unsigned lsb = LFSRBuffer & 1;
    LFSRBuffer >>= 1;
    if (lsb)
    {
        LFSRBuffer ^= 0xB400;
    }
    return LFSRBuffer;
}