점화식에서의 특성방정식(characteristic equation)

 

포스팅 개요

과거 피보나치 수열의 일반항 구하는 포스팅(>>피보나치 수열의 일반항과 비율의 극한(황금비)<<)을 작성하였다.

사실 작성하던 중에는 크게 못느꼈는데, 다른 사람에게 설명을 하던 중 특성방정식을 잠깐 빌려와서 근과 계수와의 관계로 풀어내는 과정에서 '왜 $ a_{n+2} = a_{n+1} + a_{n} \Leftrightarrow x^2 = x + 1 $ 인가?'에 대해서 너무나도 당연하게 받아들였다는 것을 깨닫고 추가로 더 공부해본 결과 이를 '특성방정식'이라고 한다는 것을 알게되고, 이에 포스팅을 작성한다.

 

점화식에서의 특성방정식(characteristic equation)

점화식을 풀 때 우리는 특성방정식(characteristic equation)을 이용해서 해결을 하게 된다.
(과거 고등학교 수학에서 나왔던 점화식의 해결법(계차의 등비수열로 해결)도 어떻게보면 특성방정식의 활용이다.)

그런데 '왜 특성방정식을 사용해서 점화식을 푸는가?'에 대해서 궁금하진 않은가? 그냥 된다니까 하기에는 조금 껄쩍지근하다.

한줄로 정의해보자면
'점화식 자체로는 뭔가를 찾기 힘드니까 본질이 같은 다른 것으로 바꾸어서 해를 찾자'이다.

여기서 좀 더 자세히 따져보자면
'본질이 같은'은 '같은 선형성을 가지는'이란 의미이고
'다른 것'은 '기저(basis)'를 뜻한다.
(갑자기 대수학에서 벡터공간에서 쓰는 '기저'라는 단어가? 싶기도 하겠지만, 사실 모든 '함수'는 벡터공간 안에서 구현이 가능하다는 점을 보면 이해할 수 있을 것이다.)

진짜 결국 그냥 '쉽게 구할 수 있는 걸로 변형하자!'이거다..

보통은 점화식 뿐만 아니라 미분방정식, 선형대수에 모두 사용가능하기 때문에 '특성방정식'이라고 검색하면 사실 점화식보다는 미분방정식이나 선형대수 관련한 벡터공간 관련 내용 더 나아가 고유값/고유벡터 등이 나오게 된다.(사실 고유값분해를 대충이라도 이해할 수 있다면 특성방정식이 뭐하는 놈인지는 쉽게 이해가 간다)

그러나 일단은 이렇게 복잡한 내용 이전에 여기서는 아주 간단하게 점화식에 대해서만 설명해보기로 한다.

이제부터 이해해야 하는 키워드는

1. 점화식의 구분
 *선형성
 *선형의 또다른 의미
2. 특성방정식이란
이다.

차례대로 알아보자


1. 선형성(linearity)이란 무엇인가?

선형성을 만족시키기 위해서는 두 가지 조건인 가산성(Additivity)동차(제차)성(Homogeneity)을 만족해야한다.

-가산성(Additivity)은 f(a)+f(b)=f(a+b)를 만족하는 함수를 말한다.
다른말로는 중첩의 원리(principle of superposition)라고도 한다.

-동차(제차)성(Homogeneity)이란 f(ax)=af(x)를 만족하는 함수를 동차성이 있다고 한다.(일부 서적의 번역으로는 제차성이라고한다)
쉽게말해 입력이 조정된 비율만큼 동일하게 결과도 조정된 값이 나온다는 것이다.
선형성과 마찬가지로 상수항이 없는 함수에 대하여 성립하며, 상수항(혹은 이에 준하는 상수를 출력하는 함수)이 있는 경우 동차성에 위배된다.

간단하게 선형성과 동차성에 대해 쉽게 알 수 있는 예제가 있다.

y=ax+b는 선형인가?

가산성을 먼저 살펴보자
f(x1)+f(x2)=f(x1+x2)이면 가산성이 있는 함수이다.
a(x1+x2)+2b $ \neq $ a(x1+x2)+b
가산성에 위배된다.

동차성은 어떤지 보자
f(k x1) = kf(x1)
akx1+b $ \neq $ k(ax1+b)
동차성에 위배된다.

결국 y=ax+b는 선형이 아니다.


근데 신기한건 엄밀한 선형이 아닌데도 '선형'이라는 단어를 붙이는 경우가 있다는 것이다.
아니 또 이것은 무엇인가?
선형이 아닌데 선형이라고?

아까 선형성의 정의에서 '가산성'을 보았다. 여기서 파생되어서 덧셈으로 연결되는 함수들을 보고 '함수들이 선형 결합을 한다'라고 말한다.

그리고 이게 줄어들어서 '선형'이 된 것이다.

그래서 다항함수는? 선형 함수이다. 만약 상수항이 없다면 엄밀한 '선형'함수이고, 상수항이 있다면 선형(결합을 한)함수이다.

따라서 특정 계수의 곱을 통한 덧셈으로 정의되는 일반적인 점화식의 경우 선형이다.

그러면 이렇게 선형이라는 말을 막쓰면, '엄밀한 선형'인지 '일반적 선형'인지는 또 어떻게 알 것인가?

그래서 선형이란 말 뒤에 '동차' 혹은 '비동차'라는 말을 써준다.

이렇게 되면 '선형 동차 점화식' 혹은 '선형 비동차 점화식'이라는 말이 생겨날 수 있는데, 결국 이 단어로 구분이 완벽하게 되는 것이다.

선형 동차 점화식: 모든 항이 선형 결합을 한 상태이며, 상수항(혹은 그에 준하는 상수를 출력하는 함수)이 없는 점화식
선형 비동차 점화식: 모든 항이 선형 결합을 한 상태이며, 상수항(혹은 그에 준하는 상수를 출력하는 함수)이 있는 점화식

자 이제 점화식의 종류에 대해서 알아보았다.
사실 '비'자가 붙으면 뭐든 어려워진다. 선형함수보다 비선형함수가 어렵고, 동차보다는 비동차가 어렵다.
현재 이 포스팅은 '쉽게!' 알아보려는게 목적이므로 앞으로는 '선형 동차'에 대해서만 써보려고한다.
이제 '특성방정식'이란게 뭔지 알아보러가자.

 


2. 특성방정식이란?

선형 동차 점화식은 결국 선형성을 띈다.
그리고 이것은 점화식의 어떠한 해 a, b에 대하여 이 둘에 특정 계수를 곱한 선형결합역시도 점화식을 만족시킨다는 것이다.
결국 어떠한 해를 찾고 이 해에 곱해지는 계수를 찾으면 점화식을 풀어낼 수 있다(일반항을 구할 수 있다)는 것이다.

그럼 일단 이 '어떠한 해'를 찾아야하는데, 이게 그냥 점화식만 뚫어져라 쳐다보면 툭 답이 나오는 것도 아니고.. 참 힘들다.
그래서 이 어떠한 해를 찾기위해 우리는 주어진 점화식을 변형할 것이다.
어떻게?
'같지만 다르게!'
같은 선형결합을 가지지만, 이 점화식을 다른 각도로 볼 수 있는 새로운 '틀'(=기저)을 찾아서 바꿔주면 될 것이다.
결국 이 '틀'은 진짜 오만가지 것이 다 되지만, 제일 간단하며 우리가 무언가를 찾아내기 쉬운 틀은 $ x^n $일 것이다.
x를 찾아내면 점화식의 어떠한 해를 찾아낸 것이며, 이 어떠한 해에 특정 계수를 곱한 선형결합이 점화식을 만족시킬 것이기 때문이다.
그리고 새로운 틀을 $ x^n $으로 정의했으니, 이 틀을 이용해 만든 변화시킨 점화식에서는(해가 두개라고 가정하면) $ k_1 * x_{1}^n + k_2 * x_{2}^n $이 일반적인 해를 나타낸다고 볼 수 있겠다.
그렇다면 결국 $ a_n $이라는 수열을 새로운 틀 $ x^n $으로 놓게 된 것이다.

