ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

arduinoコミュのアドレスが遠いとダメ?

  • mixiチェック
  • このエントリーをはてなブックマークに追加
1つのサブルーチンがあまりにも長いときにも感じましたが....今回は大きいデータにアクセスしようとしたら、長いサブルーチンの時と同じような雰囲気になりました。

例えば....

byte data1[] = {0,1,2,3,4,5,6.......999,1000};
byte data2[] = {0,1,2,3,4,5,6.......999,1000};
byte data3[] = {0,1,2,3,4,5,6.......999,1000};
int counter;
setup() {
counter = 0;
}
loop() {
byte tmp1,tmp2,tmp3;
tmp1 = data1[counter];
tmp2 = data2[counter];
tmp3 = data3[counter];
Serial.print(tmp1,HEX);
Serial.print("/");
Serial.print(tmp2,HEX);
Serial.print("/");
Serial.print(tmp3,HEX);
counter++;
delay(100);
}

このプログラム、問題なく動きますか?
コード的に問題はないと思います。
問題になってると思う部分はbyte配列に大量のデータが入っている事です。
もちろんコンパイル後の容量的な問題は出ていません。
しかし....なんと言うかdata1にアクセスしようとしている部分から
実際にdata1が置いてある位置までの距離(バイト数)が遠いからか(?)
アクセス出来ないんだか(?)アクセスが変になっているような気がします....。

もし上記には問題がある場合、大量のデータを扱いたい時には、どのようにコーディングしたら良いのでしょうか?

コメント(38)

自分で書いてて問題を発見。
byte配列のdata1やdata2、data3の中に999とか1000が入っていますが、実際は255迄の数値です。
イメージとして1000バイトもの量のデータが入っているって意味です。
なんとなく思い当たる事が....
Javaには1つのメソッドが32kを超えてはいけない...とか言うのがあった気がしてきました。
arduinoでも同じような制限があるのですか?
data1〜3合わせて3003バイトってことですか?
ATmega328のRAMは2048バイトなので、それ以上のデータを保持したい場合は外付けでRAMが必要ですね。
大量のデータは、PROGMEMでフラッシュ領域に置きましょう。
http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1613
じぇーけーそふと様
 えっ?コンパイル終了時に表示される(of a 30720 byte maximum)が最大容量じゃないのですか?!
 だって....arduinoMEGAとかにするとあそこの数字も増えるから....
 と思ってました。

まりす様
 そーなんですよ、どっかにFlashが付いていた気がして調べたのですが....
 EEPROMが512バイトしか無いのか....で終わってました。
 PROGMEMってのがあるのですか!
 しかしこのFlashメモリは....arduinoDuemilanoveに元々付いてるメモリなのですか?
 容量もどれだけあるのかイマイチ判りませんが....
 ライブラリもSketchのImportLibraryにはありませんね。
 arduinoってのはボード(完成基板)のことで、AVRってのはチップの事で...
 PROGMEMってのは直接チップ(AVR)を扱う感じなのですかね?

もう少し調べます....
>わかにゃんさん
例のプログラムの場合、初期値をフラッシュ(この容量は32Kバイト)から起動時に読み込んでRAM(これは2Kバイト)に展開する様になっています。RAMの容量は2Kバイトですが、実際はスタック分もあるのでもうちょっと少ないです。
PROGMEMでしていすればフラッシュ上の値として扱われるので、変更しない値としてなら使えます。普通のC言語で言うconst型と似たような感じです。
PROGMEM→PROG MEM→Program Memory
つまりプログラム(を置く)メモリー(に配置せよ)という意味ですね。
arduinoDuemilanove328なら32KBあるわけです。
もっとも、そこにブートローダーもプログラム本体も置かれるのですが。

普通に初期値付きの変数を宣言した場合、
まず、プログラムメモリーに置かれたデータがRAMにコピーされ、
その後、スケッチで書いたプログラムがスタートするのです。
それをせずにプログラムメモリーに置いたままで余計な事をするなと宣言するのがPROGMEMです。
ただし、ここにおいた場合、通常の変数の様にはアクセスできないので、
専用の関数を使ってデータを取得しなければいけません。

こういうところは、パソコンのプログラミングとマイコンのプログラミングとの違いですね。
パソコンのプログラムはプログラム本体もデータ(変数)もRAMに置かれる前提で作りますから。

