Arduinoマイコン

2011年1月16日 (日)

Arduinoブートローダ書き込み

京都ノードの日程が迫ってきたにもかかわらず、ロボットができていないので、とりあえず超音波センサー自作はやらずおいておきます。
結構精度も上がって、あと少しで完成する気はするのですが・・・残念!!時間さえあればできるのに・・・
ロボットがとりあえず動いたら再開しようと思います。

ロボットが走るためには、最低限
・IRセンサー
・方位センサー
・モーターを制御できること
が必要なので、これらを早く作りたいと思います。

モーター関係は、マブチモータとタミヤのギヤード部分をつなげるスペーサ的なものをアルミ加工して作りました。
このスペーサ的なものを作るのにけっこう時間がかかりました。
これで、モーターとギヤード部分は連結できます。
L字金具は市販の物を使えるのであとは土台のアルミ板を作らないといけません。

さて、デバッグするためには液晶は必須ですので、液晶をI2Cで表示できるようにモジュール化してみました。
液晶はロボットは付けず、ロボットが止まってる時に液晶をつなげようと思っているので、通信する線が10もあれば困ります。
そこで、ATmega328Pを一つ液晶用に犠牲にして、I2Cによって、通信線2本で液晶を制御できるようにしました。

ATmega328Pにブートローダを書き込み、
ユニバーサル基板に設置し配線して、オリジナルの通信方法を決めて、完成です。

これで、Arduinoのソフトウェアから、ATmega328Pに直接書き込めるようにもなりました。
Arduinoも書き込み機も買わなくてよくなりました。

IRセンサーを作りたかった→様子は液晶で知りたい→いちいち10本つなげるのはめんどくさい→I2Cで制御できるようにした
ということです。

まだ、パルスボール用のIRセンサーを作っていないのでがんばって作ります。
ちなみにPSoCマイコンのCounterを利用する予定です。センサー類は全部I2Cで統一したいと思っています。

2010年11月30日 (火)

Arduinoの処理速度

Arduinoって1つのコマンドに1クロックで処理できるようです。
ただ、ライブラリ関数は1つの関数でたくさんのコマンドを実行するので遅くなるようです。

digitalWrite(10, HIGH)  …Arduinoの出力
→ 44 CPUクロックサイクル
PORTD = i; …AVRのレジスタ直接操作による出力
→ 3 CPUクロックサイクル
だそうです。
こうなるとレジスタにアクセスするほうが格段に速いですね。

数学関数とかとにかく関数が充実しているので、Arduinoはすごいと思います。

 

STM32マイコン徹底入門が発売されますが、どんどん本・マイコンが増えていきますね。すばらしい!!

僕はSTM32を使おうかArduinoのどちらを使おうかと迷ってますが、そんなに処理速度を求めないと思うので、Arduinoかなとも思っています。なにしろArduinoは三角関数から液晶まで関数化されていてだいぶ楽ですから。

プレゼンテーションについて少しネットサーフィンしてたら、
http://www.youtube.com/watch?v=L0XeQhSnkHg&feature=player_embedded
こんな動画がありました。
さすがアップル社です!細かい性能を言うとかじゃなくて、人を引きこんでいくこのプレゼンテーションはすごいと思いました。
観客を笑わせるとかは僕には不可能ですが、もう少し分かりやすい発表とかできたらなと思います。

明日から12月ですね。もう今年が終わりそうな気がします。
時間がたつのは早いものです。

2010年11月16日 (火)

簡単なミスほど見つかりにくく時間がかかる!?

PSoCでのADCのデーターをI2C通信でArduinoに送って液晶に表示させようとしたら、80035とか   -2405とか出たのであります(アラビックリ!!)。
なぜかを簡潔にいうと
バグその①PSoCのADCのデーターは12ビットの場合「-2048 ~ +2047」で表される。だからそのまま使うとマイナスが出るのは当たり前。
このバグはまだ納得できるのですが・・・
バグその②液晶でいちいちクリアしなきゃならなかった。いちいちクリアしないと、例えば"12345"と表示した後"800"と表示しようとすると、重なって"80045"と表示される。
そりゃ~変な値がでるはずです!
これを見つけるのに4時間くらいかかりました。ADCからは正しいデータが出ているかとか1つずつ原因をつぶしていっても奇妙なことが起こるので、う~~んとうなり、PSoCとArduinoにそれぞれ液晶につなげてどういう風にデーターが曲げられているかを眺めたら、あぁぁ~~なるほど!!となりました。
もう爆笑しました!何時間もバグを探し続けてこれですから!
同時に後悔と自分を責めるという気持ちとでもいいますか・・とにかくひどい!

