私はArduinoの助けを借りて定期的なテーブルを作るつもりですが、いくつか質問があります

私は学校のプロジェクトでそれをやっていますが、コンポーネントを購入する前にいくつか質問があります。

まず最初に、どのように動作するかを説明しましょう。

4x20 LCD、Arduino、おそらく2つのポテンショメータがあります(ポテンショメータの感度のため)。ユーザーがポテンショメータを回すと、感度の問題のために、最初のポテンショメータの値がもう一方のポテンショメータの値に加算されます。次に、プログラムは2つのポテンショメータの値に対応する要素をチェックします。

その後、プログラムはその要素の情報をLCDに表示します(名前、記号、中性子数、陽子数、価電子など)。

質問:

  • 周期表には118元素があります。私はプログラミングの専門家ではありませんが、これは118の else if ... ステートメントが存在することを意味します。関数によって if ステートメントの内部を短くすることはできますが、 if ステートメントは118個あります。私はそれがArduinoの記憶(スケッチサイズ制限)を超えてしまうのではないかと恐れています。コードをどのように短縮できますか?

  • メガを買うべきか、それとも十分にうまくいくのだろうか?

  • ポテンショメータと4x20バックライトの両方に5V Arduinoピンを接続すると問題はありますか?そうでない場合は、どうすれば修正できますか?私はArduino以外の電源を使用したくないです。

1
Unoでは、要素あたり約100〜150バイトをPROGMEM配列として格納できる必要があります。それはあなたのLCDの一ページ以上です。また、2つのポットの代わりにロータリーエンコーダを使用することもできます。
追加された 著者 Sprogz,
@Gerben:この使用例では、配列は長い switch-case よりもはるかに適切です。
追加された 著者 Sprogz,
要素のすべてのデータを保持する構造体を定義し、必要なすべてのデータを保持できるような構造体を118個配列します。次に、プログラムは配列をブラウズして、ユーザーが選択した要素のデータを抽出して出力します。どのようにデータを整理できるかを示す基本的な例を書くことができますが、24時間前には時間がありません。
追加された 著者 Sprogz,
if の代わりに switch-case を見てください
追加された 著者 Al.,
配列とPROGMEMの使い方を学んでください。 Arduino PlaygroundにGoogleを使っているなら、それはすべてです。
追加された 著者 Majenko,
手掛かりは「PROGMEM」という言葉に...
追加された 著者 Majenko,
@EdgarBonet 10ターン10kohmのポットも私の意見でそれを行う必要があります。あなたは私がどこで配列を使うべきかについてのヒントを与えることができますか? progmemはRAMの代わりにアレイのデータを通常のメモリ(32kb)に格納しますか?
追加された 著者 iThek,

4 答え

あなたの質問に対する私のコメントからの答えを広げる:

まず、必要なすべてのデータを保持する構造体を定義することです 1つの要素の保存と表示:

struct Element {
    char symbol[3];
    char name[16];
    float mass;
    char electronic_state[9];
   //etc...
};

原子番号はインデックスから推測されるので保存しないでください 構築する配列。この構造体の各文字列(symbol、name ...) 可能な限り長い文字列を格納するのに十分な大きさでなければなりません。 最終的なNULLターミネータ。コンパイラはここであなたを助けます: 十分な部屋を確保すると、後で "エラー: chars配列の初期化子文字列が長すぎます "。

各文字列に最大値を割り当てることは明らかにいくぶん非効率的です 可能な長さ。簡単にするためにこれを行うことをお勧めします。 私はあなたが宇野であっても、フラッシュが不足しているとは思わないからです。もし あなたは本当にフラッシュで短くなってしまいます jwpat7の答えを考えてください。やや複雑ですが、そうである可能性があります フラッシュ使用の点で私よりもはるかに効率的です。

2番目のステップは、周期表をPROGMEM配列として書き留めることです。

const Element periodic_table[] PROGMEM = {
   //symbol  name    mass      electronic state
    {"H",  "Hydrogen", 1.008,    "1s1"     },
    {"He", "Helium",   4.002602, "1s2"     },
    {"Li", "Lithium",  6.94,     "[He] 2s1"},
   //etc...
};
const size_t table_length = sizeof periodic_table/sizeof *periodic_table;

