勝手な電子工作・・

勝手なオリジナル電子工作に関する記事を書きます

つぶやくロボカーを少しお利口に(Arduinoプログラムつき)

f:id:a-tomi:20190530210405j:plain

少し前に書いたロボカーの続きです。ジャイロと近接センサーを加えて木箱に組みました。ステッパー、70ミリタイヤ、前輪に相当するタミヤのボールキャスターなどは、試作品からそのままこちらに組みなおしました。

回路は次のようにしました。毎度きたない手書きですみません^^;

f:id:a-tomi:20190530210824j:plain

使用しているICのブレークアウトモジュールは、センサーを含め次の4種類です。

f:id:a-tomi:20190530210949j:plain

左からToF(反射光測距)、ジャイロ、赤外線近接センサー、デジタル音声アンプ

ToFセンサーはVL6180X、ジャイロコンパスはHMC5883L、近接センサーは古典的なIR反射センサーです。

ジャイロコンパスの読取は簡単ですからライブラリーを使わずI2Cプロトコルを直接扱っています。下の方に掲載するプログラムをご参照下さい。

IR近接センサーはローテクで、電流を30mAも消費する(2つつけて60mA)ので、測定時にのみ電源をオンとする回路にしました。

Arduinoプログラム(後ろの方に掲載します)は全体でマイコン(ATmega328P)の容量を、プログラム域・グローバル記憶域とも40%未満の使用状態で余裕十分です。

この変更でおしゃべりロボカーは前よりだいぶお利口になりました。次の動画は迷路の出口を自分でみつける様子です。

www.youtube.com


 躯体には百均にある木箱をそのまま使いました。

f:id:a-tomi:20190530214440j:plain

側板の真ん中にあるスリットをステッパーの取付穴としてそのまま利用しました。

蓋やグリルなどとして、加工しやすいシナ合板を適当にカットしながら木ネジとボンドで簡単にとりつけました。

f:id:a-tomi:20190530214642j:plain

f:id:a-tomi:20190530214713j:plain

前方の蓋をあければマイコンが簡単に取り出せます。当面は無圧ソケットで下駄をはいています。後ろの箱はデジタルアンプ入りスピーカーボックスで、前回の試作品をそのままこちらに取り付けたもの。

f:id:a-tomi:20190530214752j:plain

ステッパーは後ろの方にありますが、メンテナンスができるように一応は蓋をネジ止めとしました。相手は厚さ4ミリの側板なので壊さないように注意して下穴をあけないといけませんが。

f:id:a-tomi:20190530215335j:plain

全体の大きさは長さ19センチ、幅はIR近接センサーの端から端まsでで14センチほどです。

基板は次のようにデザインしました。生基板をCNCで切削しますので、15分ほどでできます。ブレッドボードの状態でテスト済み、かつ単純なので部品取付後一発で問題なく稼働しました。

f:id:a-tomi:20190530215652j:plain

基板サイズは95ミリx50ミリ

べたグランドですが、それがループにならないようにするためカットしています。ドライブICでサージ吸収が行われていますが、ステッピングモーターマイコンが電源を共有しますので雑音防止のためです。

今回はスピーカーボックス側にアンプを仕込んだものを使うために、アンプは基板にとりつけていません。

次回作る際はこれに音声用デジタルアンプも直接取り付けます。今回は基板組みあがりの写真を撮るのを忘れてくみこんでしまいましたが、次回作った際に部品取り付け状態もご紹介したいと思います。

省エネのために次のことをしていますので簡単にご紹介します。

1)ステッパー停止時の電流断

ステッパー停止時には電流を止める必要があります。止めないと無駄なだけでなく、コイルの抵抗成分は10数Ωしかないため直流状態ではショートに近くなり、ステッパーとドライブICは過熱しますので注意が必要です。一瞬だけブレーキを掛けたいときは別ですが。

ここでは5線式ユニポーラ―型で2相励磁をしていますが、停止時には電流を素直に止めています。

なお、余談ですが4線式バイポーラー型をイージードライバーやA4988モジュールなど経由で楽に接続する場合も同じことで、停止する際はステップ信号を止めるだけでなく、Sleep信号を送るなどの停止処理が必要です。マイコンの本などでステッパー停止時に流しっぱなしの例が多く見られますが注意が必要と思います。

また、トルクの許す限りフェイズ間隔を短くする(ドライブの周波数を上げる)と、インピーダンスが高くなり消費電流が減ります。

 2)IR近接センサーの省エネなど

赤外LEDに常時30mAも流す構造となっています。2つ使えば60mAも消費するため工夫が必要です。ここでは、測定時にだけ電流を流す回路(ダーリントントランジスタならなんでもよい)とプログラムにしています。

ついでですが、検知距離はVRで調節でき、テストすると8cm程度まで検知可能です。ただ数十円の安価な装置なので、特別な温度補正などがされていないように見えますので、感度をぎりぎりまで高めるのは誤作動の元かと思います。また太陽光が当たる場所の近くなどでは誤作動することがあるようです。

実際、上の動画では最後のほうで出口へ素直に向かうべきところ、窓に近い位置でIRを誤検出していったん逆へ曲がったようです。同じ論理でのシミュレーションと比較するとそこが異なりますから。

www.youtube.com

次の写真はIR近接センサーのVR調整の様子です。上から板などを近づけることで、検知距離以下でH信号がL信号に変わります。この装置で簡単に調整してからとりつけます。

f:id:a-tomi:20190530222659j:plain

 

ところで、迷路に出口をつけないとこのロボットはいつまでも出口を探し続けます。昼飯時に動かし始めたことをすっかり忘れて、夕方に戻って気づいたらまだ動き続けていました。忍耐強いものです。消費電流は平均80mA程度なのでアルカリ電池は長時間もちます。

そのロングランで、タミヤのボールキャスターががたつくようになり、動画のとおりカタカタとうるさい状態です。そのうちにボールキャスターは交換したいと思いますが、この際、物流用のボールキャスターも試そうと考えています。

f:id:a-tomi:20190530223650j:plain

