ArduinoでWebに簡単アクセス!(その2)

2月 28th, 2010

まず始めに。以下のEthernetDNSとEthernetDHCPを使う場合、ArduinoはDuemilanoveじゃないとROM容量が足らないので気をつけて。それから、RAMもかなりギリギリだよ。なにかSketchを書いて動きがメチャクチャになったら、RAMが足りなくなったと思っていい。その時はATMEGA328よりも大きなメモリを持ったArduinoレプリカを使うしかない。

前回はArduinoでDNSを使えるようにしたけど、今回はDHCP対応にしてみよう。

DHCPって、なんだ?という人もいるよね。

ArduinoのEthernetライブラリをそのまま使っている場合、ArduinoにIPアドレスを直接Sketchに書いていると思う。例えば、”192.168.0.10″とかね。

でも、大体みんなはブロードバンドルータの下のLANに接続して、そこからインターネットにアクセスしているよね?そのLANにPCとかを接続する時にちゃんとPCにIPアドレスを入れなくても、ちゃんとインターネットにアクセス出来るよね。これは、ブロードバンドルータにDHCPサーバという、自動的に接続したPCにIPアドレスを割り当ててくれる機能があって、PC側にはそのDHCPによるIPアドレスをして欲しいっているDHCPクライアント機能が働いているから。

そして、前回のDNSクライアント機能と併せることで、インターネットアクセスが自動化出来ているというわけ。(ホントはもう少し複雑なんだけどね。)

で、今回紹介するのが、そのDHCPクライアントライブラリのEthernetDHCPだ。前回のEthernetDNSと同じ人が提供してくれている。

EthernetDHCP

このライブラリは特に不具合はないので、前回のEthernetDNSと同じようにArduinoのライブラリディレクトリにコピーして登録しよう。

これで、SketchにIPアドレスは書かなくてよくなる。(もちろん、その代わりにこのDHCP機能が働くようにSketchを書くことになるけどね。:P)

だから、いつもと違うどこかのLANに接続してもちゃんと動く。すごいでしょ?

僕の場合はモバイルでArduinoを動かす時に、MacやPCのインターネット共有機能を使って、クロス配線のEthernetケーブルでArduinoをつなげて楽しんでいる。

EthernetDHCPにもサンプルSketchがあるから、それを参考にSketchを書けばいいだけだ。

今回は、EthernetDHCPとEthernetDNSを使って、シリアルモニタに入力したサーバのIPアドレスを取得するまでのサンプルSketchを書いてみた。例えば、”www.google.com”みたいに入力してみればちゃんとIPアドレスが表示されるよ。参考にしてね。

※EthernetDNSとEthernetDHCPがGNUのLGPLであり、そのサンプルもLGPLに含まれているため、以下のサンプルSketchも改変コードのためLGPLになっています。

//  Copyright (C) 2010 Hitoshi Yamada
//  http://emergeplus.jp
//
//  This file is sample sketch using Arduino EthernetDNS and EthernetDHCP.
//
//  This sketch is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as
//  published by the Free Software Foundation, either version 3 of
//  the License, or (at your option) any later version.
//
//  This sketch is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this sketch. If not, see
//  <http://www.gnu.org/licenses/>.
//
#include <Ethernet.h>
#include <EthernetDHCP.h>
#include <EthernetDNS.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Change to your
Ethernet Shield's MAC

const char* ip_to_str(const uint8_t*);

void setup()
{
  Serial.begin(9600);
  Serial.println("Attempting to obtain a DHCP lease...");
  EthernetDHCP.begin(mac);

  const byte* ipAddr = EthernetDHCP.ipAddress();
  const byte* gatewayAddr = EthernetDHCP.gatewayIpAddress();
  const byte* dnsAddr = EthernetDHCP.dnsIpAddress();

  Serial.println("A DHCP lease has been obtained.");

  Serial.print("My IP address is ");
  Serial.println(ip_to_str(ipAddr));

  Serial.print("Gateway IP address is ");
  Serial.println(ip_to_str(gatewayAddr));

  Serial.print("DNS IP address is ");
  Serial.println(ip_to_str(dnsAddr));

  Serial.println("Enter a host name via the Arduino Serial Monitor to have it "
                 " resolved.");

  EthernetDNS.setDNSServer(dnsAddr);
}