次に、あなたのプログラムは、このテーブルを順番にブラウズするだけです 必要な情報を得る。ここで厄介なのは、あなたが それを使用する前にRAMにデータをコピーする必要があります。 何かのようなもの:

Element elt; //element in RAM
memcpy_P(&elt, &periodic_table[i], sizeof elt);

私はLCDを持っていないので、私は単にテストプログラムを書きました。 シリアルポートを介してテーブル:

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.println(F("Z  Symbol  Name  Atomic mass  El. state"));
    Serial.println(F("---------------------------------------"));
    for (size_t i = 0; i < table_length; i++) {
        Element elt; //element in RAM
        memcpy_P(&elt, &periodic_table[i], sizeof elt);
        Serial.print(i+1); //Z = i+1
        Serial.print(F("    "));
        Serial.print(elt.symbol);
        Serial.print(F("     "));
        Serial.print(elt.name);
        Serial.print(F("  "));
        Serial.print(elt.mass);
        Serial.print(F("  "));
        Serial.println(elt.electronic_state);
    }
    Serial.println();
    delay(1000);
}

このプログラムは4480バイトのフラッシュしか必要としません。これは私が展開できることを意味する テーブルを118個の要素に、200バイトを超える要素を前に Unoのフラッシュが不足しています。

2
追加された

定期的なテーブルのデータを手動でプログラムに入れるのではなく、ソフトウェア開発用のコンピュータ上のプログラムを使用して周期的なテーブルのデータファイルを読み込んで対応するC-プログラムデータ構造。

以下に示すpythonプログラムは、そのアプローチの例を示しています。 (データテーブルはタプルのリストに含まれています。つまり、データは読み込まれませんが、タプルのようなデータはファイルから読み込むことも、プログラミングの一部で< a href = "http://www.meta-synthesis.com/webbook/35_pt/pt_database.php?PT_id=194" rel = "nofollow">周期表データのスプレッドシートを参照してください)。

Pythonプログラムは出力のために datatables.data.c というファイルを開き、そのファイルにCの文を書き出します。その後、そのファイルをスケッチ datatables.ino に追加することができます。後で示す。

Pythonプログラム、 densconmelt.py

#!/usr/bin/python
# From data as shown in slide 19 of 39 at
# http://www.slideshare.net/bravetiger1964/lecture-11-metals-and-its-alloys-their-crystalline-structure-and-properties

# Physical Properties of several Metals and Alloys.
#   Metal or Alloy
#     Density (kg/m3) 
#       Thermal conductivity W/(m*K) (t=20 C)
#         Melting point (Tm) (C)
adtm = [
    ('Aluminum', '2712', '204', '659'),
    ('Aluminum alloys', '7700-8700', '120-180', '462-671'),
    ('Brass-casting', '8400-8700',  '',  '990-1025'),
    ('Red Brass',     '8746', '159', '1027'),
    ('Yellow Brass',  '8470', '115', '930'),
    ('Bronze - lead', '7700-8700', '',  '850-1000'),
    ('Copper', '8930', '385', '1083'),
    ('Gold', '19320',  '318', '1063'),
    ('Pure iron',     '6800-7800', '72', '1530'),
    ('Cast Iron',     '7850', '', 'Gray 1370, Malleable 1360, White 1370'),
    ('Wrought Iron',  '7750', '58', '1450'),
    ('Lead',  '11340', '35.3', '327'),
    ('Nickel', '8800', '89', '1453'),
    ('Silver', '10490', '406', '961'),
    ('Solder 50/50 Pb/Sn', '8885', '', ''),
    ('Non-alloyed and low-alloy steel', '7850', '53.6', '1480'),
    ('Stainless Steel', '7480-8000', '12.11-45.0', '1430-1500'),
    ('Tin',  '7280', '63', '232'),
    ('Zinc', '7135', '115', '419')
    ]

