산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

궁극의 Kegerator

구성품 및 소모품

SparkFun Arduino Pro Mini 328 - 3.3V/8MHz
× 7
SparkFun 로드 셀 증폭기 - HX711
× 1
Leviton 47603-12B 4x12 전화 배전반
× 1
라즈베리 파이 2 모델 B
× 1
AC 100-120V 200-220V 5V 6A 30W 스위치 전원 공급 장치
× 1
IR 모션 센서
× 1
10.6 cu. ft. 체스트 냉동고
× 1
스마트 무게 디지털 우편 요금 저울
× 5
Rii K12 울트라 슬림 2.4GHz 키보드
× 1
Rasbperry Pi WiFi 동글
× 1
Arduino DC 5V 릴레이 모듈
× 1
DHT11 온도 및 습도 센서(4핀)
× 2
DHT22 온도 센서
× 3
HomeBrewStuff 스테인리스 스틸 더블 생맥주 타워
× 2
맥주 타워 냉각기
× 1
0-30 PSI I2C 압력 센서(3.3V) ABPMANN030PG2A3
× 1

필요한 도구 및 기계

목재 작업 도구
냉동고 외부를 사용자 정의하는 도구
와이어 커터
납땜 인두(일반)
열수축 튜브

이 프로젝트 정보

면책 조항: 우선, 이 프로젝트는 알코올의 사용이나 오용을 조장하지 않으며, 이 kegerator의 내용물을 구성하는 음료는 전적으로 사용자에게 달려 있습니다.

이 프로젝트는 kegerator의 콘텐츠를 더 잘 관리하고자 하는 열망에서 태어났습니다. kegerator는 음료를 차갑게 유지하고 음료를 특정 PSI에서 탄산 상태로 유지하는 기본 원리에 대해 작동합니다. 또한 자신에게 차가운 음료를 붓는 것만으로는 술통에 얼마나 남았는지 알 수 없습니다. 일요일 미식축구 경기에 사람들을 데려가서 경기 중반에 루트 비어를 다 써버리면 안타까운 일이 될 것입니다.



이 프로젝트의 목표는 다음과 같습니다.

