참고자료

아두이노, 오렌지보드 등의 오픈소스하드웨어를 사용하는데 필요한 것들을 알아봅니다.

데이터 저장

2014-10-29 10:13:35

개요

보통 변수를 만들고 값을 저장하면 아두이노 보드 전원이 켜져 있는 동안만 변수 값을 기억합니다.
전원이 꺼지거나 리셋을 하면 데이터가 사라집니다.

만약 전원을 다시 키거나 리셋을 한 후에도 데이터를 그대로 유지하고 싶은 경우는 어떡해 해야 할 까요?

또 보통 데이터는 2KB RAM에 저장합니다.
만약 많은 데이터를 저장하는 등의 여러가지 문제로 메모리 용량이 넉넉하지 않다면 어떡해 해야 할 까요?

본문에서는 전원차단, 용량부족에 대비해서 데이터를 저장하는 방법에 대해 다뤄보겠습니다.

 

PROGMEM 지시자

맨 처음 방법은 플래시 메모리에 저장하는 방법입니다.
플래시 메모리는 프로그램을 저장하는 데 사용되면 보통 32KB정도의 용량을 가지고 있습니다.
저장을 하기 위해서는 라이브러리로 제공되는 PROGMEM 지시자를 사용하여야 합니다.

참고로 이 방법은 데이터가 상수인 경우에만 사용할 수 있습니다.
즉 스케치가 실행되는 동안 데이터가 변경되서는 안됩니다.

1. 사용법

#include 

먼저 avr/pgmspace라는 라이브러리를 포함시켜야 합니다.
기본 아두이노 내장 라이브러리입니다. 

//PROGMEM 문자열 유형 개별 변수 정의
PROGMEM prog_char sA[] = ".-";
PROGMEM prog_char sB[] = "-...";

//.....

//위의 모든 변수를 PROGMEM 배열 변수에 정의
PROGMEM const char* letters[] = 
{
 sA, sB, sC, sD, sE, sF, sG, sH, sI, sJ, sK, sL, sM,
 sN, sO, sP, sQ, sR, sS, sT, sU, sV, sW, sX, sY, sz
};

PROGMEM을 사용할 때는 특별한 데이터 유형을 사용해야 하는데
char 배열은 이 데이터 유형에 해당하지 않습니다.

각 PROGMEM 문자열 마다 원하는 데이터 변수를 저장한 후 
그 변수들을 또 다시 PROGMEM 배열 변수에 저장합니다.

//PROGMEM 문자열을 buffer 변수에 복사
char buffer[6];
strcpy_P(buffer, (char*)pgm_read_word(&(letters[ch - 'a'])));

pgm_read_word함수로 값을 읽어온 후
strcpy_P함수로 변수에 복사합니다.


 

EEPROM

EEPROM을 사용하는 것은 변경될 수 있는 데이터를 저장할 수 있는 방법입니다.
아두이노 우노의 ATMega328에는 1KB의 EEPROM이 있습니다.
EEPROM은 여러번 동안 새롭게 기억할 수 있는 비휘발성 메모리입니다.
물론 이름의 뜻에 읽기 전용이라는 말이 포함되어 있지만 실제로는 
기록할 수도 있으며 단순 읽기 전용이 아닙니다.

EEPROM에 대한 자세한 설명과 사용법은 다음 링크를 참고하세요.
 

데이터 압축

그런데 위 두 가지 방법으로 해결하지 못하는 경우가 있습니다.
즉, EEPROM, PROGMEM을 사용해도 메모리 용량이 부족할 때가 발생될 수 있다는 것입니다.
이런 경우 데이터를 압축해서 저장하는 방법을 생각해봐야 합니다.

1. 작은 타입으로 변환
float형 같이 2byte가 필요한 값을 int형으로 바꿔 저장하는 방법입니다.
물론 이 경우, 소수점이하 부분을 버릴 수도 있기 때문에 정밀도는 낮아집니다.

float tempFloat = 2.25;
int tempInt = (int)tempFlaot;

위 코드는 float형태를 int타입으로 바꿔서 저장한 것입니다.

2. 바이트로 변환
위 코드의 tempInt를 출력하면 2라고 나옵니다.
정밀도가 많이 떨어집니다.
정밀도를 좀더 높이기 위해서 다음과 같은 방법을 사용할 수도 있습니다.

#include 

float numFloat= 2.25;

void setup() {
 Serial.begin(9600);
 
 //float값을 4배 후 byte로 변환
 byte numByte= (int)(numFloat * 4);
 EEPROM.write(0, numByte);
 Serial.println(numByte);

 //byte 값을 float값으로 변환 후  /4
 byte numByte2 = EEPROM.read(0);
 float numFloat2 = (float)(numByte2) / 4;
 Serial.println(numFloat2);
}

void loop() {
}

물론 4배를 해서 저장하기 때문에 더 큰 값을 저장하므로
일정 범위가 있는 경우에 이렇게 활용하면 좋습니다.

3. 차이 저장하기
만약 온도를 측정할 경우, 특정 시간마다 측정되는 
모든 온도를 저장하는 것이 아니라 첫번째 온도만 높은 정밀도의 값으로 저장합니다.
다음 온도 부터는 차이만 저장합니다. 
그 후 다시 특정 시간의 특정 온도값이 필요한 경우 첫번째 온도와 온도 차이를 이용해서 알 수 있습니다.

 

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

데이터 저장, 기타

박선우 2018-10-29 00:06:07

데이터를 저장할 수 있다는 것을 처음알았습니다. 좋은정보 알아갑니다~