void loop()
{
  char hostName[128];
  int length = 0;

  while (Serial.available()) {
    hostName[length] = Serial.read();
    length = (length+1) % 128;
    EthernetDHCP.maintain();
    delay(1);
  }
  hostName[length] = '\0';

  if (length > 0) {

    byte ipAddr[4];

    Serial.print("Resolving ");
    Serial.print(hostName);
    Serial.println("...");

    DNSError err = EthernetDNS.resolveHostName(hostName, ipAddr);

    if (DNSSuccess == err) {
      Serial.print("The IP address is ");
      Serial.print(ip_to_str(ipAddr));
      Serial.println(".");
    } else if (DNSTimedOut == err) {
      Serial.println("Timed out.");
    } else if (DNSNotFound == err) {
      Serial.println("Does not exist.");
    } else {
      Serial.print("Failed with error code ");
      Serial.print((int)err, DEC);
      Serial.println(".");
    }
  }
}

const char* ip_to_str(const uint8_t* ipAddr)
{
  static char buf[16];
  sprintf(buf, "%d.%d.%d.%d\0", ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
  return buf;
}

これでかなり簡単にインターネットにアクセス出来るようになった。あとは、どんなSketchにするかはあなた次第!

次回は、これを使ってArduinoからSNTPで正確な時間を取得するSketchを紹介するね。

Author: Ouch! Categories: D.I.Y, Electronics, Hobby, IT Tags:

ArduinoでWebに簡単アクセス!(その1)

2月 25th, 2010

もうすでに、ArduinoでEthernetシールド使ってインターネットにアクセスしている人は多いと思うけど、IPアドレスをダイレクトに指定しているんじゃない?

たいていの人は、プロバイダにブロードバンドルータ経由でArduinoをつなげているだろうから、DNSでドメイン名をIPアドレスに変換することが出来れば、そんな必要もなくなるよね。

特にArduinoをWebクライアントにして遊ぶ時は、毎回IPアドレスを調べなくて済むEthernetDNSを使うと便利だよ。

EthernetDNS

EthernetDNSは、接続先サーバのドメイン名を入れてあげればIPアドレスに変換してくれるライブラリなので、いちいち接続先サーバのIPアドレスをSketchに書かなくてもよくなるので、とても便利。

ただし一つバグ(仕様?)があって、例えば、Google(www.google.com)にアクセスすると、IPアドレスに変換できない。僕はあまりDNSはよくわからないんだけど、これは、DNSのCNAME(Canonical Name)というホストに別名をつけてサーバ運用している場合、このEthernetDNSはうまく動かない。

そこで、僕が勝手にEthernetDNSでCNAMEが対応できるように元ライブラリをいじっちゃった。あとで、作者には連絡するつもりなんだけど、とりあえずここに公開しておきます。(なにせ英語圏の人なので、英語で教えるのが大変。(^^;))

ダウンロードしたEthernetDNSの”EthernetDNS.cpp”を開いて、366行目(version1.0b3の場合)に以下のコードがあるので、

                if (1 == buf[1] && 1 == buf[3] && 4 == buf[5]) {
                   read_data(this->_socket, (vuint8*)(ptr+offset), (vuint8*)ipAddr, 4);
                   statusCode = DNSSuccess;
                   break;
                }

それを以下の様にコードを追加する。

                if (1 == buf[1] && 1 == buf[3] && 4 == buf[5]) {
                   read_data(this->_socket, (vuint8*)(ptr+offset), (vuint8*)ipAddr, 4);
                   statusCode = DNSSuccess;
                   break;
                /*** Support type CNAME from here by H.Yamada ***/
                // if "type CNAME" match, skip next Answer.
                } else if (5 == buf[1]) {
                   offset += buf[5];
                /*** Support type CNAME to here by H.Yamada ***/
                }

これを、

“(Arduinoのディレクトリ)\hardware\libraries”(Windowsの0017以前)

“(Arduinoのディレクトリ)\libraries”(Windowsの0018以降)

にコピーすれば使えるようになる。

“www.google.com”にアクセスしてもちゃんとIPアドレスを取得出来るようになるはずだよ。試してみてね。

その2ではDHCPでIPアドレスを自動取得するライブラリを紹介するね。

Author: Ouch! Categories: D.I.Y, Electronics, Hobby, IT Tags:

ペーパークラフト・テオ・ヤンセンのダウンロード一時停止のお知らせ

11月 30th, 2009

ご好評頂いている、テオ・ヤンセンのペーパークラフトですが、現在、Theo Jansen ライセンス会社との間で公認プロセスに入っており、一時的にデータのダウンロードを停止させて頂いています。

大変申し訳ございませんが、ご了承願います。

なお、すでにダウンロードされた方は、作り方は公開しておりますので、ご利用ください。

Ouch!

Author: Ouch! Categories: D.I.Y Tags:

ペーパークラフトでテオ・ヤンセンメカを作ってみよう

11月 25th, 2009

少し遅くなってしまったけど、ペーパークラフトのテオ・ヤンセンメカのpdfデータとその作り方を更新しました。
ぜひ、作ってみてね。ホントに感動するはずだから。
ペーパークラフトで作るテオ・ヤンセン

基本テオ・ヤンセンメカ

Author: Ouch! Categories: D.I.Y, Hobby, Mechanics Tags:

Make Tokyo Meeting 04にテオ・ヤンセンレプリカペーパークラフトを出展します

11月 15th, 2009

11/22,23に開催されるMake Tokyo Meeting04に出展するよ。
前回のMTM03で好評だったペーパークラフトのテオ・ヤンセンレプリカをさらにスムーズに動くように改良して、Rhenonicsライクなモデルが出来上がった!かなり苦労したけどね:)