locs = []
# To track current offset into datatext, and longest single string part
used = longy = 0 
with open('datatables.data.c', 'w') as fo:
    fo.write('#ifdef ADDTABLE //Disallows separate compile\n')
    fo.write('const char datatext[] PROGMEM = \n  ')
    for i in adtm:
        #a, d, t, m = i
        #print '{:20} {:12} {:12} {:12}'.format(a, d, t, m)
        for x in i:
            locs.append(used)
            used += len(x)+1
            longy = max(longy, len(x)+1) 
            fo.write('"{}\\0" '.format(x))
        fo.write('\n  ')
    fo.write(';\nconst int offsets[] = {')
    for o in locs:
        fo.write(' {},'.format(o))
    fo.write(' {}{};\n'.format(used, '}'))
    fo.write('enum {} LONGSTR={}, ITEMS={}{};\n'.format('{', longy, len(adtm), '}'))
    fo.write('char buffy[LONGSTR];\n')
    fo.write('#endif\n')

注釈付きの行

        #a, d, t, m = i
        #print '{:20} {:12} {:12} {:12}'.format(a, d, t, m)

Pythonプログラムを修正するのに適した場所になりますので、4x20 LCDに表示されたときの線がどのように見えるかを表示します。あなたのUnoやMegaにファイルを繰り返しダウンロードするのではなく、ちょっと長すぎたり、整列していない行を修正したりするのではなく、Pythonプログラムで同じループに表示されるようにして、 Arduinoのスケッチ。

with の構文に精通していない場合は、pythonforbeginners.comの Pythonでファイルを読み書きするページを参照してください。

Pythonプログラムが生成するもの:

densconmelt.py によって生成されたファイルからのいくつかの行は、これらの行が何をしているのかに関するコメントが散在しています。その後、 datatables.data.c ファイル全体が表示されます。

#ifdef ADDTABLE //Disallows separate compile

この行は、 datatables.data.c が単独でコンパイルされないようにするプリプロセッサ文です。コンパイル時に、Arduino IDEは datatables.inodatatables.data.c を一時作業ディレクトリにコピーし、それぞれをコンパイルします。しかし、 datatables.data.c の本文は、(スケッチの外で)単独では正しくコンパイルされないので、 #ifdef ... #endif 行にあります。

const char datatext[] PROGMEM =

この行は、 datatext [] の値をプログラムメモリに格納するようにCコンパイラに指示します。 datatext の値と内容は定数で、 datatext は文字の配列です。

  "Aluminum\0" "2712\0" "204\0" "659\0" 
  "Aluminum alloys\0" "7700-8700\0" "120-180\0" "462-671\0" 
  "Brass-casting\0" "8400-8700\0" "\0" "990-1025\0" 
...
  "Tin\0" "7280\0" "63\0" "232\0" 
  "Zinc\0" "7135\0" "115\0" "419\0" 
  ;

これらの線はそれぞれ、金属または合金の名前、密度、熱伝導率、および融点を示す。値は数値ではなく文字列なので、範囲と欠損値を扱うことができます。 Cの規則では、演算子のない文字列同士を連結していることに注意してください。たとえば、 "Tin \ 0" "7280 \ 0" "63 \ 0" "232 \ 0" の行は、 "Tin \ 07280 \ 063 \ 0232 \ 0 "\ 0 は、部分文字列の最後にヌル文字であることに注意してください。スペースが足りない場合は、 \ 0 をすべて省略して、 offset [] の隣接エントリの違いとして計算することができます。

const int offsets[] = { 0, 9, 14, ... 524, 528, 533, 538, 542, 546};

その行は、大きな文字列 datatext の中で各部分文字列の始まりを示します。オフセットと部分文字列を格納するこの方法は、1項目につき12バイト、すなわち4つの int の値の4・2バイトとヌル文字の4バイトを使用します。オーバーヘッドを1項目あたり5〜10バイトに減らす方法は6つありますが、最も効果的な単純な変更はPROGMEMに offset [] を置くことです。さらに、項目のレコードの前に固定オフセットで配置されている場合は、ヌル区切り文字やオフセット値を必要としない、フィールドを文字列から整数または浮動小数点に変更することがあります。

enum { LONGSTR=38, ITEMS=19};
char buffy[LONGSTR];
#endif

これらの行は、LONGSTRとITEMSという2つの定数を作成し、最長部分文字列の長さと項目数を示します。最も長い部分文字列である限り、バッファを割り当てます。ガード #ifdef ... #endif を閉じます。

datatables.data.c, shown whole:

#ifdef ADDTABLE //Disallows separate compile
const char datatext[] PROGMEM = 
  "Aluminum\0" "2712\0" "204\0" "659\0" 
  "Aluminum alloys\0" "7700-8700\0" "120-180\0" "462-671\0" 
  "Brass-casting\0" "8400-8700\0" "\0" "990-1025\0" 
  "Red Brass\0" "8746\0" "159\0" "1027\0" 
  "Yellow Brass\0" "8470\0" "115\0" "930\0" 
  "Bronze - lead\0" "7700-8700\0" "\0" "850-1000\0" 
  "Copper\0" "8930\0" "385\0" "1083\0" 
  "Gold\0" "19320\0" "318\0" "1063\0" 
  "Pure iron\0" "6800-7800\0" "72\0" "1530\0" 
  "Cast Iron\0" "7850\0" "\0" "Gray 1370, Malleable 1360, White 1370\0" 
  "Wrought Iron\0" "7750\0" "58\0" "1450\0" 
  "Lead\0" "11340\0" "35.3\0" "327\0" 
  "Nickel\0" "8800\0" "89\0" "1453\0" 
  "Silver\0" "10490\0" "406\0" "961\0" 
  "Solder 50/50 Pb/Sn\0" "8885\0" "\0" "\0" 
  "Non-alloyed and low-alloy steel\0" "7850\0" "53.6\0" "1480\0" 
  "Stainless Steel\0" "7480-8000\0" "12.11-45.0\0" "1430-1500\0" 
  "Tin\0" "7280\0" "63\0" "232\0" 
  "Zinc\0" "7135\0" "115\0" "419\0" 
  ;
const int offsets[] = { 0, 9, 14, 18, 22, 38, 48, 56, 64, 78, 88, 89, 98, 108, 113, 117, 122, 135, 140, 144, 148, 162, 172, 173, 182, 189, 194, 198, 203, 208, 214, 218, 223, 233, 243, 246, 251, 261, 266, 267, 305, 318, 323, 326, 331, 336, 342, 347, 351, 358, 363, 366, 371, 378, 384, 388, 392, 411, 416, 417, 418, 450, 455, 460, 465, 481, 491, 502, 512, 516, 521, 524, 528, 533, 538, 542, 546};
enum { LONGSTR=38, ITEMS=19};
char buffy[LONGSTR];
#endif

プログラムメモリからアイテムデータを取得して表示するためのスケッチ:

上記のように densconmelt.py を使用して datatables.data.c を生成しました。プログラムのメモリからアイテムのデータを取り出して表示するスケッチが表示されます。スケッチがシリアル入力で項目番号を受け取るたびに

// Sketch that accepts a number via serial input, and responds with
// two lines of data via serial output.  The reply-data consists of an
// Alloy name on the first line, and Density, Thermal conductivity,
// and Melting point on the next line.

// See http://arduiniana.org/libraries/streaming/ for Streaming library
#include 
// This sets up datatext in PROGMEM; offsets[]; buffy; LONGSTR; ITEMS
#define ADDTABLE
#include "./datatables.data.c"

void setup() {
  Serial.begin(115200);        //init serial port
}

void loop() {
  Serial << "Please enter item number from 1 to " << _DEC(ITEMS) << ": ";
  int item = 0;
  while (1) {
    while (!Serial.available()) {};//Wait for a character
    int c = Serial.read();
    if (c == '\n') break;
    item = 10*item + c - '0';
  }
  if (item < 1 || item > ITEMS) {
    Serial << item << endl << item << " is out of range -- try again.\n";
    return;
  }
 //Display specified item's title on first line
  strcpy_P(buffy, datatext + offsets[item*4-4]);
  Serial << item << endl << "Item #" << item << ", " << buffy << endl;
 //Show other data items on next line
  strcpy_P(buffy, datatext + offsets[item*4-3]);
  Serial << "Density " << buffy;
  strcpy_P(buffy, datatext + offsets[item*4-2]);
  Serial << "   Thermal cond. " << buffy;
  strcpy_P(buffy, datatext + offsets[item*4-1]);
  Serial << "   [email protected] " << buffy << " C" << endl << endl;
}

