大好きArduino

Arduino総合情報サイト

Arduinoの動きが急におかしくなるメモリー不足

2018/11/25

さっきまで動いていたのに何かを付け加えた途端、急に動作がおかしくなることがよくあります。
そんなときはだいたいがメモリーを使いすぎて残りが少ないときです。
コンパイルの結果まだ数%のこっているにも関わらず、こんな現象がよく置きます。

今日は digitalWriteがいったいどれだけプログラム領域を圧迫するのかを調べてみました。
作ったプログラムは下記のような単純なもので、使用したボードはArduinoLeonardo。
動作は実に簡単で、Leonardoの13番ピンについているLEDをチカチカ1秒ごとにさせるもので実験です。

スポンサードサーチ


1ポートのみの比較

まずはごく普通にpinModeとdigitalWriteを使って書いてみる。

void setup() {
    pinMode(13,OUTPUT) ;
}
void loop() {
    digitalWrite(13,HIGH) ; 
    delay(1000); 
    digitalWrite(13,LOW) ; 
    delay(1000); }

コンパイル後に表示されたサイズは、
最大28672バイトのフラッシュメモリのうち、スケッチが4128バイト(14%)を使っています。
そしてhexファイルのサイズは11,636バイトだった。

次にポート直接でたたいてみる。

 
void setup() { 
    DDRC = DDRC | B11111111; 
}
void loop() {
    PORTC = B10000000;
    delay(1000) ;
    PORTC = B01111111; 
    delay(1000) ;
}

コンパイル後に表示されたサイズは、
最大28672バイトのフラッシュメモリのうち、スケッチが3740バイト(13%)を使っています。
そしてhexファイルのサイズは10,548バイトだった。

実に、ポート直接たたくだけでプログラムサイズは388バイト小さくなる

全ポートの比較

まずはforで回さないでべた書きをしてみる

void setup() {
   pinMode(0,OUTPUT) ;
   pinMode(1,OUTPUT) ;
   pinMode(2,OUTPUT) ;
   pinMode(3,OUTPUT) ;
   pinMode(4,OUTPUT) ;
   pinMode(5,OUTPUT) ;
   pinMode(6,OUTPUT) ;
   pinMode(7,OUTPUT) ;
   pinMode(8,OUTPUT) ;
   pinMode(9,OUTPUT) ;
   pinMode(10,OUTPUT) ;
   pinMode(11,OUTPUT) ;
   pinMode(12,OUTPUT) ;
   pinMode(13,OUTPUT) ;
}
void loop() {
   digitalWrite(0,HIGH) ;
   digitalWrite(1,HIGH) ;
   digitalWrite(2,HIGH) ;
   digitalWrite(3,HIGH) ;
   digitalWrite(4,HIGH) ;
   digitalWrite(5,HIGH) ;
   digitalWrite(6,HIGH) ;
   digitalWrite(7,HIGH) ;
   digitalWrite(8,HIGH) ;
   digitalWrite(9,HIGH) ;
   digitalWrite(10,HIGH) ;
   digitalWrite(11,HIGH) ;
   digitalWrite(12,HIGH) ;
   digitalWrite(13,HIGH) ;
   delay(1000);
   digitalWrite(0,LOW) ;
   digitalWrite(1,LOW) ;
   digitalWrite(2,LOW) ;
   digitalWrite(3,LOW) ;
   digitalWrite(4,LOW) ;
   digitalWrite(5,LOW) ;
   digitalWrite(6,LOW) ;
   digitalWrite(7,LOW) ;
   digitalWrite(8,LOW) ;
   digitalWrite(9,LOW) ;
   digitalWrite(10,LOW) ;
   digitalWrite(11,LOW) ;
   digitalWrite(12,LOW) ;
   digitalWrite(13,LOW) ;
   delay(1000);
 }



コンパイル後に表示されたサイズは、
最大28672バイトのフラッシュメモリのうち、スケッチが4444バイト(15%)を使っています。
そしてhexファイルのサイズは12,528 バイトだった。

これを forでまわすと

void setup() {
   for(int i=0;i<=13;i++){
       pinMode(i,OUTPUT) ;
   }
}
void loop() {
   for(int i=0;i<=13;i++){
       digitalWrite(i,HIGH) ;
   }
   delay(1000);
   for(int i=0;i<=13;i++){
       digitalWrite(i,LOW) ;
   }
   delay(1000);
}

コンパイル後に表示されたサイズは
最大28672バイトのフラッシュメモリのうち、スケッチが4178バイト(14%)を使っています。
そしてhexファイルのサイズは11,775 バイトだった。
べた書きより266バイト減った。

ポート直接でやってみる。

void setup() {
DDRC = DDRC | B11111111;
DDRB = DDRB | B11111111;
DDRD = DDRD | B11111111;
}
void loop() {
PORTC = B11111111;
PORTB = B11111111;
PORTD = B11111111;
delay(1000) ;
PORTC = B01111111;
PORTB = B01111111;
PORTD = B01111111;
delay(1000) ;
}

コンパイル後に表示されたサイズは
最大28672バイトのフラッシュメモリのうち、スケッチが3756バイト(13%)を使っています。
そしてhexファイルのサイズは10,593 バイトだった。

ポートべた書きより688バイト減り、forで回すものより422バイト減った。

すぐに足りなくなるプログラム領域

Arduinoの関数は使いやすくていいのですが、この実験のように結構なプログラム領域を食います。
しかもdigitalWriteはポート直接よりおそいのですから、メンテナンス性が少し悪くなっても、大きなプログラムが予測される場合はポート直接制御のほうがいいかもしれませんね。

メモ

フラッシュメモリー プログラム・ブートローダ・読み取り専用ユーザデーターを格納
SRAM レジスター・ユーザーデータ

フラッシュ専用ユーザーデータとは....

通常プログラム内で使用する変数はSRAM側で操作されるのだが、あえてフラッシュメモリー側に焼きこむことができる。
このデータは、不揮発性部分にプログラムと一緒に記憶されるため意図的に書き換わったり変化したりなくなることはない。
EEPROMとほぼ同じ役目をしますが、取り扱いが通常の変数のように簡単だけど....プログラム領域を圧迫してしまうので、取り扱いは注意が必要です。

-プログラミング