でも、今日中に見つかってよかったかな?とポジティブになりつつ(?)、これを書いている次第でございます。
I2Cのエラーは今のところ出ていないです・・(たぶん)

明日もボチボチ頑張ります!

(あとちなみに、前の記事のI2C日本語仕様書はやはり誤植で原文が正しいようです)

2010年11月15日 (月)

ArduinoとPSoCのI2C通信(複数バイト)

2バイトでのArduinoとPSoCのI2C通信をしてみました。

PSoCではI2CHWブロックを使い、Arduinoがマスタ、PSoCがスレーブというように設定しました。

ここで注意すべきことがありまして、

たとえばPSoC側を
  dat = 1234;             //16進数で4D2になります
  buf_tx[0] = dat >> 8; //この場合0x04になります
  buf_tx[1] = dat;        //この場合0xD2になります
(buf_tx[n]とは送信するためのバッファ変数です。またdatはintでbuf_txはBYTEです。)
(PSoCマイコンではバッファ変数に送りたいものをあらかじめ入れておいて、マスタから送信しなさいと言われたら何も考えずにバッファ変数の内容を答えます。だから、マスタからいつ「送信しなさい!」といわれても良いようにあらかじめ言うことを準備しておきます。これらは、その準備のコードです。)

というコードにして、Arduino側で
  Wire.requestFrom(18,2);//1バイト要求することを宣言
  rd_data[1] = Wire.receive();//受信してrd_data[1]に代入
  rd_data[0] = Wire.receive();//受信してrd_data[0]に代入
という風に受信すると、
rd_data[1]には0x04が入り、rd_data[0]には0xD2が入ります。

つまり、PSoCでは「変数名[0]」にMSBを入れて、「変数名[n]」にLSBを入れなければいけないと考えられます。

普通上位バイトから受信して、後で下位バイトを受信すると思い込んでいるのですが、ArduinoのWire関数は少々ブラックボックス化されているので、確実ではありません。
ただ、PSoCのバッファ変数の[0]は、Arduinoでは最初に受信されるのは確かです。

配列の[n]のnが少ないほうが下位バイトで後から送信するのだと思っていた僕は混乱しました。

ともかく、Wire.receive();で最初に返されたデーター(つまり最初に何らかの変数に代入したデーター)は、I2Cで実際に最初に受信したデーターであるということがはっきりすればこれらが確実になるということでございます。

分かりにくい文章ですみませんが、Wire.receive();で最初に返されたデーターが、I2Cで実際に最初に受信したデーターであるかどうか分かる方は御教授ください。お願いします。

  

 

さて、ちなみに僕がなぜこんなにPSoCマイコンとArduinoとのI2C通信をやっているかというと、
IRセンサー ― PSoC ========== Arduino (===はI2Cでつなぐと思ってください)
という感じでつないで、
利点①Arduinoの少ないアナログ入力を節約でき、1つのArduinoでたくさんのIRセンサーと2本の線だけでつなぐことができる
利点②アナログでないので、(PSoCとArduinoの間の線が長くても)モーターからの外部ノイズの影響を受けにくい(たぶん・・)
利点③外付け部品がほとんどいらない
と考えているからです。
といいながら想像だけでIRセンサー部分がまったくできていないのですが・・・
早くI2C通信を終えてLPF(ローパスフィルタ)に移りたいと思います。

2010年11月11日 (木)

I2C通信によるArduinoと外部EEPROMの接続成功&PSoCの超音波センサの想像

I2C通信によるArduinoと外部EEPROMの接続に成功しました。使用したEEPROMはマイクロチップ社の24LC64です。

EEPROMのデーターシートを読んでがんばってプログラムを作ったのですが最初全く動きませんでした。
ひとつづつうまく動かない原因となるものを探していったのですが、まずは、EEPROMのアドレスはきちんと合っているということは確認できたのですが、うまく動かない原因はなかなか見つかりませんでした。
いろいろ検索していると、あるyou tubeの動画を見つけました。
自分のプログラムと照らし合わせてみると、delay(5);を送信と受信とかの間に挟んでいないことに気づき、半信半疑でやってみたら成功しました!!
たったそれだけなのに原因を見つけるのは大変です。
ただ、なぜdelayを入れなければいけないのかはまだ分かりません。

ロボットのデータロガーが取れたらまあ便利かなと思ってやったんですが、モーターもIRセンサーも方位センサーもまったくできていないのに僕はいったい何を目指しているのでしょうか・・・? 早くIRセンサーとかやらないと間に合わない・・・

ちなみにArduinoのWireライブラリは再度開始条件は使用できないみたいなのですが、停止条件を出したあと、何ミリ秒か空けて、開始条件を出せばEEPROMのデーターは読み込めるようです。

