google-site-verification: google3bd66dd162ef54c7.html

ArduinoにSDメモリーカードを接続する実験

 最近は無線LANでデーターを飛ばして適当なサーバーに保存するのが流行っています。確かに便利ですが、SDメモリーカードにデーターを保存して、自己完結型にするのも悪くない方法だと思います。

 実はこの間から取り組んでいる電力量計の測定結果をロギングする方法について検討していますが、SDメモリーカードにデーターを保存するのが使い易いかな、と思っています。実は以前気圧ロガーを作った時にSDメモリーカードを使いましたが、この時はとにかく動かすことを優先したので、作り込みがちょっと甘いところがあって気になっていました。

 そんなことで、インターフェイスレベルからもう一度確認していくことにします。

 SDカードの接続アダプタはいろいろありますが、今回は秋月で売っているSDカードスロットDIP化モジュールを使うことにしました。

▼秋月のSDカードアダプタ
秋月のSDカードアダプタ
 標準サイズのSDカード用のアダプタです。なおこの写真は東芝のSDメモリーカードが挿さった状態です。

▼SDカードアダプタの回路図 (秋月の資料から抜粋)
秋月のSDカード接続アダプタ
 ボード上に3.3Vのレギュレータが実装されているので使い易いです。当然J1を接続して使います。すべての信号線が10kΩで+3.3Vにプルアップされています。

 Arduino UNOは5Vで動いているので信号を3.3Vに変換する必要があります。10kΩの抵抗はそのままにして数百Ωの抵抗で分圧する方法が判り易いですが、ネットを調べると抵抗はそのままでダイオードを使った事例がありました。ちなみに以前私が分圧抵抗方式で動かした時の記事はこちら。

▼ダーオードを使ったレベル変換回路
5V to 3.3Vレベル変換回路
 ダイオードを直列に入れるだけの簡単な回路です。プルアップ抵抗(Rp)はアダプタ内蔵の物を使うと10kΩになります。これでSDのサンプルプログラムは動いたのですが、いくらなんでも10kΩは高すぎると思うので波形を見てみました。

▼SDの信号波形調査中
ArduinoへSDカード接続テスト

▼Rp=10kΩの場合の波形
10kΩ
 写真が見づらいですが、上がSDA、下がクロックで、縦軸は1V/Div.です。

 案の定立ち上がりがものすごくなまっていて十分なレベルに達していません。プログラムを走らせながらプロービングすると、ハングアップすることがあるので、全くマージンが無い状態です。これではダメです。