実際には、パソコンとマイコンの違いじゃなくて、CPUのアーキテクチャの違いなんですけど。
パソコンのCPUはノイマン型、AVRマイコンはハーバード型と言われます。
http://ja.wikipedia.org/wiki/%E3%83%8E%E3%82%A4%E3%83%9E%E3%83%B3%E5%9E%8B
http://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%BC%E3%83%90%E3%83%BC%E3%83%89%E3%83%BB%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
http://cai.int-univ.com/sugsi/Lecture/CPU/3/Memory.html
PROGMEMの使い方は理解出来ました!
ちゃんとデータが取れてるかは判りません....
#エラーやハングアップ、暴走はしていない
少なくともJPEGデータをデコードしたものを画面に表示すると「壊れた絵がでる」事だけは確認済み(笑)

ちゃんとデータが読めてるかの確認をするべきか?
それともJPEGデコーダのデバックをするか?
悩む....。
Arduinoで動くJPEGデコーダが有ったら、それは便利かも。
エンジン部分を公開してオープンでデバッグしたら?
成果としてJPEGデコーダのライブラリが出来たらみんなハッピーになれるよ。
とは書いたものの、2KのRAMでJPEG展開をするのは至難の業じゃなかろうかと想像中。
http://blog.goo.ne.jp/sirius506/e/bbd7b2cfe285228797e3ec350f97997f
マイコンは違うものの、ここで使っているJPEGデコーダは
JPEG展開時、静的に24KBほどのメモリーを必要としているようです。
その他に画像の幅に応じたバッファも必要。

これが一般的なメモリ使用量かどうかは分かりませんが、
よっぽど工夫しないと2KBには収まらなさそうな。

わかにゃんさんは、もとのプログラムは何処から持ってこられました?
元のプログラムはない。
書籍でJPEGフォーマットを見ながら。

大変そうなので、とりあえずGIFでも出してみようかな?とか思ったり。
GIFの256色なら簡単だしね!

とりあえず絵が出ないと面白くない感じです。
>元のプログラムはない。
>書籍でJPEGフォーマットを見ながら。
それはすごい。なんか気持ちを削いでしまったみたいですみません。

http://www.ekisho-ichiba.com/shopdetail/001001000001/
この5000円液晶に画像を表示させようとしてるんですね?
16ビットカラーで画像表示出来るなら、
やっぱりJPEGなどの写真を表示させてみたいところですね。

JPEGの手法を使いつつも、専用の圧縮プログラムで作成したデータを
Arduinoで展開するなら、使用メモリを減らせるかもしれませんね。

よろしかったら参照されている書籍をご紹介いただけませんか?
話が逸れるかもですが、ちょとと前に8x8のマトリクスLEDに表示しようとして、パターン定義範囲を超えて文字指定してしまったら、スタックのカウンタとしてつかわれてるっぽい領域が表示されてしまったことが…。
リフレッシュする度に更新されたカウンタ値が反映された表示パターンに変化するという…。

それはそれとして、デコードルーチンの途中経過を表示してみれば、なにかわかりそう&おもしろそうな気が。
1.JPEGデコードは放置してGIF表示に切り替え
2.GIF表示を作ってて気が付いたが、2KしかRAMが無いとの事で微妙に....
3.そもそもPROGMEMのデータは正しく読み込めてるの?
4.256色のBMP(非圧縮)で実験

とりあえず256色のBMP(非圧縮)は正しく反転表示されました(笑)

しかしこれではいくらメモリがあっても足りません。
さて、何圧縮展開を移植しようかな?
追記
PROGMEMが遅いのかなぁ?
話にならないくらい鈍いです。
ベタでこれだと展開はもっと遅いのかなぁ?
いや、PROGMEMを使う回数が減るので早くなる可能性も?
むむむ....
e-dispで絵を!?
表示ってエスケープシーケンスで1ドットずつ書いてるんですか?
1ループで1ドット描画、ループにdelayは入れていない。

PROGMEM〜1バイト拾って
拾った値をカラーパレットから実データに読み込み
38400bpsで17バイトくらいのドット描画コマンド発行

この程度です。
液晶は320*240ドットですが、容量の関係160*120を書いています。
横一列160ドットで1秒弱ですかね。
つまり100秒くらいかかります!
160*120で100秒って....チト萎えました。
e-dispで絵を表示させるのが無理があるような・・。

絵を表示させるなら↓の液晶モジュールが3ピンで制御できるのでArduinoでもできると思いますよ。
http://solitonwave.shop-pro.jp/?pid=14220453

Arduinoではありませんが、以前同じATmega328で表示させたことがあります。
http://mixi.jp/view_album_photo.pl?album_id=44754016&owner_id=2377493&number=617213835&page=1
残念な事がわかりました。

PROGMEMは速かったです。
遅かったのはe-dispでの描画もしくはSerial.printでのコマンド転送でした。
上にも書きましたが転送速度は38400bpsにしているのですが....

因みにe-dispへは「四角描画」のコマンドを送っています。
実データとしては
[ESC]@0;0;2;2;000;000;00000z
と言った感じの24バイト。

e-dispの描画コマンドは「四角描画」と「ライン描画」の2つです。
四角は2頂点と2サイズ、ラインは4頂点なので送るバイト数は変わらない感じかと。
e-dispでは、ここが限界ですかね。

ただ発色も綺麗で使い勝手も良いので2台目を購入しました。
#ナゼ2台か?それは「欲しかったから」と「差し替えが面倒だから」などですね

------

全然関係ない話で申し訳ないのですが.....
e-dispを売ってるメーカーのTOPページに

リユースLCDで開発したオリジナル作品を発表しよう!
  リプロ製品アイディアコンテスト 開催!

と書かれています。
http://www.ekisho-ichiba.com/
なんとなく(賞金と賞品に)興味があるのですが(笑)
こーゆーの、エントリーした事ないので「ナニ出せば恥ずかしくないのかなー」なんて思ったり。

どなたか、この手のコンテストに応募したことある方いらっしゃいますか?
なんとなく教えていただけらたと思ったりします。
「e-DISPソフトウェアマニュアル」P.17の
背景画像のシリアル経由を使ってはどうですか?
画像データは1ドット2バイトのバイナリで送れるから概ね12倍速くなりそう。

        と思ったのですけど、

これはe-DISP/RS232C,e-DISP/USBのみの機能なんですね。
http://www.ekisho-ichiba.com/shopdetail/001001000002/order/
http://www.ekisho-ichiba.com/shopdetail/001001000003/order/

拡張基板が付いているだけじゃなく、
メイン基板のメモリ容量やファームウェアが違うのかなぁ。
2台目買うならe-DISP/RS232Cにしてみても良かったかも。
更にわかりました。

問題はe-dispではありません。

38400bpsを9600bpsに変更しました。
そしたら「そのぶん」遅くなりました。
そーか、38400bpsって、こんなに遅いんだ。

と言う事で「シリアル1bit転送の限界」だったようです。

もしe-disp屋さんが見ていたら「申し訳ありませんでした」って事で。
もしe-disp屋さんが見ていたら「4bitや8bit転送版とか作って下さい」って事で!
#見てないか.....

-----

まりす様

232CやUSB....必要なにいのに高いしぃ〜
いや、12倍速は魅力だったかなぁ?

-----

SoftwareSerialで2台目接続です!
白黒液晶は4ピン必要だったのにe-dispは1ピンで良いのでお得な感じ!
でも....SoftwareSerialは9600bpsなので更なる遅さに....
さて、どーしよっかな?!
自分は応募しなかったのですが、昨年こんなコンテストがありましたよ。

エンジニアリングアワード「電子工作コンテスト」
http://www.engineeraward.jp/ele/
応募作品一覧
http://www.engineeraward.jp/ele/list1.html
受賞作品一覧
http://www.engineeraward.jp/ele/prize.html