strcpy_P()引数については、nongnu.orgの avr/pgmspace.h:プログラムスペースユーティリティ ]ページを開きます。

PROGMEMの概要については、arduino.ccの PROGMEM ページをご覧ください。

avrfreaks.netの GCCとPROGMEM属性については、 PROGMEMの詳細については> aページを、Nick Gammonの PROGMEMのプログラムメモリに定数データを入れるページも同様です。

シリアルモニタボックスのように、プログラム出力の例:

以下は、入力行に複数の数字を入力し、それぞれの後にEnterを押した後の、シリアルモニタボックスに表示されるプログラム出力の例です。 (シリアルモニタボックスの一番下にある行末を改行に設定し、データレートを115200 bpsに設定します)。

Please enter item number from 1 to 19: 18
Item #18, Tin
Density 7280   Thermal cond. 63   [email protected] 232 C

Please enter item number from 1 to 19: 19
Item #19, Zinc
Density 7135   Thermal cond. 115   [email protected] 419 C

Please enter item number from 1 to 19: 20
20 is out of range -- try again.
Please enter item number from 1 to 19: -2220
-2220 is out of range -- try again.
Please enter item number from 1 to 19: 2
Item #2, Aluminum alloys
Density 7700-8700   Thermal cond. 120-180   [email protected] 462-671 C

Please enter item number from 1 to 19: 0
0 is out of range -- try again.
Please enter item number from 1 to 19: 5
Item #5, Yellow Brass
Density 8470   Thermal cond. 115   [email protected] 930 C

Please enter item number from 1 to 19: 

スケッチはユーザー入力アイテム番号を2回エコーします。したがって、各入力勧誘の最後に、「Item#5、Yellow Brass」のような行ラベルに表示されます。

1
追加された
@ÇayÖncesi、スケッチはイラストレーションのためだけにシリアルを使います - あなたはロータリーエンコーダーかポットを入力用に、LCDを出力用に置き換えます。開発システムのプリプロセッサ(Pythonで書かれたコードジェネレータ、Cなど)を使用していなくても、Arduinoコードを図示のように整理することができます。
追加された 著者 Martin C. Martin,
それは複雑に思えます。私は考えを持っていますが、私はPython構文、ステートメントについては何も知らないし、arduino以外の外部デバイスを運ぶこともできません。 arduinoと電気部品だけ。アイデアのためのThx
追加された 著者 iThek,

おそらくメガは必要ありませんが、Arduinoと一緒にいじったり、より大きなプロジェクトに取り掛かったりしたい場合は、長期投資として考えてください。

残念ながら、すべてのコードを入力するのは非常に面倒です。しかし、すべての要素名の文字列に対して別々の配列を作ることができます:

https://stackoverflow.com/questions/1088622/ how-do-i-create-an-string-in-c

また、すべての数値データに対して対応する配列を作成することができます。

次に、信号を取って、信号を使って1-118の整数を得る方法を理解し、それを整数(iと言う)に書いて、name [i]、symbol [i]中性子[i]などをLEDスクリーンに表示します。

最も困難なことは、ポテンショメータを回すという点で2つの要素の間の遷移が自然に感じられるように、数学を行うことです。

あなたの数学がどうにかして200を生成するならば、名前[200]はメモリからあなたのLEDスクリーンに無作為に値を書き込むでしょう。おもう。あなたのLED画面がナンセンスを表示している場合は、まずそれを見て/デバッグする必要があります。

1
追加された
答えのために、私はおそらく増分ロータリーエンコーダを購入するでしょう。しかし、私はR.E.を設定することはできません。私は鍋で行く。配列は私の心に以前には来なかったが、今は配列がうまくいくことを理解している。私はメガを買うだろう、私は安いものを見つけた(非クローン)。再びThx
追加された 著者 iThek,

私はあなたがメガを購入しなければならないかもしれないと思う(おそらくより高価!)

i also fear someone putting countless nights into coding (preferably on pc for me, because 1: sketch is only available as an ancient version on raspberrypi. & 2: easier transfer of code.)

0
追加された
メガがより良い選択になる理由を説明してください。
追加された 著者 user67244,
私はこのプロジェクトと将来のためにメガを買うつもりです
追加された 著者 iThek,