<올>
  • 음료의 온도를 일정하게 유지하고 음료가 너무 덥거나 차가워지지 않도록 하고 얼지 않도록 합니다.
  • 최적의 풍미를 유지하기 위해 허용 가능한 양의 탄산이 통에 적용되었는지 확인합니다.
  • 각 술통에 담긴 음료의 양을 추적하고 큰 경기를 위해 충분한 양의 음료를 준비할 수 있도록 시각적 피드백을 제공합니다.
  • 음료를 탄산화하는 데 사용되는 탱크에 남아 있는 CO2의 양을 추적합니다.
  • 기본 전자 부품 및 용도:

    <올>
  • 냉장고는 멋진 가구를 만들기 위한 프레임을 제공하고 냉각 장치에 사용됩니다.
  • Windows 10 IoT 코어를 실행하는 Raspberry PI 2는 작동의 두뇌로 사용됩니다.
  • 소형 우표 저울은 각 통과 CO2 탱크의 무게를 측정하는 데 사용되며, 이 우표 저울에는 전자 장치가 제거되고 로드 셀 증폭기와 소형 Arduino가 저울에 내장되어 있습니다. 이 저울은 I2C를 통해 Raspberry PI 2와 통신합니다(나중에 자세히 설명)
  • 장치에 5개의 디지털 온도 센서가 설치되어 있습니다. 하나는 냉동고의 바닥에, 하나는 상단의 아래쪽에 부착되고, 하나는 탭 핸들이 있는 타워에 각각 설치됩니다(자세한 내용은 나중에 ) 및 주변 온도를 측정하기 위해 장치 외부에 설치됩니다. 이 온도 센서는 소형 Arduino에 연결되며 I2C를 통해 Raspberry PI 2와 통신합니다.
  • Honeywell 압력 센서는 통에 탄산을 제공하는 데 사용되는 공기 라인에 부착되어 있습니다. PSI 조정은 수동이지만(현재로서는) 통에 적용되는 CO2의 정확한 측정값을 제공합니다.
  • 5V 전원 공급 장치는 Raspberry PI2에 전원을 공급하는 데 사용됩니다. 주소 지정이 가능한 LED 스트립에도 전원을 공급할 수 있도록 더 큰 버전(최대 6A 제공)이 선택되었습니다.
  • 압축기의 전원에 인라인으로 간단한 릴레이가 배치됩니다. 이 릴레이를 사용하여 압축기에서 전원을 인가하고 제거할 수 있으며 압축기는 차례로 케게레이터의 온도를 제어합니다(자세한 내용은 나중에 설명)
  • 클라우드 연결

    Ultimate Kegerator에는 REST 서비스를 통한 원격 구성과 현재 상태의 간단한 정적 보기를 허용하는 웹 서버가 포함되어 있습니다. 이 웹사이트는 http://slsys.homeip.net:9501에 접속할 수 있습니다.

    또한 Ultimate Kegerator는 중요한 통계를 Windows Azure 이벤트 허브에 업로드합니다. 이벤트 허브와 통신하기 위해 표준 Nuget 패키지를 사용할 수는 없지만

    에서 사용할 수 있는 동료 Windows Embedded MVP Paolo Patierno가 제공하는 구현하기 쉬운 라이브러리입니다.

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

    Stream Analytics에 의한 궁극적인 처리를 위해

    Stream Analytics의 최종 계획은 다음과 같습니다.

    1) 온도가 너무 덥거나 너무 추울 경우 모니터링 및 알림

    2) CO2 탱크가 너무 낮아지면 모니터링 및 알림

    3) CO2 탱크에서 누출이 감지되면 모니터링 및 알림(점진적인 중량 감소)


    다음은 조립 과정의 추가 사진입니다.


    -twb

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • 케그 클래스
  • 스케일 클래스
  • Kegerator 클래스
  • 케그 클래스C#
    GitHub에 전체 소스가 출시되기 전 소스 코드 미리보기. 사전 체험판을 원하거나 기여를 돕고 싶다면 LagoVista.Common.Commanding;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System .Threading.Tasks, Windows.UI.Xaml 사용, 네임스페이스 LagoVista.IoT.Common.Kegerator.Models{ public class Keg :DeviceBase { int _idx; 시간 범위 _updateInterval; 개인 Scales.Scale _scale; 공개 케그(int idx, Scales.Scale 스케일, TimeSpan updateInterval) { _idx =idx; _updateInterval =업데이트 간격; _규모 =규모; } 공개 재정의 TimeSpan UpdateInterval { get { return _updateInterval; } } 공개 재정의 void Refresh() { LastUpdated =DateTime.Now; LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { ContentsWeight =Scale.Weight - ContainerWeightLb, if (FullContentsWeightLb> 0) PercentFull =Convert.ToInt32((ContentsWeight / (FullContentsWeightLb - ContainerWeightLb0)) *10b else PercentFull =0, PercentFull =Math.Min(PercentFull, 100), if (GlassSizeOz> 0) QtyRemaining =Convert.ToInt32((ContentsWeight * 16)/ GlassSizeOz), else QtyRemaining =0, RaisePropertyChanged("PercentFullHeight 변경") ("PercentFullDisplay"); }); } 공개 Scales.Scale 스케일 { get { return _scale; } } #region 계산된 속성 private int _qtyRemaining; 공개 정수 QtyRemaining { get { 반환 _qtyRemaining; } 세트 { Set(ref _qtyRemaining, 값); } } 비공개 DateTime? _설치날짜; 공개 날짜 시간? InstallDate { get { return _installDate; } set { Set(ref _installDate, 값); } } 개인 int _percentFull; public int PercentFull { get { return _percentFull; } set { Set(ref _percentFull, 값); } } public String PercentFullDisplay { get { return String.Format("{0}%", Convert.ToInt32(PercentFull)); } } public double PercentFullHeight { get { return Convert.ToDouble(_percentFull * 2); } } 공개 int KegIndex { get { 반환 _idx; } } #endregion #region 입력된 속성 private bool _isEmpty; 공개 bool IsEmpty { get { 반환 _isEmpty; } 설정 { _isEmpty =값; RaisePropertyChanged(); } } 개인 더블 _glassSize; 공개 이중 GlassSizeOz { get { return _glassSize; } 세트 { Set(ref _glassSize, 값); } } 비공개 DateTime? _태어난 날짜; 공개 날짜 시간? BornDate { get { return _bornDate; } 세트 { Set(ref _bornDate, 값); } } 더블 _containerWeight; 공개 이중 ContainerWeightLb { get { 반환 _containerWeight; } 세트 { Set(ref _containerWeight, 값); } } 더블 _contentsWeight; 공개 이중 ContentsWeight { get { return _contentsWeight; } set { Set(ref _contentsWeight, 값); } } 더블 _fullContentsWeight; 공개 이중 FullContentsWeightLb { get { 반환 _fullContentsWeight; } 세트 { Set(ref _fullContentsWeight, 값); } } 개인 문자열 _contentsName; 공개 문자열 ContentsName { get { 반환 _contentsName; } 세트 { Set(ref _contentsName, 값); } } #endregion 공개 무효 Save() { LagoVista.Common.PlatformSupport.Services.BindingHelper.RefreshBindings(); PutSetting(String.Format("KEG{0}_CONTENTS", _idx), 콘텐츠 이름); 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)); } 공개 무효 Load() { 콘텐츠 이름 =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); 그렇지 않으면 BornDate =null; var installDate =GetSetting("KEG{0}_INSTALL_DATE", String.Empty); if (!String.IsNullOrEmpty(installDate)) InstallDate =DateTime.Parse(installDate); 그렇지 않으면 설치 날짜 =null; } 공개 비동기 무효 SaveFullWeight() { FullContentsWeightLb =await Scale.GetAverageWeight(); 구하다(); } 공개 RelayCommand SaveFullWeightCommand { get { return new RelayCommand(() => SaveFullWeight()); } } }}
    스케일 클래스C#
    GitHub에 전체 소스가 출시되기 전 소스 코드 미리보기. 사전 체험판을 원하거나 기여하는 데 도움이 되고 싶다면 이 프로젝트의 저자에게 연락하십시오. .텍스트, System.Threading.Tasks 사용, Windows.Devices.I2c 사용, 네임스페이스 LagoVista.IoT.Common.Kegerator.Scales{ public class Scale :DeviceBase { Windows.Devices.I2c.I2cDevice _scaleI2CChannel; 정수 _countOffset; 더블? _calibrationFactor =null; 개인 TimeSpan _updateInterval; 바이트 _주소; 공개 스케일(바이트 주소) { _address =주소; } private void WriteValue(바이트 주소, 정수 값) { if (!IsDemoMode) { var offsetBuffer =new byte[5]; 오프셋 버퍼[0] =주소; offsetBuffer[1] =(바이트)(값>> 24); offsetBuffer[2] =(바이트)(값>> 16); offsetBuffer[3] =(바이트)(값>> 8); offsetBuffer[4] =(바이트)(값); _scaleI2CChannel.Write(오프셋 버퍼); } } 공개 비동기 작업 초기화(문자열 i2cDeviceId, TimeSpan updateInterval) { var 설정 =new I2cConnectionSettings(_address) { BusSpeed ​​=I2cBusSpeed.StandardMode, SharingMode =I2cSharingMode.Shared }; _updateInterval =업데이트 간격; IsDemoMode =String.IsNullOrEmpty(i2cDeviceId); if (!IsDemoMode) { _scaleI2CChannel =Windows.Devices.I2c.I2cDevice.FromIdAsync(i2cDeviceId, 설정)를 기다립니다. if (Windows.Storage.ApplicationData.Current.LocalSettings.Values.ContainsKey(String.Format("{0:X}.OFFSET", _address))) { _countOffset =Convert.ToInt32(Windows.Storage.ApplicationData.Current.LocalSettings .Values[String.Format("{0:X}.OFFSET", _address)]); { WriteValue((byte)'O', _countOffset); } catch(예외 예외) { Debug.WriteLine("오프라인 크기 조정"); } } 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(() => { 상태 ="준비"; }); } } else { LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { 상태 ="준비"; }); } } 정수? _lastRaw =null; private int GetRaw() { try { var inbuffer =새로운 바이트[4]; _scaleI2CChannel.Write(새 바이트[] { (바이트)0x11}); _scaleI2CChannel.Read(인버퍼); /* 규모에 유의하십시오. 여기서는 긴(64비트) int(64비트)입니다. */ var thisRaw =(int)(inbuffer[0] <<24 | inbuffer[1] <<16 | inbuffer[ 2] <<8 | 버퍼[3]); if (_lastRaw.HasValue) { if (Math.Abs(_lastRaw.Value - thisRaw)> 0xFFFF) return _lastRaw.Value; } else _lastRaw =thisRaw; thisRaw를 반환합니다. } catch(예외) { 반환 -1; } } 공개 재정의 void Refresh() { LastUpdated =DateTime.Now; 정수 원시 결과 =0; var isOnline =참; try { var inbuffer =새로운 바이트[4]; var statusBuffer =새로운 바이트[1]; if (!IsDemoMode) { _scaleI2CChannel.Write(새 바이트[] { (바이트)0x0A}); _scaleI2CChannel.Read(상태 버퍼); 원시 결과 =GetRaw(); } if (_calibrationFactor.HasValue) { 가중치 =(rawResult - _countOffset) * _calibrationFactor.Value; Debug.WriteLine(String.Format("0x{0:X} 무게 값 => {1:0.00} lbs", _address, 무게)); } else if (_countOffset> 0) Debug.WriteLine(String.Format("0x{0:X} ZEROED VALUE => {1}", _address, rawResult - _countOffset)); else Debug.WriteLine(String.Format("0x{0:X} RAW 값 => 0x{1:X}", _address, rawResult)); } catch(예외 예외) { rawResult =-1; isOnline =거짓; Debug.WriteLine(예:메시지); } LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { Raw =rawResult; IsOnline =isOnline; if (!IsOnline) { 상태 ="오프라인"; WeightDisplay ="?"; } else { if (_calibrationFactor .HasValue) { 상태 ="준비"; WeightDisplay =String.Format("{0}lb {1:00}oz", Math.Truncate(Weight), ((Weight % 1.0) * 16.0)); } else { WeightDisplay ="?"; Status ="보정되지 않음"; } } RaisePropertyChanged("LastUpdateDisplay"); }); } const 정수 CALIBRATION_COUNT =10; 공개 비동기 무효 StoreOffset() { LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { 상태 ="영점화"; }); Debug.WriteLine("제로 프로세스 시작"); 긴 zeroSum =0; for (var idx =0; idx { 상태 ="0"; }); } 공개 비동기 무효 Calibrate() { 상태 ="교정 중"; LagoVista.Common.PlatformSupport.Services.BindingHelper.RefreshBindings(); 긴 countSum =0; for (var idx =0; idx GetAverageWeight(int pointCount =5) { var weightSum =0.0; for(var idx =0; idx StoreOffset()); } } 공개 RelayCommand CalibrationCommand { get { return new RelayCommand(() => Calibrate()); } } }}
    Kegerator 클래스C#
    GitHub에 전체 소스가 출시되기 전 소스 코드 미리보기. 사전 체험판을 원하거나 기여를 하고 싶다면 이 프로젝트의 저자에게 연락하십시오. System.Linq 사용, System.Runtime.CompilerServices 사용, System.Text 사용, System.Threading.Tasks 사용, Windows.Devices.Enumeration 사용, Windows.Devices.I2c 사용, 네임스페이스 LagoVista.IoT.Common.Kegerator{ public class Kegerator :INotifyPropertyChanged { 공개 이벤트 PropertyChangedEventHandler PropertyChanged; 개인 Models.Keg _keg1; 개인 Models.Keg _keg2; 개인 Models.Keg _keg3; 개인 Models.Keg _keg4; 개인 CO2.CO2Tank _co2Tank; 개인 Kegerator() { } 공개 List _devices =new List(); 개인 무효 RaisePropertyChanged([CallerMemberName] 문자열 propertyName =null) { var eventHandler =this.PropertyChanged; if (eventHandler !=null) { eventHandler(이, 새로운 PropertyChangedEventArgs(propertyName)); } } private bool Set(ref T storage, T value, string columnName =null, [CallerMemberName] string propertyName =null) { if (object.Equals(storage, value)) return false; 저장 =가치; this.RaisePropertyChanged(속성 이름); true를 반환합니다. } 바이트[] _scalesAddresses ={ 0x43, 0x41, 0x40, 0x42 }; 개인 const 문자열 I2C_CONTROLLER_NAME ="I2C1"; 개인 Thermo.Temperatures _온도; 개인 Thermo.Controller _tempController; 개인 Scales.Scale _co2Scale; 개인 사전 _kegScales; 개인 CO2.PressureSensor _pressureSensor; 개인 LED.LEDManager _ledManager; 개인 REST.KegeratorServices _kegServices; 개인 정적 Kegerator _kegerator =new Kegerator(); 공개 정적 Kegerator 인스턴스 { get { return _kegerator; } } 개인 CloudServices.EventHubClient _eventHubClient; System.Threading.Timer _timer; 개인 부울 _초기화 =거짓; 공개 비동기 작업 Init() { if (!_initialized) { _initialized =true; var 선택기 =I2cDevice.GetDeviceSelector(I2C_CONTROLLER_NAME); /* I2C 버스 컨트롤러에 대한 선택기 문자열 찾기 */ var deviceInfo =(await DeviceInformation.FindAllAsync(selector)).FirstOrDefault(); /* 선택기 문자열로 I2C 버스 컨트롤러 장치를 찾습니다. */ var deviceId =deviceInfo ==null ? (문자열) null :deviceInfo.Id; _온도 =새로운 Thermo.Temperatures(0x48); _온도.초기화(장치 ID)를 기다립니다. _devices.Add(_온도); _tempController =새로운 Thermo.Controller(); _tempController.Init(_온도); _devices.Add(_tempController); _pressureSensor =새로운 CO2.PressureSensor(); _pressureSensor.Init(deviceId, TimeSpan.FromSeconds(1))을 기다립니다. _devices.Add(_pressureSensor); _co2Scale =새로운 Scales.Scale(0x44); _co2Scale.Init(deviceId, TimeSpan.FromSeconds(1))을 기다립니다. _devices.Add(_co2Scale); _co2Tank =새로운 CO2.CO2Tank(_co2Scale, TimeSpan.FromSeconds(2)); _co2Tank.Load(); _devices.Add(_co2Tank); _kegScales =새로운 사전(); _eventHubClient =새로운 CloudServices.EventHubClient(이, TimeSpan.FromSeconds(2)); _devices.Add(_eventHubClient); for (var idx =0; idx <4; ++idx) { var scale =new Scales.Scale(_scalesAddresses[idx]); scale.Init(deviceId, TimeSpan.FromMilliseconds(500))을 기다립니다. _kegScales.Add(idx, 규모); _devices.Add(규모); } _keg1 =새로운 Models.Keg(1, _kegScales[0], TimeSpan.FromMilliseconds(500)); _keg1.로드(); _장치.추가(_keg1); _keg2 =새로운 Models.Keg(2, _kegScales[1], TimeSpan.FromMilliseconds(500)); _keg2.Load(); _장치.추가(_keg2); _keg3 =새로운 Models.Keg(3, _kegScales[2], TimeSpan.FromMilliseconds(500)); _keg3.로드(); _장치.추가(_keg3); _keg4 =새로운 Models.Keg(4, _kegScales[3], TimeSpan.FromMilliseconds(500)); _keg4.Load(); _장치.추가(_keg4); DateInitialized =DateTime.Now.ToString(); Web.WebServer.Instance.StartServer(); _kegServices =새로운 REST.KegeratorServices() { 포트 =9500 }; _kegServices.EventContent +=_kegServices_EventContent; _kegServices.StartServer(); _timer =새로운 System.Threading.Timer((상태) => { 새로 고침(); }, null, 0, 250); } } 개인 무효 _kegServices_EventContent(객체 발신자, 문자열 e) { var 부품 =e.Split('/'); if (parts.Count()> 0) { switch (parts[1]) { 경우 "0":{ var scaleIndex =Convert.ToInt32(parts[2]); _kegScales[scaleIndex].StoreOffset(); } 부서지다; case "cal":{ var scaleIndex =Convert.ToInt32(parts[2]); _kegScales[scaleIndex].CalibrationWeight =Convert.ToDouble(파트[3]); _kegScales[scaleIndex].Calibrate(); } 부서지다; } } } public void Refresh() { foreach (_devices의 장치 변수) { if (DateTime.Now> (device.LastUpdated + device.UpdateInterval)) device.Refresh(); } LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { CurrentTimeDisplay =DateTime.Now.ToString(); RaisePropertyChanged("CurrentTimeDisplay"); }); } 공개 Thermo.Temperatures 온도 { get { return _temperature; } } 공개 Thermo.Controller 온도 컨트롤러 { get { return _tempController; } } 개인 문자열 _statusMessage; 공개 문자열 StatusMessage { get { 반환 _statusMessage; } 세트 { Set(ref _statusMessage, 값); } } 공개 목록 KegScales { get { return _kegScales.Values.ToList(); } } 공개 무효 ToggleCompressor() { if (_tempController.IsCompressorOn) _tempController.CompressorOff(); 그렇지 않으면 _tempController.CompressorOn(); } 공개 문자열 DateInitialized { get; 세트; } 공개 문자열 CurrentTimeDisplay { 가져오기; 세트; } 공개 Scales.Scale CO2Scale { get { return _co2Scale; } } 공개 CO2.PressureSensor PressureSensor { get { 반환 _pressureSensor; } } 공개 Models.Keg Keg1 { get { return _keg1; } } 공개 Models.Keg Keg2 { get { return _keg2; } } 공개 Models.Keg Keg3 { get { return _keg3; } } 공개 Models.Keg Keg4 { get { return _keg4; } } 공개 CO2.CO2Tank CO2Tank { get { return _co2Tank; } } 공개 RelayCommand ToggleCompressorCommand { get { return new RelayCommand(ToggleCompressor); } } }}

    회로도

    높은 수준의 시스템 구성 요소 다이어그램

    제조공정

    1. 인공 지능을 사용한 장애물 회피
    2. NeoPixel Ring으로 재미있는 자이로스코프
    3. Arduino 게임 컨트롤러
    4. 구름 의상
    5. 자재 공급을 위한 산업용 라인 팔로워
    6. Pixie:Arduino 기반 NeoPixel 손목시계
    7. Arduino 기반 물병
    8. 휴일 그림자 극장
    9. 모바일 원격 감시 카메라
    10. 대만 최고의 와이어 방전가공기