工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

究極のケゲレーター

コンポーネントと消耗品

> >
SparkFun Arduino Pro Mini 328-3.3V / 8MHz
× 7
SparkFunロードセルアンプ-HX711
× 1
Leviton 47603-12B4x12電話配布ボード
× 1
Raspberry Pi2モデルB
× 1
AC 100-120V 200-220V 5V 6A30Wスイッチ電源
× 1
IRモーションセンサー
× 1
10.6cu。フィートチェストフリーザー
× 1
スマートウェイトデジタル体重計
× 5
Rii K12 Ultra Slim 2.4GHzキーボード
× 1
Rasbperry PiWiFiドングル
× 1
Arduino DC5Vリレーモジュール
× 1
DHT11温度および湿度センサー(4ピン)
× 2
DHT22温度センサー
× 3
HomeBrewStuffステンレス鋼ダブルドラフトビールタワー
× 2
ビールタワークーラー
× 1
0-30 PSI I2C圧力センサー(3.3V)ABPMANN030PG2A3
× 1

必要なツールとマシン

木工ツール
冷凍庫の外側をカスタマイズするためのツール
ワイヤーカッター
はんだごて(汎用)
熱収縮チューブ

このプロジェクトについて

免責事項: まず、このプロジェクトはアルコールの使用や誤用を促進するものではありません。このケゲレーターの内容物を構成する飲料はユーザー次第です。

このプロジェクトは、ケゲレーターの内容をより適切に管理したいという願望から生まれました。ケゲレーターは、飲料を冷たく保つことと、飲料を特定のPSIで炭酸化することの基本原則に取り組んでいます。さらに、冷たい飲み物を自分に注ぐだけでは、樽にどれだけ残っているかわかりません。日曜日のフットボールの試合に人々が集まり、試合の途中でルートビアがなくなるのは残念なことです。



したがって、このプロジェクトの目標は次のとおりです。

  1. 飲料の温度を一定に保ち、飲料が暖かくなりすぎたり冷たすぎたりして凍結しないようにします
  2. 最適なフレーバーを維持するために、許容できる量の炭酸化が樽に適用されていることを確認してください
  3. 各樽の飲み物の量を追跡し、視覚的なフィードバックを提供して、ビッグゲームに十分な飲み物が手元にあることを確認します。
  4. 飲料の炭酸塩に使用されるタンクに残っているCO2の量を追跡します

基本的な電子部品とその使用法:

  1. チェストフリーザーは、冷却ユニットと、素敵な家具を作成するためのフレームを提供するために使用されます。
  2. Windows 10IoTコアを実行するRaspberryPI2は、運用の頭脳として使用されます
  3. 各樽とCO2タンクの重量を測定するために、小さな体重計が使用されます。これらの体重計には、電子機器が取り外され、ロードセルアンプと小さなArduinoが組み込まれています。これらのスケールは、I2Cを介してRaspberry PI 2と通信します(これについては後で詳しく説明します)
  4. ユニットには5つのデジタル温度センサーが取り付けられています。1つはチェストフリーザーの下部に、もう1つは上部の下側に取り付けられ、それぞれがタップハンドルがあるタワーに取り付けられています(これについては後で詳しく説明します) )および周囲温度を測定するためにユニットの外側に取り付けられたもの。これらの温度センサーは小さなArduinoに接続されており、I2Cを介してRaspberry PI2とも通信します
  5. ハネウェル圧力センサーは、樽に炭酸化を提供するために使用されるエアラインに取り付けられています。 PSIの調整は(今のところ)手動ですが、これにより、樽に適用されるCO2の量を正確に測定できます。
  6. 5V電源は、RaspberryPI2に電力を供給するために使用されます。アドレス可能なLEDストリップにも電力を供給できるように、より大きなバージョン(最大6アンペアを提供)が選択されました。
  7. シンプルなリレーがコンプレッサーの電源にインラインで配置されます。このリレーを使用して、コンプレッサーに電力を供給したり、コンプレッサーから電力を除去したりできます。次に、コンプレッサーがケゲレーターの温度を制御します(これについては後で詳しく説明します)。

クラウド接続

Ultimate Kegeratorには、RESTサービスを介したリモート構成と、現在のステータスの単純な静的ビューを可能にするWebサーバーが含まれています。このWebサイトには、http://slsys.homeip.net:9501からアクセスできます。

