'디버깅'에 해당되는 글 2건

  1. 2018.12.02 Hardware | MAX30105 파티클 센서 - 2
  2. 2017.09.01 Software | Visual Studio Code 를 사용해 보자

Hardware | MAX30105 파티클 센서 - 2

|

이 글은 이전 MAX30105 파티클 센서를 활용하여 OLED 에 심전도를 그려보는 도전기 입니다.

이전 글은 아래 link 를 참고하세요.


* Hardware | MAX30105 파티클 센서 - 1

http://chocoball.tistory.com/entry/Hardware-MAX30105-particle-sensor-1





1. min, max 와 scalar


일단 MAX30105 에서 입력받는 값은 5만에서 많게는 10만도 넘어갑니다.

이를 32 pixel 너비를 갖는 OLED 에 표현하려면 그 값에 맞도록 축소시켜야 합니다.



이에 더하여, 값들의 기준이 아래 그림처럼 널을 뛰므로 기준값을 잡기가 여간 쉽지 않습니다.



기준값을 잡기 위해 min, max 값을 한 사이클당 판별하여 scale in 치환값을 잡아줘야 합니다.


이를 위해 일단, 이전 사이클에서 얻은 제일 작은 min 값을 이용하여,

입력받는 값에서 빼면 그래프가 아래 그림처럼 내려갑니다.



OLED 폭이 128 pixel 이므로, 이 폭을 한 사이클로 잡습니다.

EXCEL 을 통하여 위의 방식을 검증해 본 결과 문제 없이 표현되는 것을 확인할 수 있었습니다.



OLED 의 y 값에 해당하는 값을 EXCEL 에서 32 pixel 기준으로 변환된 값을 array 에 입력하고

순서대로 출력해서 OLED 에 맞는지 최종 확인해 봅니다.



요리조리 검증해 본 결과 아래 식을 통해서 min, max 값과 한 사이클을 OLED 폭인 128 에 표현하고

다시 0 부터 시작하는 - 화면이 바뀌는 방법을 확인하였습니다.


	irValue = particleSensor.getIR();
	
	if( x > 127) { //refresh OLED screen
		display.clearDisplay();
		lastx=0;
		x=1;
		
		scaler = (max_irValue - min_irValue) / 32;
		pre_min_irValue = min_irValue;
		
		// reset min, max value
		max_irValue = irValue;
		min_irValue = irValue - 1;
	}





2. y값 reverse


OLED 에 표현시, x/y 값은 우리가 일반적으로 배운 왼쪽 아래에서 시작되는 것이 아니라,

왼쪽 위로부터 값의 증가를 표현합니다.



즉, sensor 로부터 값을 입력 받으면, 상하 전치를 시켜줘야 합니다.

제가 쓰고 있는 것은 상하 32 pixel 이므로, 아래 한 pixel 을 빼면 31 이므로,

31 에서 입력받은 값을 빼주면 표현하고자 하는 위치로 바꿀 수 있습니다. 



	// invert y values to fit OLED display
	if ( pre_min_irValue > irValue) {
		y = 31;
	} else {
		y = 31 - ((irValue - pre_min_irValue) / scaler);
	}

값이 너무 적어지면, 값이 역전하여 아래 그림같이 튀어버립니다.

그래서 전 사이클에서 확인 되었던 min value 보다 적어지면 강제적으로 최저값을 할당합니다.

여기서 "y = 31" 은 OLED 상에서는 제일 밑에 표시되는, 일상의 0 값과 같습니다.






3. BPM 과 piezo buzzer


심전도의 값이 가장 높아지면 buzzer 를 울리게 하는 소스 입니다.

또한 BPM 값도 표현해 줍니다.


BPM 값은 심전도의 한 사이클 평균을 내어 1분동안 얼마나 맥박이 뛰는지를 수치화 한 값입니다.



소스는 다음과 같고, 아래 blog 를 전면 참고하였습니다.


* Heart beat Sensor and “ECG” Display

http://www.xtronical.com/basics/heart-beat-sensor-ecg-display/


	ThisTime=millis();
	if( y < UpperThreshold ) {
		if(BeatComplete) {
			BPM=ThisTime-LastTime;
			BPM=int(60/(float(BPM)/1000));
			BPMTiming=false;
			BeatComplete=false;
			tone(2,1000,250);
		}
		if(BPMTiming==false) {
			LastTime=millis();
			BPMTiming=true;
		}
	}
	if((y > LowerThreshold) && (BPMTiming))
		BeatComplete=true;






4. source


지금까지의 작업을 모두 합하여 하나의 소스로 만들었습니다.


#include "Wire.h"
#include "MAX30105.h"

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"

// Hardware SPI
#define OLED_DC     6
#define OLED_CS     7
#define OLED_RESET  8
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);

MAX30105 particleSensor;