このモデルも近いうちに作り方を公開するので、ぜひトライしてみて。

Arduinoでモーターを使うときのTips その2

8月 31st, 2009

もう一つTipsを紹介しよう。

これはArduinoの無邪気な回路が引き起こす悪影響をどうクリアするか?という話。

基本的にArduinoはAVRマイコンの端子をそのままソケットに引き出してしまっている。これが問題。

通常、回路のケアとしては、端子に対するノイズ処理が必要だ。つまり、単純に機能を実現する回路では実は不十分だと言うこと。もしモーターをArduinoで動かそうと思っているなら、結構ハマるはずだよ。

わかりやすいのは、バッテリーでモーターを使ったArduinoアプリケーションを作ろうとした場合。

バッテリーには内部抵抗というのが存在していて、バッっと電流を流そうと思っても、この内部抵抗で瞬間に流せる電流は決まってしまう。モーターみたいに大電流が流れるものをつなげると、この内部抵抗がジャマになって電圧が下がってしまう。モーターをPWMで制御するとバッテリーの電圧をオシロスコープで測定するとギザギザになっていることがわかる。

このギザギザ波形は結局、この電源を利用しているすべての回路に影響を与える。

この場面では、まずは必要な電源系にモーターの周波数の影響がないローパスフィルター(CRフィルター:抵抗とコンデンサの組合せ回路)を設けて電源電圧の変動の影響がないようにしよう。CRフィルターのカット周波数は、1/2πCRで計算できる。ハイパスフィルターも同じ式。

それから、センサの出力端子にクロストークなどでノイズが乗ってしまう場合にもフィルターは有効だ。センサの出力周波数にマッチしたフィルターを用意しよう。

ちなみに、ArduinoのPin2を割込み(attachInterrupt)で設定してFA-130を動かしてみたら、ものの見事にノイズが乗って割込みが入りまくってしまったので、対策しようと思ったんだけど、うまくいかなかった〜。もっと勉強しないとダメだなぁ、と思ったのでした。アナログ回路は奥ふぁふかい。orz