좀 더 이해를 쉽게하기위해서 하나의 예시를 가지고 논지를 진행시켜보자

$ a_n = a_{n-1} + a_{n-2} $

라는 점화식이 있다고하자(상수항이 없는 이유는? 우리는 현재 선형 동차 점화식에 대해서 보고있다.)
이 점화식에서는 차수(order)가 2이다.
갑자기 뜬금없이 차수? 선형 동차 점화식이 몇개의 항으로 연결되었는가를 나타내는 것으로, 선형적인 다항함수의 차수와 그 의미가 같다.

이를 새로운 틀 $ x^n $으로 치환하면
$ x^n = x^{n-1} + x^{n-2} $
차수로 n을 제한하면(n의 최대값은 차수가 된다)
$ x^2 = x + 1 $ 이 된다.
(위에서도 논의했듯이 항이 두개로 연결된 점화식은 두개의 해를 가지며, 두개의 해를 가지기 위해서는 다항함수의 차수=수열의 항수 이다)

자, 여기까지의 논지가 바로 이전 포스팅(피보나치 수열의 일반항 구하기)에서 근과 계수와의 관계를 사용하기 위해 살짝 빌려왔던 개념되겠다. 모르고 그냥 받아들여도 크게 문제없지만 알면 더 신기한 그런거다.

각설하고, 더 논지를 진행시켜보자.

$ x^2 - x -1 = 0 $의 형태로 바꾸어 방정식을 만들어주고

여기서 해를 구하면
$ x = \frac{1+\sqrt{5}}{2} \mathrm{ or } \frac{1-\sqrt{5}}{2} $
이 나오며

이 두개의 해의 특정 상수배씩의 선형결합이 이 점화식의 일반항이 된다. (더 나아가서, 같은 말로 '특정한 벡터'를 고유값(eigen value, 아이젠 밸류)과 고유벡터(eigen vector, 아이젠 벡터)로 분해하였을 때, 두개의 고유벡터에 특정 상수배(고유값)씩의 선형결합이 '특정한 벡터'가 된다는 것과 동일하다.)

$ a_n = k_1 * x_{1}^n + k_2 * x_{2}^n $

이때 특정 상수배($ k_1,  k_2 $)를 구하는 방법은, 초기 조건을 가지고 구하면 된다.

결국 $ a_0 = 0 $, $ a_1 = 1 $ 을 이용하면

$ a_0 = 0 = k_1 + k_2 $
$ a_1 = 1 = k_1 * (\frac{1+\sqrt{5}}{2})^1 + k_2 * (\frac{1-\sqrt{5}}{2})^1 $

$ k_1 = \frac{1}{\sqrt{5}} $, $k_2 = -\frac{1}{\sqrt{5}} $

따라서 이 점화식의 일반항은

$ a_n = \frac{1}{\sqrt{5}} * (\frac{1+\sqrt{5}}{2})^n - \frac{1}{\sqrt{5}} * (\frac{1-\sqrt{5}}{2})^n $

어디서 많이 본 일반항 아닌가?

맞다. 피보나치 수열의 일반항이다.

전 포스팅에서는 특성방정식을 그대로 이용하지 않고, 특성방정식의 아주 일부분만 잠깐 빌려다가 쓰고(특성 방정식에서 '틀'을 바꿔 수열을 잠깐 다항함수의 방정식 형태로 바꾼 뒤 근과 계수와의 공식으로 수열의 계수를 바꾼 정도) 계차의 공비를 구하는 식으로 점화식을 풀어내었다.

솔직히 전 포스팅에서는 이정도로 자세하게 특성방정식의 개념과 그 활용을 사용하지 않았기에 '일단 받아들여보세요~'하고 진행하였지만(사실 그 부분만 참고 넘어가면 이후에 유도하는데는 전혀 문제가 없다) 이후 좀 더 자세한 설명이 필요해보이기에 추가 포스팅한다.

안드로이드 갤럭시(galaxy) 예약 문자 확인 방법

 

안녕하세요!

 

안드로이드 갤럭시 문자는 예약 문자라는 아주 편리한 기능이 있죠!

 

그런데, 이게 원래 아는 사람한테 보낼때는 과거 문자 내역에서 예약으로 뜨는 걸 볼 수 있지만, 아예 생판 처음 보내는 사람한테는 예약 문자를 걸면 이게 갑자기 사라져버리는 상황이 연출됩니다!

 

완전히 완벽하게 보내서 확인이나 수정이 필요 없을때는 문제가 없지만, 수정이 필요하거나 다시 한 번 확인이 필요한 경우에는 갑자기 답답해지죠!

 

그러면 이거는 다시 확인할 수 없나!? 하면 할 수 있습니다!!

 

그럼 한번 알아볼까요?

 

1) 자 일단 "메시지" 앱으로 들어갑니다.

 

2) 오른쪽 제일 위에 돋보기 모양이 있습니다. 돋보기 모양을 눌러줍니다.

 

3) 검색창이 열립니다. 여기서 아까 예약문자를 걸었던 내용을 검색해줍니다. 가령 "좀 있다 10시에 봐~"라는 문자를 예약을 걸었으면 "10시"만 입력해도 됩니다!

 

4) 입력과 동시에 검색을 시작하죠! 혹~시 안뜬다면 "자판에서" 돋보기 모양을 한번 더 클릭해주세요. 아래쪽에 검색결과가 나타나는데 여기서 예약 문자도 나타납니다.

 

5) 예약문자를 누르면 대화창이 생성되며 예약문자가 뜹니다! 예약문자는 문자 옆에 시계표시가 있어요! 여기서 확인하고, 수정 및 삭제가 가능합니다!(문자 자체를 길게 누르면 문자의 수정이 가능하며, 시계를 누르면 예약 메시지 "지금보내기", "삭제", "편집"이 가능합니다!)

 

자! 엄청쉽죠!? 근데 이거 모르면 당황합니다! 인터넷에서 아무리 찾아도 안나와서 제가 직접 찾아낸 꿀!팁! 입니다!

 

여러분에게 도움이 되기를 간절히 바랍니다!

 

저는 이만 물러갑니다!

좋은하루 되세요!

[Arduino/아두이노] 3색 LED 켜기!

 

안녕하세요! 여러분!

오랜만에 다시 아두이노 포스팅으로 돌아왔습니다!

 

저번시간까지 아두이노를 컴퓨터와 연결하고, 예제 프로젝트를 실행해보고(블링크(Blink)), 외부라이브러리까지 추가해보았는데요!

 

오늘은 대망의 아두이노 외에 다른 '부품'(혹은 '소자' 라고도 하죠?)을 써보는 프로젝트를 해보도록 하겠습니다! 와~

 

대망의 첫 부품은 아주아주 간단한 3색 LED입니다!

 

