今日は思いのほかよく晴れ、花が良かった。先週の週間天気予報では今日は雨との予報だったのだが、週が明けてみれば、少し花冷えの感じもありながら、青空の広がるよいお天気になった。
自転車で花見に出かけることにした。座り込んで酒食するのも勿論悪くはないが、時勢柄、人の
オッサンは生きている。
今日は思いのほかよく晴れ、花が良かった。先週の週間天気予報では今日は雨との予報だったのだが、週が明けてみれば、少し花冷えの感じもありながら、青空の広がるよいお天気になった。
自転車で花見に出かけることにした。座り込んで酒食するのも勿論悪くはないが、時勢柄、人の
えっ、アクセサリ16点付属でこの値段、って、これ、欲しいかも。……って、スポーツとか特にしないので、撮って面白い絵柄など身の回りにゃないんですけどね(苦笑)。
コレをゾンデに載せて空撮する、とかですかね。
唐突だが、
モーターで動く小さい台車にデジカメを乗せ、走り回らせて動画を撮りたい。虫の視点で動画を撮るわけだ。人の視点では思いもよらない、家の中のいろいろなものが写り込んで、面白いのではないだろうか。
Arduinoで制御し、手持ちの超音波センサで障害物を避けるようにしたい。
できるだけシンプルに作るため、操向装置を工夫する。普通ならサーボなどを用いて操向輪の向きを操作するのだろうが、ここを単純にしたい。
3輪の台車にし、後輪をキャスターのようなものにする。前進時はまっすぐに向くが、後退させるとモーメントがかかって後輪が傾き、左右どちらかに振れるようにする。そうすると、前進・後退の制御のみであちらこちらに台車を走行させることができるだろう。直進していって、ある程度まで壁などの障害物に近づくと、後退させる。後退させると、左右どちらかに向きが振れるので、超音波センサで測距しつつ後退させ、ある程度障害物が離れたらまた前進させる。
Arduinoでモーターを回すには、FETやトランジスタを用いる方法もあるが、前進・後退をさせるためには逆転ができた方がよい。それをFETなどを使ってスクラッチでやるのは面倒くさい。そこで、「モータードライバIC」を購入して、手っ取り早く済ませよう。
検索すると、よく売れていて入手しやすく、かつ他人の作例も多そうなものには東芝のTA7291Pというのがある。メーカーのサイトには生産終了予定と出ているものの、秋葉原へ行けば多分千石電商あたりに置かれているだろう。180円とか300円とか、そんな値段なので、どうってことはない。
このモータードライバに合うような模型用のモーターを選ぶ。スペックシートによるとTA7291Pは1A流せる。乾電池で台車を動かすとして、Arduinoには5Vがいるから、単3×4本の6Vとして、良さげなものをマブチのページで見繕う。
6Vだと電流が途端に2.9Aくらいにハネ上がり、モータードライバに合わない。しかも、急に1000円近くするので、趣味の工作にはちょっとどうかと思う。それで、電圧は3端子レギュレータを一つ買って落とすとして、3Vのものを見繕うと、「FA-130RA」というのに結局落ち着きそうだ。このモーターはよく使われているようで、他の方の作例にも良く出てくる。電圧は3Vまで、500mAだから、TA7291Pで動かすにはぴったりだ。
このモーターをタミヤあたりのギアボックスにうまく取り付ければいいだろう。
ギヤボックスを探すと、モーター込みのものも多くあるようだ。見ていると、このFA-130RA込みのギヤボックスがある。「タミヤ・3速クランクギヤーボックス」というやつだ。モーター込みで600円かそこらは安い。
最後に、ゴムの車輪を三つ、だな。まあ、これは何か、いいものがあるだろう。
休みなので、さっそく秋葉原へ行き、いろいろと買い込んでくる。秋葉原にはないものを、帰りに北千住の東急ハンズで買う。
まず、タミヤの「ミニモーター標準ギヤボックス」というのを買ってみた。モーター付きだが810円。安いかと言うと微妙なところだが、自力でギヤをいろいろやるとこれが結構大変なので、まあ、値段はこんなところだろう。
それから、走行させるためのゴムタイヤを買う。向きをうまく変えるための「キャスター」は東急ハンズで買う。
タイヤはさておき、この「キャスター」が、今回の私の工夫だ。前進・後退のみ、モーター1個の制御で、操向もしてしまおう、という工夫だ。このキャスターの変向角度を一定に制限し、後退する時だけランダムに向きが変わるようにするのだ。
それから東芝のモータードライバ「TA7291P」と、モーター用に電圧を落とす3端子レギュレータ。3端子レギュレータは3.3Vのものを探したが、なかったので、2.5Vのものを買った。これでだめなら、抵抗分圧で電圧を落とそう。
ギヤボックスは組み立てるとこうなる。
これを、いつもの100円ショップ「ダイソー」にあるアクリルの枠にねじ止めし、タイヤを取り付け、例のキャスターも取り付ける。
このキャスターの根元に、適当な金具を共締めし、変向角度を制限してやる。
これが、「モーター1個だけで向きも変える工夫」である。ためしに、2.5Vで動かしたがどうも力がなくていけない。そこで、ギア比をうんと落とし、9Vを直接モータにくれてやることにした。まあ、壊れやせんだろ。電流を測ると、200mAくらいなので、Arduinoに直接流さなければ許容範囲である。
さて、機械のほうはこれくらいのぞんざい適当、次に電子回路のほうに取り掛かる。
次のように考え、この通りブレッドボードを作る。
モータ付きの台車に取り付けると、次のとおりである。
スケッチは次のように書く。
// // crawlCar.ino // 27.10.11(日) 0600~ // 佐藤俊夫 // 台車を這いまわらせる // // モータードライバ const int MOTOR1 = 7; const int MOTOR2 = 8; const int MOTORPWM = 6; // 超音波センサ const int TRIG = 9; const int ECHO = 10; // 現在の台車の状態 const unsigned int STOP = 0, FORWARD = 1, BACK = 2; // ストップさせる距離、前進を再開させる距離 const float FOWSTOP = 20.0, FOWCONT = 50.0; // ある程度はバックを持続するようバック継続時間制限(ミリ秒) const unsigned int BACKLIMIT = 2000; // PWMの強さ const unsigned int POWER = 128; void setup(){ pinMode(MOTOR1,OUTPUT); // モータードライバ入力1へ pinMode(MOTOR2,OUTPUT); // モータードライバ入力2へ pinMode(TRIG,OUTPUT); pinMode(ECHO,INPUT); } void loop(){ static unsigned int state = FORWARD; static unsigned long int backstart = 0; float range = 0.0; range = ranging(); if(range >= FOWSTOP && state != BACK){ state = motor(FORWARD); } else if(range < FOWCONT){ if(state == FORWARD){ state = motor(BACK); backstart = millis(); } else{ if(millis() >= (backstart + BACKLIMIT)){ state = motor(FORWARD); } else{ state = motor(BACK); } } } else{ if(millis() >= (backstart + BACKLIMIT)){ state = motor(FORWARD); } } } // // モーター制御 // unsigned int motor(unsigned int command){ switch(command){ case FORWARD: digitalWrite(MOTOR1, LOW); digitalWrite(MOTOR2, HIGH); analogWrite(MOTORPWM, POWER); break; case BACK: digitalWrite(MOTOR1, HIGH); digitalWrite(MOTOR2, LOW); analogWrite(MOTORPWM, POWER); break; case STOP: digitalWrite(MOTOR1, LOW); digitalWrite(MOTOR2, LOW); break; default: digitalWrite(MOTOR1, LOW); digitalWrite(MOTOR2, LOW); break; } return command; } // // 測距 // float ranging(){ float time = 0.0, range = 0.0; digitalWrite(TRIG,LOW); delayMicroseconds(1); digitalWrite(TRIG,HIGH); delayMicroseconds(1); digitalWrite(TRIG,LOW); time = pulseIn(ECHO,HIGH); if (time > 0) { range = (time / 2) * 340 * 100 / 1000000; return(range); }else{ return(9999); } }
これを走り回らせると、次のようになる。
これにカメラを積み込み……
で、動画を撮影するわけだ。
なかなか這いまわっている感じが出て、いいと思う。
秋月電子のサイトを見ていると、小さなカメラがあり、Arduinoに付きそうな感じだ。
3850円。Arduino自体が2800円かそこらなので、それに比べるとちょっと高いが、早速行って購入。
だが、あまり情報は多くない。まず、メーカーのサイトを見ていくと、チュートリアルがあり、「とりあえずテストするには、電源をくれてやって、一番端のピンをテレビにつなぎゃあ絵が出る」みたいなザックリ感満載の解説が。それで、テレビにつなぐためのRCAジャックなども買う。
チュートリアルはこれを読んでおけばだいたいいいようだ。
ほどいてみるとこんな感じで、かなり小さい。
ピンのピッチが2mmで、ブレッドボードで扱いにくい。それで、普通の2.54mmのピンヘッダを出して、その根元をこんなふうにムリヤリ(笑)2mmピッチにせばめる。
こいつをカメラの基盤にえいやっ、とねじ込み、半田付けする。
なかなか小さいので、ルーペと老眼鏡を併用しつつ、ICなんか壊しちゃってもナンだから、20Wのぬるくて細い半田鏝でさっさとつける。
我ながらなかなかスピーディな仕事だなあ(笑)。
で、メーカーのサイトには「5V」と書いてあるが、これは互換品の別の製品のためのチュートリアルのようで、買ってきたものの基盤をよく見ると「3.3V」と印刷されている。壊してはもったいないから、3.3Vで試す。3.3Vの電源代わりにArduinoの3.3Vピンを使う。
基盤の印刷通り、3.3V、GND、それから右端のピンをRCAジャックのセンターに、RCAジャックのアースを同じくGNDに入れて、テレビの前に持っていく。
テレビにつなぐと、おお、確かに、値段なりのフザけた画質(笑)で、自分の顔が映る。
上下が逆だが、まあ、いいや。
で、今度はArduinoで画像を撮影してみよう。
チュートリアルにしたがってArduino用のライブラリをダウンロードし、これをArduinoのインストールフォルダの「libraries」に配置する。
そうしておいてArduinoのIDEを起動すると、「ファイル」→「スケッチの例」の中に「Adafruit VC0706 Serial Camera Library」が現れるから、この中から「Snapshot」を選ぶ。これは静止画をjpegで撮影するスケッチのサンプルだ。
// This is a basic snapshot sketch using the VC0706 library. // On start, the Arduino will find the camera and SD card and // then snap a photo, saving it to the SD card. // Public domain. // If using an Arduino Mega (1280, 2560 or ADK) in conjunction // with an SD card shield designed for conventional Arduinos // (Uno, etc.), it's necessary to edit the library file: // libraries/SD/utility/Sd2Card.h // Look for this line: // #define MEGA_SOFT_SPI 0 // change to: // #define MEGA_SOFT_SPI 1 // This is NOT required if using an SD card breakout interfaced // directly to the SPI bus of the Mega (pins 50-53), or if using // a non-Mega, Uno-style board. #include <Adafruit_VC0706.h> #include <SPI.h> #include <SD.h> // comment out this line if using Arduino V23 or earlier #include <SoftwareSerial.h> // uncomment this line if using Arduino V23 or earlier // #include <NewSoftSerial.h> // SD card chip select line varies among boards/shields: // Adafruit SD shields and modules: pin 10 // Arduino Ethernet shield: pin 4 // Sparkfun SD shield: pin 8 // Arduino Mega w/hardware SPI: pin 53 // Teensy 2.0: pin 0 // Teensy++ 2.0: pin 20 #define chipSelect 10 // Pins for camera connection are configurable. // With the Arduino Uno, etc., most pins can be used, except for // those already in use for the SD card (10 through 13 plus // chipSelect, if other than pin 10). // With the Arduino Mega, the choices are a bit more involved: // 1) You can still use SoftwareSerial and connect the camera to // a variety of pins...BUT the selection is limited. The TX // pin from the camera (RX on the Arduino, and the first // argument to SoftwareSerial()) MUST be one of: 62, 63, 64, // 65, 66, 67, 68, or 69. If MEGA_SOFT_SPI is set (and using // a conventional Arduino SD shield), pins 50, 51, 52 and 53 // are also available. The RX pin from the camera (TX on // Arduino, second argument to SoftwareSerial()) can be any // pin, again excepting those used by the SD card. // 2) You can use any of the additional three hardware UARTs on // the Mega board (labeled as RX1/TX1, RX2/TX2, RX3,TX3), // but must specifically use the two pins defined by that // UART; they are not configurable. In this case, pass the // desired Serial object (rather than a SoftwareSerial // object) to the VC0706 constructor. // Using SoftwareSerial (Arduino 1.0+) or NewSoftSerial (Arduino 0023 & prior): #if ARDUINO >= 100 // On Uno: camera TX connected to pin 2, camera RX to pin 3: SoftwareSerial cameraconnection = SoftwareSerial(2, 3); // On Mega: camera TX connected to pin 69 (A15), camera RX to pin 3: //SoftwareSerial cameraconnection = SoftwareSerial(69, 3); #else NewSoftSerial cameraconnection = NewSoftSerial(2, 3); #endif Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection); // Using hardware serial on Mega: camera TX conn. to RX1, // camera RX to TX1, no SoftwareSerial object is required: //Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1); void setup() { // When using hardware SPI, the SS pin MUST be set to an // output (even if not connected or used). If left as a // floating input w/SPI on, this can cause lockuppage. #if !defined(SOFTWARE_SPI) #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) if(chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega #else if(chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc. #endif #endif Serial.begin(9600); Serial.println("VC0706 Camera snapshot test"); // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); // don't do anything more: return; } // Try to locate the camera if (cam.begin()) { Serial.println("Camera Found:"); } else { Serial.println("No camera found?"); return; } // Print out the camera version information (optional) char *reply = cam.getVersion(); if (reply == 0) { Serial.print("Failed to get version"); } else { Serial.println("-----------------"); Serial.print(reply); Serial.println("-----------------"); } // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 // Remember that bigger pictures take longer to transmit! cam.setImageSize(VC0706_640x480); // biggest //cam.setImageSize(VC0706_320x240); // medium //cam.setImageSize(VC0706_160x120); // small // You can read the size back from the camera (optional, but maybe useful?) uint8_t imgsize = cam.getImageSize(); Serial.print("Image size: "); if (imgsize == VC0706_640x480) Serial.println("640x480"); if (imgsize == VC0706_320x240) Serial.println("320x240"); if (imgsize == VC0706_160x120) Serial.println("160x120"); Serial.println("Snap in 3 secs..."); delay(3000); if (! cam.takePicture()) Serial.println("Failed to snap!"); else Serial.println("Picture taken!"); // Create an image with the name IMAGExx.JPG char filename[13]; strcpy(filename, "IMAGE00.JPG"); for (int i = 0; i < 100; i++) { filename[5] = '0' + i/10; filename[6] = '0' + i%10; // create if does not exist, do not open existing, write, sync after write if (! SD.exists(filename)) { break; } } // Open the file for writing File imgFile = SD.open(filename, FILE_WRITE); // Get the size of the image (frame) taken uint16_t jpglen = cam.frameLength(); Serial.print("Storing "); Serial.print(jpglen, DEC); Serial.print(" byte image."); int32_t time = millis(); pinMode(8, OUTPUT); // Read all the data up to # bytes! byte wCount = 0; // For counting # of writes while (jpglen > 0) { // read 32 bytes at a time; uint8_t *buffer; uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups! buffer = cam.readPicture(bytesToRead); imgFile.write(buffer, bytesToRead); if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up Serial.print('.'); wCount = 0; } //Serial.print("Read "); Serial.print(bytesToRead, DEC); Serial.println(" bytes"); jpglen -= bytesToRead; } imgFile.close(); time = millis() - time; Serial.println("done!"); Serial.print(time); Serial.println(" ms elapsed"); } void loop() { }
で、これはSDカードに書き込むようになっている。
私の手持ちの、ArduinoにSDカードをつなぐ手段は、先日から愛用中の「ETHERNET SHIELD 2」に搭載されているSDカードスロットだけだから、とりあえずこれを使う。
手持ちのSDカードをETHERNET SHIELD 2に挿し、Adafruitのサイトのチュートリアルを参考に回路をブレッドボードに組む。
注意する点は2つだ。
そうやってArduinoをスタートさせると、写真が1枚だけ撮れる。
下は、そうやって撮った私の顔である。
……むっちゃむさくるしいなあw。
先週カメラのシャッターをイーサネット経由で切るのを作ったり、それをバラして雲の写真を撮ったりして面白おかしく遊んでいたら、WIZnetという韓国のメーカーに見つけられ、「よかったらサイト上で紹介しますよ。あと、最新のWiFiシールドとかも案内しますよ」というような感じのコメントがつき、「いやあ、拙いので恥ずかしいんですけど、ともかくご紹介はご自由にどうぞ」みたいな返事をしたら、WIZnetのサイト上で紹介されたでござるの巻。
Shutter control using ethernet shield 2 | WIZnet Museum
http://wiznetmuseum.com/portfolio-items/shutter-control-using-ethernet-shield-2/
なんか、当ブログ、「オッサンとバイエル、ピアノ等」、ピアノの記事がどんどんどんどん少なくなっている気がするが、まあ、いいや(笑)。
私は右翼だが、韓国人や韓国と手を結び、仲良くすべきだと思っている変な右翼なので、韓国企業に紹介されたことは、まことに嬉しいことである。
変な諍いは政治家が勝手にやっているので、そういうのはソッチに任せ、コッチは韓国ドラマをみたり韓国料理を食ったりSAMSUNGの携帯でネットをやったり韓国製チップの採用されたイーサネットシールドを使って面白おかしくやればいいのである。ソレはそれ、コレはこれ。はっはっは。