みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

機器のI/OをArduinoでSDに記録したい

皆様、お世話になります。

Arduinoでデーターロガーのスケッチを作成しています。
スケッチしてみましたが動くかどうか確認とこう直した方が良いなど改善点が有れば、お願い致します。

2番ピンに変化が有った時(ONかOFF)に時間と2番ピンの状態をSDカードに記録したいのです。
これが、うまくいけば系統を増やしていきたいです。

書いたスケッチ

#include <SD.h>

// この値は使用しているシールドや基板に合わせて変更すること。たとえば、
// イーサーネットシールドは 4
// Adafruit のSDシールドは 10
// Sparkfun のSDシールドは 8
const int chipSelect = 4;

void setup()
{
// シリアルポート初期化
Serial.begin(9600);
while (!Serial) {
; // USBケーブルが接続されるのを待つ。この待ちループは Leonardo のみ必要。
pinMode(2,INPUT) ; //スイッチに接続ピンをデジタル入力に設定A
}

Serial.print(F("Initializing SD card..."));

// SSピン(Unoは10番、Megaは53番)は使わない場合でも出力にする必要があります。
// そうしないと、SPIがスレーブモードに移行し、SDライブラリが動作しなくなります。
pinMode(SS, OUTPUT);

// SDライブラリを初期化
if (!SD.begin(chipSelect)) {
Serial.println(F("Card failed, or not present"));
// 失敗、何もしない
while(1);
}
Serial.println(F("ok."));

// 日付と時刻を返す関数を登録
SdFile::dateTimeCallback( &dateTime );
}

void loop()
{
// ファイルを開く
File dataFile = SD.open("datalog.txt", FILE_WRITE);

// もし2番ピンに変化が有れば書き込む
if (digitalRead(2)==HIGH) {
int value = digitalRead(2);
dataFile.println(value);
dataFile.close();
// シリアルポートにも出力
Serial.println(value);
}
if (digitalRead(2)==LOW) {
int value = digitalRead(2);
dataFile.println(value);
dataFile.close();
// シリアルポートにも出力
Serial.println(value);
}
// ファイルが開けなかったらエラーを出力
else {
Serial.println(F("error opening datalog.txt"));
}
}

void dateTime(uint16_t* date, uint16_t* time)
{
uint16_t year = 2014;
uint8_t month = 7, day = 22, hour = 14, minute = 0, second = 0;

// GPSやRTCから日付と時間を取得
// FAT_DATEマクロでフィールドを埋めて日付を返す
*date = FAT_DATE(year, month, day);

// FAT_TIMEマクロでフィールドを埋めて時間を返す
*time = FAT_TIME(hour, minute, second);
}



よろしくお願い致します。

投稿日時 - 2014-07-22 14:56:22

QNo.8688063

すぐに回答ほしいです

質問者が選んだベストアンサー

なんか切れているようですが…。
> val=digitalRead(2); ここで黄色になり
>下に
>stry '¥'in program
>と、でます。
ですかね。(半角円マークはうまく表示できない場合があるので全角にしてみた)


>明記はしていませんがインデントを「全角空白」であらわしていますので、そのままコピペするとエラーになりますよ。

と回答した通り、その場所に全角空白があるから…でしょう。
「全て選択」してコピー、テキストエディタに貼り付けてみてください。
# できれば全角空白を記号などで表示できるテキストエディタで。(秀丸など。)
# 有名どころのテキストエディタなら記号で表示するオプションがあるでしょう。
テキストエディタの置換機能で全角空白を半角空白2つに置換するか…単純に削除した後で再度arduinoのスケッチにペーストしてください。
# ペーストした後で[ツール][自動整形]すればインデントとか調整してくれるでしょう。



あとは…Valとvalか混じっていたり、ブロック区切りがおかしくなっていたりするようですのでその辺りを見直してくださいな。

投稿日時 - 2014-07-23 13:08:11

お礼

ありがとうございます。

いろいろいじっていたら動きました。

勉強させて戴き、ありがとうございました。

投稿日時 - 2014-07-25 09:48:17

ANo.4

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

Wr5

>早速、貼り付けてみましたが検証するとエラーに…

どんなエラーだったのか掲示されないと……。

ちなみに、明記はしていませんがインデントを「全角空白」であらわしていますので、そのままコピペするとエラーになりますよ。

投稿日時 - 2014-07-23 08:33:52

お礼

記入せず、申し訳ありません。


 val=digitalRead(2); ここで黄色になり