그냥 LED도 아니고, 왜 3색이냐구요..?

 

어차피 그냥 LED와 3색 LED가 큰 차이가 없기 때문입니다. 그냥 R/G/B, 레드/그린/블루 LED 3개를 쓰나, 3색 LED 하나를 쓰나!

 

그럼 이제 아주 간단한 3색 LED를 만들어 보기 위해 차근차근 알아가 보도록 하겠습니다!

항상 이제부터는 아두이노와 물리적인 부품들을 연결할 것이기 때문에, 부품의 스펙을 알아보고 아두이노와 어떻게 연결(배선)할지를 알아본 뒤, 코딩을 통하여 프로젝트를 완성할 것입니다.

 

그럼 일단 3색 LED 부품의 스펙을 먼저 알아보고 가겠습니다!

 

1. 3색 LED 스펙-

제가 사용하는 3색 LED 부품은 HW-479이지만, 다른 부품을 사용해도 상관이 없는게, 이 3색 LED는 무조건 4개의 핀으로 이루어져 있으며, 하나는 -로 표기되어있는 GND, 나머지 세 핀이 각 각 R, G, B를 입력받는 핀입니다.

각각, 앞면과 뒷면 이미지인데요! 각 핀이 어떤건지 너무 잘 나와있죠? 여기서 우리는 -에 아두이노 GND를, RGB에 각각 해당하는 핀을 연결할 겁니다!

 

그리고 오늘은 대망의 첫 부품을 가지고 진행하는 프로젝트인 만큼, 아두이노와 부품의 연결에 제일 중요한 두가지를 알아보려고 합니다.

바로 케이블(선)브레드보드(빵판) 입니다.

 

1. 케이블

케이블은 말 그대로 부품과 아두이노를 연결는 선 입니다.!

아두이노는 좋은 점이 '점퍼 케이블'이라고하는, 케이블 양 끝에 점퍼가 있는 케이블로 쉽게 연결을 할 수 있다는 점입니다.

따로 납땜을 하지 않아도 된다는 것이지요.

케이블에는 두가지 종류가 있습니다.

F-M(암-수) 케이블, 그리고 M-M(수-수) 케이블입니다.

F-M 케이블
M-M 케이블

 

2. 브레드보드(빵판)

브레드보드의 경우 크기는 매우 다양할 수 있습니다. 보통이 30 홀(hole)짜리 브레드보드를 쓰게되구요, 그거보다 작은 브레드보드도 있고, 저처럼 60 홀 짜리도 있고, 이보다 더 큰 것도 있습니다. 여기는 구멍이 나있어서 부품을 막 꽂을 수 있도록 되어있는데 여기서도 규칙이 있습니다.

자 위의 그림처럼, ABCDE끼리는 세로로 서로 연결되어있습니다.(가로로는 서로 끊어져 있습니다)[빨간선]

FGHIJ끼리도 세로로 연결되어있습니다.(가로로는 서로 끊어져 있습니다)[빨간선]

ABCDE와 FGHIJ는 끊어져있습니다.

제일 위에는 전원 선입니다. GND(-)[파란색] 라인과 전원(+)[빨간색] 라인이죠.

전원 선의 경우 가로로 쭉 이어져 있습니다. 당연히 +와 -간은 서로 끊어져 있구요.[주황선]

60홀의 경우 30홀을 기준으로 좌우가 끊어져있습니다.

지금은 개념이 어렵더라도 한번 읽고 머리에 기억해두면 이후에 소자를 연결하거나 할때 '왜 이렇게 꽂는지'에 대해서 이해하기 쉬워지니 그냥 가볍게 읽고 넘어가 봅시다! 간단하게 말하자면 저런 규칙이 있어서 브레드 보드를 쓸 수 있습니다.

참고로 브레드보드의 어원은 말 그대로 초기 비전문가들이 빵(브레드) 자르는 판(보드)에다가 회로를 구성했기에 브레드보드로 이름 붙었다네요! 빵판이라고도하죠!

 

* 그리고 여기서 아두이노와 부품을 연결하는 방식 두가지!

하나는 F-M케이블(암-수케이블)로 아두이노와 직접 연결!

또하나는 M-M케이블(수-수케이블)로 빵판(브레드보드)를 이용하여 연결!

이렇게 두가지 방법이 있습니다.

현재 3색 LED에는 내부적으로 내장 저항이 있어서 아두이노와 직접 F-M케이블로 연결해도 되지만, 보통 소자들은 내부적으로 저항이 없기 때문에, 브레드보드(빵판)에 부품을 꽂고, 저항을 꽂고, 거기에 M-M케이블로 연결하는 것이 보통입니다.

그렇기에 오늘은 브레드보드를 이용하여 아두이노와 소자를 케이블로 연결해보겠습니다.

 

2. 아두이노와 연결(배선)

배선 첫 시간이니 배선에 대해서 말씀드리자면, 가능한한 색을 다르게 써서 보기 편하게, 헛갈리지 않게 하는것이 중요합니다!

우선 전원 선(+선)은 빨간색, 접지 선(-선, GND선)은 까만색이 기본이고, 그 외에는 구분이 잘 가고 직관적인 색이면 됩니다!

오늘 저희는 전원 선이 따로 없기 때문에 RGB에 각각 빨간색, 초록색, 파란색 선을 쓸 것이고 GND에 검은색 선을 쓸 것입니다.

3색 LED이기 때문에 각 R, G, B에 입력신호를 줄 pin이 하나씩 있어야 겠죠? 그러니 일단 선 세개를 쓸 것이구요, 입력할때 전기를 넣어 줬으면 이 전기가 빠져나갈 곳이 있어야 하니 GND pin도 하나 있어야 하겠습니다. 결국 3색 LED는 선 4개로 아두이노와 연결하여 쓸 수 있습니다.

한번 부품도로 그려보면

이와 같이 되겠습니다. 별건 아니고요, 이 그림에서는 3색 LED 핀 순서가 R - B G 이기때문에 이런 식의 배선이 되었습니다만, 실제 부품에서는 부품 핀 순서가 - R G B 순서이므로 이렇게 꽂아주시면 됩니다.

아두이노에 연결할때는 아두이노 우노 기준으로 9번핀에 R, 10번핀에 B, 11번핀에 G를 할당해 주었고, GND(-)는 아두이노 GND핀에 바로 연결하였습니다.

실제로 부품을 꽂아봅시다!

'기기나 기판에 장치나 부품 따위를 실제로 사용할 수 있도록 설치'하는 것을 '실장하다'라고 하는데요, 실제로 부품을 실장해보면 위의 이미지와 같을 것입니다.

R, G, B, - 3색 LED 핀에 각각 9, 10, 11, GND를 연결해 주었습니다. 이로써 아두이노와 부품간 배선이 끝났습니다!

 

3. 코딩

저는 개인적으로 이 영역을 가장 좋아합니다. 이미 연결된 상태에서 코딩으로 이 부품을 자유자재로 다룰 수 있기 때문이죠!

자 일단 기본적인 세팅을 해 봅시다!

이전까지 저희가 열심히 설치했던 아두이노 IDE를 켜주세요!

처음 켜면

이렇게 setup 구간(함수)와 loop 구간(함수)로 구성되어 있는 것을 볼 수 있습니다.