▼Rp=750Ωの場合 (正確には750//10k)
750Ω
 10kΩに並列に750Ωを入れた状態です。縦軸は2V/Div.です。
 やや立ち上がりが遅いのとダイオードの影響でLowレベルが少し持ち上がっていますが、これくらいなら大丈夫でしょう。クロック 周波数4MHzで、クロックの立ち上がりでデーターを読んでいるようです。

▼追加のプルアップ抵抗の実装方法
プルアップ抵抗を750Ωに改造
 チップ抵抗を持っていないのでラジアル部品をこの位置に取り付けて、内部の10kΩとパラにしました。

▼全体回路図
ArduinoにSDカード接続する回路
 Arduinoと接続する場合の全体回路図です。750Ωのプルアップ抵抗はCS, SDI, CLKに入れています。右下は使い勝手を良くするためのスイッチやLEDで、この後の記事で使います。

 この回路図の状態で、Arduino IDE に入っているSDのサンプルプログラムは全て動かすことが出来ました。

◆まとめ
 ということでインターフェイス回路は大丈夫そうなので、次はSDメモリーカードロガーのプログラムを作っていきます。

 なお、いきなり電力ロガー用のプログラムを作ると汎用性が無くなってしまうので、ある程度一般的なロガープログラムを先に作りたいと思います。こうしておくとプログラムの改造が楽になるので、どなたかがが応用プログラムを書いてくださるかも知れません。

キャラクタ液晶とスイッチでパラメーター設定する関数 (Arduino)

 日の出日の入り時刻を計算で求めることが出来たので、ソーラータイマースイッチを作っているところです。ソーラータイマースイッチとは、日の出日の入り時刻に連動して動作するタイマーです。このタイマーは、例えば日の入り時刻の10分前にON、などと動作条件を細かく設定出来ると使い勝手が良くなります。

 このようなパラメーター設定を、Arduinoを使い、キャラクタ液晶と限られた数のスイッチだけで行うのは結構面倒なプログラムを書かないといけません。

 今回、ソーラータイマー用に液晶画面を使って数値を入力する関数を作りましたが、これ、けっこう汎用的に使えそうです。ということで、自分用のメモも兼ねてデモプログラムとして公開します。

▼プログラムを動かすための回路
回路図
 液晶はI2Cの16文字、2行(AQM1602)。スイッチは dec.(-)、inc.(+)、Enterの三つを使います。

◆液晶とボタン3つで値を設定するデモプログラム
/* キャラクタ液晶と押しボタンを使って数値を入力するデモ
* 液晶:AQM1602A
* 2017/7/13 ラジオペンチ http://radiopench.blog96.fc2.com/
*/

#include <I2CLiquidCrystal.h> // N. MitsunagaさんのI2C液晶ライブラリ http://n.mtng.org/ele/arduino/i2c.html

I2CLiquidCrystal lcd(30, true); // コントラスト(0-63),液晶電源(true=5V, false=3.3V)

int DecB = 8; // - (Dec) ボタンのピン指定
int IncB = 9; // +(Inc)ボタンのピン指定
int EntB = 10; // Enterボタンのピン指定

int Data1 = 0; // テスト用データー
int Data2 = 6;
void setup() {
pinMode(IncB, INPUT_PULLUP); // + (Increment)ボタン
pinMode(EntB, INPUT_PULLUP); // Enterボタン
pinMode(DecB, INPUT_PULLUP); // - (Decrement)ボタン
lcd.begin(16, 2); // 16文字2行のI2C液晶を使用
}

void loop() {
lcd.clear();lcd.print("Input sNN +-20"); // 2桁の正負の値の入力(符号付き表示)
lcd.setCursor(0, 1); lcd.print("Data1 sNN");
Data1 = lcdInput(Data1, 8, 1, -20, 20); // Data1を±20の範囲で入力(値は上下限で飽和)
lcd.clear();
lcd.print("Data1 = "); lcd.print(Data1); // 確認のために表示
delay(2000);

lcd.clear();lcd.print("Input NN 1-12"); // 2桁の整数入力(符号無し表示)
lcd.setCursor(0, 1); lcd.print("month NN");
Data2 = lcdInput(Data2, 7, 1, 1, 12); // Data2を1~12の範囲で入力(値はサーキュレート)
lcd.clear();
lcd.print("month = "); lcd.print(Data2); // 確認のために表示
delay(2000);
}

int lcdInput(int d, int x, int y, int minV, int maxV) { // 液晶表示と値の入力関数
// +-ボタンで値を変更、Enterボタンで確定
// d=初期値、x, y=液晶座標、 minV,maxV=下限上限、戻り値=入力決定値
// 下限値(minV)が負なら符号付き表示(sNN) 正なら符号無し表示(NN)を行う
// minVが正なら値をサーキュレート、minVが負なら値は上下限でストップ

lcdDisp(d, x, y, minV); // 値を表示
while (digitalRead(EntB) == LOW) { // もしEntBが押されていたら離されるまで待つ
delay(30);
}
while (digitalRead(EntB) == HIGH) { // EntBが押されていなければ以下の処理を繰り返す
if (digitalRead(IncB) == LOW) { // +ボタンが押されていたら
delay(30);
d++; // dをインクリメント
if (d > maxV ) { // 上限を超えていたら
if (minV < 0) { // minVがマイナスの場合は
d = maxV; // 上限で抑える
} else { // そうでなければ
d = minV; // 値を下限に変更(サーキュレート)
}
}
lcdDisp(d, x, y, minV); // 指定フォーマットで表示
while (digitalRead(IncB) == LOW) { // +ボタンが離されるまで待つ
}
delay(30);
}

if (digitalRead(DecB) == LOW) { // -ボタンが押されていたら
delay(30);
d--; // dをデクリメント
if (d < minV ) { // 下限を下回っていたら
if ( minV < 0) { // minVがマイナスの場合は
d = minV; // 下限で抑える
} else { // そうでなければ
d = maxV; // 値を上限に変更(サーキュレート)
}
}
lcdDisp(d, x, y, minV); // 指定フォーマットで表示
while (digitalRead(DecB) == LOW) { // -ボタンが離されるまで待つ
}
delay(30);
}
}
delay(30);
lcd.noCursor(); // 入力が終わったのでカーソルを消す
return d;
}

void lcdDisp(int d, int x, int y, int minV) { // 指定位置に2桁の値を表示する関数
// minVが正ならNN形式、負ならsNN形式
if (minV < 0) { // 負の値がある場合
lcd.setCursor(x - 2, y); // 2文字左にカーソルを移動して
if (d >= 0) { // 値が正なら
lcd.print("+"); // +を表示
} else { // それ以外(つまり負)なら
lcd.print("-"); // -を表示
d = abs(d);
}
}
lcd.setCursor(x - 1, y); // 1文字左から
if (d < 10) { // 値が10以下なら
lcd.print("0"); // 0を埋めて
}
lcd.print(d); // 値を表示
lcd.setCursor(x, y); // 1桁目にカーソル移動
lcd.cursor(); // カーソル表示
}

 このプログラムは2桁の数値の入力を行うデモになっています。カーソル(アンダーバー)が出ている位置の値(2桁)を変更します。値は inc. (+)ボタンで増加、dec. (-)ボタンで減少し、Enter ボタンで入力決定して次の処理へ進みます。

▼デモプログラムの表示
液晶の表示

 lcdInput( )関数を適当な引数を付けて呼び出すと、設定した値が関数の戻り値として帰ってきます。細かい動作はコメントに書いておいたので、興味のある方はご覧ください。なお、このプログラムは順番にゴリゴリと書いただけで、たぶん誰が描いても同じようなものになると思います。ということで、勝手に改変して使って頂いてかまいません。

◆参考
 現在作りかけのソーラータイマースイッチに使う関数のテスト用のスケッチは以下の通りです。これは上の関数を中心に、もう少し複雑な機能を入れたものです(同じ回路図で動きます)。なお、まだテスト中なのでおかしな所があるかも知れませんが、何かの参考になれば幸いです。
 ソーラータイマースイッチ設定機能テストプログラム、20170713SolarTimerSetTest.txt (拡張子をinoに要変更)

ArduinoでI2Cキャラクタ液晶を使う(その3) 最終動作確認

 ArduinoからI2Cインターフェイスのキャラクタ液晶を使う話の最終回です。前回の記事で選んだI2Cキャラクタ液晶表示ライブラリの I2CLiquidCrystal (N. Mitsunagaさん) を使って実際に表示を行ってみます。なお、このライブラリにはいろいろなサンプルが入っているのでデモプログラムには事欠かないのですが、私が特に気にしている lcd.setCursor と lcd.print について自作のテストプログラムを動かしてみます。と言っても以前作ったものをちょっと手直ししただけのものです。

 プログラム自体の説明は後回しにして、表示結果は以下の写真の通りです。なお、接続回路図は、以前の記事に掲載したものと同じです。また、ライブラリのバージョンは I2CLiquidCrystal-1.5.zip を使いました。

▼実行結果
Arduino UNOの電源電圧
 CPUチップの温度と電源電圧を連続表示します。うまくいっているようです。

 なお、CPU温度の測定精度はかなり怪しくて大きなオフセットを伴っています。つまりこの表示の絶対精度はあてになりません。但し、分解能は高くて 0.1度あるので、CPUを指で触ると温度がどんどん上がることが判ります。

▼プログラム
/* CPU温度センサーと電源電圧の読み出し、表示デモ
初版 2014/7/19
改版 2017/06/11 I2C液晶用に修正 ラジオペンチ
http://radiopench.blog96.fc2.com/
*/
#include <I2CLiquidCrystal.h> // http://n.mtng.org/ele/arduino/i2c.html
#include <Wire.h>

I2CLiquidCrystal lcd(20, true); // コントラスト(0-63),液晶電源(true=5V, false=3.3V)

void setup() {
pinMode(13, OUTPUT);
lcd.begin(16, 2);
lcd.print("Starting...");
delay(1000);
Serial.begin(9600);
}

void loop() {
float temp, Vcc;
digitalWrite(13, HIGH);
temp = cpuTemp(); // CPU温度測定
Vcc = cpuVcc(); // 電源電圧測定
digitalWrite(13, LOW);

Serial.print("Temp= "); // シリアルに温度を出力
Serial.print(temp,1);
Serial.print(", Vcc= "); // シリアルにVccを出力
Serial.println(Vcc,2);

lcd.setCursor(0, 0); // 液晶に表示
lcd.print("Temp= ");
lcd.print(temp,1); // 温度、小数点以下1桁表示
lcd.print("c "); // 単位表示と後ろのゴミ消し
lcd.setCursor(0, 1);
lcd.print("Vcc = "); // Vcc
lcd.print(Vcc,2);
lcd.print("V "); // 単位表示と後ろのゴミ消し

delay(500);
}

// 流用する場合は以下を全てコピーする

float cpuTemp(){ // CPU温度測定関数
long sum=0;
adcSetup(0xC8); // Vref=1.1V, input=ch8
for(int n=0; n < 100; n++){
sum = sum + adc(); // adcの値を読んで積分
}
return (sum * 1.1/102.4)- 342.5; // 温度を計算して戻り値にする。-342.5は要調整
}

float cpuVcc(){ // 電源電圧(AVCC)測定関数
long sum=0;
adcSetup(0x4E); // Vref=AVcc, input=internal1.1V
for(int n=0; n < 10; n++){
sum = sum + adc(); // adcの値を読んで積分
}
return (1.1 * 10240.0)/ sum; // 電圧を計算して戻り値にする
}

void adcSetup(byte data){ // ADコンバーターの設定
ADMUX = data; // ADC Multiplexer Select Reg.
ADCSRA |= ( 1 << ADEN); // ADC イネーブル
ADCSRA |= 0x07; // AD変換クロック CK/128
delay(10); // 安定するまで待つ
}

unsigned int adc(){ // ADCの値を読む
unsigned int dL, dH;
ADCSRA |= ( 1 << ADSC); // AD変換開始
while(ADCSRA & ( 1 << ADSC) ){ // 変換完了待ち
}
dL = ADCL; // LSB側読み出し
dH = ADCH; // MSB側
return dL | (dH << 8); // 10ビットに合成した値を返す
}
 このプログラムはかなり前に書いた「外付け部品無しでArduinoの電源電圧を測定する」という記事に掲載したもので、インクルードするライブラリを入れ替えて、初期化の設定を修正しただけです。動作としては、CPUの電源電圧と温度を連続表示します。43行以降が測定ルーチンですが、このプログラムはCPUのレジスタを設定するだけで動いています。つまり外部の配線は何もしなくていいので、今回のように、ちょっとした動作確認をしたい時に使うと便利です。

 33行で温度を小数点以下1桁、37行で電圧を小数点以下2桁表示するように指定しています。こういうふうに表示フォーマットを指定出来るとプログラム作りが楽になります。

◆まとめ
 ということでうまく表示が出来るようになったので、I2Cインターフェイスのキャラクタ液晶を動かすライブラリの話は終わりです。I2Cインターフェースは少ないピン数で表示が出来るので便利になるはずです。

 あと、この後はこの液晶を使って日の出日の入りタイマーを作る予定です。そちらは進展があったら記事にする予定です。
カレンダー
08 | 2017/09 | 10
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード