m&m’s選別機の回路&コードをつくる
こんにちは、くろべこです。
前回に引き続き、m&m’s色彩選別機を作っていきます。
今回は、色彩選別の核となる電気回路と制御コードの作成を進めていきます。
では、早速どうぞ!!
m&m’s色彩選別機の電気回路
追記:前回の材料紹介の際に不足がありました。カラーセンサの動作電圧が2.25V~3.63Vであるためレベル変換器が必要になります。
回路図はEasy EDAというソフトで書いています。このソフトはライブラリが充実しているので結構使いやすくお勧めです。
組み立て
組み立ては、前編で描いた3D図を基に現物合わせで作っていきます。出来上がればOK!!肝となる部分のみ載せていきますね。
- 色彩検出器(上の穴にカラーセンサ、下の穴に光源用の白色LEDを埋め込んでいます)
- 扉部分(m&m’sが詰まることが多いので段ボールでガイドをしています)
- 回転梯子(Daisoのプラ板をH型にくっつけています。真ん中にサーボホーンを付ける感じ)
いずれの加工においてもグルーガンが大活躍します。100円ショップで売っているので購入をオススメします。
制御コード紹介
本コードではカラーセンサ(S11059-02DT)のライブラリとして以下を使用しています。
サーボ制御に関してはライブラリを使用していません。コード内でTimer1のレジスタをいじってサーボ制御用に調整しています。delayとかmillisはTimer0を使用しているので問題なく使用可能です。Timer1ってarduinoではなんかの関数に割り当てられていますかね?
ちなみに、arduino nanoに内蔵されているTimerレジスタの各割り付けは以下の通りです。
Timer0 | D5, D6 |
Timer1 | D9, D10 |
Timer2 | D3, D11 |
では、早速コードの紹介です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
#include <Wire.h> #include <S11059.h> uint8_t flag=4;//状態フラグ static uint16_t pos;//反射型在荷センサ static uint16_t red; static uint16_t green; static uint16_t blue; static uint16_t IR; static uint8_t deg; S11059 colorSensor; void setup() { Serial.begin(9600); pinMode(9, OUTPUT);//Servo1(扉) pinMode(10, OUTPUT);//Servo2(回転梯子) pinMode(6, OUTPUT);//LED上 pinMode(5, OUTPUT);//LED横 //PWMレジスタ設定 TCCR1A = 0b10;//位相基準PWM(TOP) TCCR1B &= ~0b111;//プリスケーラ―クリア TCCR1B |= 0b100;//256プリスケーラ― TCCR1B |= 0b00010000;//TOP値ICR1 ICR1 =625;//20ms周期 Wire.begin(); // 積分モードをマニュアル設定モードに設定 colorSensor.setMode(S11059_MODE_MANUAL); // ゲイン選択 // * S11059_GAIN_HIGH: Highゲイン // * S11059_GAIN_LOW: Lowゲイン colorSensor.setGain(S11059_GAIN_HIGH); // 1色あたりの積分時間設定(下記は指定する定数とマニュアル設定モードの場合の積分時間) // * S11059_TINT0: 175 us // * S11059_TINT1: 2.8 ms // * S11059_TINT2: 44.8 ms // * S11059_TINT3: 358.4 ms colorSensor.setTint(S11059_TINT0); // マニュアルタイミング(0~65535) // setTint()で指定した積分時間を何倍まで長くするかを設定 colorSensor.setManualTiming(50); } uint16_t detect1(){ for(int i=0;i<1000;i++){//1ループ112usくらい pos+=analogRead(7);//posにforループ分加算 } pos/=1000;//1000回平均 return pos; } void servo1(uint8_t a){ switch(a){ case 1: analogWrite(9, 72);//閉 break; case 2: analogWrite(9, 50);//開 break; } } void color(){ for(int i=0;i<50;i++){ // ADCリセット、スリープ解除 if (!colorSensor.reset()) { Serial.println("reset failed"); } // ADCリセット解除、バスリリース if (!colorSensor.start()) { Serial.println("start failed"); } // 積分時間よりも長く待機 // // マニュアル設定モード時のS11059.delay()で実行される待機処理の時間は // S11059.setTint(tint)、S11059.setManualTiming(manualTiming)で // 設定した値に応じて異なります colorSensor.delay(); // 赤、緑、青、赤外データをリード if (colorSensor.update()) { red+=colorSensor.getRed(); green+=colorSensor.getGreen(); blue+=colorSensor.getBlue(); IR+=colorSensor.getIR(); } else { Serial.println("update failed"); } } red/=50; green/=50; blue/=50; IR/=50; Serial.print(red); Serial.print(","); Serial.print(green); Serial.print(","); Serial.print(blue); Serial.print(","); Serial.print(IR); Serial.println(""); } void servo2(uint8_t b){ switch (b){ case 0://フラット analogWrite(10, 25); break; case 1://右上黄 analogWrite(10, 64); break; case 2://右下緑 analogWrite(10, 54); break; case 3://下赤 analogWrite(10, 48); break; case 4://左下青 analogWrite(10, 39); break; case 5://左上 analogWrite(10, 34); break; } } void check(){ int sum, rg, rb, gb; float a,b,c; sum=red+green+blue; rg=red-green; rb=red-blue; gb=green-blue; a=green/red; if(green>150 && rg<0 && rb>0 && gb>0){ deg=1; Serial.println("黄"); } else if(green>160 && rg<0 && rb<0 && gb>0 ){ deg=2; Serial.println("緑"); }else if(rb>0 && gb>0){ deg=3; Serial.println("赤"); }else if(blue>100 && rg<0 && rb<0){ deg=4; Serial.println("青"); }else{ deg=5; Serial.println("茶"); } } //QUIMATの実験パルス範囲0.65ms~2.05ms(21~65) void loop() { uint8_t posav; switch (flag){ case 0://在荷検出中 //サーボモーターが唸るので待機中はpinをハイインピにする pinMode(9, INPUT); pinMode(10, INPUT); posav=detect1(); //Serial.println(posav); if(pos<40){ flag=1; } break; case 1://カラー検出 analogWrite(5,200);//カラー検出用照明 analogWrite(6,200);//カラー検出用照明 delay(1000);//カラー検出遅延時間 color();//カラー検出 digitalWrite(5,LOW); digitalWrite(6,LOW); check(); Serial.println(deg); flag=2; break; case 2://回転台座移動 pinMode(10, OUTPUT); servo2(deg); delay(500); flag=3; break; case 3://扉開 pinMode(9, OUTPUT); servo1(2); delay(500); flag=4; break; case 4://原点復帰動作 servo1(1); delay(600); servo2(0); delay(600); flag=0; break; } } |
以下の機能は関数化しています。
- 扉の開閉
- 回転梯子の駆動
- 色彩検出(条件分岐も)
- m&m’sの在荷確認
そして、Switchによりシーケンス処理を行っています。
一番難しかったのが、色彩検出により抽出した各色データを基にm&m’sが何色であるか判断する条件式の構築でした。今回は、数パターン色のサンプリングを行って条件を出しましたが、それでも100%選別はできていません、、、
m&m’s色彩選別機を動かす
さあ、実際に動かしてみましょう!
その時の動画が以下の物になります。
どうでしょうか!?色彩検出通りに選別できていますよね、、、といってもこれ、5回くらい取り直しているんですね。
三原色の赤、緑、青はほぼ100%選別できるのですが混色である茶色や黄色の選別が難しいですねー
色彩検出を安定させるためには、以下の項目をさらに検討する必要がありそうです。
- 測定環境を一定にする(極力外部光が入らないようにする)
- 反射光を効率的に採光する(照明の角度とカラーセンサとのワークディスタンスの最適化)
- m&m’sの姿勢を一定にする(光の反射を常に一定にする)
という事で、検討の余地は結構ありそうという結果でした。
FA機器でもそうですが、画像検査関連は調整が難しいですね。
あとはさらに改造してみたい点として、今回は1粒ずつ手動で投入していましたが、バッファー容器を設けて一粒ずつ自動で選別出来たら面白いですね。でも、一粒ずつ切り出す機構が結構難しそうです。
m&m’sの色彩選別機の記事は今回でいったんは終了となりますが、何かしら改造とかする機会があったらまた記事にしたいと思います。
では、ばいばいノシ
コメント