さらに、Ultimate Kegeratorは、人口動態統計をWindowsAzureイベントハブにアップロードします。イベントハブとの通信に標準のNugetパッケージを使用することはできませんが、

で入手可能なWindowsEmbeddedMVPの仲間であるPaoloPatiernoが提供するライブラリを簡単に実装できます。

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

<図>

StreamAnalyticsによる究極の処理のために

<図>

Stream Analyticsの最終的な計画は、次のとおりです。

1)温度が暖かくなりすぎたり、冷たすぎたりしないかどうかを監視して通知します

2)CO2タンクが低くなりすぎた場合は、監視して通知します

3)CO2タンクに漏れが検出されたかどうかを監視して通知します(重量が徐々に減少します)


組み立てプロセスの追加の写真を次に示します。

<図>


<図> <図> <図> <図> <図> <図> <図> <図> <図> <図>

-twb

コード

  • 樽クラス
  • スケールクラス
  • ケゲレータークラス
樽クラス C#
GitHubで完全なソースがリリースされる前のソースコードのプレビュー。早期アクセスが必要な場合、または貢献したい場合は、このプロジェクトの作成者に連絡してください
 using LagoVista.Common.Commanding; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System .Threading.Tasks; using Windows.UI.Xaml; namespace LagoVista.IoT.Common.Kegerator.Models {public class Keg:DeviceBase {int _idx; TimeSpan _updateInterval;プライベートScales.Scale_scale; public Keg(int idx、Scales.Scale scale、TimeSpan updateInterval){_ idx =idx; _updateInterval =UpdateInterval; _scale =スケール; } 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");}); } public Sc​​ales.Scale Scale {get {return _scale; }}#region計算されたプロパティprivateint _qtyRemaining; public int QtyRemaining {get {return _qtyRemaining; } set {Set(ref _qtyRemaining、value); }}プライベートDateTime? _installDate; public DateTime? InstallDate {get {return _installDate; } set {Set(ref _installDate、value); }} private int _percentFull; public int PercentFull {get {return _percentFull; } set {Set(ref _percentFull、value); }} public String PercentFullDisplay {get {return String.Format( "{0}%"、Convert.ToInt32(PercentFull)); }} public double PercentFullHeight {get {return Convert.ToDouble(_percentFull * 2); }} public int KegIndex {get {return _idx; }}#endregion#region入力されたプロパティprivatebool _isEmpty; public bool IsEmpty {get {return _isEmpty; } set {_isEmpty =value; RaisePropertyChanged(); }} private double _glassSize; public double GlassSizeOz {get {return _glassSize; } set {Set(ref _glassSize、value); }}プライベートDateTime? _bornDate; public DateTime? BornDate {get {return _bornDate; } set {Set(ref _bornDate、value); }} double _containerWeight; public double ContainerWeightLb {get {return _containerWeight; } set {Set(ref _containerWeight、value); }} double _contentsWeight; public double ContentsWeight {get {return _contentsWeight; } set {Set(ref _contentsWeight、value); }} double _fullContentsWeight; public double FullContentsWeightLb {get {return _fullContentsWeight; } set {Set(ref _fullContentsWeight、value); }} private String _contentsName; public String ContentsName {get {return _contentsName; } set {Set(ref _contentsName、value); }} #endregion public void Save(){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);それ以外の場合、BornDate =null; var installDate =GetSetting( "KEG {0} _ INSTALL_DATE"、String.Empty); if(!String.IsNullOrEmpty(installDate))InstallDate =DateTime.Parse(installDate);それ以外の場合、InstallDate =null; } public async void SaveFullWeight(){FullContentsWeightLb =await Scale.GetAverageWeight();保存する(); } public RelayCommand SaveFullWeightCommand {get {return new RelayCommand(()=> SaveFullWeight()); }}}} 
スケールクラス C#
GitHubで完全なソースがリリースされる前のソースコードのプレビュー。早期アクセスが必要な場合、または貢献したい場合は、このプロジェクトの作成者に連絡してください
 using LagoVista.Common.Commanding; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System .Text; using System.Threading.Tasks; using Windows.Devices.I2c; namespace LagoVista.IoT.Common.Kegerator.Scales {public class Scale:DeviceBase {Windows.Devices.I2c.I2cDevice _scaleI2CChannel; int _countOffset;ダブル? _calibrationFactor =null;プライベートTimeSpan_updateInterval;バイトアドレス; public Sc​​ale(byte address){_ address =address; } private void WriteValue(byte address、int value){if(!IsDemoMode){var offsetBuffer =new byte [5]; offsetBuffer [0] =アドレス; offsetBuffer [1] =(byte)(value>> 24); offsetBuffer [2] =(byte)(value>> 16); offsetBuffer [3] =(byte)(value>> 8); offsetBuffer [4] =(byte)(value); _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 =await Windows.Devices.I2c.I2cDevice.FromIdAsync(i2cDeviceId、settings); 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(Exception ex){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(()=> {Status ="Ready";}); }} else {LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(()=> {Status ="Ready";}); }} int? _lastRaw =null; private int GetRaw(){try {var inbuffer =new byte [4]; _scaleI2CChannel.Write(new byte [] {(byte)0x11}); _scaleI2CChannel.Read(inbuffer); / *スケールに注意してください。これは長い(64ビット)ここではint(64ビット)です* / var thisRaw =(int)(inbuffer [0] <<24 | inbuffer [1] <<16 | inbuffer [ 2] <<8 | inbuffer [3]); if(_lastRaw.HasValue){if(Math.Abs​​(_lastRaw.Value --thisRaw)> 0xFFFF)return _lastRaw.Value; } else _lastRaw =thisRaw; thisRawを返します。 } catch(Exception){return -1; }} public override void Refresh(){LastUpdated =DateTime.Now; int rawResult =0; var isOnline =true; {var inbuffer =new byte [4];を試してください。 var statusBuffer =new byte [1]; if(!IsDemoMode){_ scaleI2CChannel.Write(new byte [] {(byte)0x0A}); _scaleI2CChannel.Read(statusBuffer); rawResult =GetRaw(); } if(_calibrationFactor.HasValue){Weight =(rawResult --_ countOffset)* _calibrationFactor.Value; Debug.WriteLine(String.Format( "0x {0:X} WEIGHT VALUE => {1:0.00} lbs"、_ address、Weight)); } 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 VALUE => 0x {1:X}"、_ address、rawResult)); } catch(Exception ex){rawResult =-1; isOnline =false; Debug.WriteLine(ex.Message); } LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(()=> {Raw =rawResult; IsOnline =isOnline; if(!IsOnline){Status ="Offline"; WeightDisplay ="?";} else {if(_calibrationFactor .HasValue){Status ="Ready"; WeightDisplay =String.Format( "{0} lb {1:00} oz"、Math.Truncate(Weight)、((Weight%1.0)* 16.0));} else { WeightDisplay ="?"; Status ="Not Calibrated";}} RaisePropertyChanged( "LastUpdateDisplay");}); } const int CALIBRATION_COUNT =10; public async void StoreOffset(){LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(()=> {Status ="Zeroing";}); Debug.WriteLine( "Staritng Zero Process"); long zeroSum =0; for(var idx =0; idx  {Status ="Zeroed";}); } public async void Calibrate(){Status ="Calibrating"; LagoVista.Common.PlatformSupport.Services.BindingHelper.RefreshBindings(); long countSum =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()); }}}} 
Kegeratorクラス C#
GitHubで完全なソースがリリースされる前のソースコードのプレビュー。早期アクセスが必要な場合、または貢献したい場合は、
 using LagoVista.Common.Commanding; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using Windows.Devices.Enumeration; using Windows.Devices.I2c; namespace LagoVista.IoT.Common.Kegerator {public class Kegerator :INotifyPropertyChanged {パブリックイベントPropertyChangedEventHandlerPropertyChanged;プライベートModels.Keg_keg1;プライベートModels.Keg_keg2;プライベートModels.Keg_keg3;プライベートModels.Keg_keg4;プライベートCO2.CO2Tank_co2Tank; private Kegerator(){} public List  _devices =new List (); private void RaisePropertyChanged([CallerMemberName] string propertyName =null){var eventHandler =this.PropertyChanged; if(eventHandler!=null){eventHandler(this、new 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(propertyName); trueを返します。 } byte [] _scalesAddresses ={0x43、0x41、0x40、0x42}; private const string I2C_CONTROLLER_NAME ="I2C1";プライベートThermo.Temperatures_temperatures;プライベートThermo.Controller_tempController;プライベートScales.Scale_co2Scale;プライベート辞書 _kegScales;プライベートCO2.PressureSensor_pressureSensor;プライベートLED.LEDManager_ledManager;プライベートREST.KegeratorServices_kegServices; private static Kegerator _kegerator =new Kegerator(); public static Kegerator Instance {get {return _kegerator; }} private CloudServices.EventHubClient _eventHubClient; System.Threading.Timer _timer; private bool _initialized =false; public async Task 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; _temperatures =new Thermo.Temperatures(0x48); await _temperatures.Init(deviceId); _devices.Add(_temperatures); _tempController =new Thermo.Controller(); _tempController.Init(_temperatures); _devices.Add(_tempController); _pressureSensor =new CO2.PressureSensor(); await _pressureSensor.Init(deviceId、TimeSpan.FromSeconds(1)); _devices.Add(_pressureSensor); _co2Scale =new Scales.Scale(0x44); await _co2Scale.Init(deviceId、TimeSpan.FromSeconds(1)); _devices.Add(_co2Scale); _co2Tank =new CO2.CO2Tank(_co2Scale、TimeSpan.FromSeconds(2)); _co2Tank.Load(); _devices.Add(_co2Tank); _kegScales =new Dictionary (); _eventHubClient =new CloudServices.EventHubClient(this、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、scale); _devices.Add(scale); } _keg1 =new Models.Keg(1、_kegScales [0]、TimeSpan.FromMilliseconds(500)); _keg1.Load(); _devices.Add(_keg1); _keg2 =new Models.Keg(2、_kegScales [1]、TimeSpan.FromMilliseconds(500)); _keg2.Load(); _devices.Add(_keg2); _keg3 =new Models.Keg(3、_kegScales [2]、TimeSpan.FromMilliseconds(500)); _keg3.Load(); _devices.Add(_keg3); _keg4 =new Models.Keg(4、_kegScales [3]、TimeSpan.FromMilliseconds(500)); _keg4.Load(); _devices.Add(_keg4); DateInitialized =DateTime.Now.ToString(); Web.WebServer.Instance.StartServer(); _kegServices =new REST.KegeratorServices(){ポート=9500}; _kegServices.EventContent + =_kegServices_EventContent; _kegServices.StartServer(); _timer =new System.Threading.Timer((state)=> {Refresh();}、null、0、250); }} private void _kegServices_EventContent(object sender、string e){var Parts =e.Split( '/'); if(parts.Count()> 0){switch(parts [1]){case "zero":{var scaleIndex =Convert.ToInt32(parts [2]); _kegScales [scaleIndex] .StoreOffset(); } 壊す; case "cal":{var scaleIndex =Convert.ToInt32(parts [2]); _kegScales [scaleIndex] .CalibrationWeight =Convert.ToDouble(parts [3]); _kegScales [scaleIndex] .Calibrate(); } 壊す; }}} public void Refresh(){foreach(var device in _devices){if(DateTime.Now>(device.LastUpdated + device.UpdateInterval))device.Refresh(); } LagoVista.Common.PlatformSupport.Services.DispatcherServices.Invoke(() => { CurrentTimeDisplay =DateTime.Now.ToString(); RaisePropertyChanged("CurrentTimeDisplay"); }); } public Thermo.Temperatures Temperatures { get { return _temperatures; } } public Thermo.Controller TemperatureController { get { return _tempController; } } private String _statusMessage; public String StatusMessage { get { return _statusMessage; } set { Set(ref _statusMessage, value); } } public List KegScales { get { return _kegScales.Values.ToList(); } } public void ToggleCompressor() { if (_tempController.IsCompressorOn) _tempController.CompressorOff(); else _tempController.CompressorOn(); } public String DateInitialized { get;セットする; } public String CurrentTimeDisplay { get;セットする; } public Scales.Scale CO2Scale { get { return _co2Scale; } } public CO2.PressureSensor PressureSensor { get { 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; } } public CO2.CO2Tank CO2Tank { get { return _co2Tank; } } public RelayCommand ToggleCompressorCommand { get { return new RelayCommand(ToggleCompressor); } } }}

回路図

High Level System Component Diagram

製造プロセス

  1. 人工知能を使用した障害物の回避
  2. NeoPixelリングでジャイロスコープを楽しむ
  3. Arduinoゲームコントローラー
  4. クラウドコスチューム
  5. 材料を供給するための産業用ラインフォロワー
  6. Pixie:ArduinoベースのNeoPixel腕時計
  7. Arduinoを搭載したウォーターボトル
  8. ホリデーシャドウシアター
  9. モバイルリモート監視カメラ
  10. スマートハンドグローブ
  11. 台湾の究極のワイヤー放電加工機