下に
stry`in program

と、でます。

自分でも確認していますが、現在発見できていません。


ありがとうございました。

投稿日時 - 2014-07-23 11:18:36

ANo.2

Wr5

void loop()
{
 // 2番ピンの状態を取得
 Val=digitalRead(2);
 // 前回と変化があったら…
 if(old_val != Val) {
  // ファイルを開く
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if(dataFile) {
   // 書き込む
   dataFile.println(Val);
   dataFile.close();
  }
  else {
   // ファイルが開けなかったらエラーを出力
   Serial.println(F("error opening datalog.txt"));
  }
  // シリアルポートにも出力
  Serial.println(Val);
  old_val = Val;
 }
}

こんなところでしょうかね?
時刻は書き出していないので追加してくださいな。

ファイルオープンはsetup()でやって、dataFile.close()でクローズしない。
という方法もアリかも知れません。
# dataFileはグローバル変数にする必要があります。

ただし、その場合は途中でSDカード抜いた場合の動作が保証できませんけど。
# dataFile.flush()するとある程度は書き込まれると思われます。が、完全には保証できない点は変わらないかと。

投稿日時 - 2014-07-22 17:00:27

お礼

ありがとうございます!

早速、貼り付けてみましたが検証するとエラーに…

もう少し、勉強してみます。



#include <SD.h>

// この値は使用しているシールドや基板に合わせて変更すること。たとえば、
// イーサーネットシールドは 4
// Adafruit のSDシールドは 10
// Sparkfun のSDシールドは 8
const int chipSelect = 4;
const int BUTTON=2;

int val=0;
int old_val=0;
int state=0;

void setup()
{
// シリアルポート初期化
Serial.begin(9600);
while (!Serial) {
; // USBケーブルが接続されるのを待つ。この待ちループは Leonardo のみ必要。
pinMode(2,INPUT) ; //スイッチに接続ピンをデジタル入力に設定
}

Serial.print(F("Initializing SD card..."));

// SSピン(Unoは10番、Megaは53番)は使わない場合でも出力にする必要があります。
// そうしないと、SPIがスレーブモードに移行し、SDライブラリが動作しなくなります。
pinMode(SS, OUTPUT);

// SDライブラリを初期化
if (!SD.begin(chipSelect)) {
Serial.println(F("Card failed, or not present"));

}
Serial.println(F("ok."));

// 日付と時刻を返す関数を登録
SdFile::dateTimeCallback( &dateTime );
}

void loop(){
{
// 2番ピンの状態を取得
 val=digitalRead(2);
 // 前回と変化があったら…
 if(old_val != Val) {
  // ファイルを開く
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if(dataFile) {
   // 書き込む
   dataFile.println(Val);
   dataFile.close();
  }
  else {
   // ファイルが開けなかったらエラーを出力
   Serial.println(F("error opening datalog.txt"));
  }
  // シリアルポートにも出力
  Serial.println(Val);
  old_val = Val;
 }
}

void dateTime(uint16_t* date, uint16_t* time)
{
uint16_t year = 2014;
uint8_t month = 7, day = 22, hour = 9, minute = 0, second = 0;

// GPSやRTCから日付と時間を取得
// FAT_DATEマクロでフィールドを埋めて日付を返す
*date = FAT_DATE(year, month, day);

// FAT_TIMEマクロでフィールドを埋めて時間を返す
*time = FAT_TIME(hour, minute, second);
}
}

投稿日時 - 2014-07-22 18:15:08

ANo.1

Wr5

試していませんが……

>2番ピンに変化が有った時(ONかOFF)に時間と2番ピンの状態を

変化があった時…ではないですし、loop()実行中はガンガン書き出すスケッチになっています。
# ついでに時間は書き出されません。

loop()の中で前回通った時の2番ピンの状態を保持する変数を用意する必要があるでしょう。
その上で、現在の値と変更があったかを確認し、現在の値を書き出す。
ということになるかと。
2番ピンに接続されているモノによってはチャタリング対策とか必要です。


時間も書き出すとしたら、起動時にPCから日時データを受け取れるようにする必要があるかと思われます。
# SDカード使える状態だとどこからか時刻を取ってこれるのなら別ですが。
# SDカード使ったコトありませんのでPC側から取得…でしょうね……。

投稿日時 - 2014-07-22 15:14:36

お礼

早速のご回答ありがとうございます。

おっしゃる通り、あれこれ試していたら大量の0と1が・・・・


Val=digitalRead(2);
if((val==HIGH)&&(old_val==LOW)){
state=1-state;

こんな文章にすれば良いのでしょうか。
入力していますが、検証するとエラーに。
もっと勉強します。

ありがとうございました。

投稿日時 - 2014-07-22 16:23:34

あなたにオススメの質問