Pembuatan PCB dengan DEET (Lotion anti nyamuk)

Desain PCB

  1. Lebar track >= 20mil (0,5 mm), jarak antar track >= 20mil (kecuali ada smd yang jarak kakinya 10 mil, tidak masalah)
  2. Cetak via, hole, top/bottom dan dimension untuk Toner transfer.
  3. Cetak tCream/bCream, hole, dan dimension untuk masking. Atau cukup pilih tStop/bStop, cetak dengan memilih solid dan black.



A. Persiapkan PCB:
PCB harus bebas korosi. Jika banyak minyak, pertama tama bersihkan tembaga menggunakan sabun cuci piring lalu keringkan. Anginkan atau jemur PCB hingga kering. Jika sudah tidak ada minyak yang menempel pada tembaha, gosok tembaga menggunakan penggosok panci atau ampelas halus. Lalu bersihkan debu butiran menggunakan tisu atau kertas polos dan alkohol 95%. Jika menggunakan aceton murni akan lebih baik. Aceton ini bukan yang digunakan untuk pembersih kuku, karena biasanya aseton jenis ini sudah dilarutkan dengan air, alkohol, vitamin dan pewangi.

Catatan:
PCB harus bebas dari minyak dan korosi, sehingga toner atau senyawa lain mudah menempel. Dissarankan untuk membersihkan dengan alkohol/aseton. Membersihakn dengan air dapat menjadikan air bereaksi dengan tembaga dan membentuk korosi.

B. Proses transfer toner
1.Siapkan kertas fotokopi yang sudah di-mirror. Potong sesuai ukuran. Tempelkan bagian toner ke tembaga dan kunci dengan isolasi jika perlu.
2. Tuang beberapa titik di diethyltoluamide (DEET), biasanya ada pada lotion anti nyamuk, di atas kertas dan usapkan hingga kertas menjadi transparan. Jika belum transparant, tambahkan sedikit-demi sedikit. Jangan menambahkan terlalu banyak karena dapat mengakibatkan kertas bergelombang, dan menjadikan toner terlalu lembek.
3. Tambahkan sedikit air cukup dengan mencelupkan tangan di air lalu usapka menggunakan tangan di kertas. Tutup dengan cellophane atau mika bungkus kado.
4. Gunakan koin atau kartu PVC untuk menggosok mika secara merata dan urut dari ujung ke ujung. Jangan terlalu keras menekan, terlalu keras menekan mangakibatkan toner menyebar, jalur jadi menebal dan bisa terhubung di sebelahnya. Lakukan hingga merata.
5. Lepas mika lalu lepas kertas perlahan. Saat melepas kertas kadang menjadikan beberapa toner di pinggir jalur ikut terlepas bersama kertas. Jika masih ada yang menempel di kertas, gosok ulang denga kartu PVC.
6. Saat kertas sudah terlepas, keringkan toner dengan menganginkan. Atau dapat juga memanaskannya dengan korek api pada bagian tembaganya pada api biru. Pengeringan dapat dilakukan dengan menaruh PCB pada pada wajan dengan tembaga menghadap ke atas sampai warna tembaga sedikit berubah pucat. Kurang lebih 1 menit dengan api sedang. Awas: Jika terlalu panas, PCB dapat melengkung. Lalu segera masukkan ke air dingin segera setelah PCB dipanasi. Air dingin digunakan untuk mendinginkan secara cepat, sehingga toner mengeras kembali.
7. Jika masih ada kertas yang menempel, lanjutkan dengan mengelus-elus pcb dengan jari hingga lapisan kertas yang menempel pada toner terlepas.
8. Cek jalur PCB jika ada yang terlepas/teputus, gambar jalur dengan spidol anti air. PAstikan PCB dalam kondisi kering. Jika ada jalur bersebelahan yang terhubung, kerok sedikit menggunakan cutter atau jarum.


C. Etching
1. Gunakan Feri Chorida 1 gram + 100 ml Air. Atau dapat gunakan campuran 1 bagian Asam Chlorida dan 2 bagian Peroxida (HCl + 2H2O2) + 4 bagian Air. Jika sulit ditemukan bisa menggunakan 2 bagian Wipol / WPC + 1 bagian Vanish.
2. Masukkan PCB dengan tembaga menghadap ke atas. Jika menggunakan FeCl, perlu digoyangkan. Namun jika menggunakan HCl cukup diamkan dan amati hingga tembaga larut.
3. Jika ada toner yang terkoyak, angkat dan keringkan dengan ditiriskan dan dianginkan. Jangan mengeringkan dengan cara diusap karena toner dapat terkelupas. Lalu gambar jalur toner yang putus dengan drawing pen atau spidol anti air. Kemudian masukkan lagi.
4. Angkat dan tiriskan PCB ke tisue. Bersihkan menggunakan aseton (pembersik kutek)
5. Jika ada minyak atau korosi, amplas dengan amplas terhalus (nomor 1)