아두이노의 가장 핵심적인 부분인데요, 아두이노는 처음 프로그램이 실행되면서 setup 함수에 있는 내용을 한번 쭉 실행한 뒤에 그뒤로는 loop 함수만 반복적으로 실행합니다. 즉, setup에는 말 그대로 이 프로그램에 대한 초기 셋팅들을 해주고 loop에서 아두이노가 계속적으로 처리할 내용을 적어주는거죠!

결국 아두이노는 setup -> loop -> loop -> loop ... 이렇게 실행하게 됩니다.

그럼 먼저 setup 영역부터 코딩해볼까요?

일단 아두이노는 각 핀에 대해서 정의를 내려줘야합니다.

'이 핀은 내가 전원을 내보낼 핀이야', '이 핀은 내가 전원을 읽을 핀이야' 이런식으로요!

이 정의를 해주는 함수는 pinMode()입니다. 이 함수는 값이 두개가 필요합니다. 핀 넘버와 핀 모드죠.

핀 넘버는 말그대로 저희가 사용할 pin입니다. 아두이노에 숫자로 써져있는거죠. 오늘 저희가 사용할 핀은 9, 10, 11번 핀입니다.

핀 모드는 내가 출력할거면 OUTPUT, 내가 읽을거면 INPUT을 쓰면 됩니다.

자, 이제 바로 코딩해보도록하겠습니다. 전원선과 GND선은 따로 핀모드 설정이 필요없기 때문에 RGB에 대응하는 9,10,11번 핀만 핀모드를 설정하겠습니다.

void setup(){
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

 

자, 그럼 이제 loop함수로 가볼까요!

가장간단하게 1초동안 빨간 불을 켜고, 바로 다음 1초동안 초록 불을 켜고, 바로 다음 1초동안 파란불을 켜보도록하겠습니다.

 

void loop(){
  digitalWrite(11, LOW);
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  digitalWrite(10, HIGH);
  delay(1000);
  digitalWrite(10, LOW);
  digitalWrite(11, HIGH);
  delay(1000);
}

 

여기서 digitalWrite는 0, 1 즉 켜고 끄는 걸로 해당 핀에 신호를 주겠다는 명령어이구요, delay는 ms단위로 쉬겠다는 의미입니다!

결국 완성된 코드는 다음과 같습니다!

void setup(){
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop(){
  digitalWrite(11, LOW);
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  digitalWrite(10, HIGH);
  delay(1000);
  digitalWrite(10, LOW);
  digitalWrite(11, HIGH);
  delay(1000);
}

 

4. 결과

자, 그럼 배선과 코딩한 것을 바탕으로 결과를 한번 볼까요!?

자, 잘 돌아가는 것을 확인했습니다!

지금 현 상황에서 배선도 완료되어있고, 작동도 제대로 되고 있는 것을 확인했으니, 이제 코딩으로 다양한 활용이 가능해집니다!

더욱 자세한건 다음번에 알아보아요!

아참, 우리가 지금 한 것은 켜고 끄기만 하는 digitalWrite였는데요, 여기서 analogWrite는 0~255사이의 값을 PWM 방식으로 차등적으로 적용할 수 있습니다. 즉, '강도 조절'이 가능해진다는 말인데요!

이를 바탕으로 각 불이 점점 밝게 들어왔다가 꺼지는 것도 가능하답니다!

힌트는 여기까지! 다음번에 또 보아요~

delay함수 없이 LED 깜빡이기

 

가끔씩 우리는 아두이노에서 병렬처리(한번에 두 가지 이상의 작업을 동시에 수행하는 것)가 필요할 때가 있습니다.
아두이노의 loop는 사실상 ms단위로 작동하기 때문에 구문을 나열해도 거의 동시에 처리되는 것처럼 보이긴 합니다.
그렇기에 평상시에는 크게 병렬처리에 대해서 생각할 필요가 없는데요.
그러나 LED핀을 깜빡이는데 가장 간편하게 사용하는 delay()함수가 들어가게 되면, 여기서부터 골치가 아파집니다.
왜냐하면 delay()함수를 사용하게 되면 아두이노가 프로그램을 일시 중지되기 때문이죠.
따라서 delay()함수가 작동하게 되면 지정한 시간만큼 프로그램이 일시 중지되고, 그 사이에는 다른 구문을 작동할 수가 없습니다.
예를들어 delay()함수 작동 중 버튼 눌림 체크가 불가능 하다거나, 다른 명령어 작동이 불가능하죠.

오늘 올릴 포스팅은 delay()함수를 사용하지 않고 LED를 깜박이는 방법에 대해 작성할 겁니다.

간단하게 개요부터 말씀드리자면,
1) delay()를 사용하지 않고
2) LED를 켜고(끄고) 시간(ms 단위)을 기록하고(millis() 함수)
3) 이 시간이 원하는 시간이 지났는지 확인하고
4) 시간이 지났으면 LED를 끕(켭)니다.

이렇게되면, delay()로 아두이노를 일시중지 시키지 않고 loop()함수가 살아서 계속 반복적인 작업이 이루어지므로 LED가 깜빡거리는 동안 다른 작업이 가능해집니다.

쉬운 예시로 전자레인지에 피자데우기를 들 수 있습니다.
자, 전자레인지에 피자를 넣고 전자레인지를 작동시킵니다.
여기서
1) delay()함수로 10초간 기다리라고 하는 말의 의미는 전자레인지 앞에서 10초가 다 지나가기를 가만히 기다리라는 의미입니다. 결국 그동안에 다른 일은 못하죠!
2) 그러나 우리가 만약에 두가지 일을 하고 싶다면 어떻게 하나요? 전자레인지에는 시간 카운터가 달려있기에 전자레인지를 돌리고 짧은시간 다른 용무를 보고와서 전자레인지 시계를 확인하고, 10초가 지났는지 확인하고, 만약 10초가 지났으면 꺼내서 먹으면 됩니다!

1. 배선

우리는 아주 간단하게 실험해 볼 것이므로 내장된 Blink예제를 사용해보도록하죠!(즉, 따로 배선이 필요 없습니다)
Blink예제는 >>링크<< 포스팅에서 다루었습니다. 링크의 포스팅을 따라 블링크 예제를 불러와봅시다!

2. 코딩

블링크 예제의 코드는 아래와 같습니다.(상단의 주석부분은 제거하였습니다.)

// 보드의 파워나 리셋 버튼을 눌렀을 때 이 setup 함수는 한번만 작동합니다.
void setup() {
  // digital pin인 LED_BUILTIN을 output으로 초기화 합니다.
  pinMode(LED_BUILTIN, OUTPUT);
}

// 이 loop 함수는 계속 계속 영원히 반복하여 작동합니다.
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // LED 켜기 (HIGH는 전압 레벨)
  delay(1000);                      // 1초간 기다리기
  digitalWrite(LED_BUILTIN, LOW);   // 전압을 LOW로 설정하여 LED 끄기
  delay(1000);                      // 1초간 기다리기
}


자, 여기서 delay(1000) 즉, 1초간 아무것도 안하고 아두이노한테 기다리라고 하는 부분을 바꿔봅시다!

위의 예시에서 전자레인지의 시간만 중간중간 확인 가능하다면, 굳이 전자레인지 앞에서 지켜보고 있을 필요가 없다고했죠?
그러니 시간을 확인할 수 있는 함수를 알아봅시다!

millis()라고 하는 함수는 아두이노가 실행된 시점부터 내부적으로 카운팅하고 있는 밀리초의 시간을 반환하는 함수입니다.
즉, 이 millis()를 쓰면 중간중간 시간확인이 가능하다는 말이죠!