Arduinoでモーターを使うときのTips その1

8月 30th, 2009

前の投稿で、Arduino用のモータードライバを紹介したけど、もう少し補足しよう。

まず、このモーターライブラリは、モーターの回転数をVref端子で制御出来るわけだけど、もちろん正転・逆転制御端子だけのPWM制御でも使うことが出来る。

Vrefモードは、Vrefにかかる電圧がモーターの回転数を決めるモード。対してPWMモードは、正転・逆転制御端子の単位時間におけるOn:Off時間比でモーターの回転数を決めるモードだ。

Vrefモードでは正転・逆転制御端子の設定はデジタル出力端子にする(のが一般的だろう)。PWMモードではアナログ出力端子に設定することになる。

Vrefモードが便利な場面はなんだろう?

Arduinoのアナログ出力は実はPWM出力なので(基板のシルクにもそう印刷されている)、Vrefモードも実はモータードライバICのVref端子にOn:Off時間比で電圧を設定していることになる。

このPWMの周波数がモータードライバの規格にあっているかどうか?が問題になる(参考:エレキジャック
連載キットで作る(67) ロームのBD6211モータ・ドライバをテストする(4)
)。例えば、ロームのBD6211FではPWM周波数は20k〜100kHzなのに対し、Arduinoでは500Hzであって、規格を満たすことが出来ない。

こういう時にVrefモードが役に立つ。Vrefへはあくまで平均電圧がどのくらいか?ということになるので、500HzでPWMで平均電圧を出力していても問題がないわけだ。

対して、PWMモードの便利なところは、制御端子がVrefモードに比べて1本少ないところ。Arduino電源電圧をモーター電圧が上回っていれば、こちらの方を使って、Arduinoの使用端子を減らすことが出来る。

さて、どちらのモードで動かすかをどうやって選択するか?なんだけど、このドライバライブラリでは2つあるDCMotor::Init関数のどちらを選択するかで決まる。

DCMotor::Init(int FINpin, int RINpin, int VREFpin, int motorVIN, int boardVIN)の方がVrefモード、DCMotor::Init(int FINpin, int RINpin)の方がPWMモードだ。

setup関数でDCMotor::Initをコールすればいいよ。

Arduino用DCモータドライバライブラリを作ったよ。

8月 30th, 2009

しばらくぶりのブログ。

ネタはいろいろあるんだけど、なかなかアップできなくて反省してる。

と、いうことで、今回はArduino用DCモータドライバライブラリをアップするね。

DCモーターってのは、直流モーターのことで、よく見ることが出来るのは模型用のFA-130とかRE-260とかだね。

こういうモーターを専用のモーター制御ICを使えば、Arduinoから制御出来る。

今回対象にしているのは、東芝TA7291(P)(秋月電子通商千石電商で購入可)やBD6211F(スイッチサイエンス)というモータードライバーだ。

TA7291P

TA7291P

BD6211F

BD6211F

これらは、正転・反転(CW/CCW)をデジタル出力2本の組み合わせ+出力電圧(Vref)をアナログ出力で制御出来るICだ。

つまり、デジタル出力を2本とアナログ出力を1本、Arduinoにつなげればいいわけだ。

このファイルがそのArduino用のライブラリ。

これを解凍して、ArduinoIDEのhardware->librariesにそのままコピーする。そして、#include <DCMotor.h>とすれば、このライブラリを利用できる。

例えば、こんな感じだね。モーターは1秒間正転してから、1秒間逆転するSketchだ。

#include <DCMotor.h>

#define  FIN      7    // 回転制御端子1

#define  RIN      8    // 回転制御端子2

#define  VREF     9    // モータ電圧制御端子

#define  M_VOLTAGE     3    // モーター電圧最大値:3V

#define  B_VOLTAGE     5    // Arduino電源電圧:5V

DCMotor motor;  // モータードライバの宣言