Arduinoのプログラムは次のとおりです。


    /* Talking car-robot with 5-wire steppers x 2
 *            V 1.0 (c)Akira Tominaga. May 26th, 2019
 *                  using Talkie library: Copyright 2011 Peter Knight 
 *                                       released under GPLv2 license.
 *  Function:
 *  Runs around, sensing and avoiding walls. 
 *  Adjust directions from time to time.  
 *  Talks about actions of itselves.
 *  
 *  Sensors attached;
 *  1) Time-of-Flight to measure distance
 *  2) Gyro-compass to recognize direction
 *  3) IR-reflection obstacle-sensors
*/ #include // Wire.h I2C interface for Giro and ToF #include // VL6180X.h ToF distance sensor #include // talkie.h Talk via PWM // Pin # assignment
// D3 PWM for Talkie // D4 to D7 for stepper-1 (5 wire unipolar) // D8 to D11 for stepper-2 (5 wire unipolar) #define Led 13 // D13 for LED // D14 to D16 (A0 to A2) for Obstacle sensors #define obsPwr 14 // Power (on=H) for obstacle sensors #define obsR 15 // obstacle sensor for right side #define obsL 16 // obstacle sensor for left side VL6180X tOF; // "tOF" as time-of-flight sensor name Talkie sPK; // "sPK" as talkie name // talkie constants const uint8_t spZERO[] PROGMEM = {0x69, 0xFB, 0x59, 0xDD, 0x51, 0xD5, 0xD7, 0xB5, 0x6F, 0x0A, 0x78, 0xC0, 0x52, 0x01, 0x0F, 0x50, 0xAC, 0xF6, 0xA8, 0x16, 0x15, 0xF2, 0x7B, 0xEA, 0x19, 0x47, 0xD0, 0x64, 0xEB, 0xAD, 0x76, 0xB5, 0xEB, 0xD1, 0x96, 0x24, 0x6E, 0x62, 0x6D, 0x5B, 0x1F, 0x0A, 0xA7, 0xB9, 0xC5, 0xAB, 0xFD, 0x1A, 0x62, 0xF0, 0xF0, 0xE2, 0x6C, 0x73, 0x1C, 0x73, 0x52, 0x1D, 0x19, 0x94, 0x6F, 0xCE, 0x7D, 0xED, 0x6B, 0xD9, 0x82, 0xDC, 0x48, 0xC7, 0x2E, 0x71, 0x8B, 0xBB, 0xDF, 0xFF, 0x1F}; const uint8_t spONE[] PROGMEM = {0x66, 0x4E, 0xA8, 0x7A, 0x8D, 0xED, 0xC4, 0xB5, 0xCD, 0x89, 0xD4, 0xBC, 0xA2, 0xDB, 0xD1, 0x27, 0xBE, 0x33, 0x4C, 0xD9, 0x4F, 0x9B, 0x4D, 0x57, 0x8A, 0x76, 0xBE, 0xF5, 0xA9, 0xAA, 0x2E, 0x4F, 0xD5, 0xCD, 0xB7, 0xD9, 0x43, 0x5B, 0x87, 0x13, 0x4C, 0x0D, 0xA7, 0x75, 0xAB, 0x7B, 0x3E, 0xE3, 0x19, 0x6F, 0x7F, 0xA7, 0xA7, 0xF9, 0xD0, 0x30, 0x5B, 0x1D, 0x9E, 0x9A, 0x34, 0x44, 0xBC, 0xB6, 0x7D, 0xFE, 0x1F}; const uint8_t spTWO[] PROGMEM = {0x06, 0xB8, 0x59, 0x34, 0x00, 0x27, 0xD6, 0x38, 0x60, 0x58, 0xD3, 0x91, 0x55, 0x2D, 0xAA, 0x65, 0x9D, 0x4F, 0xD1, 0xB8, 0x39, 0x17, 0x67, 0xBF, 0xC5, 0xAE, 0x5A, 0x1D, 0xB5, 0x7A, 0x06, 0xF6, 0xA9, 0x7D, 0x9D, 0xD2, 0x6C, 0x55, 0xA5, 0x26, 0x75, 0xC9, 0x9B, 0xDF, 0xFC, 0x6E, 0x0E, 0x63, 0x3A, 0x34, 0x70, 0xAF, 0x3E, 0xFF, 0x1F}; const uint8_t spTHREE[] PROGMEM = {0x0C, 0xE8, 0x2E, 0x94, 0x01, 0x4D, 0xBA, 0x4A, 0x40, 0x03, 0x16, 0x68, 0x69, 0x36, 0x1C, 0xE9, 0xBA, 0xB8, 0xE5, 0x39, 0x70, 0x72, 0x84, 0xDB, 0x51, 0xA4, 0xA8, 0x4E, 0xA3, 0xC9, 0x77, 0xB1, 0xCA, 0xD6, 0x52, 0xA8, 0x71, 0xED, 0x2A, 0x7B, 0x4B, 0xA6, 0xE0, 0x37, 0xB7, 0x5A, 0xDD, 0x48, 0x8E, 0x94, 0xF1, 0x64, 0xCE, 0x6D, 0x19, 0x55, 0x91, 0xBC, 0x6E, 0xD7, 0xAD, 0x1E, 0xF5, 0xAA, 0x77, 0x7A, 0xC6, 0x70, 0x22, 0xCD, 0xC7, 0xF9, 0x89, 0xCF, 0xFF, 0x03}; const uint8_t spFOUR[] PROGMEM = {0x08, 0x68, 0x21, 0x0D, 0x03, 0x04, 0x28, 0xCE, 0x92, 0x03, 0x23, 0x4A, 0xCA, 0xA6, 0x1C, 0xDA, 0xAD, 0xB4, 0x70, 0xED, 0x19, 0x64, 0xB7, 0xD3, 0x91, 0x45, 0x51, 0x35, 0x89, 0xEA, 0x66, 0xDE, 0xEA, 0xE0, 0xAB, 0xD3, 0x29, 0x4F, 0x1F, 0xFA, 0x52, 0xF6, 0x90, 0x52, 0x3B, 0x25, 0x7F, 0xDD, 0xCB, 0x9D, 0x72, 0x72, 0x8C, 0x79, 0xCB, 0x6F, 0xFA, 0xD2, 0x10, 0x9E, 0xB4, 0x2C, 0xE1, 0x4F, 0x25, 0x70, 0x3A, 0xDC, 0xBA, 0x2F, 0x6F, 0xC1, 0x75, 0xCB, 0xF2, 0xFF}; const uint8_t spFIVE[] PROGMEM = {0x08, 0x68, 0x4E, 0x9D, 0x02, 0x1C, 0x60, 0xC0, 0x8C, 0x69, 0x12, 0xB0, 0xC0, 0x28, 0xAB, 0x8C, 0x9C, 0xC0, 0x2D, 0xBB, 0x38, 0x79, 0x31, 0x15, 0xA3, 0xB6, 0xE4, 0x16, 0xB7, 0xDC, 0xF5, 0x6E, 0x57, 0xDF, 0x54, 0x5B, 0x85, 0xBE, 0xD9, 0xE3, 0x5C, 0xC6, 0xD6, 0x6D, 0xB1, 0xA5, 0xBF, 0x99, 0x5B, 0x3B, 0x5A, 0x30, 0x09, 0xAF, 0x2F, 0xED, 0xEC, 0x31, 0xC4, 0x5C, 0xBE, 0xD6, 0x33, 0xDD, 0xAD, 0x88, 0x87, 0xE2, 0xD2, 0xF2, 0xF4, 0xE0, 0x16, 0x2A, 0xB2, 0xE3, 0x63, 0x1F, 0xF9, 0xF0, 0xE7, 0xFF, 0x01}; const uint8_t spSIX[] PROGMEM = {0x04, 0xF8, 0xAD, 0x4C, 0x02, 0x16, 0xB0, 0x80, 0x06, 0x56, 0x35, 0x5D, 0xA8, 0x2A, 0x6D, 0xB9, 0xCD, 0x69, 0xBB, 0x2B, 0x55, 0xB5, 0x2D, 0xB7, 0xDB, 0xFD, 0x9C, 0x0D, 0xD8, 0x32, 0x8A, 0x7B, 0xBC, 0x02, 0x00, 0x03, 0x0C, 0xB1, 0x2E, 0x80, 0xDF, 0xD2, 0x35, 0x20, 0x01, 0x0E, 0x60, 0xE0, 0xFF, 0x01}; const uint8_t spSEVEN[] PROGMEM = {0x0C, 0xF8, 0x5E, 0x4C, 0x01, 0xBF, 0x95, 0x7B, 0xC0, 0x02, 0x16, 0xB0, 0xC0, 0xC8, 0xBA, 0x36, 0x4D, 0xB7, 0x27, 0x37, 0xBB, 0xC5, 0x29, 0xBA, 0x71, 0x6D, 0xB7, 0xB5, 0xAB, 0xA8, 0xCE, 0xBD, 0xD4, 0xDE, 0xA6, 0xB2, 0x5A, 0xB1, 0x34, 0x6A, 0x1D, 0xA7, 0x35, 0x37, 0xE5, 0x5A, 0xAE, 0x6B, 0xEE, 0xD2, 0xB6, 0x26, 0x4C, 0x37, 0xF5, 0x4D, 0xB9, 0x9A, 0x34, 0x39, 0xB7, 0xC6, 0xE1, 0x1E, 0x81, 0xD8, 0xA2, 0xEC, 0xE6, 0xC7, 0x7F, 0xFE, 0xFB, 0x7F}; const uint8_t spEIGHT[] PROGMEM = {0x65, 0x69, 0x89, 0xC5, 0x73, 0x66, 0xDF, 0xE9, 0x8C, 0x33, 0x0E, 0x41, 0xC6, 0xEA, 0x5B, 0xEF, 0x7A, 0xF5, 0x33, 0x25, 0x50, 0xE5, 0xEA, 0x39, 0xD7, 0xC5, 0x6E, 0x08, 0x14, 0xC1, 0xDD, 0x45, 0x64, 0x03, 0x00, 0x80, 0x00, 0xAE, 0x70, 0x33, 0xC0, 0x73, 0x33, 0x1A, 0x10, 0x40, 0x8F, 0x2B, 0x14, 0xF8, 0x7F}; const uint8_t spNINE[] PROGMEM = {0xE6, 0xA8, 0x1A, 0x35, 0x5D, 0xD6, 0x9A, 0x35, 0x4B, 0x8C, 0x4E, 0x6B, 0x1A, 0xD6, 0xA6, 0x51, 0xB2, 0xB5, 0xEE, 0x58, 0x9A, 0x13, 0x4F, 0xB5, 0x35, 0x67, 0x68, 0x26, 0x3D, 0x4D, 0x97, 0x9C, 0xBE, 0xC9, 0x75, 0x2F, 0x6D, 0x7B, 0xBB, 0x5B, 0xDF, 0xFA, 0x36, 0xA7, 0xEF, 0xBA, 0x25, 0xDA, 0x16, 0xDF, 0x69, 0xAC, 0x23, 0x05, 0x45, 0xF9, 0xAC, 0xB9, 0x8F, 0xA3, 0x97, 0x20, 0x73, 0x9F, 0x54, 0xCE, 0x1E, 0x45, 0xC2, 0xA2, 0x4E, 0x3E, 0xD3, 0xD5, 0x3D, 0xB1, 0x79, 0x24, 0x0D, 0xD7, 0x48, 0x4C, 0x6E, 0xE1, 0x2C, 0xDE, 0xFF, 0x0F}; const uint8_t spTEN[] PROGMEM = {0x0E, 0x38, 0x3C, 0x2D, 0x00, 0x5F, 0xB6, 0x19, 0x60, 0xA8, 0x90, 0x93, 0x36, 0x2B, 0xE2, 0x99, 0xB3, 0x4E, 0xD9, 0x7D, 0x89, 0x85, 0x2F, 0xBE, 0xD5, 0xAD, 0x4F, 0x3F, 0x64, 0xAB, 0xA4, 0x3E, 0xBA, 0xD3, 0x59, 0x9A, 0x2E, 0x75, 0xD5, 0x39, 0x6D, 0x6B, 0x0A, 0x2D, 0x3C, 0xEC, 0xE5, 0xDD, 0x1F, 0xFE, 0xB0, 0xE7, 0xFF, 0x03}; const uint8_t spELEVEN[] PROGMEM = {0xA5, 0xEF, 0xD6, 0x50, 0x3B, 0x67, 0x8F, 0xB9, 0x3B, 0x23, 0x49, 0x7F, 0x33, 0x87, 0x31, 0x0C, 0xE9, 0x22, 0x49, 0x7D, 0x56, 0xDF, 0x69, 0xAA, 0x39, 0x6D, 0x59, 0xDD, 0x82, 0x56, 0x92, 0xDA, 0xE5, 0x74, 0x9D, 0xA7, 0xA6, 0xD3, 0x9A, 0x53, 0x37, 0x99, 0x56, 0xA6, 0x6F, 0x4F, 0x59, 0x9D, 0x7B, 0x89, 0x2F, 0xDD, 0xC5, 0x28, 0xAA, 0x15, 0x4B, 0xA3, 0xD6, 0xAE, 0x8C, 0x8A, 0xAD, 0x54, 0x3B, 0xA7, 0xA9, 0x3B, 0xB3, 0x54, 0x5D, 0x33, 0xE6, 0xA6, 0x5C, 0xCB, 0x75, 0xCD, 0x5E, 0xC6, 0xDA, 0xA4, 0xCA, 0xB9, 0x35, 0xAE, 0x67, 0xB8, 0x46, 0x40, 0xB6, 0x28, 0xBB, 0xF1, 0xF6, 0xB7, 0xB9, 0x47, 0x20, 0xB6, 0x28, 0xBB, 0xFF, 0x0F}; const uint8_t spTWELVE[] PROGMEM = {0x09, 0x98, 0xDA, 0x22, 0x01, 0x37, 0x78, 0x1A, 0x20, 0x85, 0xD1, 0x50, 0x3A, 0x33, 0x11, 0x81, 0x5D, 0x5B, 0x95, 0xD4, 0x44, 0x04, 0x76, 0x9D, 0xD5, 0xA9, 0x3A, 0xAB, 0xF0, 0xA1, 0x3E, 0xB7, 0xBA, 0xD5, 0xA9, 0x2B, 0xEB, 0xCC, 0xA0, 0x3E, 0xB7, 0xBD, 0xC3, 0x5A, 0x3B, 0xC8, 0x69, 0x67, 0xBD, 0xFB, 0xE8, 0x67, 0xBF, 0xCA, 0x9D, 0xE9, 0x74, 0x08, 0xE7, 0xCE, 0x77, 0x78, 0x06, 0x89, 0x32, 0x57, 0xD6, 0xF1, 0xF1, 0x8F, 0x7D, 0xFE, 0x1F}; const uint8_t spTHIR_[] PROGMEM = {0x04, 0xA8, 0xBE, 0x5C, 0x00, 0xDD, 0xA5, 0x11, 0xA0, 0xFA, 0x72, 0x02, 0x74, 0x97, 0xC6, 0x01, 0x09, 0x9C, 0xA6, 0xAB, 0x30, 0x0D, 0xCE, 0x7A, 0xEA, 0x6A, 0x4A, 0x39, 0x35, 0xFB, 0xAA, 0x8B, 0x1B, 0xC6, 0x76, 0xF7, 0xAB, 0x2E, 0x79, 0x19, 0xCA, 0xD5, 0xEF, 0xCA, 0x57, 0x08, 0x14, 0xA1, 0xDC, 0x45, 0x64, 0x03, 0x00, 0xC0, 0xFF, 0x03}; const uint8_t spFIF_[] PROGMEM = {0x08, 0x98, 0x31, 0x93, 0x02, 0x1C, 0xE0, 0x80, 0x07, 0x5A, 0xD6, 0x1C, 0x6B, 0x78, 0x2E, 0xBD, 0xE5, 0x2D, 0x4F, 0xDD, 0xAD, 0xAB, 0xAA, 0x6D, 0xC9, 0x23, 0x02, 0x56, 0x4C, 0x93, 0x00, 0x05, 0x10, 0x90, 0x89, 0x31, 0xFC, 0x3F}; const uint8_t sp_TEEN[] PROGMEM = {0x09, 0x58, 0x2A, 0x25, 0x00, 0xCB, 0x9F, 0x95, 0x6C, 0x14, 0x21, 0x89, 0xA9, 0x78, 0xB3, 0x5B, 0xEC, 0xBA, 0xB5, 0x23, 0x13, 0x46, 0x97, 0x99, 0x3E, 0xD6, 0xB9, 0x2E, 0x79, 0xC9, 0x5B, 0xD8, 0x47, 0x41, 0x53, 0x1F, 0xC7, 0xE1, 0x9C, 0x85, 0x54, 0x22, 0xEC, 0xFA, 0xDB, 0xDD, 0x23, 0x93, 0x49, 0xB8, 0xE6, 0x78, 0xFF, 0x3F}; const uint8_t spTWENTY[] PROGMEM = {0x0A, 0xE8, 0x4A, 0xCD, 0x01, 0xDB, 0xB9, 0x33, 0xC0, 0xA6, 0x54, 0x0C, 0xA4, 0x34, 0xD9, 0xF2, 0x0A, 0x6C, 0xBB, 0xB3, 0x53, 0x0E, 0x5D, 0xA6, 0x25, 0x9B, 0x6F, 0x75, 0xCA, 0x61, 0x52, 0xDC, 0x74, 0x49, 0xA9, 0x8A, 0xC4, 0x76, 0x4D, 0xD7, 0xB1, 0x76, 0xC0, 0x55, 0xA6, 0x65, 0xD8, 0x26, 0x99, 0x5C, 0x56, 0xAD, 0xB9, 0x25, 0x23, 0xD5, 0x7C, 0x32, 0x96, 0xE9, 0x9B, 0x20, 0x7D, 0xCB, 0x3C, 0xFA, 0x55, 0xAE, 0x99, 0x1A, 0x30, 0xFC, 0x4B, 0x3C, 0xFF, 0x1F}; const uint8_t spHUNDRED[] PROGMEM = {0x04, 0xC8, 0x7E, 0x5C, 0x02, 0x0A, 0xA8, 0x62, 0x43, 0x03, 0xA7, 0xA8, 0x62, 0x43, 0x4B, 0x97, 0xDC, 0xF2, 0x14, 0xC5, 0xA7, 0x9B, 0x7A, 0xD3, 0x95, 0x37, 0xC3, 0x1E, 0x16, 0x4A, 0x66, 0x36, 0xF3, 0x5A, 0x89, 0x6E, 0xD4, 0x30, 0x55, 0xB5, 0x32, 0xB7, 0x31, 0xB5, 0xC1, 0x69, 0x2C, 0xE9, 0xF7, 0xBC, 0x96, 0x12, 0x39, 0xD4, 0xB5, 0xFD, 0xDA, 0x9B, 0x0F, 0xD1, 0x90, 0xEE, 0xF5, 0xE4, 0x17, 0x02, 0x45, 0x28, 0x77, 0x11, 0xD9, 0x40, 0x9E, 0x45, 0xDD, 0x2B, 0x33, 0x71, 0x7A, 0xBA, 0x0B, 0x13, 0x95, 0x2D, 0xF9, 0xF9, 0x7F}; const uint8_t spTHOUSAND[] PROGMEM = {0x0C, 0xE8, 0x2E, 0xD4, 0x02, 0x06, 0x98, 0xD2, 0x55, 0x03, 0x16, 0x68, 0x7D, 0x17, 0xE9, 0x6E, 0xBC, 0x65, 0x8C, 0x45, 0x6D, 0xA6, 0xE9, 0x96, 0xDD, 0xDE, 0xF6, 0xB6, 0xB7, 0x5E, 0x75, 0xD4, 0x93, 0xA5, 0x9C, 0x7B, 0x57, 0xB3, 0x6E, 0x7D, 0x12, 0x19, 0xAD, 0xDC, 0x29, 0x8D, 0x4F, 0x93, 0xB4, 0x87, 0xD2, 0xB6, 0xFC, 0xDD, 0xAC, 0x22, 0x56, 0x02, 0x70, 0x18, 0xCA, 0x18, 0x26, 0xB5, 0x90, 0xD4, 0xDE, 0x6B, 0x29, 0xDA, 0x2D, 0x25, 0x17, 0x8D, 0x79, 0x88, 0xD4, 0x48, 0x79, 0x5D, 0xF7, 0x74, 0x75, 0xA1, 0x94, 0xA9, 0xD1, 0xF2, 0xED, 0x9E, 0xAA, 0x51, 0xA6, 0xD4, 0x9E, 0x7F, 0xED, 0x6F, 0xFE, 0x2B, 0xD1, 0xC7, 0x3D, 0x89, 0xFA, 0xB7, 0x0D, 0x57, 0xD3, 0xB4, 0xF5, 0x37, 0x55, 0x37, 0x2E, 0xE6, 0xB2, 0xD7, 0x57, 0xFF, 0x0F}; const uint8_t spT[] PROGMEM = {0x01, 0xD8, 0xB6, 0xDD, 0x01, 0x2F, 0xF4, 0x38, 0x60, 0xD5, 0xD1, 0x91, 0x4D, 0x97, 0x84, 0xE6, 0x4B, 0x4E, 0x36, 0xB2, 0x10, 0x67, 0xCD, 0x19, 0xD9, 0x2C, 0x01, 0x94, 0xF1, 0x78, 0x66, 0x33, 0xEB, 0x79, 0xAF, 0x7B, 0x57, 0x87, 0x36, 0xAF, 0x52, 0x08, 0x9E, 0x6B, 0xEA, 0x5A, 0xB7, 0x7A, 0x94, 0x73, 0x45, 0x47, 0xAC, 0x5A, 0x9C, 0xAF, 0xFF, 0x07}; const uint8_t spAND[] PROGMEM = {0xA9, 0x6B, 0x21, 0xB9, 0x22, 0x66, 0x9F, 0xAE, 0xC7, 0xE1, 0x70, 0x7B, 0x72, 0xBB, 0x5B, 0xDF, 0xEA, 0x56, 0xBB, 0x5C, 0x65, 0xCB, 0x66, 0xC5, 0x3D, 0x67, 0xD7, 0xAB, 0x6D, 0x2E, 0x64, 0x30, 0x93, 0xEE, 0xB1, 0xCD, 0x3D, 0x92, 0xB9, 0x9A, 0xDA, 0xB2, 0x8E, 0x40, 0x12, 0x9A, 0x6A, 0xEB, 0x96, 0x8F, 0x78, 0x98, 0xB3, 0x2A, 0xB4, 0xD3, 0x48, 0xAA, 0x2F, 0x7D, 0xA7, 0x7B, 0xFB, 0x0C, 0x73, 0x71, 0x5C, 0xCE, 0x6E, 0x5C, 0x52, 0x6C, 0x73, 0x79, 0x9A, 0x13, 0x4B, 0x89, 0x45, 0xE9, 0x6E, 0x49, 0x42, 0xA9, 0x57, 0xFF, 0x3F}; const uint8_t spMINUS[] PROGMEM = {0xE6, 0x28, 0xC4, 0xF8, 0x44, 0x9A, 0xFB, 0xCD, 0xAD, 0x8D, 0x2A, 0x4E, 0x4A, 0xBC, 0xB8, 0x8C, 0xB9, 0x8A, 0xA9, 0x48, 0xED, 0x72, 0x87, 0xD3, 0x74, 0x3B, 0x1A, 0xA9, 0x9D, 0x6F, 0xB3, 0xCA, 0x5E, 0x8C, 0xC3, 0x7B, 0xF2, 0xCE, 0x5A, 0x5E, 0x35, 0x66, 0x5A, 0x3A, 0xAE, 0x55, 0xEB, 0x9A, 0x57, 0x75, 0xA9, 0x29, 0x6B, 0xEE, 0xB6, 0xD5, 0x4D, 0x37, 0xEF, 0xB5, 0x5D, 0xC5, 0x95, 0x84, 0xE5, 0xA6, 0xFC, 0x30, 0xE0, 0x97, 0x0C, 0x0D, 0x58, 0x40, 0x03, 0x1C, 0xA0, 0xC0, 0xFF, 0x03}; const uint8_t spMILLI[] PROGMEM = {0x6E, 0xF0, 0x8A, 0xB3, 0x4B, 0xEB, 0xC6, 0xAE, 0x36, 0xA7, 0x1A, 0x3A, 0x54, 0x53, 0xD6, 0xDC, 0xEC, 0x66, 0x23, 0xDF, 0x58, 0x26, 0x43, 0xB4, 0xCD, 0xEA, 0x74, 0x5D, 0x94, 0x46, 0xF0, 0x96, 0x3B, 0x9D, 0x79, 0x98, 0x26, 0x75, 0xDB, 0xB3, 0xD7, 0xB6, 0xF5, 0x90, 0xA8, 0x91, 0x9F, 0xEA, 0x9E, 0xEE, 0xE9, 0x9B, 0x20, 0x7D, 0xCB, 0xFF, 0x03}; const uint8_t spMETER[] PROGMEM = {0xA1, 0x8F, 0x5C, 0xB5, 0x56, 0x92, 0xE4, 0xE1, 0xF4, 0xDD, 0x0B, 0x59, 0x6B, 0xE3, 0x53, 0x8C, 0x14, 0x44, 0x15, 0x8B, 0x46, 0x3A, 0xB3, 0x03, 0x7B, 0xBE, 0x99, 0x89, 0x49, 0xB7, 0x72, 0xC4, 0xEA, 0x4C, 0x01, 0xD8, 0x2E, 0xC8, 0x03, 0xA3, 0xAB, 0x91, 0x39, 0x2C, 0x17, 0x8D, 0xAE, 0x36, 0xE6, 0x34, 0x7F, 0x3D, 0xE6, 0xEA, 0x13, 0x6C, 0x79, 0x73, 0x3B, 0xAA, 0x1B, 0xB0, 0xD3, 0x3C, 0xFD, 0x6A, 0x4F, 0xF1, 0x09, 0x35, 0x9E, 0xA5, 0xBE, 0xFF, 0x0F}; const uint8_t spADJUST[] PROGMEM = {0xAD, 0xAD, 0xA1, 0xD5, 0xC4, 0x5A, 0x9F, 0xB1, 0xFA, 0x14, 0xB3, 0x78, 0xBC, 0x87, 0x31, 0x55, 0x9B, 0xEC, 0xC2, 0x6B, 0xC4, 0xE6, 0xB9, 0xDB, 0xB8, 0x97, 0x24, 0x87, 0xA6, 0x99, 0x59, 0x61, 0x4B, 0x1C, 0x05, 0x63, 0x56, 0x79, 0x6C, 0x05, 0x4C, 0xC5, 0x14, 0x81, 0x35, 0xB4, 0x98, 0xAC, 0xAE, 0x7D, 0x6E, 0x77, 0xAA, 0xE2, 0xD2, 0x5A, 0x63, 0xD5, 0xAD, 0x6E, 0xBD, 0xBA, 0xE2, 0xD3, 0x8A, 0xAB, 0xF2, 0x1C, 0x15, 0x50, 0x41, 0x8A, 0x03, 0x7E, 0x29, 0xF1, 0x80, 0x05, 0x2C, 0xA0, 0x01, 0x01, 0xFC, 0xD6, 0x2A, 0x01, 0x60, 0xC0, 0x0B, 0xEC, 0x16, 0x60, 0x40, 0xB7, 0x63, 0xFF, 0x0F}; const uint8_t spDIRECTION[] PROGMEM = {0xA5, 0x7E, 0xBE, 0x3C, 0x49, 0x14, 0xAF, 0x6E, 0xAA, 0x52, 0x72, 0xCD, 0x77, 0xBA, 0x66, 0x4A, 0x38, 0xAC, 0xDB, 0xE9, 0x8A, 0x0F, 0xB6, 0xB0, 0xF4, 0xAD, 0x4B, 0x5D, 0xDC, 0x35, 0xED, 0xCF, 0xF6, 0xD4, 0xA5, 0x68, 0xB8, 0x85, 0xFB, 0x53, 0xD6, 0x90, 0x34, 0x1E, 0x9D, 0x6E, 0x31, 0xF2, 0x36, 0x9D, 0x4A, 0x6C, 0x91, 0xC9, 0x47, 0x18, 0x63, 0xD1, 0xD8, 0x02, 0xE8, 0xC1, 0xCC, 0x01, 0x63, 0x6C, 0x45, 0x20, 0x02, 0x1E, 0x68, 0x45, 0x8D, 0xAA, 0x6E, 0xD1, 0x69, 0x36, 0x63, 0x69, 0x81, 0x2D, 0x25, 0x9A, 0xD4, 0x23, 0x1D, 0x5D, 0x0B, 0xA5, 0x7B, 0xB4, 0x78, 0xF9, 0xDB, 0x7D, 0x23, 0x18, 0xB9, 0x58, 0x7C, 0xFF, 0xBB, 0xAF, 0x19, 0xC1, 0x54, 0x4B, 0xF6, 0xFF}; const uint8_t spGO[] PROGMEM = {0x06, 0x08, 0xDA, 0x75, 0xB5, 0x8D, 0x87, 0x4B, 0x4B, 0xBA, 0x5B, 0xDD, 0xE2, 0xE4, 0x49, 0x4E, 0xA6, 0x73, 0xBE, 0x9B, 0xEF, 0x62, 0x37, 0xBB, 0x9B, 0x4B, 0xDB, 0x82, 0x1A, 0x5F, 0xC1, 0x7C, 0x79, 0xF7, 0xA7, 0xBF, 0xFE, 0x1F}; const uint8_t spREADY[] PROGMEM = {0x6A, 0xB4, 0xD9, 0x25, 0x4A, 0xE5, 0xDB, 0xD9, 0x8D, 0xB1, 0xB2, 0x45, 0x9A, 0xF6, 0xD8, 0x9F, 0xAE, 0x26, 0xD7, 0x30, 0xED, 0x72, 0xDA, 0x9E, 0xCD, 0x9C, 0x6D, 0xC9, 0x6D, 0x76, 0xED, 0xFA, 0xE1, 0x93, 0x8D, 0xAD, 0x51, 0x1F, 0xC7, 0xD8, 0x13, 0x8B, 0x5A, 0x3F, 0x99, 0x4B, 0x39, 0x7A, 0x13, 0xE2, 0xE8, 0x3B, 0xF5, 0xCA, 0x77, 0x7E, 0xC2, 0xDB, 0x2B, 0x8A, 0xC7, 0xD6, 0xFA, 0x7F}; const uint8_t spTO[] PROGMEM = {0x09, 0xD8, 0x4E, 0x34, 0x00, 0x4B, 0xA7, 0xA5, 0xBC, 0xE9, 0x62, 0x55, 0x4B, 0x53, 0x9A, 0xAC, 0x5C, 0x2D, 0xF9, 0x4B, 0xE9, 0x32, 0x73, 0xD3, 0xA1, 0x3D, 0xA5, 0x4F, 0x52, 0x2D, 0x9B, 0xB6, 0xA4, 0x21, 0x79, 0x95, 0xC0, 0xAC, 0xAD, 0x16, 0xED, 0xDC, 0x22, 0x23, 0xC2, 0xFF, 0x03}; const uint8_t spTURN[] PROGMEM = {0x01, 0x18, 0xA9, 0xCC, 0x02, 0x06, 0x28, 0x4E, 0xA9, 0x14, 0x39, 0x25, 0x69, 0x4B, 0xBA, 0x5D, 0xAE, 0xAA, 0x84, 0x15, 0x5A, 0xF5, 0xBE, 0xAB, 0x59, 0xCF, 0x61, 0xCE, 0x7D, 0x6B, 0x5B, 0x09, 0x49, 0x76, 0xEE, 0xB5, 0x1E, 0xE5, 0x69, 0x2E, 0x44, 0xD3, 0x9A, 0xE6, 0x27, 0x7C, 0x4D, 0x09, 0xA5, 0x47, 0xDC, 0xF8, 0xB9, 0xAF, 0x7B, 0x62, 0xB7, 0x70, 0xE6, 0xBE, 0x1A, 0x54, 0x4C, 0xB8, 0xDD, 0xFF, 0x03}; const uint8_t spUNIT[] PROGMEM = {0x61, 0xB9, 0x96, 0x84, 0xB9, 0x56, 0xE5, 0xB9, 0xCE, 0x63, 0xDE, 0xCE, 0x0D, 0x30, 0x36, 0x9F, 0x6E, 0x86, 0x36, 0x60, 0xE9, 0x7B, 0xCA, 0x5E, 0x93, 0x45, 0xA4, 0xEB, 0xC9, 0xBB, 0x77, 0x72, 0xE7, 0x2D, 0x2B, 0xAB, 0xD6, 0x24, 0x94, 0x17, 0x8F, 0xA2, 0x79, 0x4C, 0xD5, 0x48, 0x5D, 0xAA, 0xEE, 0x21, 0x23, 0x42, 0xF1, 0x1A, 0x66, 0x54, 0x15, 0x97, 0xD6, 0x6B, 0x19, 0xD1, 0xC5, 0xC5, 0x77, 0xEF, 0xB3, 0x9F, 0x7E, 0x47, 0xA0, 0x08, 0xE5, 0x2E, 0x22, 0x1B, 0x00, 0x01, 0xCB, 0xBB, 0x3B, 0xE0, 0xD7, 0x0A, 0x05, 0x9C, 0xD0, 0x4D, 0x80, 0xE6, 0x92, 0xFE, 0x1F}; // Constants and variables #define gY_a 0x1E // gyro IIC address ( 3C/3D for PIC W/R ) long Yv; // Y value of gyro compass long sYv; // save area for Yva float Yf; // Yv average (float) // for 28BYJ-48 steppers int TmStp = 3; // delay time per step (minimum 3) #define rPi 498 // rotation count for 180 degrees // for VL6180X ToF distance sensor float Tot = 0; // ToF measurement total float Ave = 0; // average of ToF measurement #define sFar 255 // ToF response value (spec) if too-far #define sPos 6 // sensor inside distance from front edge int Imm = 0; // integer value of milli-meter int dGo; // distance to go forward int Far = sFar - sPos; // wall is far int Near = 45; // wall is near (mm) // IR-reflective obstacle-sensors byte obsS; // obstacle status byte #define RLok B00000011 #define Rok B00000001 #define Lok B00000010 #define RLng B00000000 // Rotation priority #define Right 0 // rotate right #define Left 1 // rotate left int RLprty = Right; // Set initial priority right int nRt = 0; // # of continuous right turns int nLt = 0; // # of continuous left turns #define tMax 3 // max # of cont. same-dir turns // Hoko as current direction #define HokoN 0 // north #define HokoE 1 // east #define HokoS 2 // south #define HokoW 3 // west int Hoko = HokoN; // Set initial Hoko = north void setup() { // Arduino Setup ************* // for steppers DDRD = B11110000; // RD4-7(D4-7) output for stpper-1 PORTD &= B00001111; // set all stepper-1 pins LOW DDRB = B00001111; // RB0-3(D8-11) output for stepper-2 PORTB &= B11110000; // set all stepper-2 pins LOW // for R/L obstacle sensors pinMode(obsPwr, OUTPUT); // Power for obstacle sennsors digitalWrite(obsPwr, LOW); // power-off pinMode(obsR, INPUT_PULLUP); //right side obstacle sensor pinMode(obsL, INPUT_PULLUP); //left side obstacle sensor Serial.begin(9600); bLed(1, 500, 500); // blink Led to show I am awake Wire.begin(); // for ToF tOF.init(); // initialize ToF tOF.configureDefault(); tOF.setTimeout(50); // for Gyro compass // single measurement (wait>6mS i.e.: !dRdy unused) pgY(); // initialize gyro delay(200); // initial turn to north *** for test // ttN(); // *** for test // delay(300); } void loop() { // Arduino Loop ************* // Measure distance to wall and set Imm Distance(); // Serial.print("Imm="); // Serial.println(Imm); // 1)when wall is far away if (Imm >= Far) { dGo = (float)Imm * 1.8 - 30; // 1mm = 1.8xFwd (adjusted) Fwd(dGo); // go forward } // 2) when wall is not far if (Imm < Far) { sayNum(Imm); sPK.say(spMILLI); sPK.say(spMETER); delay(250); // and if wall is very near, turn if (Imm < Near) { sPK.say(spTURN); Turn(); } else { // not very near dGo = (float)Imm * 1.8 - 30; // 1mm = 1.8xFwd (adjusted) if (dGo > 0) { // if still okay sPK.say(spGO); Fwd(dGo); // go forward } else { // if not okay sPK.say(spTURN); Turn(); } // end of else (not okay) } // end of else (Imm >= Near) } // end of if (Imm < Far) } // end of main Loop /******************************** * *** User defined functions *** * *****************************/ // *** Measure distance to wall void Distance(void) { #define mcount 5 float Tot = 0; for (int i = 0; i < mcount; i++) { Tot = Tot + tOF.readRangeSingleMillimeters(); } float Ave = (float) Tot / mcount; Imm = Ave - sPos; // minus sensor position } // *** Blink Led void bLed(int nTimes, int onLen, int offLen) { for (int m = 0; m < nTimes; m++) { digitalWrite(Led, HIGH); delay(onLen); digitalWrite(Led, LOW); delay(offLen); } } // *** gyro compass funcions // prepare gY(HMC5883L) = set control registers void pgY(void) { // Conf-reg A = B011(#samples=8)110(75Hz@Cont-mode)00(no bias)=0x78 // Conf-reg B = B000(±0.88Gauss)00000(must be cleared)=0x00 // Mode reg = B00000(must be cleared)01(single measurement)=0x01 Wire.beginTransmission(gY_a); Wire.write(0x00); // point addr 0 (Conf-reg A) Wire.write(0x78); // Conf-reg-A = 0x78 Wire.write(0x00); // Conf-reg-B = 0x00 Wire.endTransmission(); } // read Y-axis value of gyro HMC5883L=GY271 void rgY(void) { #define numadd 20 // number of additions for Yv average long Yvt; // Yv total Yvt = 0; // clear total for (int j = 0; j < numadd; j++) { Wire.beginTransmission(gY_a); Wire.write(0x02); // point Mode-register Wire.write(0x01); // set signle measm't mode Wire.endTransmission(); delay(6); // wait>6mS for data update Wire.requestFrom(gY_a, 6); // read six bytes while (Wire.available() < 6) {} // wait for data ready byte bXh = Wire.read(); // X high byte byte bXl = Wire.read(); // X low byte byte bZh = Wire.read(); // Z high byte byte bZl = Wire.read(); // Z low byte byte bYh = Wire.read(); // Y high byte byte bYl = Wire.read(); // Y low byte Wire.endTransmission(); Yv = bYl + bYh * 256; // Set Yv Yvt = Yvt + Yv; } Yf = Yvt / numadd; // get average (float value) Yv = Yf + 0.5; // set integer value } // *** Turn to appropriate direction void Turn(void) { obsChk(); // check obstacle sensors switch (obsS) { // results in obsStatus case 0: // when both directions NG while (1) { bLed(1, 100, 300); // blink Led } case 1: // when the right is OK & left is NG TurnR(); break; case 2: // when the left is OK & right is NG TurnL(); break; case 3: // when both directions are OK if (RLprty == Right) { if (nRt < tMax) { TurnR(); } else { RLprty = Left; // new priority is Left TurnL(); } } else { if (nLt < tMax) { TurnL(); } else { RLprty = Right; // new priority is Right TurnR(); } } } if (Hoko == HokoN) ttN(); // if back to North, adjust direction } // *** Turn right void TurnR(void) { Tr(rPi / 2); // right turn 90 degrees nLt = 0; // clear # of continuous Left turns nRt ++; // inclease # continuous Right turns Hoko++; if (Hoko >= 4) Hoko = HokoN; } // *** Turn left void TurnL(void) { Tl(rPi / 2); // left turn 90 degrees nRt = 0; // clear # of continuous Right turns nLt ++; // inclease # continuous Left turns Hoko--; if (Hoko <= -1) Hoko = HokoW; } // *** Obstacle checking void obsChk(void) { obsS &= B00000000; // clear obsStatus digitalWrite (obsPwr, HIGH); // sensor power on delay (20); // wait for power stability if (digitalRead(obsL) == HIGH)obsS |= B00000010; if (digitalRead(obsR) == HIGH)obsS |= B00000001; digitalWrite (obsPwr, LOW); // save power } // *** Adjusting direction to North void ttN(void) { sPK.say(spADJUST); delay(20); sPK.say(spDIRECTION); #define nNc 20 // number of adjustings ± North float Ang = 2.55 * rPi / 180.0; // unit 2.55 degrees int Fdeg = Ang; // convert Ang to integer Fdeg Tl(Fdeg * nNc / 2); // turn left by Fdeg x nNc/2 float maxY = 0; // to set max Y int Nchk = 0; // number of checks int maxN = 0; // Number of checks when Y is max for (Nchk = 1; Nchk <= nNc; Nchk++) { Tr(Fdeg); // turn right by Fdeg delay(100); // avoid mechanical vibration rgY(); // get Y axis value if (Yf >= maxY) { maxY = Yf; maxN = Nchk; } } if (maxN == nNc)maxN--; int mDeg = (nNc - maxN) * Fdeg; Tl(mDeg); delay(100); sPK.say(spREADY); } // *** Stepper movement function list *** // 1)Go forward, Backward :Fwd,Bwd // 2)Turn right, Turn left: Tr,Tl // *** Go forward with both steppers void Fwd(int nTimes) { for (int i = 0; i < nTimes; i++) { // phase 31 PORTD=0011xxxx, PORTB=xxxx0011 PORTD &= B00111111; // clear bits PORTD |= B00110000; // set bits PORTB &= B11110011; // clear bits PORTB |= B00000011; // set bits delay(TmStp); // phase 32 PORTD=0110xxxx, PORTB=xxxx0110 PORTD &= B01101111; // clear bits PORTD |= B01100000; // set bits PORTB &= B11110110; // clear bits PORTB |= B00000110; // set bits delay(TmStp); // phase 33 PORTD=1100xxxx, PORTB=xxxx1100 PORTD &= B11001111; // clear bits PORTD |= B11000000; // set bits PORTB &= B11111100; // clear bits PORTB |= B00001100; // set bits delay(TmStp); // phase 34 PORTD=1001xxxx, PORTB=xxxx1001 PORTD &= B10011111; // clear bits PORTD |= B10010000; // set bits PORTB &= B11111001; // clear bits PORTB |= B00001001; // set bits delay(TmStp); } // return to phase 31 PORTD=0011xxxx, PORTB=xxxx0011 PORTD &= B00111111; // clear bits PORTD |= B00110000; // set bits PORTB &= B11110011; // clear bits PORTB |= B00000011; // set bits delay(TmStp); Stp(); } // *** Go backward with both steppers void Bwd(int nTimes) { for (int i = 0; i < nTimes; i++) { // phase 34 PORTD=1001xxxx, PORTB=xxxx1001 PORTD &= B10011111; // clear bits PORTD |= B10010000; // set bits PORTB &= B11111001; // clear bits PORTB |= B00001001; // set bits delay(TmStp); // phase 33 PORTD=1100xxxx, PORTB=xxxx1100 PORTD &= B11001111; // clear bits PORTD |= B11000000; // set bits PORTB &= B11111100; // clear bits PORTB |= B00001100; // set bits delay(TmStp); // phase 32 PORTD=0110xxxx, PORTB=xxxx0110 PORTD &= B01101111; // clear bits PORTD |= B01100000; // set bits PORTB &= B11110110; // clear bits PORTB |= B00000110; // set bits delay(TmStp); // phase 31 PORTD=0011xxxx, PORTB=xxxx0011 PORTD &= B00111111; // clear bits PORTD |= B00110000; // set bits PORTB &= B11110011; // clear bits PORTB |= B00000011; // set bits delay(TmStp); } // return to phase 34 PORTD=1001xxxx, PORTB=xxxx1001 PORTD &= B10011111; // clear bits PORTD |= B10010000; // set bits PORTB &= B11111001; // clear bits PORTB |= B00001001; // set bits delay(TmStp); Stp(); } // *** Turn left void Tl(int nTimes) { for (int i = 0; i < nTimes; i++) { // phase 41 PORTD=0011xxxx, PORTB=xxxx1001 PORTD &= B00111111; // clear bits PORTD |= B00110000; // set bits PORTB &= B11111001; // clear bits PORTB |= B00001001; // set bits delay(TmStp); // phase 42 PORTD=0110xxxx, PORTB=xxxx1100 PORTD &= B01101111; // clear bits PORTD |= B01100000; // set bits PORTB &= B11111100; // clear bits PORTB |= B00001100; // set bits delay(TmStp); // phase 43 PORTD=1100xxxx, PORTB=xxxx0110 PORTD &= B11001111; // clear bits PORTD |= B11000000; // set bits PORTB &= B11110110; // clear bits PORTB |= B00000110; // set bits delay(TmStp); // phase 44 PORTD=1001xxxx, PORTB=xxxx0011 PORTD &= B10011111; // clear bits PORTD |= B10010000; // set bits PORTB &= B11110011; // clear bits PORTB |= B00000011; // set bits delay(TmStp); } // return to phase 41 PORTD=0011xxxx, PORTB=xxxx1001 PORTD &= B00111111; // clear bits PORTD |= B00110000; // set bits PORTB &= B11111001; // clear bits PORTB |= B00001001; // set bits delay(TmStp); Stp(); } // *** Turn right void Tr(int nTimes) { for (int i = 0; i < nTimes; i++) { // phase 44 PORTD=1001xxxx, PORTB=xxxx0011 PORTD &= B10011111; // clear bits PORTD |= B10010000; // set bits PORTB &= B11110011; // clear bits PORTB |= B00000011; // set bits delay(TmStp); // phase 43 PORTD=1100xxxx, PORTB=xxxx0110 PORTD &= B11001111; // clear bits PORTD |= B11000000; // set bits PORTB &= B11110110; // clear bits PORTB |= B00000110; // set bits delay(TmStp); // phase 42 PORTD=0110xxxx, PORTB=xxxx1100 PORTD &= B01101111; // clear bits PORTD |= B01100000; // set bits PORTB &= B11111100; // clear bits PORTB |= B00001100; // set bits delay(TmStp); // phase 41 PORTD=0011xxxx, PORTB=xxxx1001 PORTD &= B00111111; // clear bits PORTD |= B00110000; // set bits PORTB &= B11111001; // clear bits PORTB |= B00001001; // set bits delay(TmStp); } // return to phase 44 PORTD=1001xxxx, PORTB=xxxx0011 PORTD &= B10011111; // clear bits PORTD |= B10010000; // set bits PORTB &= B11110011; // clear bits PORTB |= B00000011; // set bits delay(TmStp); Stp(); } // *** Stop both steppers void Stp(void) { // PORTB=xxxx0000, PORTD=0000xxxx PORTB &= B11110000; PORTD &= B00001111; delay(TmStp); } // *** Say number from-999,999 to 999,999 void sayNum(long n) { if (n < 0) { sPK.say(spMINUS); sayNum(-n); } else if (n == 0) { sPK.say(spZERO); } else { if (n >= 1000) { int thousands = n / 1000; sayNum(thousands); sPK.say(spTHOUSAND); n %= 1000; if ((n > 0) && (n < 100)) sPK.say(spAND); } if (n >= 100) { int hundreds = n / 100; sayNum(hundreds); sPK.say(spHUNDRED); n %= 100; if (n > 0) sPK.say(spAND); } if (n > 19) { int tens = n / 10; switch (tens) { case 2: sPK.say(spTWENTY); break; case 3: sPK.say(spTHIR_); sPK.say(spT); break; case 4: sPK.say(spFOUR); sPK.say(spT); break; case 5: sPK.say(spFIF_); sPK.say(spT); break; case 6: sPK.say(spSIX); sPK.say(spT); break; case 7: sPK.say(spSEVEN); sPK.say(spT); break; case 8: sPK.say(spEIGHT); sPK.say(spT); break; case 9: sPK.say(spNINE); sPK.say(spT); break; } n %= 10; } switch (n) { case 1: sPK.say(spONE); break; case 2: sPK.say(spTWO); break; case 3: sPK.say(spTHREE); break; case 4: sPK.say(spFOUR); break; case 5: sPK.say(spFIVE); break; case 6: sPK.say(spSIX); break; case 7: sPK.say(spSEVEN); break; case 8: sPK.say(spEIGHT); break; case 9: sPK.say(spNINE); break; case 10: sPK.say(spTEN); break; case 11: sPK.say(spELEVEN); break; case 12: sPK.say(spTWELVE); break; case 13: sPK.say(spTHIR_); sPK.say(sp_TEEN); break; case 14: sPK.say(spFOUR); sPK.say(sp_TEEN); break; case 15: sPK.say(spFIF_); sPK.say(sp_TEEN); break; case 16: sPK.say(spSIX); sPK.say(sp_TEEN); break; case 17: sPK.say(spSEVEN); sPK.say(sp_TEEN); break; case 18: sPK.say(spEIGHT); sPK.say(sp_TEEN); break; case 19: sPK.say(spNINE); sPK.say(sp_TEEN); break; } } } // end of program

 

上のほうにある#include文3つの<>内が、このブログへの表示方法(PreおよびCodeタグの使用)では消えてしまうようなので、右側にコメントをいれました。

今後何か気づくたびに記事とプログラムは更新させていただくことがありますが、ご容赦ください。

では今回はこのへんで。

 

©2019 Akira Tominaga, All rights reserved.