프로그램의 골자를 생각해봅시다.
1) 전자레인지를 돌리고 시간을 본다 => LED를 켜고 millis()로 시간을 확인한다(변수에 저장한다)
2) 시간을 확인한다 => 현재 시간이 처음 LED를 켠 시간에 비해 얼마나 지났는지 확인한다(현재시간 - LED 켠 시간)
3) 정해진 시간이 지났으면 피자를 꺼내먹는다 => [(현재시간 - LED 켠 시간) > 정해진 시간]이면 LED를 끈다

간단하죠? loop함수 내부 로직을 아래와 같이 짜봅시다.

// 1)
unsigned long startMillis;

digitalWrite(LED_BUILTIN, HIGH);
startMillis = millis();
// 2)&3)
if(millis()-startMillis >= 1000){
  startMillis = millis();
  digitalWrite(LED_BUILTIN, LOW);
}



자, 모든 조건을 만족하게 프로그래밍을 이렇게 하면... 작동하지 않습니다!
왤까요?
loop함수는 아두이노가 작동하는한 끊임없이 반복된다고 했습니다.
그런데 이 loop함수 내부에서 시작한 시간을 변수에 저장시키면, 매 loop함수가 작동할 때마다 변수에 새로운 값이 저장되기에 정확히 시작한 시간을 알 수 없죠!
그러면 대안은? 가장간단한건 loop함수 밖에서 시작시간을 설정해주거나, loop내에서도 일정한 조건일 때만 변수에 값을 넣어주는 겁니다.
게다가 loop함수 내부에서 digitalWrite(LED_BUILTIN, HIGH) 구문이 있기때문에 사실 LED_BUILTIN은 계속 켜져있을 겁니다.
일단은 가장 간단하게 갑시다! loop함수 밖에서 시작시간과 LED 켜기를 설정해줍시다.

unsigned long startMillis = millis(); // 전역변수는 함수 밖에 있어야 합니다.

void setup() {
  // digital pin인 LED_BUILTIN을 output으로 초기화 합니다.
  pinMode(LED_BUILTIN, OUTPUT);
  // 1)
  digitalWrite(LED_BUILTIN, HIGH);
}

// 이 loop 함수는 계속 계속 영원히 반복하여 작동합니다.
void loop() {
  if(millis()-startMillis >= 1000){
    startMillis = millis();
    digitalWrite(LED_BUILTIN, LOW);
  }
}



자, 이러면 작동합니다!
그러나 딱 한번만 작동합니다!
왤까요?
말그대로
1] 시작하면서 LED켜고 시간측정해!
2] 타이머가 1초가 지나가면 꺼!
끝이기 때문이죠. 1초가 지나면 꺼진상태가 그대로 유지됩니다.
그러면 어떻게 이 친구를 깜빡거리게(토글) 할 수 있을까요?
가장 간단한건 '1초일땐 꺼, 2초일땐 켜, 3초일땐 꺼...'지만, 이러면 모든 시간을 다 기록해줘야하죠..?
조금 더 머리를 써 봅시다.
지금 현재 LED 상태를 기억했다가 1초가 됐을 때 현재 LED상태를 보고 반대상태로 만들어주면 매 초마다 코딩을 하지 않아도 되지 않을까요!?
바로 실험해봅시다!

// 전역변수는 함수 밖에 있어야 합니다.
bool ledState; // led상태를 알 수 있는 변수를 하나 만듭니다. bool은 int와 다르게 참/거짓의 딱 두가지 값만 가질 수 있습니다. 우리는 결국 led가 켜졌냐/꺼졌냐 만 사용할 것이므로 bool을 사용합니다.
unsigned long startMillis = millis(); // 그리고 led 상태를 기록한 시간을 기록합시다.

void setup() {
  // digital pin인 LED_BUILTIN을 output으로 초기화 합니다.
  pinMode(LED_BUILTIN, OUTPUT);
  // 1)
  ledState = HIGH; // 그리고 바로 led를 켜지 말고, '상태'를 입력해주죠. 현재 led는 '켜짐상태'입니다.
}

// 이 loop 함수는 계속 계속 영원히 반복하여 작동합니다.
void loop() {
  if(millis()-startMillis >= 1000){ // led상태를 기록한 시간(startMillis)와 현재 시간(millis())를 비교해서 1초(1000ms)가 지났는지 판단합니다. 지났으면 if문 안으로! 만약 1초가 지나지 않았으면 이 if문은 통과합니다!
    if(ledState == HIGH){ // 현재 led상태를 확인합니다. 현재 led가 '켜짐상태'이면 '꺼짐상태'로, '꺼짐상태'이면 '켜짐상태'로 바꿔줄 겁니다.
      ledState = LOW; // 현재 led 상태가 '켜짐상태'였기에 '꺼짐상태'로 바꿔줍니다.
    }
    else{ // 아니면! 즉, 현재 led상태가 '꺼짐상태' 면
      ledState = HIGH; // 현재 led 상태를 '켜짐상태'로 바꿔줍니다.
    }
    startMillis = millis(); // 그리고 상태를 바꿔줬으니 바로 상태를 기록한 시간을 다시 기록합니다.
  }

  digitalWrite(LED_BUILTIN, ledState); // 마지막으로 '상태'를 LED에 진짜로 반영해줍니다!
}



자, 이 구문은 제대로 잘 작동합니다! 1초마다 LED_BUILTIN이 켜졌다 꺼졌다 하는군요!
전체적으로 작동로직을 한번 살펴볼까요?
처음 시작하면 setup함수 내부에서 LED를 '켜짐상태'로 설정하고, 그 시간을 기록합니다.
그리고 loop함수로 넘어오죠.
loop함수에서는 시작한시간과 현재시간을 비교하는데, 시작하고 1초도 지나지 않았습니다.
따라서 첫 if문은 바로 통과!
그 이후 loop함수 마지막에 digitalWrite로 LED_BUILTIN에 실제적으로 '상태'를 반영해줍니다.
결국 LED는 켜지고, 1초뒤에 첫번째 if문 안으로 들어갑니다.
첫번째 if문 안에서 현재 led상태가 HIGH이므로 두번째 if문으로 들어가 ledState를 LOW로 바꿔주고, 상태를 바꾼 시간을 다시 기록하고 if문을 빠져나와 digitalWrite로 LED_BUILTIN에 실제적으로 '상태'를 반영해줍니다.
그리고 이 반복이죠!

3. 더 나아가기

사실 위의 프로그램(스케치)은 loop함수 작동시마다 계속 digitalWrite를 부릅니다. 즉, 1초마다 한번씩만 바꿔주면 되는걸, 1초가 되기 전에 계속 '켜 켜 켜 켜 켜 켜 켜 켜'하고 반복신호를 주는거죠.(그리고 사실 이게 병렬처리가 되는 이유기도 합니다. 시간 체크하는 동안 계속해서 신호를 주는거죠.)
1초마다 신호를 주고, 더 짧은 코드를 공개합니다.
이번엔 주석을 지울테니 보고 더 생각해보세요!

bool ledState = LOW;
unsigned long startMillis = millis();

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if(millis()-startMillis >= 1000){
    digitalWrite(LED_BUILTIN, ledState=!ledState);
    startMillis = millis();
  }
}

함수설명: delay()

 

설명:

매개변수로 지정된 시간(밀리초(millisecond, ms)) 동안 프로그램을 일시 중지합니다. (1초(s)는 1000밀리초(ms)입니다.)

 