void setup()

{

    motor.Init(FIN, RIN, VREF, M_VOLTAGE, B_VOLTAGE);

}

void loop()

{

    motor.Forward(1000);    // 1秒間正転

    motor.Free();  // モーター回転方向変更による電流保護

    motor.Backward(1000);    // 1秒間逆転

    motor.Free();  // モーター回転方向変更による電流保護

}

ここで、M_VOLTAGEというのは、実際にモーターにかける電圧で、B_VOLTAGEというのは、Arduinoの電源電圧。

もし、2つのモーターを制御したければ、同梱したDoubleDCMotorが役に立つ。

これは、2つのモーターを1つのコマンドで制御出来るようにしたライブラリだ。

#include <DoubleDCMotor.h>

#define  L_FIN      7    // 左モーター回転制御端子1

#define  L_RIN      8    // 左モーター回転制御端子2

#define  L_VREF     9    // 左モータ電圧制御端子

#define  R_FIN      13    // 右モーター回転制御端子1

#define  R_RIN      12    // 右モーター回転制御端子2

#define  R_VREF     11    // 右モータ電圧制御端子

#define  M_VOLTAGE     3    // モーター電圧最大値:3V

#define  B_VOLTAGE     5    // Arduino電源電圧:5V

DoubleDCMotor motor;  // モータードライバの宣言

void setup()

{

    motor.Init(L_FIN, R_FIN, L_RIN, R_RIN, L_VREF, R_VREF, M_VOLTAGE, B_VOLTAGE, 1.1);    // 例)左右のモータ回転速度のバラツキ補正は1.1
}

void loop()

{

    motor.Go(1000);    // 1秒間前進

    motor.TurnLeft(1000);    // 1秒間左回転

    motor.TurnRight(1000);    // 1秒間右回転

    motor.Back(1000);    // 1秒間後退

}

2つのモータを同時に制御出来る。このライブラリは、モーターの空回転(Free)を取り込んであるので、特に明示的にFreeを実行しなくてもいい。

バラツキってなに、って?同じモータでも同じ電流を流しても同じ速さで回転はしないんだ。それはどうしても発生してしまって、特に2つのモーターを使って動くようにしたくても、まっすぐ前進・後進できないで曲がって動いてしまう。そこで、左右の回転差を割合で指定して、モーターにかけるVrefを調整することでまっすぐ前進・後進出来るようにするパラメータだ。これはモーターによって変わるので、実際にくみ上げた後に最適な値を選んで欲しい。

トライしてみてね。

スターリングエンジンを作ったよ。

6月 12th, 2009

大人の科学No.10の付録のスターリングエンジンを作ってみた。

外燃で閉鎖系の面白いエンジンだ。

温度差だけでエンジンになるというのは、とても魅力的だね。

実際の製作過程は、tumbr(http://emergeplus.tumblr.com)に載せてあるよ。

動いている動画はこれ。温度差を出すために焼酎お湯割り(約90°)と保冷剤(0°)を使っている。焼酎はこの後おいしく飲んだけどね :p)

この付録のエンジンは小さな温度差(数十度)で動作するので、あまり大したトルクは出ていない。指で触れば泊まっちゃうし、実際トルクがないので、少しの組み立てフリクションで全く動かない。プッシュロッドの位置調整やプーリー軸の隙間調整でかなり苦労したよ。でも、スターリングエンジンは温度差が大きいほど、トルクは出るはずだ。いずれ、他の製作にもこのスターリングエンジンを使ってみたいと思っているんだ。

排気ガスが出ないのがスターリングエンジンの魅力。太陽電池の出力を熱源にすれば、とてもクリーンでエコなエンジンが出来上がる。

Author: Ouch! Categories: Hobby, Mechanics Tags:

スパムひどいので、コメントは一時受付不可にします。

6月 8th, 2009

かなりスパムコメントがひどくなっているので、コメント受付を一時停止させてもらうよ。ごめんね。

Author: admin Categories: その他 Tags: