Arduinoで書いているコード(Arduinoを使用)は複数の2次元配列を使用しています。シリアルモニターを使用して何かを印刷すると、正しく印刷されますが、2次元配列を宣言して初期化すると、印刷されません。
コード:
void setup() { Serial.begin(9600); int image_width = 56; int image_height = 96; int image_result[image_width][image_height]; for (int i=0; i<image_height; i++) { for (int j=0; j<image_width; j++) { image_result[j][i] = 5; } } Serial.print("code works"); }
この場合、「コードは機能します」は出力されませんが、配列宣言を削除すると、初期化コードが出力されます。問題は何ですか?
Arduinoでは2次元配列の動作が異なりますか、それともスペースの問題ですか?
コメント
- 2048バイトのプロセッサでは、5376バイトの1次元配列でも失敗します。
- つまり、 10752 バイトです。各配列項目が2バイトであることを見落としていました。 'これらの2048バイトすべてを使用できるわけではないことに注意してください。シリアル送信および受信バッファだけで128バイトを使用します。
- マイクロSDカーを接続する場合、そのメモリで配列を宣言する方法はありますか?
- 接続できます。 SDカードを使用して、心のコンテンツにデータを書き込みます'。ただし、' t "メモリ内の配列を宣言することはできません"。ここでのアプリケーションは何ですか? 2KBのRAMを搭載したArduinoは'画像処理に最適ではありません。
- Arduinoのintの配列にある小さなBMPファイルを読み取る必要があります。それにいくつかの処理を行う必要があります。また、ファイルサイズは56 x96ピクセルです。
回答
2D配列はarduinoで正常に機能しますが、スペースがすぐに不足します。
unoには2キロバイトのRAMがあります。配列には56 * 96 = 53762バイト要素があります。
ある時点で5を使用して重要なメモリ値を上書きしているため、プログラムが失敗していると思います。
コメント
- メモリだけでなく、おそらくすべてのI / Oレジスタにも適用されます。
- 16ビットアドレス指定。SRAMは256から始まります。そのため、'の65279バイトのアドレススペース。したがって、'には到達しません。また、'これを防ぐ何らかの保護があると確信しています。
- 保護はありません。 CPUレジスタはアドレス0からメモリマップされ、次にI / Oレジスタがアドレス32から始まり、静的に割り当てられたRAMがアドレス256から始まります。
回答
使用可能なメモリよりも多くのメモリを使用しようとしています:96 * 56 * 2 = 10.752KBytes。これが発生したときにMCUが実行できることはそれほど多くありません。
データシートを見ると、マイクロコントローラー(ATmega328p)には2KバイトのRAMしかないことがわかります。
質問は、本当に大きなアレイが必要かどうかを自問することだと思います。外部フラッシュチップまたはSDカードシールドの入手を検討することもできます。読み取り専用の目的(ルックアップなど)でのみ必要な場合表)、フラッシュプログラムメモリの一部を使用できます(32Kバイトあります)。
コメント
- SDカードシールドを使用している'ですが、このように宣言された配列にデータを読み込んでいます。' SDカードメモリをどのように使用できますか。
- 通常、アレイの5376個の要素すべてを一度に処理する必要はありません。'検討してください。処理のために画像を小さなチャンクに分割します。実行する処理の種類によっては、プロセスを最適化するためにさまざまなスマートが必要になる場合があります。 。 😉
- フラッシュメモリに何度もデータを書き込むことはできますか。読み取り専用とはどういう意味ですか?一度データを書き込むにはどうすればよいですか。たとえば、フラッシュメモリに画像データを書き込みたい。どうすればそれができますか?
- あなたのプログラムのフラッシュメモリについて言及しています。 AFAIK、プログラミング中にのみプログラムフラッシュに書き込むことができます。 MCUを起動すると、プログラムフラッシュは読み取り専用メモリとして使用されます(そのため、'プログラムが'が実行されています。)データを書き込みたいので、プログラムフラッシュは適していません。
- 本当に画像全体を一度に処理する必要がありますか?前に述べたように、'画像を小さなブロックに分割できます。たとえば、チャンク[8] [8] はArduinoにとって快適なサイズです。飲み込むと、畳み込みフィルターを使用してもうまく機能します。 (そうは言っても、ArduinoUnoは深刻な画像処理アプリケーションには不向きであることを強調する必要があります。)
回答
確かに、これは利用可能なRAMの問題です。データごとに8ビットが必要ない場合(たとえば、画質を下げたい場合など)、ビットごとに複数のデータが含まれるようにデータを圧縮することを検討してください。たとえば、各データのサイズに応じて、16進値またはBCD(2進化10進数)が機能する可能性があります。
コメント
- OP BMPファイルをメモリに読み込みたいので、BCDに非常に便利に変換できるとは思えません。
- それは'良い点です。おそらく彼は'彼の画質を大幅に低下させたいと思っていますか?いずれにせよ、追加のストレージが賢明です。
回答
他の人が指摘しているように、配列はArduinoで利用可能なRAM。他の人はあなたのための解決策であるかもしれないフラッシュメモリに言及しました。 Arduinoには、アレイを保持できる32KBのメモリがあります。フラッシュメモリの詳細については、次のリファレンスを参照してください。フラッシュとEEPROMは、信頼性が低下するまでの書き込みサイクル数が限られていることに注意してください。
回答
行列がほとんど空であるか、プログラムで計算できる値がある場合は、スパースアレイが助けになるかもしれません。メモリの割り当てとホッピングが必要なため、個々の要素へのアクセス時間は決定論的ではありませんが、最悪のシナリオを計算できます。
回答
これは私がUnoに与えたものです:
#define IMAGEWIDTH 56 #define IMAGEHEIGHT 96 void setup() { Serial.begin(9600); int i, j; int image_result[IMAGEWIDTH][IMAGEHEIGHT]; for (i = 0; i < IMAGEWIDTH; i++) { Serial.print("\nIMAGEWIDTH "); Serial.print(i + 1); Serial.println(":"); for (j = 0; j < IMAGEHEIGHT; j++) { image_result[i][j] = i + j; Serial.print("image_result["); Serial.print(i + 1); Serial.print("]["); Serial.print(j + 1); Serial.print("]: "); Serial.println(image_result[i][j]); } } Serial.println(F("\nDone!")); } void loop() { }
これアレイ全体で実行され、進行状況はシリアルで出力され、「完了!」と出力されます。一度です。変更することをお勧めします:
#define IMAGEWIDTH 56 #define IMAGEHEIGHT 96
良い値がいくつかない限り、値を小さくします手元の分。
コメント
- これは彼の問題を解決することにはなりません。 '時間ではなく、配列のサイズです。 56 * 96 * 2(intは2バイト)は10752バイトを使用します。あなたの宇野は2048バイトです。問題は時間ではなく、ストレージです。
- ニックは正しかった、これは私の問題を解決していません'。とにかく、試してくれてありがとう。