문법(syntax):

delay(ms)

 

매개변수(parameters):

ms: 일시 중지할 시간(밀리초)입니다. 허용되는 데이터 유형: unsigned long(부호없는 정수).

 

리턴값(returns):

없음

 

예제 코드:

이 코드는 출력 핀을 토글하기 전에 프로그램을 1초 동안 일시 정지합니다.

int ledPin = 13; // 디지털 핀 13에 연결된 LED

void setup() {
  pinMode(ledPin, OUTPUT); // 디지털 핀을 출력으로 설정합니다.
}

void loop() {
  digitalWrite(ledPin, HIGH); // LED를 켭니다.
  delay(1000); // 1초간 기다립니다.
  digitalWrite(ledPin, LOW); // LED를 끕니다.
  delay(1000); // 1초간 기다립니다.
}

 

참고:

delay() 함수로 깜박이는 LED를 쉽게 만들 수 있고 많은 스케치에서 스위치 디바운싱과 같은 작업에 짧은 지연을 사용하지만, 스케치에서 delay()을 사용하면 상당한 단점이 있습니다. delay 함수 작동 중에는 센서 판독, 수학적 계산 또는 핀 조작을 계속할 수 없으므로 사실상 대부분의 다른 활동이 중단됩니다. 타이밍 제어에 대한 다른 접근 방식은 충분한 시간이 경과할 때까지 millis() 함수를 폴링하여 반복하는 >>delay함수 없이 LED 깜빡이기<<를 참조하십시오. 일반적으로 Arduino 스케치가 매우 간단하지 않는 한 10밀리초 이상의 이벤트 타이밍에 delay()함수를 사용하지 않습니다.

그러나 delay() 함수가 인터럽트를 비활성화하지 않기 때문에 delay() 함수가 Atmega 칩을 제어하는 동안에도 특정 작업이 계속 진행됩니다. RX 핀에 나타나는 직렬 통신이 기록되고, PWM(아날로그 쓰기) 값과 핀 상태가 유지되며, 인터럽트가 정상적으로 작동합니다.

함수설명:digitalWrite()

 

설명:

디지털 핀에 HIGH(1) 또는 LOW(0) 값을 기록합니다.
핀이 pinMode()를 사용하여 출력으로 구성된 경우, 해당 전압은 HIGH의 경우 5V(또는 3.3V 보드의 경우 3.3V), LOW의 경우 0V(접지)로 설정됩니다.
input 모드로 설정된 핀에 대하여 사용 시 pullup 저항을 활성화 하지만, 가능하면 명시적인 INPUT_PULLUP을 사용하여 설정할 것을 추천드립니다.

 

문법(syntax):

digitalWrite(pin, value)

 

매개변수(parameters):

pin: 출력모드로 설정 된 아두이노 핀 번호
value: HIGH(1) 혹은 LOW(0)

 

리턴값(returns):

없음

 

예제 코드:

이 코드는 디지털 핀 13을 OUTPUT으로 설정하고, HIGH와 LOW로 토글(toggle, 전환)합니다.

void setup() {
pinMode(13, OUTPUT); // 디지털 핀 13을 OUTPUT으로 설정
}

void loop() {
digitalWrite(13, HIGH); // 디지털 핀 13을 on으로 설정
delay(1000); // 1초 기다리기
digitalWrite(13, LOW); // 디지털 핀 13을 off로 설정
delay(1000); // 1초 기다리기
}

 

참고:

위의 예제 코드에서 //(슬래시 두개)는 주석(컴파일 시 실제 코드로 인식 하지 않겠다는 의미)이며, 다른 글에서 설명하겠지만, delay() 함수는 말 그대로 '기다리는'함수이며, 그 안에 들어가는 값은 밀리세컨드 단위입니다. 즉 1000ms=1s 입니다.
아날로그 입출력 또한 가능합니다.
아날로그 입력의 경우 A0, A1 등으로 표시된 핀에서 가능하고, 출력은 ~(틸드)표시가 붙은 디지털 핀에서 가능합니다.
또한 반대로 아날로그 출력 핀(A0, A1, etc)을 디지털 핀으로 활용도 가능합니다.
예외적으로 아두이노 나노, 프로미니, 미니의 A6과 A7 핀은 오로지 아날로그 입력 핀으로만 사용할 수 있습니다.

함수설명: pinMode()



설명:

지정한 핀이 입력 또는 출력으로 작동하도록 구성합니다. 핀의 기능에 대한 자세한 내용은 >>아두이노의 핀에 대하여<< 페이지를 참조하세요.

INPUT_PULLUP 모드로 내부 풀업 저항을 활성화할 수 있습니다. 또한 INPUT 모드는 내부 풀업을 명시적으로 비활성화합니다.

 

문법(syntax):

pinMode(pin, mode)

 

매개변수(parameter):

pin: 모드를 설정할 아두이노 핀 번호
mode: INPUT, OUTPUT 또는 INPUT_PULLUP의 세가지 중 하나를 선택. 각 모드에 대한 자세한 내용은 >>아두이노의 핀에 대하여<< 페이지를 참조하세요.

 

리턴값(returns):

없음

 

예제 코드:

이 코드는 디지털 핀 13을 OUTPUT으로 설정하고, HIGH와 LOW로 토글(toggle, 상호전환)합니다.

void setup() { 
  pinMode(13, OUTPUT);    // 디지털 핀 13을 OUTPUT으로 설정 
} 

void loop() { 
  digitalWrite(13, HIGH); // 디지털 핀 13을 on으로 설정 
  delay(1000);            // 1초 기다리기 
  digitalWrite(13, LOW);  // 디지털 핀 13을 off로 설정 
  delay(1000);            // 1초 기다리기 
}

 

참고:

위의 예제 코드에서 //(슬래시 두개)는 주석(컴파일 시 실제 코드로 인식 하지 않겠다는 의미)이며, 다른 글에서 설명하겠지만, >>digitalWrite()<<는 핀에 해당 값을 출력하는 함수, digitalRead는 핀의 현재 상태를 읽는 함수입니다.
또한 >>delay()<< 함수는 말 그대로 '지연(기다리는)'함수이며, 그 안에 들어가는 값은 밀리세컨드 단위입니다. 즉 1000ms=1s 입니다.
아날로그 입출력 또한 가능합니다.
아날로그 입력의 경우 A0, A1 등으로 표시된 핀에서 가능하고, 출력은 ~(틸드)표시가 붙은 디지털 핀에서 가능합니다.
또한 반대로 아날로그 출력 핀(A0, A1, etc)을 디지털 핀으로 활용도 가능합니다.
예외적으로 아두이노 나노, 프로미니, 미니의 A6과 A7 핀은 오로지 아날로그 입력 핀으로만 사용할 수 있습니다.

아두이노의 핀에 대하여

 

빨간색 화살표가 가리키는 것처럼 아두이노에 있는 구멍 하나하나를 핀(pin)이라고 합니다.


Arduino 핀은 디지털 핀아날로그 핀으로 구분되며, 입력(INPUT)이나 출력(OUTPUT)으로 구성할 수 있습니다.
이 글은 디지털 핀에 대해서 말하지만, 대부분의 아두이노(Atmega) 아날로그 핀은 디지털 핀과 정확히 같은 방식으로 구성되고 사용될 수 있습니다.

