私は学校のプロジェクトでそれをやっていますが、コンポーネントを購入する前にいくつか質問があります。
まず最初に、どのように動作するかを説明しましょう。
4x20 LCD、Arduino、おそらく2つのポテンショメータがあります(ポテンショメータの感度のため)。ユーザーがポテンショメータを回すと、感度の問題のために、最初のポテンショメータの値がもう一方のポテンショメータの値に加算されます。次に、プログラムは2つのポテンショメータの値に対応する要素をチェックします。
その後、プログラムはその要素の情報をLCDに表示します(名前、記号、中性子数、陽子数、価電子など)。
質問:
周期表には118元素があります。私はプログラミングの専門家ではありませんが、これは118の if
ステートメントの内部を短くすることはできますが、 if
ステートメントは118個あります。私はそれがArduinoの記憶(スケッチサイズ制限)を超えてしまうのではないかと恐れています。コードをどのように短縮できますか?
メガを買うべきか、それとも十分にうまくいくのだろうか?
ポテンショメータと4x20バックライトの両方に5V Arduinoピンを接続すると問題はありますか?そうでない場合は、どうすれば修正できますか?私はArduino以外の電源を使用したくないです。
あなたの質問に対する私のコメントからの答えを広げる:
まず、必要なすべてのデータを保持する構造体を定義することです 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のフラッシュが不足しています。
おそらくメガは必要ありませんが、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画面がナンセンスを表示している場合は、まずそれを見て/デバッグする必要があります。
定期的なテーブルのデータを手動でプログラムに入れるのではなく、ソフトウェア開発用のコンピュータ上のプログラムを使用して周期的なテーブルのデータファイルを読み込んで対応する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
に追加することができます。後で示す。
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でファイルを読み書きするページを参照してください。
densconmelt.py
によって生成されたファイルからのいくつかの行は、これらの行が何をしているのかに関するコメントが散在しています。その後、 datatables.data.c
ファイル全体が表示されます。
#ifdef ADDTABLE //Disallows separate compile
この行は、 datatables.data.c
が単独でコンパイルされないようにするプリプロセッサ文です。コンパイル時に、Arduino IDEは datatables.ino
と datatables.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」のような行ラベルに表示されます。