D. Persiapkan Curabe UV Solder Mask (CUVSM) / Dry film solder mask
1. Cureble UV harus bebas dari minyak, Minyak digunakan untuk melumasi agar tidak mudah beku. Jika Curable UV terlalu cair dan keliatan ada minyaknya, taruh curable di atas tisue dan biarkan beberapa saat. Minyak mengakibatkan curable sulit menempel ke PCB.
2. PCB harus dalam keadaan bersih. Lihat poin A.
3. Tuangkan pasta CUVSM yang sudah tanpa minyak, atau minyak sudah tidak tampak, ke PCB.
4. Gunakan plastik pembungkus kado (cellophane) untuk menutup CUVSM. Jika menggunakan plastik mika fotokopi, bisanya hasit akhir solder mask malah menempel ke mika. Jika menggunakan plastik pembungkus makanan biasanya membuat CUVSM tidak rata (bergelombang).
5. Pasang mika tebal atau kaca untuk menekan cellophane yang dipasang menempel CUVSM. Tekan hingga permukaan rata. Jika jalur PCB belum terlihat, tekan kaca/mika lebih kuat lagi
6. Siapkan hasil cetakan solder paste area yang dicetak di kertas polos dan tambahkan minyak baby oil / kayu putih hingga transparan. Cetakan solder paste dapat juga dicetak di kertas transparant atau difotokopi, sehigga tidak memerlukan minyak untuk menjadikan trasnparan. Namun perlu di cek apakah warna hitam masih tembus? jika tebus maka pasang 1 lapis lagi agar bener-benar warna hitamnya tidak tembus cahaya. Penggunaan transparant ditujukan agar saat memasang di atas CUVSM jalur dapat terlihat jelas, dibandingkan menggunakan kertas yang diberi minyak.
7. Gunakan penjepit jika inggin menggunakan kaca untuk dapat meratakan CUVSM. Pasang kertas transparan di atas cellophane sesuai relief yang diinginkan, dengan bagian permukaan cetak di bawah. Hal ini agar cahaya tidak terdispersi saat menyinari CUVSM. Jangan pula menaruh mika tebal atau kaca tebal diatas kertas transparan, karena mengakibatkan penyinaran tidak maksimal. Kaitkan dengan isolasi jika perlu, agar posisi tidak mudah berubah.
8. Gunakan Lampu UV atau pengering UV HP atau pengering kuku kutek atau apapun yang dapat menyinari gelombang UV. Lama penyinaran tergantung dari kuat cahayanya. Untuk UV 8 watt TL, membutuhkan 4 – 5 menit. Untuk 2×9 watt (2 lampu pengering kuku) cukup 20 – 30 detik. Disarankan untuk mencoba menyunari CUVSM di kertas yang tidak terpakai dan tandai dari 1 s.d 7 menit. Cari lama penyinaran yang tepat, dimana CUVSM sudah mulai mengeras dan mengkilap. Pastikan pula CUVSM yang menenpel di kertas juga sudah mengeras, sehingga tidak lagi dijumpai dalam bentuk pasta.
9. Lepas cellophane secara perlahan dengan menggeser sedikit demi sedikit pada pucuknya. Usahakan saat membuka cellophane, sudut cellophane tidak leboh dari 5 derajat terhadap PCB.
10. Bersihkan sisa pasta CUVSM yang tidak mengeras, yang tidak mendapatkan sinar UV, dengan menempel – tempel dengan tisue kering hingga tidak ada pasta CUVSM yang bsa menempel ke tisue. Tuang sedikit aseton ke tisue dan ulangi tempel-tempel ke pasta CUVSM. Jangan digosok, karena dapat menjadikan CUVSM yang telah menempel ke PCB, yang mengeras, terkoyak dan lepas dari ikatan tembaga. Jika ada lubang yang tertutup pasta, gunakan aseton yang dituang di wadah dan masukkan PCB dengan digoyang goyangkan agar pasta larut. Penggunaan tiner tidak disarankan, karena bisa mengupas CUVSM yang sudah keras. Penggunaan alkohol 70% juga tidak disarankan karena pasta malah dapat berpindah di tempat lain, karena pasta tidak menempel di tissue yang ada alkoholnya.
11. Saat pasta sudah bersih, ulangi penyinaran hingga 1 jam. Ini digunakan untuk mengeraskan CUVSM dan membuatnya lebih menempel ke tembaga. Jika perlu, panaskan PCB ke suhu 250C selama bebrapa menit dengan blower atau pemanggang. Dapat juga jemur di bawah matahari terik selama 2 jam.
12. Masukkan kapas atau tisue ke AgNO3 (perak nitrat) dan tempel-tempel (tap) ke PCB. Jika memiliki AgNO3 ukuran banyak, PCB dapat dicelupkan selama 3 menit.

Konfigurasi kedalaman guratan PCB 1 oz adalah -0.078 s.d -0.10 mm

