안녕하세요~


이번시간에는 SD카드를 이용한 데이터 로깅 방법에 대해 알아보겠습니다.


지난 시간에서 프로세싱을 통해 아두이노의 데이터를 가시화 한것 처럼,

아두이노는 '데이터의 수집' 기능을 주로 수행한답니다.


하지만 이러한 경우에는 PC가 필수적으로 함께 있어야만

데이터를 저장 및 확인할수가 있죠.


만약에 PC가 없다면 어떻게 데이터를 저장할 수 있을까요?


바로 SD카드를 이용해서 아두이노가 수집한 데이터를

SD카드에 저장해두는 것입니다.


그럼 나중에 장치를 구동한 후, 데이터가 저장된 SD카드만 있으면

아두이노에서 측정된 데이터들을 PC에서 신호처리를 할 수 있겠죠ㅋㅋ


그럼 한번 살펴봅시다.





#1 준비물




SD 카드, SD 카드 소켓

(소켓은 리더기가 아니라 우측에 보이는 모듈입니다)



아두이노

(여기서는 Bluno Beetle을 사용했습니다)





#2 SD카드 소켓 연결



자 이제 물품을 준비했다면 아두이노와 SD카드를 연결시켜 보겠습니다~


먼저 SD카드에 데이터를 저장하기위해서는

'SPI통신'을 통해 데이터를 저장한답니다.


SPI통신은 센서모듈이나, 제어모듈 등에 흔히 사용되는 통신으로,

여기를 참고하시면 될거에요~ 


자 그럼 핀들을 각각 연결해 볼까요?


먼저 Bluno Beetle 에는 MISO, MOSI, SCK,  등의 SPI 통신 핀들이

기판에 나타나있지 않습니다.


다만 뒤집어보면 작은 박스부분에 모여있지요....


아두이노의 경우에는 10~13번 디지털 핀들이 SPI통신과 연관된 핀이랍니다.

구글에 핀배치를 검색하시고 배선하세요~!  



자 그럼 연결을 해봅시다.




아무래도 연결하는곳들이 핀헤더가 없이 기판이다보니

납땜을 하는수 밖에 없네요ㅠ


여기서 SPI 통신 외적으로 하나를 더 연결하셔야 할 부분이 있는데,

바로 Chip Select Pin 인 CS 핀 입니다.


저는 CS핀을 디지털 4번핀에 연결했어요~

디지털 핀 어디다 연결하셔도 상관없습니다ㅋㅋ





#3 배선 완료후 모듈화




자 이제 배선도 완료됐으니,


전원선도 연결하고 코딩도 넣어볼까요~?



우선 전원은 사실 5V에 구동되는 아두이노라 하더라도 

리튬 폴리머(Li-po) 베터리 1cell 로도 충분히 구동은 된답니다ㅋㅋㅋ


물론 1Cell 이면 3.7V 밖에 안되긴 하지만, 아주 장시간을 구동시킬게 아니면 상관없답니다~

다만 아날로그 인풋의 경우에는 조금 영향이 있기때문에, 

그런 경우에는 2Cell 로 써서 7.4V 전원을 Vin에다가 넣어주시면 됩니다ㅋㅋ


저는 3.7V 를 Vin에 바로 연결해서 사용했습니다.



짜잔 아무런 이상없이 잘 돌아간답니다ㅋㅋㅋ


그럼 코딩을 해볼까요~




#include <SPI.h>

#include <SD.h>

#include "Timer.h"


const uint8_t CS = 4;


const unsigned long PERIOD = 100;    //one second

Timer t;                               //instantiate the timer object


File dataFile;

int numFile;

String fileName;


int data[5] = {0,0,0,0,0};

int data2[5] = {0,0,0,0,0};

int count = 0;


void setup() {


  pinMode(LED_BUILTIN,OUTPUT);

  // put your setup code here, to run once:

  t.every(PERIOD, recording);

  if (!SD.begin(CS)) {

    return;

  }


  dataFile = SD.open("/");

  numFile = printDirectory(dataFile);


  fileName = String(numFile) + ".txt";


  Serial.begin(9600);

  Serial.println(fileName);


  dataFile = SD.open(fileName, FILE_WRITE);

  dataFile.println("Start!");

  dataFile.close();

}


void loop() {

  // put your main code here, to run repeatedly:

  t.update();


}


void recording(){

  int val = analogRead(A0);

  count = count%5;

  

  dataFile = SD.open(fileName, FILE_WRITE);


  data[count] = val;

  val = (data[0]+data[1]+data[2]+data[3]+data[4])/5;

  

  dataFile.print(val);

  dataFile.print("\t");


  Serial.print(val);

  Serial.print("\t");


  val = analogRead(A3);

  data2[count] = val;

  val = (data2[0]+data2[1]+data2[2]+data2[3]+data2[4])/5;

  


  dataFile.println(val);

  Serial.println(val);


  dataFile.close();  

  count++;

  return 0;

}



int printDirectory(File dir) {

  int fileNum = 0;

  while (true) {

    File entry =  dir.openNextFile();

    if (! entry) {

      return fileNum;

    }else{

      fileNum++;

    }

    entry.close();

  }

}



위 코드를 실행하기위해서는 Timer 라이브러리가 있어야하는데,

여기 에서 찾으시면 되요~!


좀 복잡한 코드이긴 한데, 간단히 설명하자면 아날로그 신호를 SD카드에 로깅하는 코드입니다.


앞서 언급드렸다싶이 CS핀은 아무 디지털핀에 연결하셔도 됩니다만, 

맨 위에줄에서 보이는것 처럼


const uint8_t CS = 핀 번호;


를 입력해주셔야 합니다!!


그리고 SD카드가 소켓에 장착되지 않으면 로깅이 안되고,

장착이 되었다면, 내부에 있는 파일을 스캔한 후,


"존재하는 파일갯수+1.txt"


라는 이름으로 데이터가 텍스트파일로 로깅됩니다~


PERIOD는 몇ms간격으로 데이터를 로깅하는지 세팅하는 값이랍니다.


지금은 100ms간격으로 데이터를 받아오고 있지요.


그리고 데이터자체가 워낙에 노이즈가 많아서,

5번 측정한 값의 평균을 저장하도록 만들었어요~



이정도 코드면 조금만 수정하시면

원하시는 프로젝트에 바로 사용할 수 있을거라 생각이 됩니다^^


이상!

+ Recent posts