AUTO DRIVE (自動運転)

ラズタンクに赤外線障害物センサー2個を追加して、障害物を回避しながら自動走行する

追加した部品(IR赤外線障害物回避センサー)

  • (どんな機能)IR赤外線障害物回避センサー
  • (どんな用途)障害物回避、モノを追う、黒/白ライン追跡
  • (検出距離)2cm~30cm 検出距離は調整できる
  • (検出角度)35°
  • (入力電源)DC 3~5V
  • (LED赤)電源ON
  • (LED緑)障害物検出
  • (出力)ポート「OUT」は5Vリレーを駆動可能

ラズタンク(ここまでの完成の姿)

ダッシュボード

自動運転モードは[Switch]ノードのON/OFFで切り替える

Node-REDフロー

開発中のフローです。今はセンサーのON/OFFをダイレクトにモーターの正転・逆転につないでいる。

フローは下記JSONをコピペできます。

[{"id":"1c453b72.44c6a5","type":"tab","label":"フロー 1","disabled":false,"info":""},{"id":"a8f36cf4.e49e2","type":"ui_switch","z":"1c453b72.44c6a5","name":"","label":"Auto Drive 🛻","tooltip":"","group":"919a5620.d1a0e8","order":1,"width":"3","height":"1","passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":120,"y":160,"wires":[["925532a8.d62c5"]]},{"id":"868ed064.eb2c5","type":"rpi-gpio in","z":"1c453b72.44c6a5","name":"障害物センサー右","pin":"26","intype":"down","debounce":"25","read":true,"x":130,"y":240,"wires":[["e347bfee.f7d15"]]},{"id":"b07a873c.5dded8","type":"rpi-gpio in","z":"1c453b72.44c6a5","name":"障害物センサー左","pin":"24","intype":"down","debounce":"25","read":true,"x":130,"y":80,"wires":[["867f0bfb.ace648"]]},{"id":"1b6e2e5c.195672","type":"rpi-gpio out","z":"1c453b72.44c6a5","name":"左1(GPIO 27)","pin":"13","set":true,"level":"0","freq":"","out":"out","x":790,"y":80,"wires":[]},{"id":"3bff8d22.9ae402","type":"rpi-gpio out","z":"1c453b72.44c6a5","name":"左2(GPIO 17)","pin":"11","set":true,"level":"0","freq":"","out":"out","x":790,"y":120,"wires":[]},{"id":"3bf89e37.966172","type":"rpi-gpio out","z":"1c453b72.44c6a5","name":"右1(GPIO 21)","pin":"40","set":true,"level":"0","freq":"","out":"out","x":790,"y":240,"wires":[]},{"id":"401e1a80.f1f514","type":"rpi-gpio out","z":"1c453b72.44c6a5","name":"右2(GPIO 20)","pin":"38","set":true,"level":"0","freq":"","out":"out","x":790,"y":280,"wires":[]},{"id":"867f0bfb.ace648","type":"function","z":"1c453b72.44c6a5","name":"AND","func":"// 2つのメッセージを受け取るための変数を初期化\ncontext.payload1 = context.payload1 || null;\ncontext.payload2 = context.payload2 || null;\n\n// メッセージのトピックに基づいてpayloadを保存\nif (msg.topic === \"autodrive\") {\n    context.payload1 = msg.payload;\n}\nif (msg.topic === \"pi/24\") {\n    context.payload2 = msg.payload;\n}\n\n// 両方のpayloadが揃ったら掛け算を行う\nif (context.payload1 !== null && context.payload2 !== null) {\n    msg.topic = \"motor\";\n    msg.payload = context.payload1 * context.payload2;\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":80,"wires":[["1b6e2e5c.195672","b453738a.cf398"]]},{"id":"925532a8.d62c5","type":"function","z":"1c453b72.44c6a5","name":"autodrive:0,1","func":"msg.topic = \"autodrive\";\nif (msg.payload === true) {\n    msg.payload = 1;\n} else {\n    msg.payload = 0;\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":160,"wires":[["867f0bfb.ace648","e347bfee.f7d15","f16a95a8.7723a8","b453738a.cf398","910db38c.a19ae"]]},{"id":"e347bfee.f7d15","type":"function","z":"1c453b72.44c6a5","name":"AND","func":"// 2つのメッセージを受け取るための変数を初期化\ncontext.payload1 = context.payload1 || null;\ncontext.payload2 = context.payload2 || null;\n\n// メッセージのトピックに基づいてpayloadを保存\nif (msg.topic === \"autodrive\") {\n    context.payload1 = msg.payload;\n}\nif (msg.topic === \"pi/26\") {\n    context.payload2 = msg.payload;\n}\n\n// 両方のpayloadが揃ったら掛け算を行う\nif (context.payload1 !== null && context.payload2 !== null) {\n    msg.topic = \"motor\";\n    msg.payload = context.payload1 * context.payload2;\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":240,"wires":[["3bf89e37.966172","910db38c.a19ae"]]},{"id":"b453738a.cf398","type":"function","z":"1c453b72.44c6a5","name":"NOT","func":"// 2つのメッセージを受け取るための変数を初期化\ncontext.payload1 = context.payload1 || null;\ncontext.payload2 = context.payload2 || null;\n\n// メッセージのトピックに基づいてpayloadを保存\nif (msg.topic === \"autodrive\") {\n    context.payload1 = msg.payload;\n}\nif (msg.topic === \"motor\") {\n    context.payload2 = msg.payload;\n}\n\n// 両方のpayloadが揃ったら掛け算を行う\nif (context.payload1 !== null && context.payload2 !== null) {\n    // センサーがONなら逆転、OFFなら正転する\n    if (context.payload2 === 1) {\n        msg.payload = 0;\n    } else {\n        msg.payload = 1;\n    }\n    // もし自動運転がOFFなら止める\n    if (context.payload1 === 0) {\n        msg.payload = 0;\n    }\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":120,"wires":[["3bff8d22.9ae402"]]},{"id":"910db38c.a19ae","type":"function","z":"1c453b72.44c6a5","name":"NOT","func":"// 2つのメッセージを受け取るための変数を初期化\ncontext.payload1 = context.payload1 || null;\ncontext.payload2 = context.payload2 || null;\n\n// メッセージのトピックに基づいてpayloadを保存\nif (msg.topic === \"autodrive\") {\n    context.payload1 = msg.payload;\n}\nif (msg.topic === \"motor\") {\n    context.payload2 = msg.payload;\n}\n\n// 両方のpayloadが揃ったら掛け算を行う\nif (context.payload1 !== null && context.payload2 !== null) {\n    // センサーがONなら逆転、OFFなら正転する\n    if (context.payload2 === 1) {\n        msg.payload = 0;\n    } else {\n        msg.payload = 1;\n    }\n    // もし自動運転がOFFなら止める\n    if (context.payload1 === 0) {\n        msg.payload = 0;\n    }\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":280,"wires":[["401e1a80.f1f514"]]},{"id":"f16a95a8.7723a8","type":"rpi-gpio out","z":"1c453b72.44c6a5","name":"モニタ","pin":"23","set":"","level":"0","freq":"","out":"out","x":330,"y":200,"wires":[]},{"id":"919a5620.d1a0e8","type":"ui_group","name":"自動運転","tab":"1ca0e03a.98b22","order":7,"disp":true,"width":"6","collapse":false,"className":""},{"id":"1ca0e03a.98b22","type":"ui_tab","name":"ラズタンク十号","icon":"dashboard","disabled":false,"hidden":false}]

Node-RED右上のメニューバー(三本線)から「読み込み」を選ぶ

JSON形式のフローデータをコピー&ペーストして[読み込み]ボタンを押すとフローの各ノードが表示される

テスト走行してみた

ひょっとしてキチンとプログラミングしなきゃダメかも。

ラズタンク自動運転

コメントを残す