디지털 핀(혹은 아날로그 핀)의 모드는 세가지 입니다.
가장 기본적인 INPUT(입력), OUTPUT(출력)과 특수한 INPUT_PULLUP입니다.
INPUT
INPUT_PULLUP
OUTPUT


INPUT으로 구성된 핀의 속성


Arduino(Atmega) 핀은 기본적(default)으로 input mode(입력 모드)입니다. 따라서 만약 이 핀들을 입력 모드로 사용할 것이라면 pinMode() 함수를 이용하여 명시적으로 선언할 필요가 없습니다.
INPUT으로 구성된 핀은 고임피던스 상태라고 하며 이는 회로에 크게 영향을 미치지 않습니다. 그러나 매우 작은 전류만으로 INPUT 상태 (켜짐/꺼짐 or ON/OFF or HIGH/LOW or 0/1)가 변할 수 있기 때문에 pullup(풀업) 혹은 pulldown(풀다운) 회로를 구성하는 것이 좋습니다.
일반적인 INPUT 모드에서는 센서가 꺼졌을 때 0(LOW), 켜졌을 때 1(HIGH)입니다.



INPUT_PULLUP으로 구성된 핀의 속성


INPUT_PULLUP 모드의 경우 INPUT 모드에 자체적으로 PULLUP 저항을 적용하는 모드입니다. INPUT_PULLUP으로 구성된 핀에 센서를 연결할 때는 반드시 다른 쪽 끝은 접지에 연결해야 합니다.
Atmega 칩에는 기본적으로 20K(키로옴)의 풀업 저항이 내장되어있습니다.
INPUT_PULLUP 모드에서는 센서가 커졌을 때 1(HIGH), 켜졌을 때 0(LOW)입니다.


OUTPUT으로 구성된 핀의 속성


pinMode() 함수를 사용하여 OUTPUT으로 구성된 핀은 저임피던스 상태라고 합니다. 이는 다른 회로에 상당한 양의 전류를 제공할 수 있음을 의미합니다. Atmega 핀은 최대 40mA(밀리암페어)의 전류를 다른 장치/회로에 공급(양전류 제공)하거나 싱크(음전류 제공)할 수 있습니다. 이 전류는 LED를 밝게 켜거나(직렬 저항을 잊지 마십시오) 많은 센서를 작동하기에 충분한 전류이지만 대부분의 릴레이, 솔레노이드 또는 모터를 작동하기에는 충분한 전류가 아닙니다.


아두이노 핀의 단락이나 고전류 장치의 구동을 시도하면 핀의 출력 트랜지스터가 손상되거나 파괴되거나 아트메가 칩 전체가 손상될 수 있습니다. 종종 이로 인해 마이크로컨트롤러에 "데드" 핀이 발생하지만 나머지 칩은 여전히 적절하게 작동합니다.

피타고라스와 작두콩(잠두): 제 1계명 "콩을 먹지 말라"

 

오늘은 아주 흥미로운 사실에 대해 알아보려고 합니다.

 

여러분들은 피타고라스를 알고 계신가요?

피타고라스는 기원전 570년 경 태어난 사람으로 알려져 있는데요, 우리에게는 삼각형의 빗변의 제곱은 밑변의 제곱과 높이의 제곱의 합과 같다는 '피타고라스 정리'라는 것으로 제일 유명하죠.

아주 유명한 피타고라스 정리: a^2+b^2=c^2

그러나 이런 피타고라스가 한 종교의 교주였다는 사실을 알고 계셨나요?

 

피타고라스는 피타고라스 학파를 만들며 여러 계명들을 만들었는데요, 그 중에 제일 재밌는 계명이 제 1계명입니다.

바로 "콩을 먹지 말라"는 건데요, 대체 왜 이 계명이 생겼을까요?

 

썰은 정말 다양합니다.

피타고라스가 채식주의자임에도 콩을 금지한 이유는 소화가 잘 안되어서 라거나, 이상한 종교적 믿음으로 콩과 사람이 비슷해서 등등 얼핏 듣기에는 잘 이해가 가지 않는 썰들이 있습니다. 특히나 채식주의자에게 콩은 단백질 보급의 주요 원천이기에 그 옛날에 채식주의자가 콩을 금지했다는건 경험적으로도 뭔가 안맞는 이야기이기도 하구요.

 

그러나 여기에는 나름 아주 매력적인 썰이 있습니다.

바로 피타고라스가 콩을 먹으면 아팠었기 때문이라는 썰입니다. 결국 무슨 질환을 가지고 있었다는 것이었겠죠?

 

도대체 이게 왜 매력적인 썰일까요?

각 파트별로 나눠서 살펴보죠.

콩, 질환, 고찰 그리고 결론 입니다.

 

1. 콩

작두콩, 잠두, 누에콩, 파바빈, fava bean, broad bean

그 시절 지중해에서 나는 콩들은 '작두콩' 혹은 '잠두'(혹은 누에콩, 파바빈, fava bean, broad bean)라고 불리는 콩들이었습니다.

Vicin의 화학구조식 출처: Wikipedia

이 작두콩에는 Vicin(비신)이라는 성분이 있는데, 이 비신이라는 성분은 자체로는 아무런 해가 없습니다만, 이게 대장에서 정상세균총(micro flora)에 의해 가수분해되면, aglycon(아글리콘: 글루코오스(6탄당) 형태가 빠진)인 divicin(디비신)이라는 성분으로 대사되고, 이 성분은 활성산소(free radical) 생성 물질이 됩니다. 그리고 이 산화 능력은 체내 자체적인 환원 물질인 glutathione(글루타치온)에 작용, 이를 소모하게 합니다.

정상인에게는 비록 이 물질이 생성된다하더라도 빠르게 글루타치온을 재생성 할 수 있기 때문에 문제가 되지 않지만, 몇몇 사람에게는 이게 큰 문제를 일으킬 수 있습니다.

그 중 가장 유명한 것이 G6PD 결핍증입니다.

 

2. 질환

G6PD 결핍증(glucose-6-phosphate dehydrogenase deficiency, 6-인산포도당탈수소효소 결핍증)은 오탄당 인산경로(pentose phosphate pathway)에 쓰이는 G6PD가 결핍되어 생기는 질환입니다.

특히나 적혈구의 대사에서 중요한 효소지요.

산화적 손상을 일으키는 자유라디칼을 제거하는 '글루타치온(Glutathione)'을 환원시키는데 NADPH가 사용되는데, 적혈구에서는 이 오탄당 인산경로가 유일한 NADPH 공급원입니다.

따라서 여기서 이 환원적 환경을 만들어 낼 수 있는 G6PD가 결핍되게되면 결과적으로 적혈구는 매우 불안정한 상태가 됩니다. 약간의 자극에서 적혈구 세포막이 터질 수 있고, 결국 이는 용혈성 빈혈로 나타나게 되죠. 특히나 적혈구가 산화적 상태로 불안정하다는 것을 주목해야 합니다. 결국 외부에서 산화적 스트레스가 오면 아주 쉽게 적혈구가 용혈 될 수 있다는 것이죠.

출처: Wikipedia(이미지 일부 발췌)

다시 생각해보면, 결론적으로 피타고라스는 이 질병을 가지고 있었을 것이며, 그렇기에 대사과정에서 활성산소를 만들어내는 작두콩을 먹으면 용혈성 빈혈로 매우 아팠을 것입니다.(이를 잠두중독증(favism(파비즘))이라 하며, 잠두(누에콩)의 이름인 fava bean에서 유래했습니다.)