応募作品一覧みて、自分もとりあえず応募してみればよかったかなぁ?と思ったり(^^;
-------------------------------------------------------

「リプロ製品アイディアコンテスト」
http://www.reproele.jp/contest/form.php

恥かしいとか恥かしくないとか考えないで、とにかくエントリーみれば?
けど、規約の「4.権利」後半が、引っかかるなぁ。
応募しただけで、ここに写真や動画を貼るのもいちいちリプロの許可が要るようになりそう。
e-DISPとe-DISP/RS232Cのハードウェアマニュアルに載っている写真を見比べてみました。
e-DISPでは使用されていない右側の信号ラインに
e-DISP/RS232Cではコネクタが付いていて、シルクの信号名を見ると・・・
サブ基板側に背景画像用の増設メモリが載っているっぽいですね。


http://too-server.dyndns.org/cgi-bin/mt5/mt-search.cgi?blog_id=2&tag=e-DISP&limit=20
これを読むとe-DISP/RS232Cの方が面白そう。
サブ基板だけ後から買えないのかなぁ?
なんとなくですが、ファームは全部一緒じゃないかと。

ところでe-DISP単体だとマイクロSDカードスロットは、付いて無いですか?
マイクロSDカード(の差し口)は付いていません。

本日2台目購入時に「SDもしくはマイクロSDの口を付けて欲しい」とリクエストしてきました(笑)

でも...マイクロSDの口は付けたいので
http://zampoh.cocolog-nifty.com/blog/2008/12/avr---arduinosd.html
ココを参考に作る予定です!
#また新しいスレを立てる予定
>でも....SoftwareSerialは9600bpsなので更なる遅さに....
「MAX3100 SPI/MICROWIRE対応UART」
http://japan.maxim-ic.com/quick_view2.cfm/qv_pk/1731/t/al
こんなICを使えば、I2C経由でシリアルを増設出来そうです。
ソフト的にはWireライブラリから操作することになりますが。

このIC、マルツでも入手できます
https://www.marutsu.co.jp/user/shohin.php?p=39260

ただし、ArduinoでSDカード(マイクロSD)の読み書きと同時に使うと、
使用ピンがかち合うので、Wierライブラリは使えず、
SDカードのライブラリにも手を入れる必要がありそう。
どのみち速度を稼ぐ為にもWierライブラリ(I2C)を使わず、
SPI制御のソフトを書かないと意味が無さそうですが。

って、そこまでする前にArduinoMega1280使ったほうが早いか(^^;
リプロ製品アイディアコンテストは応募予定ですよ。
もう少しで完成予定です。

エンジニアアワードの電子工作コンテストも応募しました。
エントリーNo42と80が私のです。

動画で応募するコンテストは斬新でおもしろかったです。
プロモーション動画を作るのも楽しかった。
28に書いた方法は、考えてみるとずいぶん遠回りな事で(^^;
標準ライブラリのSoftSerialが高ビットレートに対応できないなら、
ポートを直接叩くような自前のシリアルルーチンを書くとか、
単純にTxのつなぎ先を変える付加回路を作って、2台の液晶に振り分けるとか、
そんなんで良さそう。
うっ!
さすが じぇーけーそふと さん。
応募予定ですか!

今やってること放置してコンテスト応募してみようかな....マジで!

-----

まりす様
難しすぎです(笑)
そーなんですよ、同じピン(TX)に2台繋ぎ、切り替えで使えれば良いのですが...
115200bpsは早い!2台繋いで半分になっても十分!
こんな回路でどうでしょう?
ロジックIC(74HC32)1つで、2台のe-Dispへの出力を切り替えます。
Digital2,3ピンのLowにした方に出力されます。
両方Lowにすれば、両方に出力できますね。
余っているORを使えば、最大4台まで接続可能です。
上の回路、Serial.printで出力直後に切り替えると
もしかして、バッファに残っていたデータを送り損ねるかも(^^;
あとで、ライブラリの中身を確認してみますね。

softSerialライブラリの.printは、関数から戻った時点で送り終わっているので、
直後に切り替えても大丈夫なんですが。
hardware\cores\arduino\HardwareSerial.cpp
を読んでみました。

シリアル送信は、メモリ上には特にバッファは設けていませんでした。(受信バッファはありました)
ただ、ハードウェア上のバッファがあるので、それをチェックする必要があるようです。

スケッチ冒頭に
  #include <avr/io.h>
を書いて置き、

送信先を切り替える前に
  while (!((UCSR0A) & (1 << TXC0))) ;
で、送信バッファが、空かどうか調べれば良さそうだけど・・・

現在検証中
チェックしたかったフラグは、一度立つと自動的にはクリアされないようで(^^;

Serial.printする前に
UCSR0A = UCSR0A | (1 << TXC0);
で、いったんクリアしておかないとチェックできないようです。

フラグのクリアとSerial.printを一体にした関数を作っておけば使えるかな。
こっちの回路だと32の回路に比べて、
・接続数は2台まで
・2台へ同時出力は出来ない
という制約はありますが、
・使用するピンを1つ減らせる
という利点もあります。

もちろんロジックIC1つで作れます。
おっ!発言36の回路はイタダキかもです。
元々TXで115200bpsとdigital2をSoftwareSerialで9600で使っていたので。
貧乏性なので数少ないPinを沢山使うのは嫌で1bit転送を選んでいるので助かります。
ただ....今日から「コンテストに出すもの」を作り始めたので、チト後になるかもです。
まりす様、いろいろ教えてもらったのにスンマセン。
いえいえ、どういたしまして。
色々調べると自分でも勉強になるので。

じぇーけーそふとさん、わかにゃんCR-Zさん、
コンテストがんばってください。

ログインすると、残り1件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

arduino 更新情報

arduinoのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。