PCB dengan Dry Film Photoresist

Membuat jalur PCB dapat menggunakan beberapa cara, dari mulai menggambar menggunakan tinta anti air, sablon, toner transfer, dan salah satunya adalah menggunakan Dry Film Photoresist. Berikut langkahnya

A. Pembersihan PCB
PCB dapat cukup dibersihkan dengan digosok menggunakan sabut cuci piring Scotch-Brite, atau sabut per cuci, atau menggunakan amplas yang paling halus. Lalu usap dengan aseton bila perlu. Aseton dapat dibeli di toko kimia atau di toko swalayan sebagai pembersih kutek (cat kuku).

Jika ada minyak yang menempel pada PCB, biasanya bekas sidik jari, dapat dibersihkan dengan sabun cuci dan keringkan. Setelah itu baru digosok dengan sabut cuci atau amplas.

B. Potong PCB sesuai ukuran
Pemotongan FR2 dapat dilakukan dengan cutter. Tandai dengan cutter di sisi tembaga dan sisi sebailknya. Lalu tekan di tempat rata dan patahkan. Pemotongan FR4 perlu menggunakan gergaji besi atau semarcamnya.

C. Siapkan DFP
Siapkan DFP dengan memotong sesuai ukuran lalu buka strip plastik pelapis menggunakan isolasi.

D. Pasang DFP ke PCB
Ada beberapa cara untuk masang DFP ke PCB.
1. Cara Kering, pastikan PCB kering lalu pasang DFP dari sudut dan ditekan menggunakan jari lalu ratakan dengan rakel / kartu ATM.
2. Cara Basah, berikan bantuan sedikit air murni (jangan pakai sabun) di PCB lalu pasang DFP dari arah diteteskannya air.
Jika memiliki laminator dapat dilaminating dengan suhu kurang dari 100 derajat. Beberapa tutorial ada yang menggunakan blower suhu rendah untuk memanasi DFP, namun pastikan suhu < 100 derajat.
Penting: Tunggu 15 menit agar kering dan perekat DFP aktif, tidak disarankan langsung disinari walaupun sudah kering!

E. Siapkan desain PCB negatif
Siapkan cetakan negatif dari jalur PCB. Dapat menggunakan kertas transparan, jika memiliki printer laser. Atau cukup difotokopi di kertas transparan. Jika kesulitan, dapat pula dicetak di printer tinta.
Untuk cetakan di kertas transparan, biasanya ada toner, gambar hitam, yang agak transparan. Solusinya adalah mendobeli gambar dan diisolasi. Sedangkan jika dicetak di kertas HVS, nantinya cukup diberikan minyak, semisal minyak baby oil agar kertas menjadi trasnparan.

F. Pasang desain ke PCB
Pasang desain ke PCB. Untuk desain pada kertas HVS, tempelkan, isolasi bagian pinggir dan tuang minyak hingga semua kertas transparan. Kertas akan menempel ke PCB karena daya ikat minyak. Sedangkan jika menggunakan kertas transparan, maka selain diisolasi bagian pinggir, perlu ditindih dengan kaca agar benar-benar menempel sempurnya.

G. Penyinaran
Penyinaran dapat dilakukan di matahari terik kurang lebih 1 menit. Atau dapat juga menggunakan lampu UV untuk cek uang 18 Watt, dengan waktu 5 menit. Atau dapat juga menggunakan lampu UV pengering kutek kuku 1.5 menit (90 detik) untuk film berupa kertas yang diolesi minyak.
Jika menggunakan film berupa mika trasnparan (biasanya perlu didobel untuk mendapatkan hitam sempurna), lama penyinaran dengan UV pengering kuku cukup 20 – 30 detik saja.
Lama penyinaran tergantung dari intensitas sinar UV. Lakukan percobaan penyinaran dengan mengambil sampel DFP ukuran kecil.

H. Melepas lapisan pelindung DFP
Lepas plastik pelindung DFP dengan menggunakan isolasi.

I. Bersihkan DFP
DFP yang tidak terkena sinar UV akan tetap menjadi pasta, sedangkan yang terkena sinar UV akan mengeras. Bersihkan DFP yang berbentuk pasta dengan Na2CO3 atau soda Ash (1 gram/100ml). Jangan terlalu banyak menggunakan sida ash, perabdingan yang lebih besar mengakibatkan DFP mudah lepas dan larut!
Jika kesulitan mendapatkan Soda Ash, dapat juga menggunakan detergen cuci baju yang mengandung Na2CO3. Rendam beberapa saat lalu bersihkan menggunakan kuas kecil. Jika tidak ada kuas kecil, gunakan kapas, namun gosok perlahan jangan sampai DFP kering ikut terkelupas.

J. PCB siap di-etching

Ket:
DRC – Design Rule Check untuk penggunaan DFP terbaik yang pernah dicoba adalah:
Clearance: >=0,3mm
Track Width: >= 0.3mm