그럼 피타고라스는 왜 이 질병을 가지고 있었을까요?

 

3. 고찰

이 G6PD 결핍증은 X염색체 연관으로 유전됩니다. 즉, 여자는 보인자, 남자는 무조건 증상이 발현된다는 말이지요.

보통 한 지역에서 유전병이 계속 지속되는 이유는, 그 유전병을 가짐으로 인해서 얻는 이득이 있을 때 사라지지 않고 유전병이 유지되는 경향이 있습니다. 겸상 적혈구 빈혈증도 말라리아에 대해서 저항성이 있기 때문에 정상적인 적혈구를 가진 사람보다 생존에 유리해서 계속해서 그 유전병이 남아있죠.

똑같이 G6PD결핍증도 적혈구를 약하게 만들기 때문에 말라리아에 저항성이 생깁니다. 정확히는 말라리아가 원충으로 적혈구에 들어갔을 때 거기서 성숙을 못하게 적혈구를 쉽게 파괴시켜버리기 때문에 말라리아에 대해 저항성이 생기는거죠.

특히나 과거 지중해에서 말라리아가 호발했기 때문에(이는 지중해성 빈혈 등 빈혈 관련 유전병이 지중해에서 유래한 것이 많다는 것이 반증하기도 합니다.) 오히려 정상인보다 G6PD 결핍증을 가진 사람이 생존에 더 유리했을 것입니다.

 

4. 결론

결국 이 모든 내용을 조합해보자면, 말라리아가 호발하던 지중해에서 태어난 피타고라스는 G6PD 결핍증을 가지고 있었고 작두콩을 먹고 잠두중독증(favism)으로 매우 아팠었을 겁니다. 그래서 교주가 된 이후에 제 1계명을 "콩을 먹지 말라"고 했겠죠.

그리고 또하나 재밌는 사실은 피타고라스의 죽음도 콩과 연관되어 있다는 점입니다.

피타고라스의 죽음도 썰이 정말 많지만, 재밌는 점은 모두다 콩과 관련되어있습니다.

도망가던 중에 콩 밭을 지나다가 그자리에서 쓰러져 죽었다던가, 결국 콩 밭을 지나지 못하고 잡혀서 죽었다던가 하는 이야기지요

 

오늘 주제 어떻게 흥미로우셨나요?

다음에 더 재밌는 주제로 찾아오겠습니다!

[가벼운 외국어] 초기 시작 가이드!!

 

안녕하세요!

얼마전부터 가벼운 외국어 학습지로 프랑스어를 시작하였습니다.

 

분명히 이것저것 제공하는 것도 많고, 정말 가볍게 하루 20분 남짓으로 일주일에 평일 딱 5일만 공부하는 건 너무 좋습니다만, 문제는 너무 제공하는것이 많은데 비해 제대로 된 가이드가 없어서 조금 아쉽다는 생각이 들었죠..

 

그래서! 뚜둔! 직접 공부하면서 경험한 내용을 여기서 풀어보겠습니다!!

저는 초반에 가이드가 좀 부실하여 여기저기 많이 헤맸지만, 제 경험을 바탕으로 더 수월하게 공부하실 수 있기를 바랍니다!

 

저는 프랑스어가 기준이니까 프랑스어를 기준으로 설명하겠지만 다른 언어들도 어느정도 비슷하지 않을까 싶습니다!

 

자, 그럼 시작해보죠!

 

1) 대망의 결제

모든 귀차니즘을 이겨내고, 새로운 도전에 대한 갈망으로 이런저런 고민을 거듭하다 나름 비싸다면 비싼 돈을 들여 '가벼운 외국어'를 결제한 당신! 짝짝짝! 시작이 반이라는 말처럼 정말 큰 한보를 내디디신 겁니다!

그런데, 딱 결제를 하고 막상 뭘 해야 할지 모르는 사태가 벌어집니다!

일단 택배가 온다고는 했는데, 그럼 택배가 올때까지 기다려야 하는건가...?

아닙니다! 강의는 결제한 그 순간부터 볼 수 있습니다!

그럼 교재없이 강의부터?

그럼 조금 기분이 좀 그렇죠..?

 

2) 발음 강의부터!

자, 그럴땐 각 언어마다 '파닉스' 혹은 '발음' 강의가 있을 것입니다!

물론 파닉스도 교재가 있긴 합니다만, '발음'강의이기 때문에 수업을 들을 때 교재가 아주 큰 비중을 차지하지는 않습니다! 또한 일단 수강하고 나중에 교재를 받고나서 복습차원에서도 좋지요! 발음은 정말 중요하니까요!

그래서 일단 결제를 바로 하자마자, 발음 강의부터 들읍시다!

우리의 열정이 택배를 기다리며 사그라들기 전 일단 더 불을 피우는거죠!

발음 강의도 한두강으로 끝나는게 아니라, 강의가 10강 내외로 꽤 됩니다!

특히 프랑스어의 경우 파닉스 강의가 두개나 되죠!

그래서 제 추천은 일단 '나의 가벼운 프랑스어 파닉스북' 강의를 먼저 들으시는 걸 추천드립니다.

그리고 다 들으면 '파비앙의 프랑스어 원어민 발음' 강의를 이어서 들으셔서 복습과 함께 원어민 선생님의 발음도 한번 더 듣구요!

그리고 교재가 오면 다시 '나의 가벼운 프랑스어 파닉스북' 강의를 들으시면서 복습을 하시거나, 교재만 가지고 한번 빠르게 복습을 해보시는 걸 추천드립니다!

 

3) 그다음은?

그 다음부터는 그래도 가이드가 좀 있습니다. 첫 택배를 받으시면 그 안에 작은 리플렛으로 '활용 백서'라는게 있습니다. 이걸 읽으시면 그 다음부터는 좀 가이드가 되는데, 사실 이 전이 가이드가 없어서 제가 포스팅을 쓰게 됐죠!

일단 간단하게 말씀드리면, 프랑스어는 '나의 가벼운 프랑스어 Level 1'부터 'Level 4'까지가 스타터팩입니다.

스타터팩만 결제하신분은 이렇게까지만 들으시면 되고, '회화팩'을 결제하신 분은 이 과정을 수료하신 뒤 '가벼운 프랑스어 회화 패턴 A1'으로 회화로 들어가게 됩니다. 그리고 이때는 '회화 패턴 A1 트레이닝'이라는 강의가 있어서 같이 병행하시고, 다 들으시면 'A2'로 승급!

추가적으로 '기적팩'을 결제하시면 이 다음 단계인 'B1'까지 들으시면 됩니다!

 

4) 마무으리..

결국 어떻게 보자면 정규 과정? 이라고 볼 수 있는 Level 1~4, A1~2, B1까지 설명을 드렸는데, 사실 이 포스팅을 처음 쓰게 된 계기는 처음에 결제하고 택배오기까지 뭘 어떻게 해야할지 몰라서 그냥 넋놓고 기다리다 결국 택배를 받고 첫 강의를 들었는데 뭘 들어야 할지 모르겠으며, 당장 Level 1 첫강의를 켜자마자 발음을 그냥 확~ 넘어가시는 바람에 진짜 한번에 강의 세개를 동시에 들어가면서 고생했던 기억이있어서 쓰게 되었습니다.

저의 작은 글이지만, 앞으로 외국어 공부하시는 분들에게 도움이 되길 바라며! 모두모두 화이팅입니다!

+ Recent posts