色分け機
コンポーネントと消耗品
> |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 20 | ||||
| × | 1 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
必要なツールとマシン
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
|
このプロジェクトについて
イントロ。
面白い話は、このプロジェクトが意図されていなかったということです。
約3。5年前、私はもっとファンキーな色分け機の設計を始めましたが、多くのプロジェクトと同様に、窓の棚にほこりを集めるのが半分終わってしまいました(他の誰もこのハハに関係しないと確信しています)。
簡単に言えば、数か月前、私はこの古いプロジェクトを取り戻すことにしました。私が最初に解決する必要があったのは、貯水池からスキットルズを収集し、システムを可能な限りコンパクトに保ちながら、スキットルズの色を非常に確実にチェックする方法でした(これは初めて達成できませんでした)。私は、収集システムの設計を正しくするためだけに、より単純な色分け機を設計することに自分自身で話しかけることができました。私は愚かなことに、それは2週末の仕事になるだろうと思っていました。素晴らしく、簡単で、迅速です...おやおや!!!私は間違っていました...
私は2つの完全に異なるデザインと多くの微調整されたプロトタイプを使用して、許容できる方法で機能するものを取得しました(まだ時々ピックアップの問題が発生しています)。
<図>完璧ではありませんが、結果には非常に満足しています。
<図> <図> <図>
どのように機能しますか。
マシンは2つのメインステージに分割できます。
上部には、分類されていないスキットルズの貯水池があります。この貯水池の底には、スキットルズを集めて色をチェックするカラーセンサーの前に配置するための給餌機構があります。
供給メカニズムには、リザーバーの内容物を振るアームが含まれており、スキットルズがリザーバー内で詰まることなく、供給メカニズムのオリフィスを通ってうまく流れるようにします(残念ながら、それはいつか発生します)。
<図>スキトルの色が見つかると、マシンの第2段階が実行されます。試験管ホルダーは、スキトルをドロップインするための供給メカニズムの前に右側のチューブを合わせます。
その後、リザーバーが空になるまでこのサイクルを繰り返すことができます。
自分で作りたい??? <図>
.................. https://www.littlefrenchkev.com/colour-sorting-machine................。 ......
<図>
組み立てます。
パーツをダウンロードして印刷すると、次のようになります:
<図>フロントシェルには2つのバージョンがあることに注意してください。見た目が違うだけで、実際の違いはありません。
<図>必要な残りの部品。
<図> <図>これが組み立てプロセスのビデオです。スローモーションの3Dプリンターショットでイントロを作ってアーティストになろうとさえしました!!!
初期設定。
電源を入れたときに機械が最初に行うことは、両方のサーボを初期位置に移動することです。初めて機械を始動するときは、スキットルズを集めるギア/シャフトが一番上の位置にあり、チューブホルダーが供給機構と整列していることを確認する必要があります。
<図>
トラブルシューティング。
この選別機を自分で作ることにした場合、いくつかの一般的な問題が発生する可能性があります。これらを解決する方法は次のとおりです。
LEDが赤く点滅-開始シーケンスなし:
初期位置に移動した後、マシンは開始シーケンスを実行する必要があります。そうではなく、代わりにLEDが赤く点滅する場合は、RBGセンサーが見つからないという問題があることを意味します。配線に問題があるか、センサーに障害があります。
チューブが正しく整列していません:
原因1
開始シーケンス中に、チューブホルダーは各色に1回ずつ、5回移動します。チューブが供給メカニズムとうまく整列していないことに気付くかもしれません。これは、サーボが非常に正確でないか、印刷寸法のばらつきが原因である可能性があります。
これは、colour_angle変数配列を変更することにより、ソフトウェアを介して修正できます。この配列の各値は、各色のサーボ位置を表します。これらの値を変更することで、各色のチューブが停止する場所を微調整できます。
原因2
印刷公差により、チューブホルダーギアにバックラッシュが発生する場合もあります。チューブがどちらの方向に回転しているかによって、慣性によって停止位置をオーバーシュートする可能性があります。これは、ソフトウェアを使用して、フォワードおよびバックウォッシュのアンチバックラッシュ変数を変更することによって修正することもできます。これらの値は、このバックラッシュを補正するためにホルダーが回転している方向に応じて、色の角度の値に追加または削除されます。
混色:
<図>混色が発生した場合は、colour_limit_values配列を変更する必要があります。これらの配列の各値は、赤、緑、青の最小値と最大値を表します。値がどうあるべきかをよりよく理解するには、1色だけでマシンをロードし、マシンをコンピューターに接続して、シリアルモニターを開きます。スキットルズがチェックされるたびに、読み取られたRGB値と、プログラムがそれをどの色であると考えるかを取得する必要があります。これにより、各色にどのような値を関連付ける必要があるかがわかります。
いくつかのクールな機能。
(とにかくそうだと思います!)
RGB LED:
マシンのベースに取り付けられたRGBLEDがあります。仕分けの過程で、落としたスキトルの色に合わせて色が変わります。リザーバーが空になると、すべてのスキットルズの色を継続的に通過します。
センサーで問題が検出された場合も、起動時に赤く点滅します。
反バックラッシュ補正:
チューブホルダーは、2つの平歯車を使用して回転します。印刷公差のため、歯車の遊びを完全に取り除くことは非常に困難です。これは、チューブホルダーが理想的な位置をオーバーシュートする傾向があることを意味します。このコードでは、ホルダーが回転している方向に応じて、ホルダーを一定量早く停止することでこれを補うことができます。
追加の遅延:
コードには「set_led(ms、color)」関数が含まれています。これは「delay(ms)」関数とまったく同じように機能しますが、遅延が発生している間、LEDを新しい色にスムーズにシフトさせることができます。チューブホルダーがその位置に回転している間にLEDの色を変えるのはおやつです!
追記。
注1:マシンを黒で印刷しました。これは、特にフィードメカニズムによってスキットルズが収集されない場合に、センサーが読み取る色の値に影響を与えます。
注2:ソートプロセスを数回行った後、スキットルズの色は確実に読みにくくなるようです。これは、リザーバー内を何度もこすった後に輝きが失われたか、手で扱うと少し粘着性が増したためだと思います(ひどい音です!)。色の値を調整するときは、「新鮮な」スキトルを使用してみてください。
注3:食品の取り扱いには、必要な予防措置をすべて講じてください。これには、食品安全印刷フィラメントを使用していることの確認が含まれます。
注4:進行中の作業と現在取り組んでいるプロジェクトをInstagramに投稿しようとしています。それがあなたのものであるならば、あなたはここで見ることができます:https://www.instagram.com/little_french_kev/
<図>
コード
- LFK_sorting_machine
LFK_sorting_machine C / C ++
ソーティングマシンのArduinoコードは次のとおりです。#include#include "Adafruit_TCS34725.h" #include / * AdafruitTCS34725ブレークアウトライブラリのサンプルコードに基づく* /// =======================RGBセンサーに関連する変数=========================Adafruit_TCS34725 tcs =Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_24MS、TCS34725_GAIN_1X); // RGBセンサーの設定color =0; // 0-黒、1-黄色、2-緑、3-オレンジ、4-赤、5-紫のprevious_colour =colour; int black_count =0; //空の/不明なcolorintのカウントstart_measurment_angle =88; //センサーの前にスキットルズを揃えるサーボ位置intmeasurment_sweep =2; //実行されたメジャーの数。 errorint measurment_angle_increment =4を平均化するために使用されます。 //測定値間の角度増分//制限値[] ={min_red_values、max_red_values、min_green_values、max_green_values、min_blue_values、max_blue_values} uint16_t black_limit_values [] ={0、200、0、200、0、200}; uint16_t yellow_limit_values [ {850、2200、800、2200、400、1100}; uint16_t green_limit_values [] ={400、800、700、1400、300、700}; uint16_t orange_limit_values [] ={650、1800、300、850、210、600 }; uint16_t red_limit_values [] ={400、950、150、450、150、400}; uint16_t Purple_limit_values [] ={150、400、150、450、150、500}; // =======================RGBに関連する変数led =========================バイトR_pin =5;バイトG_pin =6;バイトB_pin =11; int current_red_value =255; int current_green_value =255; int current_blue_value =255; const int orange [] ={0、230、255}; const int red [] ={0、255、 255}; const int green [] ={255、0、255}; const int yellow [] ={0、170、255}; const int Purple [] ={0、255、40}; // =======================フィーダーサーボに関連する変数=========================int release_delay =220; const int colour_angles [] ={10、46、82、118、154}; // {10、46、82、118、154}; // intholder_offset =0; //チューブホルダーのオフセット調整。 0から36の間に保たれますconstint backward_anti_backlash =2; const int forward_anti_backlash =2; Servofeedor_servo; //フィーダーサーボサーボholder_servoを宣言します; //チューブホルダーサーボを宣言// ===================================セットアップ=========================================void setup(void){Serial.begin(9600); pinMode(R_pin、OUTPUT); // LEDピンを設定pinMode(G_pin、OUTPUT); pinMode(B_pin、OUTPUT); analogWrite(R_pin、255); // LEDをオフにしますanalogWrite(G_pin、255); analogWrite(B_pin、255); feeder_servo.attach(3); //フィーダーサーボをピン3に取り付けますholder_servo.attach(2); //ホルダーサーボをピン2に取り付けますfeeder_servo.write(0); holder_servo.write(colour_angles [0]); int white [] ={0、0、0}; //ローカルホワイト値変数intblack [] ={255、255、255}; //ローカルの黒の値変数set_led(1000、white); // LEDをオン(白)にしますif(tcs.begin()){//センサーが見つかったかどうかを確認しますSerial.println( "センサーが見つかりました"); start_sequence(); } else {Serial.println( "TCS34725が見つかりません...接続を確認してください"); while(1)//センサーが見つからない場合は赤く速く点滅{set_led(300、red); set_led(300、黒); }}} // ===================================LOOP =========================================void loop(void){if(black_count <10){feeder_servo.write(0 ); //スキトルコレクションdelay(450);のサーボ位置を一番上に設定します。 //フィーダーサーボが位置に入るのに十分な時間を確保するための遅延previous_colour =colour; get_colour(); //スキトルカラーを読み取るif(colour ==0){black_count ++; //色が見つからない場合は、黒カウントshake(); //スキットルズがない場合でもリザーバーにもう少しシェイクを与えます} else if(colour ==6){black_count ++; //色が不明な場合は、黒のカウントを増やします-スキトルリリースなし} else {//色が見つかった場合move_holder(); //チューブホルダーを移動しますrelease_skittle(); //スキトルを解放しますblack_count =0; }} else {end_loop(1000); }} // ===================================GET COLOR =========================================void get_colour(){uint16_t r、g、b、c; //、colorTemp 、ルクス; uint16_t total_r =0; uint16_t total_g =0; uint16_t total_b =0; feeder_servo.write(start_measurment_angle); //測定角度delay(200);を開始するために移動します。 Serial.println( "----------------"); for(int i =0; i <=measurment_sweep; i ++)//各メジャーのループ{tcs.getRawData(&r、&g、&b、&c); //カラーデータを取得feeder_servo.write(start_measurment_angle + i * measurment_angle_increment); //次の測定のためにサーボ角度をインクリメントしますtotal_r + =r; //赤の値を合計の赤の値に追加しますtotal_g + =g; //緑の値を合計の緑の値に追加しますtotal_b + =b; //青の値を合計の青の値に追加delay(15); } total_r / =measurment_sweep; //すべての測定値の平均値total_g / =measurment_sweep; total_b / =measurment_sweep; Serial.print(total_r); Serial.print( ""); Serial.print(total_g); Serial.print( ""); Serial.print(total_b); Serial.print( ""); Serial.println( ""); //値を比較して色を決定します。 if((total_r =yellow_limit_values [0])&&//黄色をチェック(total_r =yellow_limit_values [2])&&(total_g =yellow_limit_values [4])&&(total_b =green_limit_values [0])&&//緑をチェック(total_r =green_limit_values [2])&&(total_g =green_limit_values [4])&&(total_b =orange_limit_values [0])&&//オレンジをチェック(total_r =orange_limit_values [2])&&(total_g =orange_limit_values [4])&&(total_b =red_limit_values [0])&&//赤をチェック(total_r =red_limit_values [2])&&(total_g =red_limit_values [4])&&(total_b =Purple_limit_values [0])&&//紫をチェック(total_r =Purple_limit_values [2])&&(total_g =Purple_limit_values [4])&&(total_b colour){//ギアのバックラッシュを補正するためにホルダーサーボを通常の位置よりも遠くに戻すように強制しますint anti_backlash_angle =new_holder_position --backward_anti_backlash; holder_servo.write(anti_backlash_angle); // delay(holder_delay); } else {int anti_backlash_angle =new_holder_position + forward_anti_backlash; //holder_servo.write(anti_backlash_angle); holder_servo.write(new_holder_position); //ホルダーを所定の位置に移動します// delay(holder_delay); } if(colour ==1){set_led(holder_delay、yellow); } else if(colour ==2){set_led(holder_delay、green); } else if(colour ==3){set_led(holder_delay、orange); } else if(colour ==4){set_led(holder_delay、red); } else if(colour ==5){set_led(holder_delay、purple); } else {}} // =============================リリースキット===========================void release_skittle(){feeder_servo.write(180); //スキトルリリースdelay(release_delay);} // ===============================の場合、サーボ位置を下に設定します==SHAKE =================================void shake(){int shake_delay =80; int shake_amount =5; int shake_min_value =90; int shake_max_value =180; feeder_servo.write(180); //スキトルリリースdelay(release_delay);のサーボ位置を下に設定しますfeeder_servo.write(120); //スキトルリリースdelay(80);のサーボ位置を一番下に設定します。 for(int i =0; i <=shake_amount; i ++)//各メジャーのループ{feeder_servo.write(shake_min_value); //スキトルリリースdelay(shake_delay);のサーボ位置を下に設定しますfeeder_servo.write(shake_max_value); //スキトルリリースdelay(shake_delay);のサーボ位置を下に設定します}} // ============================開始シーケンス============================void start_sequence(){color =1; move_holder(); set_led(300、yellow);遅延(400);色=2; move_holder(); set_led(300、緑);遅延(400);色=3; move_holder(); set_led(300、orange);遅延(400);色=4; move_holder(); set_led(300、red);遅延(400);色=5; move_holder(); set_led(300、紫);遅延(400); previous_colour =colour;色=3; move_holder(); end_loop(200);} // ================================END LOOP =================================void end_loop(int duration){set_led(duration、orange); set_led(duration、red); set_led(duration、green); set_led(duration、yellow); set_led(duration、purple);} // ============================RGBLEDの色を設定=======================//これはdelay()として機能しますが、待機中にLEDの色を変更できます。voidset_led(int duration、int color [3]){int start_time =ミリス(); //開始時刻の値intcurrent_time =start_time; //現在の時刻の値intcurrent_duration =0; //合計期間while(current_duration
回路図
配線はかなり簡単です。何かを接続する前に、バックコンバータが5Vを出力することを確認してください!!!!! 製造プロセス