DRC – Design Rule Check untuk penggunaan DFP yang disarankan adalah:
Clearance: >= 0,4 mm
Track Width: >= 0.4 mm

Hasil:

Jalur 0.3mm terbentuk jadi sekitar 0.4 – 0.5 mm, clearance 0.3mm terbentuk menjadi berkurang menjadi 0.2mm hingga 0.1mm
Jalu 0.4mm terbentuk menjadi 0.6mm, clearance 0.4mm berkurang menjadi 0.3mm.
INI ADALAH BATAS REKOMENDASI AGAR JALUR AMAN DARI SHORT ATAU PUTUS
Untuk jalur 0.2mm dengan clearance 0.2mm gagal terbentuk gap, menyambung semua. Dimungkinkan karena tiap jalur 0.2mm bleeding menjadi 0.3mm sehingga clearance mendekati 0 mm
Untuk pad komponen 0402 masih bisa terbentuk, yang seharusnya 0.6mm menjadi 0.7mm, sedangkan komponen 0201 clearance sudah hilang alias pad tergabung.

Raspberry Bluetooth Printer

You have to perform several steps in order to establish communication.

You have to pair your desired bluetooth device using bluetoothctl

sudo bluetoothctl -a

scan on

devices

pair XX:XX:XX:XX:XX:XX

trust XX:XX:XX:XX:XX:XX

quit

Where XX:XX:XX:XX:XX:XX is the MAC address of your bluetooth device.

You have to create the serial device that binds to your paired bluetooth device.

sudo rfcomm bind /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1

The last number is the communication channel. It has to bee unique for all your connections.

Then you should be able to open a connection. (Assuming your bluetooth device actually supports the required SPP protocol.)

echo “test” > /dev/rfcomm0

source: https://raspberrypi.stackexchange.com/questions/78155/using-dev-rfcomm0-in-raspberry-pi/78301#78301?s=39be540452a34b55af09cb19d04ea700

Machine Learning #7 – Menuju Klasifikasi

Pada tulisan Machine Learning #5 telah diceritakan tentang Neural Network dengan 2 input dan 1 output. Mari kita kembangkan jika menggunakan 1 input dan 2 output. Percobaan ini mengarah ke klasifikasi.

Sabagai gambaran apabila inputnya adalah suara yang diubah menjadi nilai dalam bentuk matrik x dan hasilnya adalah 2 output, yaitu output y= [0 0]. Output y = [1 0], jika hasil klasifikasinya mengarah pada output pertama, misalkan saya kata “YA”, dan outputnya y = [0 1] jika hasil klasifikasinya adalah output kedua, misalkan kata “Tidak”.

Dari model di atas, tentunya agak kesulitan untuk diterapkan di mikrokontroler. Hasil dari training dalam bentuk TFLite >5Mb. Padahal mikrokontroler, katakanlah BLE 33 Sense, tidak memiliki Flash Memori yang berkapasitas 5Mb

Cara yang pertama yaitu mengubah kuantisasi dari float menjadi int pada mikrokontoler. Berikut contoh perbandingan kuantisasi menggunakan float dibandingkan menggunakan int. Memang akurasi menjadi sedikit berubah, namun penggunaan memori jauh lebih kecil.

Menghilangkan parameter yang tidak begitu penting, dengan pruning.

Dan beberapa proses yang dapat disimpulkan seperti gambar berikut:

Mencoba seonsor yang ada pada Nano BLE Sense

Melanjutkan tulisan Mencoba Nano 33 BLE Sense saatnya mencoba sensor-sensor yang ada pada modul ini. Sensor yang ada adalah 3D accelerometer, 3D gyroscope, 3D magnetometer (LSM9DS1), MEMS Digital Microphone (MP34DT05), Digital Proximity, Ambient Light, RGB and Gesture (APDS9960), Tekanan Udara (LPS22HB), Suhu dan Kelambaban (HTS221) Chip sensornya kecil kecil sekali!

Arduino Nano 33 BLE Sense Harddware Overview

Langsung saja, untuk mencoba Microphone, bisa kita lihat di sample skecthnya. Pastikan Board sudah bisa terpilih, driver terpasang dan Port juga sudah benar, cek di tulisan Mencoba Nano 33 BLE Sense. Selanjutnya pilih di bagian example -> PDM ->PDMSerialPlotter

Program ini menggunakan mikrofon on-board untuk mendengarkan audio dan memplotnya pada plotter serial. Kita akan melakukan kompilasi yang sangat lambat, membutuhkan waktu sekitar 10 menit untuk mengkompilasi dan mengunggah program. Ini karena integrasi Mbed OS dengan Arduino IDE, semoga Komunitas Arduino bisa memberikan solusi untuk ini.

Hasil tampilan di serial plotter.

Sedangkan untuk mencoba sensor-sensor lain, perlu mengistall library sesuai dengan chip sensornya berikut:

Selanjutnya gunakan contoh sketch berikut:

