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 :

#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 :

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:

#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

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

atau

//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

//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

//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:

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:

  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:

  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:

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

#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

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

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;
}