超音波センサの話ですが、PSoCマイコンで距離を計算してArduinoに送るのはやめようと思います。PSoCは難しいです!というわけでArduinoからPSoCに送信のタイミングを送信してPSoCは超音波が返ってきたと感知したらArduinoに送る、つまり、Arduinoで時間を計測して距離をだそうと思います。
メインArduinoとPSoCの超音波センサとの間にはスレーブArduinoを別に用意してそれに計算させようと思います。

Arduinoはスタートできるタイマーは僕が探した限り見つからなかったのですが、プログラムを開始(つまり電源を入れたとき)からの時間をμ秒で返してくれる関数があるので(micros)それを使おうと思います。最小分解能が4μ秒なので、音速340m/sのとき1.36mmの分解能で距離が測れるはずです。

まあ要するに難しいPSoCを頑張るよりもできるところはArduinoに任せてしまおうということであります。

2010年11月 4日 (木)

ArduinoとPSoCとのI2C通信成功!!

ArduinoとPSoCとのI2C通信が成功しました!
3時間弱、格闘して、やっと成功したのです!うれしい!3時間弱なのにとーっても長い道のりだった気がします。

今回実験したものは
①ArduinoがマスタでPSoCがスレーブ
②ArduinoとPSoCにそれぞれLEDとスイッチを1つずつつなぐ
③ArduinoとPSoCとの間はGND、VDD、SCL、SDAの4本だけでつなぐ
④Arduinoのスイッチを押したらPSoCのLEDが点灯し、PSoCのスイッチを押したらArduinoのLEDが点灯する
こういう単純なものです。

今回、成功するまでのバグを書きます。
①PSoCのLEDにつなぐピンを間違えていた→直した
②PSoCで内部プルアップがうまくいかなかった→内部プルアップは外して外部プルアップにした
③PSoCでのスイッチ割り込みがうまくいかなかった→割り込みはせず普通の入力にした
④PSoCで②の割り込みの設定を消すときにM8C_EnableGInt;というコマンドも消してしまってI2Cができなくなった→消してしまったM8C_EnableGInt;を初期化の位置に追加した

いまだに②と③は謎のままです・・・(とりあえずI2Cができたので今回はこれでよし!)

これらの目的は
①超音波センサーからArduinoに信号を送る際に、アナログ電圧でするとノイズによって距離の誤差が増えてしまうのではないかと考え、デジタルだとノイズの影響が少ないので、I2C通信で送れるようにするため。
②Arduinoはアナログ入力が少ないのでIRセンサーもI2Cにできれば、4本だけをArduinoにつなぐだけでよくなるから。
なお、目的①のノイズの影響についてですがアナログが劣化するというのはあくまで想像です。ただ、ノイズに強くなると強いモーターが使えて、ノイズによる誤動作の心配がいらなくなるかなと。

マスターは1個の予定なのでたぶん競合の心配はいりません。(というかArduinoって競合調停の機能ってあるんでしょうか?どっちでもいいですが・・・)

あとArduinoのI2Cってたぶん再度開始条件って使えないんですかね?(こっちは外部EEPROM用)
停止条件のあと開始条件を出すしかない気がするのですが・・

2010年11月 2日 (火)

Arduinoの液晶表示は要注意!!

はっきり言うと、2行表示させるためには、setup()の中の一番最初に
lcd.begin(16,2);
と宣言しておく必要があります。
これをしないとlcd.setCursor(0,1);と1列目2行目にカーソルを移しても、
2行目は表示されません!
(みんな知ってるのだろうか!?)
1行目しか表示されず僕はかなり戸惑いました。

これさえ気をつければArduinoは涙が出そうなくらいカンタンです!
カンゲキ!!

以下メモです。

※カーソルは書くたびに次に移動する。

BIN:2進法
OCT:8進法
DEC:10進法
HEX:16進法

  lcd.setCursor(0, 1);
  lcd.print(count, DEC);
  count = count + 1;
は約0.0018秒で動作する。

2010年11月 1日 (月)

Arduino初体験

Arduinoを初体験しました(かなり遅れている気が・・・)

LEDをチカチカさせました。

スイッチを入力してみました。

ほんの少しの発見その①
while()の中には関数;のカタチで入れるとエラーがでるが、関数(セミコロンなし)だとうまくいく。
例:スイッチが押してある間だけ動作Aをする。
while(digitalRead(Switch)){
  動作A
}

ほんの少しの発見その②
Switch構文を初めて使ってみた。
使いやすいし見やすい。

ほんの少しの発見(?)その③
外部EEPROM(I2Cで送受信)を使えるような気がする。
あとArduinoとPSoCとをI2Cで通信する仕方が分かった気がする。
想像と現実は違うけど・・・