#include <Arduino_LSM9DS1.h> //IMU
#include <Arduino_LPS22HB.h> //Tekanan 
#include <Arduino_HTS221.h> //Suhu dan kelembaban 
#include <Arduino_APDS9960.h> //Gerakan, cahaya dan proksimiti

void setup(){
  Serial.begin(9600);  

  if (!IMU.begin()) 
  { Serial.println("Chip IMU tidak ditemukan!"); while (1);}

  if (!BARO.begin())  
  { Serial.println("Chip Sensor Tekanan tidak ditemukan!"); while (1);}

  if (!HTS.begin()) 
  { Serial.println("Chip Sensor Suhu & Kelembaban tidak ditemukan!"); while (1);}

  if (!APDS.begin())  
  { Serial.println("Chip Gesture, cahaya dan proksimiti tidak ditemukan!"); while (1);}
 }

float accel_x, accel_y, accel_z;
float gyro_x, gyro_y, gyro_z;
float mag_x, mag_y, mag_z;
float Pressure;
float Temperature, Humidity;
int Proximity;

void loop()
{
  //Accelerometer
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(accel_x, accel_y, accel_z);
    Serial.print("Accelerometer = ");Serial.print(accel_x); Serial.print(", ");Serial.print(accel_y);Serial.print(", ");Serial.println(accel_z);
  }
delay (200);

  //Gyroscope 
  if (IMU.gyroscopeAvailable()) {
    IMU.readGyroscope(gyro_x, gyro_y, gyro_z);
    Serial.print("Gyroscope = ");Serial.print(gyro_x); Serial.print(", ");Serial.print(gyro_y);Serial.print(", ");Serial.println(gyro_z);
  }
delay (200);

  //Magnetometer 
  if (IMU.magneticFieldAvailable()) {
    IMU.readMagneticField(mag_x, mag_y, mag_z);
    Serial.print("Magnetometer = ");Serial.print(mag_x); Serial.print(", ");Serial.print(mag_y);Serial.print(", ");Serial.println(mag_z);
  }
delay (200);

  //Pressure 
  Pressure = BARO.readPressure();
  Serial.print("Tekanan= ");Serial.println(Pressure);
  delay (200);

  //Temperature 
  Temperature = HTS.readTemperature();
  Serial.print("Suhu= ");Serial.println(Temperature);
  delay (200);

  //Humidity 
  Humidity = HTS.readHumidity();
  Serial.print("Kelembaban= ");Serial.println(Humidity);
  delay (200);

  //Proximity 
  if (APDS.proximityAvailable()) {
    Proximity = APDS.readProximity();
    Serial.print("Proksimiti= ");Serial.println(Proximity); 
    }
  delay (200);

  Serial.println(); 
  delay(1000);
}

HAsil bisa dilihat di serial monitor

Machine Learning #6 – Menerapkan Machine Learning ke Mikrokontroler (via Arduino + TinyML)

Dilihat dari situs resmi TensorFlow, saat ini board yang support dengan model training TensorFlowLite adalah board berikut:

Jadi mari kita gunakan yang saya punya, yaitu ESP-EYE (murah, 200an ribu) dan Nano 33 BLE Sense (mahal, 1,2 juta).

Untuk dapat menggunakan TinyML ada penjelasan di situs resminya, tapi cukup ribet. Mari gunakan milik Simone yang bernama EloquentTinyML. Siapkan dahulu library-nya melalui Library Manager

Selanjutnya pilih papan (board) yang tepat. Untuk Nano 33 BLE Sense lihat tutorialnya di tulisan Mencoba Nano 33 BLE Sense sedangkan jika menggunakan ESP-EYS, lihat tutorialnya di tulisan Memulai Percobaan ESP-CAM. Dicontohkan untuk kali ini kita gunakan Nano 33 BLE Sense:

Tuliskan sketch pada arduino dengan kode berikut:

#include <EloquentTinyML.h>
#include "sine_model.h"

#define NUMBER_OF_INPUTS 1
#define NUMBER_OF_OUTPUTS 1
#define TENSOR_ARENA_SIZE 2*1024

Eloquent::TinyML::TfLite<NUMBER_OF_INPUTS, NUMBER_OF_OUTPUTS, TENSOR_ARENA_SIZE> ml;


void setup() {
    Serial.begin(115200);
    ml.begin(sine_model);
}

void loop() {

    float x = 3.14 * random(100) / 100;
    float y = sin(x);
    float input[1] = { x };
    float predicted = ml.predict(input);

    Serial.print("Nilai sin(");
    Serial.print(x);
    Serial.print(") = ");
    Serial.print(y);
    Serial.print("\t Nilai prediksi: ");
    Serial.println(predicted);
    delay(1000);
}

Pada baris 2, isikan nama file hasil pengubahan tflile, misalkan hasilnya adalah sine_model.h Model yang akan digunakan adalah model 1 input dan 1 ouput sesuai pada artikel Machine Learning #3 Selanjutnya ketikkan jumlah input dan jumlah outputnya seperti yang dicontohkan di baris 4 dan 5, yaitu 1 input dan 1 output.

