Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Kegerator Utama

Komponen dan persediaan

SparkFun Arduino Pro Mini 328 - 3.3V/8MHz
× 7
SparkFun Load Cell Amplifier - HX711
× 1
Leviton 47603-12B 4x12 Papan Distribusi Telepon
× 1
Raspberry Pi 2 Model B
× 1
AC 100-120V 200-220V 5V 6A 30W Swich Power Supply
× 1
Sensor Gerak IR
× 1
10.6 cu. ft. Lemari Pembeku Dada
× 1
Timbangan Pos Digital Berat Cerdas
× 5
Keyboard Rii K12 Ultra Slim 2,4 GHz
× 1
Dongle WiFi Rasbperry Pi
× 1
Modul Relai Arduino DC 5V
× 1
Sensor Suhu &Kelembaban DHT11 (4 pin)
× 2
Sensor Suhu DHT22
× 3
HomeBrewStuff Stainless Steel Double Draft Beer Tower
× 2
Pendingin Menara Bir
× 1
0-30 Sensor Tekanan I2C PSI (3.3V) ABPMANN030PG2A3
× 1

Alat dan mesin yang diperlukan

Alat Pengerjaan Kayu
Alat untuk menyesuaikan bagian luar freezer
Pemotong Kawat
Besi solder (generik)
Heat Shrink Tubing

Tentang proyek ini

Penafian: Pertama, proyek ini tidak mempromosikan penggunaan atau penyalahgunaan alkohol, sepenuhnya terserah pengguna minuman apa yang akan menjadi isi kegerator ini.

Proyek ini lahir dari keinginan untuk mengelola isi sebuah kegerator dengan lebih baik. Kegerator bekerja dengan prinsip dasar menjaga minuman tetap dingin serta menjaga minuman berkarbonasi pada PSI tertentu. Selain itu, hanya dengan menuangkan minuman dingin untuk diri sendiri, Anda tidak tahu berapa banyak yang tersisa di tong. Akan sangat disayangkan jika orang-orang datang ke pertandingan sepak bola hari Minggu dan kehabisan root beer di tengah permainan.



Jadi tujuan dari proyek ini adalah:

  1. Pertahankan suhu minuman yang konsisten, pastikan minuman tidak terlalu hangat atau terlalu dingin dan membeku
  2. Pastikan bahwa jumlah karbonasi yang dapat diterima diterapkan ke tong untuk mempertahankan rasa yang optimal
  3. Pantau jumlah minuman di setiap tong dan berikan masukan visual untuk memastikan banyak minuman tersedia untuk pertandingan besar.
  4. Melacak jumlah CO2 yang tersisa di tangki yang digunakan untuk mengkarbonasi minuman

Komponen elektronik dasar dan kegunaannya:

  1. Sebuah lemari pembeku dada digunakan untuk unit pendingin dan untuk menyediakan bingkai untuk membuat perabot yang bagus
  2. Raspberry PI 2 Menjalankan Windows 10 IoT core digunakan sebagai otak operasi
  3. Timbangan perangko kecil digunakan untuk mengukur berat setiap tong serta tangki CO2, timbangan perangko ini memiliki elektronik yang dilepas dan penguat sel beban serta Arduino kecil yang terpasang pada timbangan. Timbangan ini akan berkomunikasi dengan Raspberry PI 2 melalui I2C (lebih lanjut tentang ini nanti)
  4. Ada 5 sensor Suhu Digital yang dipasang di unit, satu di bagian bawah chest freezer, satu dipasang di bagian bawah atas, masing-masing dipasang di menara tempat pegangan keran berada (lebih lanjut tentang ini nanti ) dan satu dipasang di bagian luar unit untuk mengukur suhu sekitar. Sensor suhu ini terhubung ke Arduino kecil dan juga berkomunikasi dengan Raspberry PI 2 melalui I2C
  5. Sensor tekanan Honeywell dipasang pada saluran udara yang digunakan untuk memberikan karbonasi ke tong. Meskipun penyesuaian PSI dilakukan secara manual (untuk saat ini), hal ini akan memberikan pengukuran yang akurat tentang berapa banyak CO2 yang diterapkan ke tong.
  6. Suatu catu daya 5V digunakan untuk menyediakan daya ke Raspberry PI2. Versi yang lebih besar (menyediakan hingga 6 amp) dipilih sehingga juga dapat memberi daya pada strip LED yang dapat dialamatkan.
  7. Relai sederhana ditempatkan sejajar dengan daya untuk kompresor. Dengan menggunakan relai ini, daya dapat dialirkan dan dikeluarkan dari kompresor, selanjutnya kompresor akan mengontrol suhu kegerator (lebih lanjut tentang ini nanti)

Konektivitas Awan

Ultimate Kegerator berisi server web untuk memungkinkan konfigurasi jarak jauh melalui layanan REST serta tampilan statis sederhana dari status saat ini. Situs web ini dapat dihubungi di http://slsys.homeip.net:9501 .

Selain itu, Ultimate Kegerator mengunggah statistik vitalnya ke Hub acara Windows Azure. Anda tidak akan dapat menggunakan paket Nuget standar untuk berbicara dengan hub acara, namun, Anda dapat mengimplementasikan library yang mudah yang disediakan oleh sesama Windows Embedded MVP Paolo Patierno yang tersedia di

https://www.nuget.org/packages/AzureSBLite/

Untuk pemrosesan akhir oleh Analisis Aliran

Rencana akhir untuk Analisis Aliran adalah:

1) Pantau dan beri tahu jika suhu menjadi terlalu hangat atau terlalu dingin

2) Pantau dan beri tahu saat tangki CO2 terlalu rendah

3) Pantau dan beri tahu jika ada kebocoran yang terdeteksi di tangki CO2 (berat badan turun secara bertahap)


Berikut adalah beberapa gambar tambahan dari proses perakitan:


-twb

Kode

  • Keg Kelas
  • Kelas Skala
  • Kelas Kegerator
Keg KelasC#
Pratinjau Kode Sumber sebelum sumber lengkap dirilis di GitHub. Jika Anda ingin akses awal atau ingin membantu berkontribusi, silakan hubungi penulis proyek ini
menggunakan LagoVista.Common.Commanding;menggunakan Sistem;menggunakan System.Collections.Generic;menggunakan System.Linq;menggunakan System.Text;menggunakan Sistem .Threading.Tasks;menggunakan Windows.UI.Xaml;namespace LagoVista.IoT.Common.Kegerator.Models{ public class Keg :DeviceBase { int _idx; TimeSpan _updateInterval; Timbangan pribadi.Skala _skala; tong publik(int idx, Scales.Scale scale, TimeSpan updateInterval) { _idx =idx; _updateInterval =UpdateInterval; _skala =skala; } public override TimeSpan UpdateInterval { get { return _updateInterval; } } public override void Refresh() { LastUpdated =DateTime.Now; LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { ContentsWeight =Scale.Weight - ContainerWeightLb; if (FullContentsWeightLb> 0) PercentFull =Convert.ToInt32((ContentsWeight / (FullContentsWeightLb - ContainerWeightLb)) * 100); else PercentFull =0; PercentFull =Math.Min(PercentFull, 100); if (GlassSizeOz> 0) QtyRemaining =Convert.ToInt32((ContentsWeight * 16)/ GlassSizeOz); else QtyRemaining =0; RaisePropertyChanged("PercentFullHeight"); RaisePropertyChanged ("PercentFullDisplay"); }); } Timbangan Publik. Skala Skala { get { return _scale; } } #region Properti yang Dihitung private int _qtyRemaining; public int QtyRemaining { dapatkan { return _qtyRemaining; } set { Set(ref _qtyRemaining, nilai); } } DateTime pribadi? _installDate; DateTime publik? InstallDate { dapatkan { return _installDate; } set { Set(ref _installDate, nilai); } } private int _percentFull; public int PercentFull { dapatkan { return _percentFull; } set { Set(ref _percentFull, nilai); } } public String PercentFullDisplay { get { return String.Format("{0}%", Convert.ToInt32(PercentFull)); } } public double PercentFullHeight { dapatkan { return Convert.ToDouble(_percentFull * 2); } } public int KegIndex { dapatkan { return _idx; } } #endregion #region Memasuki Properti private bool _isEmpty; public bool IsEmpty { dapatkan { return _isEmpty; } set { _isEmpty =nilai; RaisePropertyChanged(); } } pribadi ganda _glassSize; GlassSizeOz ganda publik { dapatkan { return _glassSize; } set { Set(ref _glassSize, nilai); } } DateTime pribadi? _tanggal lahir; DateTime publik? Tanggal Lahir { dapatkan { return _bornDate; } set { Set(ref _bornDate, nilai); } } ganda _containerWeight; public double ContainerWeightLb { dapatkan { return _containerWeight; } set { Set(ref _containerWeight, nilai); } } ganda _contentsWeight; public double ContentsWeight { dapatkan { return _contentsWeight; } set { Set(ref _contentsWeight, nilai); } } ganda _fullContentsWeight; public double FullContentsWeightLb { dapatkan { return _fullContentsWeight; } set { Set(ref _fullContentsWeight, nilai); } } String pribadi _contentsName; public String ContentsName { dapatkan { return _contentsName; } set { Set(ref _contentsName, nilai); } } #endregion public void Simpan() { LagoVista.Common.PlatformSupport.Services.BindingHelper.RefreshBindings(); PutSetting(String.Format("KEG{0}_CONTENTS", _idx), ContentsName); PutSetting(String.Format("KEG{0}_IS_EMPTY", _idx), IsEmpty.ToString()); PutSetting(String.Format("KEG{0}_CONTAINER_WEIGHT", _idx), String.Format("{0:0.00}", ContainerWeightLb)); PutSetting(String.Format("KEG{0}_GLASS_SIZE", _idx), String.Format("{0:0.00}", GlassSizeOz)); PutSetting(String.Format("KEG{0}_FULL_CONTENTS_WEIGHT", _idx), String.Format("{0:0.00}", FullContentsWeightLb)); if (BornDate.HasValue) PutSetting(String.Format("KEG{0}_BORN_DATE", _idx), BornDate.Value.ToString()); else RemoveSetting(String.Format("KEG{0}_BORN_DATE", _idx)); if(InstallDate.HasValue) PutSetting(String.Format("KEG{0}_INSTALL_DATE", _idx), InstallDate.Value.ToString()); else RemoveSetting(String.Format("KEG{0}_INSTALL_DATE", _idx)); } public void Load() { ContentsName =GetSetting(String.Format("KEG{0}_CONTENTS", _idx), "?"); ContainerWeightLb =Convert.ToDouble(GetSetting(String.Format("KEG{0}_CONTAINER_WEIGHT", _idx), "10.0")); GlassSizeOz =Convert.ToDouble(GetSetting(String.Format("KEG{0}_GLASS_SIZE", _idx), "12.0")); FullContentsWeightLb =Convert.ToDouble(GetSetting(String.Format("KEG{0}_FULL_CONTENTS_WEIGHT", _idx), "0.0")); IsEmpty =Convert.ToBoolean(GetSetting(String.Format("KEG{0}_IS_EMPTY", _idx), "True")); var bornDate =GetSetting("KEG{0}_BORN_DATE", String.Empty); if (!String.IsNullOrEmpty(bornDate)) BornDate =DateTime.Parse(bornDate); lain Tanggal Lahir =null; var installDate =GetSetting("KEG{0}_INSTALL_DATE", String.Empty); if (!String.IsNullOrEmpty(installDate)) InstallDate =DateTime.Parse(installDate); lain InstallDate =null; } asinkron publik batal SaveFullWeight() { FullContentsWeightLb =menunggu Scale.GetAverageWeight(); Menyimpan(); } public RelayCommand SaveFullWeightCommand { get { return new RelayCommand(() => SaveFullWeight()); } } }}
Kelas SkalaC#
Pratinjau Kode Sumber sebelum sumber lengkap dirilis di GitHub. Jika Anda ingin akses awal atau ingin membantu berkontribusi, silakan hubungi penulis proyek ini
menggunakan LagoVista.Common.Commanding;using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System .Teks;menggunakan System.Threading.Tasks;menggunakan Windows.Devices.I2c;namespace LagoVista.IoT.Common.Kegerator.Scales{ public class Scale :DeviceBase { Windows.Devices.I2c.I2cDevice _scaleI2CChannel; int _countOffset; dobel? _calibrationFactor =nol; pribadi TimeSpan _updateInterval; byte _alamat; Skala publik(alamat byte) { _alamat =alamat; } private void WriteValue(alamat byte, nilai int) { if (!IsDemoMode) { var offsetBuffer =byte baru[5]; offsetBuffer[0] =alamat; offsetBuffer[1] =(byte)(nilai>> 24); offsetBuffer[2] =(byte)(nilai>> 16); offsetBuffer[3] =(byte)(nilai>> 8); offsetBuffer[4] =(byte)(nilai); _scaleI2CChannel.Write(offsetBuffer); } } public async Task Init(String i2cDeviceId, TimeSpan updateInterval) { var settings =new I2cConnectionSettings(_address) { BusSpeed ​​=I2cBusSpeed.StandardMode, SharingMode =I2cSharingMode.Shared }; _updateInterval =updateInterval; IsDemoMode =String.IsNullOrEmpty(i2cDeviceId); if (!IsDemoMode) { _scaleI2CChannel =menunggu Windows.Devices.I2c.I2cDevice.FromIdAsync(i2cDeviceId, pengaturan); if (Windows.Storage.ApplicationData.Current.LocalSettings.Values.ContainsKey(String.Format("{0:X}.OFFSET", _address))) { _countOffset =Convert.ToInt32(Windows.Storage.ApplicationData.Current.LocalSettings .Nilai[String.Format("{0:X}.OFFSET", _address)]); coba { WriteValue((byte)'O', _countOffset); } catch (Pengecualian ex) { Debug.WriteLine("Skala offline "); } } if (Windows.Storage.ApplicationData.Current.LocalSettings.Values.ContainsKey(String.Format("{0:X}.CALIBRATION", _address))) { _calibrationFactor =Convert.ToDouble(Windows.Storage.ApplicationData.Current .LocalSettings.Values[String.Format("{0:X}.CALIBRATION", _address)]); LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { Status ="Siap"; }); } } else { LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { Status ="Siap"; }); } } dalam? _lastRaw =nol; private int GetRaw() { try { var inbuffer =byte baru[4]; _scaleI2CChannel.Write(byte baru[] { (byte)0x11 }); _scaleI2CChannel.Read(inbuffer); /* Perhatikan skalanya, ini panjang (64 bit) ini int (64 bit) */ var thisRaw =(int)(inbuffer[0] <<24 | inbuffer[1] <<16 | inbuffer[ 2] <<8 | inbuffer[3]); if (_lastRaw.HasValue) { if (Math.Abs(_lastRaw.Value - thisRaw)> 0xFFFF) mengembalikan _lastRaw.Value; } else _lastRaw =thisRaw; kembalikan ini Mentah; } catch (Pengecualian) { return -1; } } public override void Refresh() { LastUpdated =DateTime.Now; int hasil mentah =0; var isOnline =benar; coba { var inbuffer =byte baru[4]; var statusBuffer =byte baru[1]; if (!IsDemoMode) { _scaleI2CChannel.Write(byte baru[] { (byte)0x0A }); _scaleI2CChannel.Read(statusBuffer); rawResult =GetRaw(); } if (_calibrationFactor.HasValue) { Berat =(rawResult - _countOffset) * _calibrationFactor.Value; Debug.WriteLine(String.Format("0x{0:X} BERAT NILAI => {1:0.00} lbs", _address, Weight)); } else if (_countOffset> 0) Debug.WriteLine(String.Format("0x{0:X} NILAI NOL => {1}", _address, rawResult - _countOffset)); else Debug.WriteLine(String.Format("0x{0:X} RAW NILAI => 0x{1:X}", _address, rawResult)); } catch (Pengecualian ex) { rawResult =-1; isOnline =salah; Debug.WriteLine(mis.Pesan); } LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { Raw =rawResult; IsOnline =isOnline; if (!IsOnline) { Status ="Offline"; WeightDisplay ="?"; } else { if (_calibrationFactor .HasValue) { Status ="Siap"; WeightDisplay =String.Format("{0}lb {1:00}oz", Math.Truncate(Weight), ((Weight % 1.0) * 16.0)); } else { WeightDisplay ="?"; Status ="Tidak Dikalibrasi"; } } RaisePropertyChanged("LastUpdateDisplay"); }); } const int CALIBRATION_COUNT =10; public async void StoreOffset() { LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { Status ="Zeroing"; }); Debug.WriteLine("Memulai Proses Nol"); panjang nolJumlah =0; for (var idx =0; idx  { Status ="Nol"; }); } asinkron publik batal Kalibrasi() { Status ="Kalibrasi"; LagoVista.Common.PlatformSupport.Services.BindingHelper.RefreshBindings(); jumlah panjangJumlah =0; for (var idx =0; idx  GetAverageWeight(int pointCount =5) { var weightSum =0.0; for(var idx =0; idx  StoreOffset()); } } public RelayCommand CalibrationCommand { get { return new RelayCommand(() => Calibrate()); } } }}
Kelas KegeratorC#
Pratinjau Kode Sumber sebelum sumber lengkap dirilis di GitHub. Jika Anda ingin akses awal atau ingin membantu berkontribusi, silakan hubungi penulis proyek ini
menggunakan LagoVista.Common.Commanding;using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel; menggunakan System.Linq;menggunakan System.Runtime.CompilerServices;menggunakan System.Text;menggunakan System.Threading.Tasks;menggunakan Windows.Devices.Enumeration;menggunakan Windows.Devices.I2c;namespace LagoVista.IoT.Common.Kegerator{ public class Kegerator :INotifyPropertyChanged { acara publik PropertyChangedEventHandler PropertyChanged; Model pribadi.Keg _keg1; Model pribadi.Keg _keg2; Model pribadi.Keg _keg3; Model pribadi.Keg _keg4; CO2.CO2Tank pribadi _co2Tank; private Kegerator() { } Public List _devices =new List(); private void RaisePropertyChanged([CallerMemberName] string propertyName =null) { var eventHandler =this.PropertyChanged; if (eventHandler !=null) { eventHandler(ini, new PropertyChangedEventArgs(propertyName)); } } private bool Set(ref T penyimpanan, nilai T, string columnName =null, [CallerMemberName] string propertyName =null) { if (object.Equals(storage, value)) return false; penyimpanan =nilai; this.RaisePropertyChanged(namaproperti); kembali benar; } byte[] _scalesAddresses ={ 0x43, 0x41, 0x40, 0x42 }; string const pribadi I2C_CONTROLLER_NAME ="I2C1"; pribadi Thermo.Temperatures _temperatures; pribadi Thermo.Controller _tempController; Timbangan pribadi.Skala _co2Scale; Kamus pribadi _kegScales; pribadi CO2.PressureSensor _pressureSensor; pribadi LED.LEDManager _ledManager; private REST.KegeratorServices _kegServices; private static Kegerator _kegerator =new Kegerator(); public static Kegerator Instance { get { return _kegerator; } } CloudServices.EventHubClient _eventHubClient pribadi; System.Threading.Timer _timer; private bool _initialized =false; public async Task Init() { if (!_initialized) { _initialized =true; var pemilih =I2cDevice.GetDeviceSelector(I2C_CONTROLLER_NAME); /* Temukan string pemilih untuk pengontrol bus I2C */ var deviceInfo =(menunggu DeviceInformation.FindAllAsync(selector)).FirstOrDefault(); /* Temukan perangkat pengontrol bus I2C dengan string pemilih kami */ var deviceId =deviceInfo ==null ? (string)null :deviceInfo.Id; _temperatures =baru Thermo.Temperatures (0x48); menunggu _temperatures.Init(deviceId); _devices.Add(_temperatures); _tempController =baru Thermo.Controller(); _tempController.Init(_temperatures); _devices.Add(_tempController); _pressureSensor =CO2 baru.PressureSensor(); menunggu _pressureSensor.Init(deviceId, TimeSpan.FromSeconds(1)); _devices.Add(_pressureSensor); _co2Scale =Scales.Scale baru (0x44); menunggu _co2Scale.Init(deviceId, TimeSpan.FromSeconds(1)); _devices.Add(_co2Scale); _co2Tank =CO2.CO2Tank baru(_co2Scale, TimeSpan.FromSeconds(2)); _co2Tank.Load(); _devices.Add(_co2Tank); _kegScales =Kamus baru(); _eventHubClient =CloudServices.EventHubClient baru (ini, TimeSpan.FromSeconds(2)); _devices.Add(_eventHubClient); for (var idx =0; idx <4; ++idx) { var scale =new Scales.Scale(_scalesAddresses[idx]); menunggu scale.Init(deviceId, TimeSpan.FromMilliseconds(500)); _kegScales.Add(idx, scale); _devices.Add(skala); } _keg1 =new Models.Keg(1, _kegScales[0], TimeSpan.FromMilliseconds(500)); _keg1.Load(); _devices.Add(_keg1); _keg2 =Models.Keg baru(2, _kegScales[1], TimeSpan.FromMilliseconds(500)); _keg2.Muat(); _devices.Add(_keg2); _keg3 =Models.Keg baru(3, _kegScales[2], TimeSpan.FromMilliseconds(500)); _keg3.Load(); _devices.Add(_keg3); _keg4 =Models.Keg baru(4, _kegScales[3], TimeSpan.FromMilliseconds(500)); _keg4.Load(); _devices.Add(_keg4); DateInitialized =DateTime.Now.ToString(); Web.WebServer.Instance.StartServer(); _kegServices =new REST.KegeratorServices() { Port =9500 }; _kegServices.EventContent +=_kegServices_EventContent; _kegServices.StartServer(); _timer =new System.Threading.Timer((state) => { Refresh(); }, null, 0, 250); } } private void _kegServices_EventContent(pengirim objek, string e) { var parts =e.Split('/'); if (parts.Count()> 0) { switch (parts[1]) { case "nol":{ var scaleIndex =Convert.ToInt32(parts[2]); _kegScales[scaleIndex].StoreOffset(); } merusak; case "cal":{ var scaleIndex =Convert.ToInt32(parts[2]); _kegScales[scaleIndex].CalibrationWeight =Convert.ToDouble(bagian[3]); _kegScales[scaleIndex].Calibrate(); } merusak; } } } public void Refresh() { foreach (perangkat var di _devices) { if (DateTime.Now> (device.LastUpdated + device.UpdateInterval)) device.Refresh(); } LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { CurrentTimeDisplay =DateTime.Now.ToString(); RaisePropertyChanged("CurrentTimeDisplay"); }); } Suhu Thermo.Temperatures publik { get { return _temperatures; } } Thermo.Controller TemperatureController publik { dapatkan { return _tempController; } } String pribadi _statusMessage; public String StatusMessage { dapatkan { return _statusMessage; } set { Set(ref _statusMessage, nilai); } } public List KegScales { get { return _kegScales.Values.ToList(); } } public void ToggleCompressor() { if (_tempController.IsCompressorOn) _tempController.CompressorOff(); lain _tempController.CompressorOn(); } public String DateInitialized { get; mengatur; } publik String CurrentTimeDisplay { dapatkan; mengatur; } Public Scales.Scale CO2Scale { get { return _co2Scale; } } public CO2.PressureSensor PressureSensor { dapatkan { return _pressureSensor; } } public Models.Keg Keg1 { get { return _keg1; } } public Models.Keg Keg2 { get { return _keg2; } } public Models.Keg Keg3 { get { return _keg3; } } public Models.Keg Keg4 { get { return _keg4; } } CO2.CO2Tank CO2Tank publik { dapatkan { return _co2Tank; } } public RelayCommand ToggleCompressorCommand { get { return new RelayCommand(ToggleCompressor); } } }}

Skema

Diagram Komponen Sistem Tingkat Tinggi

Proses manufaktur

  1. Penghindaran Rintangan menggunakan Kecerdasan Buatan
  2. Giroskop Menyenangkan dengan NeoPixel Ring
  3. Pengontrol Game Arduino
  4. Kostum Cloud
  5. Pengikut Lini Industri untuk Pengadaan Bahan
  6. Pixie:Jam Tangan NeoPixel Berbasis Arduino
  7. Botol Air Bertenaga Arduino
  8. Teater Bayangan Liburan
  9. Kamera Pengawasan Jarak Jauh Seluler
  10. Mesin EDM Kawat Terbaik di Taiwan