変数名にテキストを追加する:このコードを短縮してください

私は外部EEPROMから読み込まれている120以上の変数を持つ以下の "setup"のコードを短縮しようとしています。 EEPROMアドレスの位置を格納する変数には、配置される変数の名前に "Pos"という文字列を加えたパターンがあります。

byte fanSpeed, nl1Toggle, ledsToggle;
byte fanSpeedPos = 12, nl1TogglePos = 95, ledsTogglePos = 7;

void setup() {
  fanSpeed = readEE(fanSpeedPos);
  nl1Toggle = readEE(nl1TogglePos);
  ledsToggle = readEE(ledsTogglePos);
  //there are over 120 of the above readEE statements in the actual code.
}

uint8_t readEE(uint8_t entry) {
  readEEPROM(AT24C32_ADDRESS, 1, entry);
}

理想的には、私はこのように動作するようにしたいと思います(これを行う方法がわからないので疑似コードを使用しています):

char* variableNames [] = { "fanSpeed", "nl1Toggle", "ledsToggle" };
byte fanSpeedPos = 12, nl1TogglePos = 95, ledsTogglePos = 7;

void setup() {
  for (int i = 1; i < 120; i++;) {
    variableNames[i] = readEE(variableNames[i] + 'Pos');
  }

これはC ++/Arduinoを使って可能ですか?

1
EEPROM変数をRAMにコピーする(つまり、文字配列にコピーする)。次に、 strcat を使用して単語の末尾に単語を追加します。終了した単語と0x00バイトの終端に十分な余裕を持たせます。
追加された 著者 Nick Gammon,

2 答え

これは単純なプリプロセッサマクロで実現できます:

#define readEE(VAR) VAR = readEEPROM(AT24C32_ADDRESS, 1, VAR ## Pos)

あなたは次に使用することができます:

readEE(foo);

それは次のように展開されます:

foo = readEEPROM(AT24C32_ADDRESS, 1, fooPos);

マクロの ## 演算子は、両辺(VARとPos)を展開し、結果を連結します。 VAR自体はマクロなので(マクロを呼び出すときに渡すもの)、その値で置き換えられますが、Posではマクロではないため、Posのままです。だからあなたの変数名は、単語Posと連結して終わる。

変数名は配列内の変数名を持つループで使用することはできません - 変数名はコンパイルされたコードではなくソースコードにのみ存在するため、これらの変数名では何もできません。コンパイルされた。したがって、プリプロセッサを使用してジョブを実行する必要があります。

はい、120変数すべてに対して120行のコードを書く必要がありますが、 readEE(varname); に短縮されています。

しかし、もっと良い解決策はMikaelのstructメソッドを使うか、単に配列を使って名前の概念について違った考えをすることです:

uint8_t data[120];
for (int i = 0; i < 120; i++) {
    data[i] = readEEPROM(AT24C32_ADDRESS, 1, i);
);

したがって、すべての変数の値は data [] 配列にあり、プログラム内でどの値がどの値であるかを知るだけで済みます。そして、各位置の名前をプリプロセッサマクロ:

#define FAN_SPEED 12
#define N1_TOGGLE 95
#define LEDS_TOGGLE 7

次に、数値の代わりにそれらのマクロを使用します。

Serial.println(data[FAN_SPEED]);

あるいは、マクロを使用して変数名を「マスク」することもできます。

#define fanSpeed data[12]
#define n1Toggle data[95]
#define ledsToggle data[7]

あなたが気づいたかもしれないことが1つあります:ここではあなたのコードを短縮するものはありません。 120の場所に120個の変数が格納されています。あなたが何をしても、それらの変数とその場所に何らかの形の120個のポインタが必要です。あなたが本当に行うことができるのは、コードを見ている誰かが何が起こっているのかを理解できるように、最も可読性が高いメソッドを選択することです。あなたが何をしているにしても、定義や設定を行う変数や変数名のリストがたくさんあります。これはたくさんの型付けを意味します。

3
追加された
簡潔な "大きな写真"の概要に感謝します。私はすべての方法について学ぶのが大好きでした。私は私の最初の試みはプリプロセッサマクロを使っていると思います。なぜなら、変数の書き方や名前を変更することなく、コードを短く/簡略化することです(私の主目的でした)。変数を格納する方法を変更すると、何百行ものコードを修正する必要があります。これは、将来的には時間/野心があれば実験するかもしれません。
追加された 著者 Alex Rigos,
私はちょうど私のコードにプリプロセッサのソリューションを追加し、それは邪魔をすることなく美しく動作しました。これは本当に問題に対する非常に理想的な解決策でした。ありがとう。
追加された 著者 Alex Rigos,
プリプロセッサのソリューションは本当にいいですね。
追加された 著者 Mikael Patel,
variableNames[i] = readEE(variableNames[i] + 'Pos');

これはC ++/Arduinoを使って可能ですか?

いいえ!実行時に多くの情報を必要とするため、プログラミング言語がほとんどできません。

代わりに問題を再訪しましょう。 EEPROM から大量の変数セットを読み込みます。これを助けることができるC/C ++やAVRライブラリのメカニズムは?

ここでは、「ワンライナー」という結果をもたらす本当にシンプルなソリューションがあります。 eeprom_read_block()。

struct var_t {
  byte fanSpeed, nl1Toggle, ledsToggle;
};
var_t var;
const void* pos = ...;
eeprom_read_block(&var, pos, sizeof(var));

明らかに var_tvar はあまり良い名前ではありませんが、内部EEPROM用ですが、同じテクニックをI2C EEPROM

乾杯!

BW:どのAT24CXXXライブラリを使用していますか?これは奇妙に見えるので。

 uint8_t readEE(uint8_t entry) {
   readEEPROM(AT24C32_ADDRESS, 1, entry);
 }

返品明細書等はありません

3
追加された
答えをありがとう!これは私のために少し複雑すぎるので、私はそれがもっと明確になる前に(私はもっと勉強しなければならない@Nick Gammonのコメントについても同じように)勉強しなければなりません。 AT24CXXXはDS3231 RTCボード上​​にあります。私は、Dueと一緒に動作するDS3231ライブラリを探すために、あまり一般的でないDS3231ライブラリのいくつかを見なければならないと思います(ATmegasで動作するものを見つけるのは簡単でした)。私が使用したコードは、 github.com/kriswiner/DS3231RTC にあります。私はまだそれが期限に働くためにいくつかの変更を加えなければならなかったと思うが、私は正確に覚えていない。
追加された 著者 Alex Rigos,