Di baris 8, adalah inisialisasi object EloquentTinyML sedangkan baris 13 adalah membaca model sine_model.h agar dapat diproses oleh library TinyML.

Untuk melihat hasil prediksi cukup gunakan .predict(nilai input) seperti yang terlihat di baris 21.

Saatnya upload skecth ke Nano 33 BLE Sense

Penampakan Nano 33 BLE Sense

Mari dilihat hasilnya, apakah mikrokontroler mampu memprediksi nilai y berdasarkan nilai input x? dimana rumus sebenarnya adalah y = sin(x). Mungkin ada sedikit selisih, namun untuk percobaan dengan 1 hidden layer ini bisa dimaklumi. Perlu banyak neuron dan hidden layer untuk mendapatkan nilai kesalahan (loss) yang sangat kecil.

Machine Learning #5 – Persiapan File Model untuk Mikrokontroler

Setelah mendapatkan model dari hasil training, model dapat disimpan ke file .tflite, file ini dapat kita gunakan untuk framework lain misalnya untuk mikrokontroller. Untuk membentuk file .tflite dari hasil training gunakan kode berikut:

# Convert model ke file tflite
tflite_model_name = 'sine_model'  # .tflite 

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_model = converter.convert()

#for 1.2 to 2.3
#open(tflite_model_name + '.tflite', 'wb').write(tflite_model)

#for 2.4 or later
with tf.io.gfile.GFile(tflite_model_name +'.tflite', 'wb') as f:
  f.write(tflite_model)


Hasil dari code diatas adalah file sine_model.tflite atau dapat mnegubah nama filenya di baris 2

Karena mikrokontroler yang akan digunakan dibangun menggunakan bahasa C, maka perlu mengubah tflite menjadi file header agar dapat dikenali pada bahasa pemrograman C. Ada code fungsi (prosedur) yang sudah dibuat oleh pegiat machine learning, tinggal dipakai saja.

# Function: Convert some hex value into an array for C programming
def hex_to_c_array(hex_data, var_name):

  c_str = ''

  # Create header guard
  c_str += '#ifndef ' + var_name.upper() + '_H\n'
  c_str += '#define ' + var_name.upper() + '_H\n\n'

  # Add array length at top of file
  c_str += '\nunsigned int ' + var_name + '_len = ' + str(len(hex_data)) + ';\n'

  # Declare C variable
  c_str += 'unsigned char ' + var_name + '[] = {'
  hex_array = []
  for i, val in enumerate(hex_data) :

    # Construct string from hex
    hex_str = format(val, '#04x')

    # Add formatting so each line stays within 80 characters
    if (i + 1) < len(hex_data):
      hex_str += ','
    if (i + 1) % 12 == 0:
      hex_str += '\n '
    hex_array.append(hex_str)

  # Add closing brace
  c_str += '\n ' + format(' '.join(hex_array)) + '\n};\n\n'

  # Close out header guard
  c_str += '#endif //' + var_name.upper() + '_H'

  return c_str


Selanjutnya, gunakan fungsi di atas untuk mengubah .tflite menjadi .h, nama filenya dapat diset pada baris ke-2. Kali ini dinamai dengan sine_model.h

# Write TFLite model to a C source (or header) file
c_model_name = 'sine_model'       # .h 

with open(c_model_name + '.h', 'w') as file:
  file.write(hex_to_c_array(tflite_model, c_model_name))

Machine Learning #4 – 2 input, 3 HL, 1 output

Kali ini mari membuat model untuk 2 input dan 1 output dengan menggunakan 3 hidden layer. Sebagai contoh kasus ada data dengan rumus matematika: y = cos(x1) – sin(x2) + sin(x1+x2) data ini memiliki 1 input yaitu x1 dan x2. Sedangkan nilai outputnya 1 , yaitu y. Apakah MESIN bisa memprediksi rumus matematika di atas? Mari kita mulai dengan membuat datanya.

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import math
from tensorflow.keras import layers

# Membuat 100, 77 dan 66 nilai random berdasarkan seed 1234
np.random.seed(1234)
x1_values = np.linspace(0,2*math.pi,100)
x2_values = np.linspace(0,2*math.pi,100)
x1_valuesV = np.linspace(0,2*math.pi,77)
x2_valuesV = np.linspace(0,2*math.pi,77)
x1_valuesT = np.linspace(0,2*math.pi,66)
x2_valuesT = np.linspace(0,2*math.pi,66)