unsigned int irValue;
unsigned int max_irValue;
unsigned int min_irValue;
unsigned int x = 0;
unsigned int y;
unsigned int lastx = 0;
unsigned int lasty = 0;
unsigned int scaler;
unsigned int pre_min_irValue;
int BPM;
int LastTime = 0;
int ThisTime;
bool BPMTiming=false;
bool BeatComplete=false;
#define UpperThreshold 10
#define LowerThreshold 25

void setup() {
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC);
  display.clearDisplay();
  
  // initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) { //Use default I2C port, 400kHz speed
    display.println("MAX30105 was not found. Please check wiring/power.");
    while (1);
  }
  
  //Setup to sense a nice looking saw tooth on the plotter
  byte ledBrightness = 0x1F; //Options: 0=Off to 255=50mA
  byte sampleAverage = 8; //Options: 1, 2, 4, 8, 16, 32
  byte ledMode = 3; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  int sampleRate = 1000; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411; //Options: 69, 118, 215, 411
  int adcRange = 4096; //Options: 2048, 4096, 8192, 16384
  
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
  
  // initiate min, max values
  irValue = particleSensor.getIR();
  max_irValue = irValue;
  min_irValue = max_irValue - 1; 
  for (int ini ; ini < 100 ; ini++) {
	  irValue = particleSensor.getIR();
	  
	  if (max_irValue < irValue) {max_irValue = irValue;}
	  if (min_irValue > irValue) {min_irValue = irValue;}
  }
  
  display.display();
}

void loop() {
	irValue = particleSensor.getIR();
	
	if( x > 127) { //refresh OLED screen
		display.clearDisplay();
		lastx=0;
		x=1;
		
		scaler = (max_irValue - min_irValue) / 32;
		pre_min_irValue = min_irValue;
		
		// reset min, max value
		max_irValue = irValue;
		min_irValue = irValue - 1;
	}
	
	display.setTextColor(WHITE);
	ThisTime=millis();

	// invert y values to fit OLED display
	if ( pre_min_irValue > irValue) {
		y = 31;
	} else {
		y = 31 - ((irValue - pre_min_irValue) / scaler);
	}
	
	// draw heartbeat lins
	display.drawLine(lastx, lasty, x, y, WHITE);
	lasty = y;
	lastx = x;
	
	// update min, max values
	if (max_irValue < irValue) {max_irValue = irValue;}
	if (min_irValue > irValue) {min_irValue = irValue;}
	
	ThisTime=millis();
	if( y < UpperThreshold ) {
		if(BeatComplete) {
			BPM=ThisTime-LastTime;
			BPM=int(60/(float(BPM)/1000));
			BPMTiming=false;
			BeatComplete=false;
			tone(2,1000,250);
		}
		if(BPMTiming==false) {
			LastTime=millis();
			BPMTiming=true;
		}
	}
	if((y > LowerThreshold) && (BPMTiming))
		BeatComplete=true;
	
	// display BMP
	display.fillRect(0,24,64,32,BLACK);
	display.setCursor(0,24);
	display.print("      BPM");
	display.setCursor(0,24);
	display.print(BPM);
	
	// check finger is on the sensor
	if (irValue < 10000) { display.setCursor(1,1); display.print("NO Finger?"); }
	
	// display all data to OLED
	display.display();
	x++;
}


결과 동영상을 올려 봅니다.







FIN


이걸 구현해 보려고 3주간 주말 = 토, 일 이틀간 x 3 = 6일 동안 삽질의 연속이었습니다.

이 문제는 소스에서 scalar 를 구하기 위한 나누기를 해야 하는데, % 연산자를 사용했기 때문이었습니다.


* Modulo

https://www.arduino.cc/reference/en/language/structure/arithmetic-operators/modulo/


% 연산자는 몫을 구하는 것이 아니라, 나머지를 구하는 연산자지요!!!

반대로 알고 있었던 것. 이걸 알아 차리는데 6일이나 걸렸습니다!!!



변수의 갯수도 줄여 보기도 하고, 각 값을 먼저 scale in 해서 결과를 내보기도 하고, 하여간 별짓 다 했습니다.

처음에 디버깅만 잘 했어도 이렇게 오래 걸리지는 않았을 듯 하네요.

디버깅 작업이 얼마나 중요한지 새삼 깨닳았습니다.



이렇게 하면 Serial Monitor 에도 이렇게 나오니 환장할 노릇이었습니다.


이 덕에 Hardware SPI 활용과 OLED refresh rate 등등을 공부하게 되었네요.

아이고야... 좀 쉬자.


SpO2 농도 값이나, 그래프를 좀더 안정적으로 보여줄 수 있도록 소스를 더 다듬고 싶었지만,

에너지를 너무 많이 써서 이번 작업은 여기까지 하겠습니다.


나중에 다시 생각나면, 소스코드를 다시 잡아 볼께요.


And

Software | Visual Studio Code 를 사용해 보자

|

1. Microsoft 에서 나온 IDE


Microsoft 에서도 프로그램 IDE 용으로 "Visual Studio Code" 라는 공개 소프트웨어가 있습니다.



저번에 JetBrains 사의 IntelliJ IDEA 를 써 봤으니, 이번에는 Microsoft 꺼를 써보려 합니다.


http://- http://chocoball.tistory.com/entry/Software-using-IntelliJ-IDEA





2. Visual Studio Code


사용자들이 충실하게 만들어 놓은 Wikipedia 에서 좋은 정보들을 찾습니다.


https://en.wikipedia.org/wiki/Visual_Studio_Code


파일은 다음 link 에서 다운로드 가능합니다.


- https://code.visualstudio.com/


IntelliJ 처럼 기능상 차이로 유료/무료로 나뉘지는 않고, 그냥 무료 입니다.



자, 사용을 시작해 볼까요?




3. 시작


Windows OS 기본 언어를 일본어로 설정해 놓다 보니, 초기 화면이 일본어가 떴습니다.



지금까지 여러 일본어로 된 어플을 봐 왔지만,

폰트 사용이 가독성 면에서 최고로 괜찮은것 같습니다.




4. IntelliSense


IntelliSense 란, 요즘 IDE 에서 기본적으로 탑재되고 있는 보조기능입니다.

이 기능은, programmer 가 타이핑 하고 있으면, 미리 타이핑 할 것을 예측하여 보여주고,

programmer 는 모든 code 를 타이핑하는 것이 아니라, 보여준 예시에서 선택하여, coding 속도를 높이고 typo 로 인한 debugging 을 

줄여주는 역할을 합니다.


https://en.wikipedia.org/wiki/Intelligent_code_completion



시험삼아 C 파일을 불러들이자, C++ programming 에 관련된 IntelliSense 파일을 다운로드 받으라고 알려줍니다.



관련된 파일을 받고 reload 한 후, 코딩을 해보면, 몇글자 치면 적당한 예시를 보여주게 됩니다.

IntelliJ 에서 너무 충격받아, 이제 IDE 로서는 당연한 기능인것 같습니다.




5. 형상 관리


Project 를 생성시, 형상 관리로부터 가져올 수 있습니다.

Repository URL 을 입력하면 자동으로 다운로드 받고 확인할 수 있습니다.


최종적으로 GitKraken 과 같은 형상 관리 어플과 연동이 되는지는 모르겠습니다.

 


Repository 에서 clone 하여 가져올 것이냐고 물어보네요.



문제 없이 import 된 것을 확인할 수 있습니다.




6. Java


Java 소스를 열면, Java 프로그래밍에 필요한 보조적인 플러그인 이나 파일을 받으라고 이야기 해 줍니다.



Java 에 대한 Language Support 파일 인스톨을 선택합니다.



외부 링크에서 찾아서 사이트로 가보면 아래 정보가 뜹니다.

Red hat 에서 만들었군요.




Website 에서 인스톨을 실행시키면, 어플 안에서도 동일한 내용이 뜹니다.

Web --> Application 연동이 잘 되어 있습니다.


보조기능 파일 인스톨이 끝난 후, 리로드 하면, 다음과 같이 runtime 이 없다고 뜹니다.



JDK 를 등록해야 겠죠?

File > Preferences > Settings > Search 에서 JDK 를 치면 메뉴가 아나 나옵니다.


오른쪽 pane 에 설정하면 기본 설정을 override 한다고 합니다.

JDK 가 있는 폴더를 등록해 줍니다.


{
  "java.home":
  "C:\Program Files\Java\jdk1.8.0_112"
}




정상적으로 등록이 되면 Restart 하라고 나옵니다.






7. Java 에 대한 IntelliSense 의 간단 확인


이제 환경 설정과 필요한 파일이 모두 깔렸으니,

실제로 Java coding 을 해 봅니다.


IntelliJ 에서는 "sout" 이라고 치면 "System.out.println" 이 자동 입력되었습니다.

Visual Studio Code 에서는 "Syst" 까지 쳐야 그 후에 선택할 수 있게 되어 있네요.



의도한 대로 "System.out.println();" 이 자동 타이핑 되었습니다.



다른 기능들도 이정도는 합니다.




8. 간단 총평


인터페이스는 직관적며, 혼란스럽지 않은 메뉴 구성이지만, 아쉬운 부분이 있습니다.


- class 들간의 종속관계나 람다 표현이라는 것 까지는 보여주지 못한다

- 코드를 간략화 할 수 있는 tip 을 보여주지 않는다

- 예시가 IntelliJ 만큼의 퀄리티와 내용을 보여주지 못한다


급하게 사용해야 할 상황이 되거나, 그냥 저냥의 기능 정도로 충분한 개발에는 부족함이 없습니다.

다만, 조금 깊이가 있고, 코딩을 최적화 하는 용도의 IDE 로는 부족함을 느끼게 됩니다.




FIN

프로그래밍을 업으로 삼는다면, 그냥 돈주고 "IntelliJ" 사다 쓰세요.

그냥 IntelliJ 가 갑입니다.


IntelliJ is the RULE !!!

And
prev | 1 | next