# masing masing nilai dibuat dalam bentuk sinusoida, cos(x1) - sin(x2) + sin(x1+x2)
y_values = np.sin(x1_values) - np.cos(x2_values) - np.sin(x1_values+x2_values) + (0.2 * np.random.randn(x1_values.shape[0]))
y_valuesV = np.sin(x1_valuesV) - np.cos(x2_valuesV) - np.sin(x1_valuesV+x2_valuesV) + (0.2 * np.random.randn(x1_valuesV.shape[0]))
y_valuesT = np.sin(x1_valuesT) - np.cos(x2_valuesT) - np.sin(x1_valuesT+x2_valuesT) + (0.2 * np.random.randn(x1_valuesT.shape[0]))

plt.plot(x1_values, y_values, 'r.', label="Data u/ Training")
plt.plot(x1_valuesV, y_valuesV, 'b.', label="Data u/ Validasi")
plt.plot(x1_valuesT, y_valuesT, 'g.', label="Data u/ Test")
plt.legend()


Kode di atas adalah untuk membuat data training, data validasi dan data test. Hasil dari plot data x dan y adalah berikut:

Selanjutnya mari kita buat permodelan NN seperti berikut:

Karena inputnya 2, maka baris 28 kita ketikkan: input_shape=(2,)

# Membuat model dengan 3 hidden layer
model = tf.keras.Sequential()
model.add(layers.Dense(2, activation='tanh', input_shape=(2,)))
model.add(layers.Dense(10, activation='tanh'))
model.add(layers.Dense(10, activation='tanh'))
model.add(layers.Dense(10, activation='tanh'))
model.add(layers.Dense(1))
# Lihat pemodelan, lihat secara grafis di https://alexlenail.me/NN-SVG/index.html
model.summary()

Kedua input (x1 dan x2) perlu dibuat stack agar dapat diproses untuk permodelan. Kali ini, data training dan data validasi saja yang perlu dibuat stack. Lihat cara membuat stack pada baris 36-37.

x1x2_array = np.stack([x1_values, x2_values], axis=1)
x1x2V_array = np.stack([x1_valuesV, x2_valuesV], axis=1)

Saatnya membuat model. Kali ini menggunakan tensorboard untuk memvisualisasikannya. Jumlah epochnya adalah 1000 percobaan, dengan batch size 100

import datetime
%load_ext tensorboard
log_dir =  datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)

# Gunakan optimizer adam , loss function Mean square error
model.compile(optimizer='adam', loss='mse', metrics=['mse'])

# Training model
#model.fit(x1x2_array,y_values, batch_size=100, epochs=1000)
history = model.fit(x1x2_array, y_values, epochs=1000, batch_size=100,
   validation_data=(x1x2V_array, y_valuesV), 
          callbacks=[tensorboard_callback])

# %tensorboard --logdir logs/gradient_tape # buka komentar jika ingin melihat di tensorboard

Setelah proses belajar berlangsung, saatnya mencoba, membutktikan prediksi MESIN dengan data yang sebenarnya

# Plot hasil prediksi terhadap nilai sebenarnya yaitu y = sin(x)
x1x2T_array = np.stack([x1_valuesT, x2_valuesT], axis=1)

predictions = model.predict(x1x2T_array)

plt.clf()
plt.title("Perbandingan nilai Test dengan nilai Prediksi")
plt.plot(x1_valuesT, y_valuesT, 'b.', label='Nilai Test')
plt.plot(x1_valuesT, predictions, 'r.', label='Nilai  Prediksi')
plt.legend()
plt.show()

Ternyata hasil prediksi mesin mirip dengan data sebenarnya. Hanya saja pada nilai input 5 ke atas masih ada kesalahan. Titik warna merah(nilai prediksi), terletak agak jauh dengan titik warna biru(nilai seharusnya). Untuk memperbaikinya bisa dengan mengubah aktivasi, menambah neuron atau layer. Silahkan dicoba coba hingga hasil terbaik. Setidaknya MESIN sudah belajar dengan baik

Jika ingin menyimpan hasil model training, skrip kode berikut bisa digunakan untuk mengexport model hasil training ke tflite. Dengan file tflite ini kita bisa gunakan untuk menyimpan hasilnya dan dibuka di platform lain.

# Convert Keras model to a tflite model
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_model = converter.convert()

#for 1.2 to 2.3
#open(tflite_model_name + '.tflite', 'wb').write(tflite_model)

#for 2.4 or later
with tf.io.gfile.GFile('2input.tflite', 'wb') as f:
  f.write(tflite_model)

Machine Learning #3 – Persamaan NonLinier

Pada Machine Learning #2 MESIN belajar (training) untuk menyelesaikan persamaan linear, sekarang selanjutnya training untuk persamaan non linear. Kita contohkan menggunaan persamaan sinusoida.

Mari gunakan persamaan sederhana y = sin(x).

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import math
from tensorflow.keras import layers

# Membuat 1000 nilai random berdasarkan seed 1234, silahkan diganti untuk pola random lain
nsamples=1000
np.random.seed(1234)
x_values = np.random.uniform(low=0, high=(2 * math.pi), size=nsamples)
# masing masing nilai dibuat dalam bentuk sinusoida
y_values = np.sin(x_values) + (0.1 * np.random.randn(x_values.shape[0]))
plt.plot(x_values, y_values, '.')

# membagi menjadi 3 kategori data, untuk validasi, untuk test dan untuk training
val_ratio = 0.2     # 20% untuk data validasi
test_ratio = 0.2    # 20% untuk data test, dan sisanya untuk data training

val_split = int(val_ratio * nsamples)
test_split = int(val_split + (test_ratio * nsamples))
x_val, x_test, x_train = np.split(x_values, [val_split, test_split])
y_val, y_test, y_train = np.split(y_values, [val_split, test_split])

# Cek hasil split apakah benar, jika salah maka munculkan assertment
assert(x_train.size + x_val.size + x_test.size) == nsamples

# TAmpilkan data dengan warna yang berbeda:
plt.plot(x_train, y_train, 'b.', label="Data u/ Train")
plt.plot(x_test, y_test, 'r.', label="Data u/ Test")
plt.plot(x_val, y_val, 'y.', label="Data u/ Validasi")
plt.legend()
plt.show()
# Membuat model dengan 2 layer
model = tf.keras.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(1,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1))
# Lihat pemodelan
model.summary()

Kode diatas adalah untuk membuat model 2 layer yang sekuensial. Layer pertama 16 neuron dengan 1 input. Layer kedua dengan 16 neuron, dan outpunya 1 neuron untuk 1 output. jenis aktivasinya adalah ReLU atau Rectified Linear Unit

Hasil Kompilasi
# Gunakan optimizer RMSprop , loss function Mean absolute error
model.compile(optimizer='rmsprop', loss='mae', metrics=['mae'])

# Training model
history = model.fit(x_train, y_train, epochs=500, batch_size=100,
   validation_data=(x_val, y_val))

Untuk kali ini, menggunakan RMSProp sebagai optimizer. Pada training untuk persamaan linear Machine Learning #1, yang digunakan adalah SGD (Stochastic Gradient Descent). Pada training ini SGD terlalu lambat dan bisa jadi tidak bisa menemukan nilai minimum lost terendah. Perhatikan perbandingan berikut, SGD ditunjukkan dot warna merah:

Sedangkan untuk mencari nilai loss, yang digunakan adalah MAE (Mean absolute error) dimana selisih erornya di absolutekan jadi nilai positif semua. Berbeda dengan yang sebelumnya, dimana menggunakan MSE (Mean Squared Error) yang mengakarkan total nilai error.

Pada baris ke 47, MESIN diberikan 500 epoch untuk proses training, berdasarkan data training (x_train, y_train) dan kemudian mengevaluasi dengan data evaluasi (x_val, y_val). Ukuran batch yang digunakan adalah 100.

Jika ukuran tumpukan batch kecil, misalnya 1, maka gradien hanya dihitung dengan satu contoh pelatihan. Hal ini dapat membuat kerugian pelatihan yang berosilasi, karena setiap kali memperkirakan gradien hanya dengan satu contoh pelatihan, yang sering kali tidak mewakili seluruh data pelatihan. Jadi, semakin banyak contoh pelatihan yang digunakan, semakin baik dalam memperkirakan gradien (yang akan sesuai dengan semua contoh pelatihan), sehingga ini berpotensi mengarah pada konvergensi yang lebih cepat. Namun, jika menggunakan banyak contoh pelatihan, biayanya juga bisa mahal secara komputasi. Misalnya, bayangkan data pelatihan terdiri dari jutaan contoh pelatihan. Dalam hal ini, untuk melakukan satu langkah penurunan gradien, harus melalui semua pelatihan yang dapat memakan banyak waktu.

Line Plots of Classification Accuracy on Train and Test Datasets With Different Batch Sizes
Akurasi dari hasil training dan pengetesan pada nilai batch yang berbeda. Jika batch 1 maka banyak hasil test jauh meleset berdasarkan nilai proses training

Jika ingin melihat history loss dari hasil training, dapat gunakan skrip berikut:

# Plot hasil training, jika tidak diperlukan kode ini bisa diabaikan
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(loss) + 1)

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()

Selanjutnya mari buat perbandingan hasil training berdasarkan dengan model matematikan sebenarnya (y=sin(x))

# Plot hasil prediksi terhadap nilai sebenarnya yaitu y = sin(x)
predictions = model.predict(x_test)

plt.clf()
plt.title("Perbandingan hasil training berdasarkan dengan model matematikan sebenarnya")
plt.plot(x_test, y_test, 'b.', label='Nilai Test')
plt.plot(x_test, predictions, 'r.', label='Nilai Prediksi')
plt.legend()
plt.show()

Warna biru adalah nilai data test hasil sinus yang sudah diberi noise. Warna merah adalah prediksi MESIN. Walaupun data training sudah ditambahkan noise (Baris 12), mesin dapat mesin dapat memprediksi bahwa data training adalah persamanan sinus.