반응형

【 윈도우-문제해결 SMB 서버 설정방법 / SMB1 프로토콜이 필요합니다 / 시스템에 SMB2 이상이 필요합니다. 안전하지 않기 때문에 파일 공유에 연결할 수 없습니다. 와같은 에러 메시지 해결방법!

 

 안녕하세요~
 오늘은 윈도우 환경에서 위와 같은 에러가 발생했을 때, 조치 / 해결하는 방법에 대해 다루어 봅니다. 
윈도우 환경에서 네트워크 공유를 통해 또는 NAS와 같은 네트워크 드라이브 폴더에 접근하려고 할 때, 아래와 같은 메시지를 띄우며 연결되지 않는 상황이 발생합니다. 

이는 윈도우 시스템이 보안이 취약하다고 판단되는 폴더 공유에 대해 기본적으로 차단되어 있는 상태여서 이런 경고 혹은 에러 메시지를 띄우게 됩니다.    

 이럴 때는 아래와 같은 방법으로 옵션을 체크해 주면 간단히 해결 됩니다. 
1. 먼저, 윈도우 검색란에 "Windows 기능 켜기/끄기" 로 검색 후 실행합니다. (또는 제어판에서 찾을 수 있습니다)

 

2. 아래와 같은 Windows 기능 켜기/끄기 메뉴가 나타나면, "SMB 1.0/CIFS 파일 공유 지원" 항목을 찾으세요.

3. "SMB 1.0/CIFS 파일 공유 지원" 항목에 있는 세가지 항목 모드 체크하고 확인을 누르세요.

4.  변경사항을 적용하기 위해 재부팅 후,  다시 네트워크 공유 폴더에 접근해 보시면, 이제는 에러 메시지 없이 접근이 가능합니다. 

 

 감사합니다. 
오늘은 윈도우 환경에서 공유폴더에 접근하려 할 때, SMB 서버 설정방법 / SMB1 프로토콜이 필요합니다 / 시스템에 SMB2 이상이 필요합니다. 안전하지 않기 때문에 파일 공유에 연결할 수 없습니다. 와같은 에러 메시지 해결방법에 대해 다루었습니다. 
 그럼, 오늘 하루도 쾌적한 하루 되세요~ ^^&

반응형
반응형

 파이썬 기초#6】 파이썬 기초 한방에 정리하기!  #2편 , 조건문-함수편-기타 핵심 요약, 총정리!

(내용은 게시글 마지막 부분부터 계속 추가 예정입니다 , 마지막 편집일: 21.08.08)

아래 1편의 내용을 먼저 참고하세요
▶ 파이썬 한 방에 정리 1편 보기  : https://rasino.tistory.com/333  
▶ 파이썬 한 방에 정리 3편 보기  : https://rasino.tistory.com/338  

 

1. 《  if  문  》
 : 조건이 맞으면 실행을 하라~!
 "if 조건 : " 문은  if 뒤에 조건이 맞으면(true)  if 문에 속해 있는 문장들을 실행하게 됩니다. 

 파이썬에서는 C언어에서 처럼, if문에서 { 중괄호 } 같은 것을 사용하지 않고, 인터프리터 언어의 특성인 한 줄씩 처리되도록 하기 위해 ' : ' 콜론을 사용합니다. 
 그렇기 때문에, if문에 속해 있는 문장들은 모두 들여 쓰기(탭키, 혹은 보통 4칸)를 하여 구분합니다. 
 또한,  파이썬은 유연성이 좋아 위 예시처럼 한 줄에 출력까지 기술해 줄 수 있습니다. 


2. 《  if  ~ else 문  》
 : 조건이 참(True)이면 실행할 코드와, 조건이 거짓(False)이면 실행할 코드를 구분하여 작성할 때, 사용하게 됩니다. 

 if <조건> : 
       (조건이 True 참이면 실행할 문장들 ...  )
 else :
       (조건이 False 거짓이면 실행할 문장들 ...  )

- def '함수명( )' 은 사용자 정의 함수입니다.   
- num = int (input(" 입력....: "))   >>  화면에 숫자를 입력받을 때, 글자를 출력하고, 입력받은 숫자(문자)를 정수형으로 처리하여 num이라는 변수에 대입하는 형태를 많이 사용합니다.

 

3. 《  if  ~  elif  ~  else 문  》
 : 조건이 여러개인 상황에서 하나를 선택하도록 할 때 사용하게 되는 코드 유형입니다.

 if <조건 1> : 
       (조건 1이 True 참이면 실행할 문장들...  )
 elif <조건 2> : 
       (조건 2가 True 참이면 실행할 문장들...  )

 elif ...

 else :
       (위의 모든 조건이 False 거짓이면 실행할 문장들...  )

< 아래 예제 코드를 참고하세요 >

 

※  if 문의 기본 구조는 ,    if  《 조건 》입니다.   그래서  조건이 참(True)이면,  if :  문에 속해 있는 내용들이 실행되며, 조건이 거짓(False) 이면, 실행되지 않습니다. 
 그럼 여기서, 조건의 기준인 True와 False 가 되는 기준이 있다는 것을 알 수 있습니다. 
Bool 값인  'False'와 숫자 '0'  그리고 '  ' 공백은 False로 처리되며,   이것 이외의 모든 것 들은 True로 처리됩니다. 
 예를 들어,  논리 값 'True' , 숫자 '1' 뿐 아니라,  '2', '3', ...  ,  영문자 'A' , 'a',  'b',  등등 모두 True로 처리되어,  if 문에 속한 코드들이 실행됩니다. 

 

3. 《  if  문과 논리 연산자  》
 :  if 문에서 하나 이상의 조건을 비교해야 할 때, 논리 연산자를 사용하여 처리할 수 있습니다.
 아래가 사용할 수 있는 논리 연산자입니다.

연산자 설명 예시  
and
두 조건이 모두 참인 경우  성립되는 연산자.
if  a == 1 and b== 2 :
      print("OK")

: a가 1이고, b가 2 모두를 만족할 때 print문이 실행됩니다
or
두 조건 중 하나라도 참이면 성립되는 연산자.

if  a == 1 or b== 2 :
      print("OK")

: a가 1이거나, 또는 b가 2라면, 둘 중 하나만 만족한다면  print문이 실행됩니다
not
조건을 반대로 뒤집는 연산자.
if  not a == 1 :
      print("OK")

: a가 1이 아니라면, print문이 실행됩니다

물론, 위의 연산자 여러 개를 조합하여 사용 가능합니다. 
그 밖에, 아래 비교 연산자를 활용할 수 있습니다. 

연산자 설명
== 같다
!= 다르다 (같지 않다)
< 좌변이 우변보다 작다
> 좌변이 우변보다 크다
<= 좌변이 우변보다 작거나 같다
>= 좌변이 우변보다 크거나 같다


4. 《  in과  not  in  연산자 》
 :  리스트 혹은 문자열에 해당 문자(숫자)가 있는지? 확인하여  참(True) 또는 거짓(False)으로 반환합니다.
 in과 not in 연산자는 뒤에 for 문과 if문에도 사용되니 기억해 두세요.
1.    x in str   :   str에  x가 있으면 True,  없으면 False를 반환
2.    x not in str   :   str에  x가 없으면 True,  있으면 False를 반환

 

5. 《  for  루프 》
 : for 루프 문의 기본 골격은 아래와 같습니다. 
  for 《변수》 in 《범위》
       <for에 속하는 문장들...>
       <for에 속하는 문장들...>

<예시>

또는 위에 범위에 해당되는 부분을 range( )로 표시하여 아래처럼 줄여 표현할 수 있습니다. 

 

6. 《  while  루프 》
 : while 루프문의 기본 골격은 아래와 같습니다. 
 while조건 》 :
        <조건이  True인 경우 동안 계속 반복 실행될 코드들...>
        <조건이  True인 경우 동안 계속 반복 실행될 코드들...>

<예시>

 

7. 《  break 》
 : while 루프 문이나, for 루프문에서 사용할 수 있으며,  break가 실행되면,  해당 루프 문을 종료하고 빠져나오게 됩니다.

 <예시>

 

8. 《  continue 》
 : while 루프문이나, for 루프문에서 사용할 수 있으며,  while문이나,  for 루프문 속에서 continue 문장을 만나면, continue 문 아래 문장들은 실행되지 않으며, while문이나 for문의 다음 반복으로 계속 이어집니다. 

 <예시>
continue문을 이용하여 < 1에서 10까지 홀수만 출력하기 > & <1에서 10까지 짝수만 출력하기 >

 

9. 《  for문 이중 루프 》
 : for 루프문을 이중으로 이용할 수 있으며,  이중으로 반복해야 하는 곳에 사용하게 됩니다. 
아래, 구구단을 예시로 들겠습니다.
  < 파이썬 구구단 >

>>> < 구구단 2단부터 9단까지 한 단씩 세로로 출력하기 >
>>> for dan in range(2, 10):
            print("=====",dan,"단=====")
            for hang in range(1, 10):
                print(dan," * ", hang,"=",dan*hang)
                print()    # 한 줄 띄움

 

※ 그럼, 이번에는 구구단을 가로로 한 번에 출력해 볼게요. 
>>> < 구구단 2단부터 9단까지 가로로 한 번에 출력하기 >
>>>def gugudan() :
          print (" ====== 구구단 가로로 출력하기 =====")
          for hang in range(1, 10) :
              for dan in range(2, 10):
                  print(dan,"*",hang,"=",dan*hang," | ",end="\t")
                  print()

이미지 클릭시 확대 됩니다

위와 같이 "\t" 탭 출력을 이용해서 가로로 출력이 잘 되었습니다. 
그런데, 약간의 문제는 두 자릿수 값 출력의 경우 출력 자리가 밀려서 정렬이 깔끔하게 되지 않는데요, 
이때는, print문의 출력 형식을, C언어에서와 같은 형식으로 정수의 자리를 지정하여 출력하면 해결할 수 있습니다. 

 < 구구단,  출력 정렬하여 가로로 출력하기 >
>>>def gugudan() :
           print (" ====== 구구단 가로로 자리 정렬하여 출력하기 =====")
           for hang in range(1, 10) :
                for dan in range(2, 10):
                print("%d * %d = %2d | "%(dan, hang, dan*hang), end="\t")
           print()
>>> gugudan()

이미지 클릭시 확대 됩니다

10. 《  pass 》
 : 파이썬에서는 아무 기능을 하지 않는 빈 코드의 역할로 pass 키워드를 사용합니다.
보통 C언어의 비어있는 코드의 역할로 { } 중괄호를 사용하는데,  파이썬에서는 { } 중괄호를 사용하지 않기 때문에,  pass라는 키워드를 사용합니다. 
 pass는 코드가 다소 복잡하거나 사이즈가 어느 정도 되는 코드를 작성할 때 나중에 완성할 함수 같은 부분에 pass를 넣어놓고 최소한의 구조를 완성시켜 놓고 작업하게 되는데, 이러면 나중에 완성해야 할 부분에 대한 표시도 되고, 다른 코드 부분을 테스트하기에도 방해되지 않아 편합니다. 

< 예시 >
score = 100
if score >= 80 :
else:
이와 같이 작성한다면,  나중에 작성한다 하더라도, 우선적으로 구문 형식이 맞지 않고, 다른 부분 에러 테스트에도 이 부분 때문에 에러가 발생하여 불편을 주게 됩니다. 
이럴 때,  아래처럼 우선 아무 역할도 하지 않는 pass를 넣어 작업을 진행하면 됩니다. 
score = 100
if score >= 80 :
    pass
else : 
    pass


11. 《  함수 》

 : 함수는 반복적으로 처리해야 하는 부분을 함수로 만들어 놓고 호출하게 되면, 소스코드가 짧아지고, 크기도 줄어들기 때문에 많이 활용하게 됩니다.  이를 사용자 정의 함수라고 하며,  def  ...  형식으로 만들어 사용할 수 있습니다.
 또한 이미 통상적으로 사용되는 기능들을 함수로 만들어 놓았는데,  이를 내장 함수라 칭합니다. 
내장 함수이기 때문에,  별도의 import 문을 사용하여 라이브러리를 추가하지 않고 바로 사용가능합니다. 

< 파이썬 내장 함수 >

파이썬 내장 함수들 ( Built-in Functions )
abs( ) dict( ) help( ) min( ) setattr( )
all( ) dir( ) hex( ) next( ) slice( )
any( ) divmod( ) id( ) object( ) sorted( )
ascii( ) enumerate( ) input( ) oct( ) staticmethod( )
bin( ) eval( ) int( ) open( ) str( )
bool( ) exec( ) isinstance( ) ord( ) sum( )
bytearray( ) filter( ) issubclass( ) pow( ) super( )
bytes( ) float( ) iter( ) print( ) tuple( )
callable( ) format( ) len( ) property( ) type( )
chr( ) frozenset( ) list( ) range( ) vars( )
classmethod( ) getattr( ) locals( ) repr( ) zip( )
compile( ) globals( ) map( ) reversed( ) __import__( )
complex( ) hasattr( ) max( ) round( )  
delattr( ) hash( ) memoryview( ) set( )  

내장함수 각각에 해당하는 설명은, 공식 사이트의 링크 설명을 참조해보세요.
링크 :  https://docs.python.org/ko/3/library/functions.html

 

내장 함수 — Python 3.9.5 문서

내장 함수 파이썬 인터프리터에는 항상 사용할 수 있는 많은 함수와 형이 내장되어 있습니다. 여기에서 알파벳 순으로 나열합니다. abs(x) 숫자의 절댓값을 돌려줍니다. 인자는 정수, 실수 또는 __

docs.python.org


<문자열 검색 관련 함수들>
문자열에 내용을 검색하여 알려주는 기능의 함수 들입니다. 
함수의 이름은 is xxx ( )의 조합으로 이해하면 기억하기 쉽습니다.

함수 설명    
isalpha( ) 모든 문자가 알파벳인지 조사합니다.
islower( ) 모든 문자가 소문자인지 조사합니다.
isupper( ) 모든 문자가 대문자인지 조사합니다.
isspase( ) 모든 문자가 공백인지 조사합니다.
isalnum( ) 모든 문자가 알파벳 또는 숫자인지 조사합니다.
isdecimal( ) 모든 문자가 숫자인지 조사합니다.
isdigit( ) 모든 문자가 숫자인지 조사합니다.
isnumeric( ) 모든 문자가 숫자인지 조사합니다.
isidentifier( ) 명칭으로 쓸 수 있는 문자로만 구성되어 있는지 조사합니다.
isprintable( ) 인쇄 가능한 문자로만 구성되어 있는지 조사합니다.

위와 같은 함수는 사용자로부터 특정 값을 입력받았을 때, 입력값이 숫자로만 이루어져야 한다든지? 알파벳 소문자로만 이루어져야 한다든지? 특수문자가 있으면 안 된다든지? 등과 같은 상황에서 체크를 쉽게 할 수 있어 활용성이 좋습니다. 

<예시 : 사용자 입력값에 숫자만 허용하고자 할 때>

 

12. 《  튜플과 리스트 》
 : 튜플은 리스트[list] 처럼 파이썬이 인식하는 데이터의 한 종류입니다.  리스트와 비슷한점이 있지만, 결정적인 차이가 있습니다. 
 - 리스트와 튜플은 모두 하나 이상의 값을 묶는 용도로 사용합니다. 
 - 리스트는 [ 1, 2, 3, ... ]  중괄호를 사용하고,  튜플은 ( 1, 2, 3, ... ) 소괄호를 사용합니다.


 - 리스트는 아래 이미지처럼, 요소를 추가하거나 다른 값으로 수정이 가능합니다.


- 하지만, 튜플은 값을 참조하는 것은 가능하지만, 처음 정해진 값의 요소를 수정 변경할 수 없는 차이가 있습니다.

튜플은 기존 값에 값을 추가하거나 변경이 불가 합니다

- 이렇듯 튜플은 리스트에 비해 유연하지도 않고, 리스트형만 있어도 될 것 같지만, 분명한 쓰임새가 있습니다.
- 예를 들어, 생년월일 정보나, 고유 ID 요소 등, 의도하지 않은 조작에 의해 요소값이 변경되어서는 안 되는 데이터 유형에 사용할 수 있습니다.

- 리스트관련 사용가능한 함수와 연산에 대해서는 앞선 내용에서 많이 다루었는데요,  그럼 튜플 관련 함수와 연산에 대해 살펴볼게요.  여기서 리스트 데이터형에 사용된 함수의 대부분이 튜플에도 그대로 적용되는 경우가 많습니다.

함수 설명  
len(x) 튜플 x의 길이(요소의 개수) 반환
min(x) 튜플 x의 요소 중에서 가장 작은 값 반환
max(x) 튜플 x의 요소 중에서 가장 큰 값 반환
s.count(x) 튜플 s에 저장된 요소 중에서 x의 개수 반환
s.index(x) 튜플 s에 저장된 요소 중 첫 번째 x의 인덱스 값 반환

튜플의 함수 적용 예시

그리고, 튜플은 리스트와 마찬가지로 아래와 같은 연산이 가능하다.

위 연산에서 보면, Tpl + (6, 7) 연산의 결과로 기존 튜플에 요소가 추가(변경) 된 것으로 보이지만, 다시 Tpl을 출력해보면, 기존 값(1, 2, 3, 4, 5)이 그대로 있으며,  수정된 것이 아니라 새로운 튜플이 만들어 진 것입니다. 그래서 이를 Tpl2에 저장해서 보여준 것입니다.  기타 리스트에서 가능했던 * 곱하기 연산이나 [2:6] 인덱스 값 읽기 등 수정되지는 않지만 모두 동일하게 가능합니다. 
 그리고 아래처럼 for 루프 문에서 사용하던 문법도 동일하게 적용가능합니다. 

for 문에서의 리스트와 튜플 요소 참조

  단,  아래와 같은 range ( ... ) 함수는 튜플이 아니라 range( ) 라는 자체 함수를 참조 사용한 것입니다. 
  range 함수 원형 :  range( 초기값, 최종값, 증가값)  - 증가값은 생략가능(1씩 증가)

그런데,  range( .... ) 함수가 없다면, 예를들어, 1에서 100까지의 수를 리스트나 튜플로 참조하려면 매우 짜증?이 나겠지요?    (ex,  for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ....  ]   ) 
  그래서 range ( ) 함수를 사용하면 간단히 해결 되며,  step 간격도 넣어 줄 수 있습니다.

- 또한 아래처럼, range( ) 함수를 이용하면,  매우 긴 연속된 수를 간단히 리스트나 튜플로 만들 수 있습니다. 
  (예, 만약 1~100까지의 수를 리스트 변수나, 튜플 변수의 요소로 만든다고 한다면,  Lst = [1, 2, 3, 4, 5.... 100??? ], 
Tpl =  (1, 2, 3, 4, 5, ... 100???)    어휴....  생각만해도 손목의 피로도가... )

range( )함수를 이용하면 많은 수의 요소를 직접 입력하지 않아도 된다


[ 리스트와 튜플 데이터의 상호 변환이 가능합니다! ]

아래처럼   list(  ) 함수와,  tuple( ) 함수를 이용하면, 리스트 데이터를 튜플데이터로, 튜플데이터를 리스트 데이터로 상호 변환이 가능합니다.

리스트와 튜플 데이터의 상호 변환

 

[ 문자열을 리스트와 튜플 데이터로 저장하기! ]
아래처럼, 문자열을 하나하나 떼어 리스트 데이터나 튜플 데이터로 각각 저장 가능합니다. 

문자열을 리스트와 튜플 데이터로 저장하기!

 

[ range (  ) 함수 의 범위 거꾸러 지정하기 ]
 
range 함수 원형 :  range( 초기값, 최종값, 증가값)  - 증가값은 생략가능(1씩 증가)

range 함수의 범위를 거꾸로 넣기 위해 range (10, 1) ,  또는 range(10, 1, 1) 로 해서는 안 됩니다.  
range 함수 원형을 보면, 생략가능한 세번째 요소가 기본적으로 증가값 이기 때문에, 초기값 10에서 1까지 증가 시킬 수는 없기 때문입니다.  만약 이렇게 하면 비어 있는 값으로 저장됩니다. 
따라서, 아래 이미지 처럼, -1, 또는 -2처럼 음수 값의 감소값을 주어야 합니다. 

range 함수의 범위를 거꾸로 넣기 위해서는 세번째 요소를 음수로 주어야 함

 

13. 《  함수 만들기 》
 : 파이썬에서 함수 만들기에 대해 다루어 보겠습니다.  파이썬에서 함수를 'def' 라는 표시자를 사용하여 함수를 정의하고, 함수명 예를 들어 Hello( )을 정하고 ' : ' 콜론을 붙여서 그 아래 줄부터 함수의 내용을 넣으면 됩니다.   그리고 함수명 Hello( )를 호출 하여 사용할 수 있습니다. 
⊙ 함수의 유형은 대략 아래 세가지로 분류할 수 있습니다. 
1. 아무 값도 전달 받지 않는 함수
2. 값을 전달받는 함수
3. 값을 반환하는 함수 (return 명령을 갖는 함수) 

먼저 1번 함수의 예시는 아래와 같습니다. 
<1. 아무 값도 전달 받지 않는 함수 예시>

인자의 전달이 없는 기본 함수의 유형

<2. 값을 전달 받는 함수 예시>
두 번째 함수 유형으로, 인자 값을 전달만 받고 처리하는 함수의 유형입니다.  함수를 호출 할 때, 인자값 또는 인수값이라 불리우는 영어로 argument 를 전달해 주고 ,  함수에서는 이 값을 처리해서 출력하거나 하며 결과값은 되돌려 주지 않는 형태의 함수 유형입니다.  아래 예시에서는 결과값 확인을 위해 print문을 사용했으나, 보통은 처리만 하고 아무결과도 반환하지 않도록 작성할 수 있습니다.

인자값을 전달하는 함수 유형 만들기

 

<3. 값을 전달(반환) 받는 함수 예시>
일반적으로 인자값을 매개변수를 통해 전달받아 처리하고 'return' 명령어를 통해 결과값을 반환하는 유형의 함수입니다. 

인자값을 매개변수로 받아 처리후 전달(리턴)하는 함수 만들기 유형

 

<4. 매개변수 값 이름을 지정하여 전달하기 >
함수내에서 지정한 매개 변수 이름과 순서대로 전달해야 원하는 출력을 얻을 수 있습니다.

만약,  함수에서 정의한 순서를 무시하고 바꾸면, 아래처럼, 원하지 않는 결과를 얻을 수 있습니다.

그래서, 아래 처럼, 매개변수를 직접 지정해서 전달 할 수도 있습니다. 

이렇게 지정하게 되면, 매개 변수 입력 순서에 상관 없이 전달 할 수 있게 됩니다 .

print 문도 일종의 함수 이며, 사용자 정의 함수가 아닌, 내장함수 입니다.  여기에도, 매개 변수가 사용되는데요, 

end 라는 매개 변수는 출력문 내용 끝에 출력을 지정할 수 있습니다.
- end ='  '      →  print 함수의 경우 기본적으로 이렇게 단따옴표''혹은, 공백이 있는 단따옴표를 매개변수를 넣게 됩니다 
- end =''        →  출력 결과는 공백이 없어도,  더 많은 공백을 넣어도 동일하게 처리 됩니다. 
- end =')^^('   →  end 문에 특정한 문자를 넣으면 해당 문자로 마무리 됩니다. 
- sep ='/  '      →   sep은 separator 구분자로 출력 내용 사이에 출력하여 구분시켜 줍니다. 
  또한, 이 둘을 같이 사용할 수 있습니다.  아래 예시들을 참고해 보세요.

 

<5. 매개변수에 디폴트 값 지정하기 >
: 사용자 정의 함수에서 매개변수에 디폴트 값을 지정해 줄 수 있습니다. 
단, 디폴트 값이 있는 매개변수 항목은 디폴트 값 없는 항목 뒤에 위치해야 합니다. 

 

반응형
반응형

권장사항 :  기초 부분 전체를 총정리하였기에 내용이 상당히 길어 전체적으로 쭉 보시거나,  원하는 부분을 찾을 때는 'Ctrl + F' 키를 눌러 단어 검색으로 바로 이동해서 보시면 됩니다.  첨부된 이미지는 모두 직접 작업하여 첨부하였기에 이미지 클릭시 확대되어 선명하게 보실 수 있습니다. 


파이썬 기초#5】 파이썬 기초 한방에 정리하기!  #1편 , 코드 작성법 핵심 요약, 총정리!

파이썬은 스크립트 방식의 프로그래밍 언어입니다. 

- 스크립트(Script) 언어의 사전적 의미는 ,  연극의 대사 등이 적혀 있는 스크립트(Script)에서 유래하였으며, 연기자가 스크립트를 보고 연기를 수행하듯이 컴퓨터가 스크립트를 읽어 수행한다는 의미를 지니고 있습니다.    
- 또한 파이썬은 한 줄 한 줄 읽어 바로바로 실행하는 인터프리터(Interpreter) 방식을 취하고 있습니다. 

그럼, 여기서 컴파일(Compile) 언어와 스크립트(Script) 방식 언어의 차이점을 설명드릴게요. 

컴파일러와 인터프리터의 차이점(이미지 참조: guru99.com)

위 이미지를 보면  컴파일 언어(컴파일러)는 소스코드를 컴파일러에 의해 기계가 알아 먹을 수 있는 기계 어코드(Machine Code-2진수)로 코드 전체를 변환한 다음 실행을 하는 방식이며, 
스크립트 언어(인터프리터)는 한 줄씩 바로 해석하여 실행을 시키는 구조로 , 2진수로된 기계어가 아닌, 인터프리터 방식으로 해석할 수 있는 Byte Code로 변환하여 한 줄씩 바로바로 실행시키는 구조의 방식입니다.

1. 컴파일 언어의 장단점 :

컴파일 언어의 장점은  컴파일 과정에의해 코드 전체가 이미 해석이 된 2진수의 기계어 코드를 실행시키기 때문에, 실행 속도가 매우 빠른 장점을 가지고 있고,   단점으로는 약간의 코드 수정이 필요하더라도, 코드 전체를 다시 컴파일해야 하며,  코드의 크기가 크고 방대할 경우 이런 별도의 컴파일 과정으로 인해 다소 번거롭고 시간 소요가 있는 단점이 있습니다.   
 (컴파일 언어의 종류 : C , C++ , C# , Java ...  )

 

2. 스크립트 언어의 장단점 :

스크립트 언어의 장점은 소스 코드 수정이 빠르고 간단해서 수정이 빈번하게 발생하는 프로젝트에 유리하며, 따라서 개발 시간이 단축되는 장점이 있습니다.  
스크립트 언어의 단점으로는 실행속도가 컴파일 방식의 언어에 비해 상대적으로 많이 느리다는 단점이 있습니다.  
 (스크립트 언어의 종류 : Python, Ruby, Perl, PHP, JavaScript )


3.  소스코드 형식 : 

 C언어나 JAVA와 같은 언어의 경우  중괄호 {  } 등으로 코드 블록을 구분하는 포맷을 지니고 있고 중괄호 내에서는 일정한 형식을 지키지 않아도 됩니다.  예를 들어,  들여 쓰기가 문법적으로는 필요하지 않으며, 공백의 개수나 코드 길이가 길 경우 별다른 형식 없이 다음 줄로 내려쓸 수 있는 구조를 가지고 있습니다. 

 Python과 같은 경우는 들여쓰기나 공백의 사용에 주의가 필요합니다. 

 

4. 파이썬(Python) 코드의 작성 구조 및 형식

 ① 대소문자를 구분해야 합니다.  예를 들어, 변수명으로 'NUM' 과  'Num'과 'num'은 각각 다른 변수입니다.
 ② 명령어(내장 함수)는 일반적으로 모두 소문자입니다. 
    예를 들어, 
    >>>  print(2+3)        ⟵  (맞음)  
    >>>  Print(2+3)        ⟵  (에러)  
    >>>  PRINT(2+3)      ⟵  (에러)  
 

  파이썬에서는 if 문장이나 for문장의 경우 하위 문장들을 중괄호 { } 등으로 구분 짓지 않기 때문에, 들여 쓰기(Indent)로 구분합니다.  일반적으로는 4칸의 공백을 권장합니다. 
 ③ 인터프리터 언어의 특성상 한 줄씩 코드 구조가 해석이 되어야 하기 때문에, if 문장이나 for 문장의 경우 문장 끝에  ' : ' 콜론으로 마쳐서 표시하게 되며,  ' : ' 콜론 표시 이후 들여 쓰기 된 문장들은 모두 해당 if나 for 문장에 포함된 내용으로 인식 및 처리하게 됩니다.
  
>>>if num > 15 :            ⟵  ' : ' 을 표시하여 if 문장의 시작을 알림
   >>>    print("=====")    ⟵  공백을 주어 if 문에 속해 있는 문장으로 처리함
   >>>    print(num)         
⟵  공백을 주어 if 문에 속해 있는 문장으로 처리함
   >>>print("감사합니다")    ⟵  if 문에 속해 있지 않은 문장

 

 ④ 들여쓰기해야 하는 문장이 아닌 경우는 맨 앞에 공백이 들어가서는 안 됩니다. 

   >>>1+2 
   >>>3        ⟵  정상 실행

   >>>1+2↵      ⟵  맨 앞에 공백이 들어간 경우
   SyntaxError :  unexpected indent     ⟵  실행 에러
      

  ⑤ 코드 주석은  '#'으로 표시합니다.  (다만, 아쉽게도 파이썬은 여러 줄 묶음 주석은 지원하지 않음)
  ### 파이썬 실습 1번  
  for i in range(5) :        # 0~5 까지 반복 실행합니다. 
      print( "num =" , i )

 >>> num=0
 >>> num=1
 >>> num=2
 >>> num=3
 >>> num=4

⑥  위의 예제에서 처럼 파이썬 쉘(Shell) 실행 모드에서 작성하고 있던 for 문이나  if 문에서 벗어나려면 그리고 실행이 되려면 엔터 입력을 두 번 하면 됩니다.
  for i in range(5) :       # 0~5 까지 반복 실행합니다. 
      print( "num =" , i )  ↵  
      ↵  

 >>> num=0
 >>> num=1
 >>> num=2
 >>> num=3
 >>> num=4

 

⑦ 파이썬 다운로드 버전?  및  실행시키는 두 가지 모드. 
 파이썬 다운로드 페이지(python.org)에서  파이썬을 다운로드하고 설치할 수 있습니다.
파이썬은 2000년도에 2.0 버전 발표 이후,  2.x 대 버전과,  3.x 버전의 두 갈래로 나뉘어 발표됩니다. 
2.x 대 버전에서부터 비 영어권 언어를 지원하기 시작했지만, 여러가지 문제점과 시스템의 한계로 인해 
3.x 대 버전에서는 과거의 시스템을 단절하고 파이썬을 완전히 새롭게 만든 버전을 출시한 건데요,  유니코드를 전면적으로 도입하고 내부적으로 많은 변화가 있어 2.x 대 버전과 호환되지 않습니다. 
그런데,  2008년에 3.0 버전을 발표하고 그 뒤에 다시 2010년도에 2.7 버전이 발표 된 이유는,  기존 2.x 버전 베이스로 구축한 시스템에서는 3.x 버전 적용이 되지 않기 때문에,  유지보수 및 업그레이드를 위해 별도로 발표된 것인데요,  그 마저도 더 이상의 버전 업그레이드나 지원이 2020년도에 종료되는 것으로 발표되었습니다.    따라서, 기존 2.x 대 시스템을 다루어야 하는 것이 아니고, 새로 파이썬을 시작하시는 분들은 당연히 3.x 대 버전을 활용하는 것이 좋습니다. 
2021년 04월 기준으로 최신 버전은 3.9.4 Version 입니다. 


그럼,  파이썬을 다운로드 받아 설치하면 대략 두 가지 형태의 실행 모드를 선택할 수 있는데요, 
 Python Shell(쉘 모드) 모드에서 대화형으로 한 줄씩 작성하고 실행하는 형태로 할 수도 있고, 

파이썬 쉘(Shell) 모드에서 대화형으로 코드 작성

 메모장과 같은 문서 작성 페이지를 열고 "test.py"  형태로 파일을 저장하고 실행 시키는 형태로 작성할 수 있습니다. 

파이썬 IDLE를 실행시키고 File 》 New 메뉴로 새파일 작성 후 실행한 모습

위 이미지에서 보듯 파이썬 IDLE를 실행시키고 File 》 New 메뉴로 새 파일 작성 후 실행(F5)하면,  결과 값은 뒤에 있는 Shell 창을 통해 나타납니다.

 

⑧ print 명령


 대화식 모드에서는 print 명령을 사용하지 않더라도 수식이나 변수를 입력하면 출력문으로 해석하여 그 값을 출력해 줍니다.   ( 아래 예시,   'print ( x )'로 출력하는 것이 기본이지만,  x를 입력 후 엔터 하여도  x 값이 출력됨)

 

print ( ) 함수의 기본 원형  : 
     print (출력 내용 [, sep=구분자]  [, end=끝 문자] )       
 [ ] 괄호의 내용은 생략 가능하며 필요할 경우 입력합니다. 

 아래 이미지의 print ( ) 문의 옵션 출력에 대한 예시를 참고하세요. 


⑨ 명령어 (내장 함수) 속 수식 계산이나  문자열 출력이 상당히 자유롭습니다. 
>>> print (2+3+(2*3)-5)

6

>>> print ("고양이 " * 3) 

고양이 고양이 고양이

이런 방식은 아래처럼 유용하게 응용할 수 있습니다.   보통 화면 출력 시 구분선으로 '---------------------' 같은 것을 여러 개 출력하려 할 때 응용하면 편리합니다. 

⑩ 입력 :  입력은 아래와 같은 형태를 취합니다. 


 변수 = input(' 질문 내용 ')

아래 이미지의 입력법 예시를 참조하세요

다만, 현재와 같은 입력은 '2010'이라는 값이 문자로 처리되기에 아래와 같은 산술 계산 시 에러가 발생합니다. 

 따라서,  이런 경우에는 eval( ..... )이라는 내장 함수를 사용하여 결과 값을 int 형으로 바꾸어 줄 수 있습니다.

다만, eval (  ) 함수는 함수 자체의 막강한 변환 기능으로 인해  코드 구조가 복잡한 곳에 사용하게 되면, 의도하지 않은 값을 변환받을 가능성이 있어,  단순 코드 외에는 사용을 권하지는 않습니다.   
따라서,  보통의 경우  int(  ) 변환 함수를 사용하는 것을 권합니다.


마지막으로 print (  ) 함수와 input (  ) 함수를 결합하여 아래와 같은 형태로도 활용 가능합니다. 

 

⑪  키워드 (Keyword)와  변수명 
  : 키워드는 if ,  for , while과 같은 단어로, 내장 함수 이름과 같은 예약어를 의미합니다.   따라서 키워드에 해당하는 이름으로는 변수명으로 만들어서는 안 됩니다.    
 즉, print와 같은 내장 함수를 변수명으로 사용할 수는 있지만  일단 사용하는 순간 이후부터는 print를 출력 함수로 사용할 수 없게 됩니다. 
예시)


 《 키워드 》

분 류 키워드(Keyword)
제어문 if    else    elif    for    while     break   continue
상 수 True    False    None
논리 연산자 and   or   not    in
함 수 def   return   lambda   nonlocal    global
예외 처리 try    except    finally    raise
모 듈 import    from    class
기 타 is    del    with    as    yield    assert    pass


  ※ 변수명 지정 원칙 :
 -  변수명은 대소문자를 구분하며 소문자로 작성하는 것을 권합니다.  ( num ,  Num ,  NUM  은 모두 다른 변수명으로 처리됨)
 -  변수명에는 알파벳, 밑줄 문자, 숫자로 구성할 수 있으며, 공백이나 +, - 나 : / 같은 특수기호 등은 사용할 수 없습니다
    (두 단어를 하나의 변수로 만들 경우에는 보통  예를 들어,  'year_data'   혹은  'YearData'와 같은 형태로 작성하면 됩니다.)
 -  변수명에 첫 글자로 숫자는 쓸 수 없습니다.   'run2you'  ,  'start100'과 같은 형태는 가능합니다.
 -  파이썬은 유니코드를 지원하기 때문에, 한글이나 한자와 같은 문자도 변수명으로 사용 가능합니다. 

 다만,  협업 작업 등에서의 호환성을 위해 일반적으로는 짧고 간결한 영어 표기를 권합니다. 
 
 - 파이썬의 변수는  정수형, 실수형, 문자열형 등과 같은 변수의 타입을 사전에 지정하지 않아도 됩니다. 
   변수에 어떤 값이 저장되는지에 따라  타입이 결정됩니다.

 또한, 아래 예시처럼,  특정 타입으로 이미 지정된 변수 명도, 다른 타입의 자료가 입력되면 변수의 타입이 바뀝니다.

 이런 파이썬 변수의 특성을 동적 타입 (Dynamic Type)이라고 합니다. 

  끝으로 하나의 코드에 사용된 변수명을 코드 내에서 삭제할 수 있습니다.    ( 다만, 프로그램이 종료되면 어차피 메모리에서 삭제됨으로 자주 활용되지는 않습니다)

 - 변수에 초기값 입력시 한꺼번에 (순차적으로) 입력하는 것도 가능합니다. 
  예) 아래는 변수 초기값 지정시 기본 스타일
 >>> name = "Rasino"
 >>> age = 21
 >>> attractive = True

   하지만 아래처럼 간편하게 한 번에 대입시키는 것도 가능합니다. 
 >>> name , age, attractive = "Rasino" , 21 , True

   또한, 변수명이 각각 달라도 (초기)값이 같을 때는 아래처럼 지정할 수도 있습니다. 
>>> kimbob  =  mandu =  odeng  =  noodle  =  5 

⑫ 파이썬의 주요 자료형 

자료형 설명   예시  
정수 소수가 없는 숫자 ex)  a = 5   ,   b = 10   
부동소수 소수가 있는 숫자 ex)  a = 3.5 ,   b = 3.14169
불 (Bool (불) True 또는 False 값을 가진 자료형 ex)  a = True ,    b = False 
문자열(String) 문자 데이터를 순서대로 나열한 데이터

ex)  a ='Rasino'   ,     >>> print(a[0])  →  R  
리스트(List) 숫자나 문자열 등의 요소를 순서대로 나열한 구조체 (추가 / 삭제 가능) ex)  a = [ 'R','a','s','i','n','o' ] ,  >>> print(a[3])  →  i  
튜플(Tuple) 리스트와 비슷하나, 초기값이 정해지면, (데이터 추가 / 삭제가 불가함) ex)  a = ( 'R','a','s','i','n','o' ) ,  >>> print(a[4])  →  n  
딕셔너리(Dictionary) 각 데이터 마다, 이름(Key)이 있는 데이터 모음.  연관성 있는 데이터들의 묶음으로 사용하기 좋음
{'key' : 'Value' , 'key' : 'Value' , ... }
ex) a = { 'name' : '홍길동' , 'age' : 29 , 'phone' : '010-123-1234' }

 1) 문자열 특징 :
- 문자열은 큰따옴표 "...." , 단 따옴표 '....' 모두 가능하며,  "....' 섞어 쓰면 에러 발생합니다.  
- 코드 작성 시 문자열 길이가 길 경우, 임의로 두 줄 이상 내려쓸 수 없습니다.  
 ( 문자열 두 줄 이상 표기 에러 x)
 stringA = "동해물과 백두산이 마르고 닳도록
                하느님이 보우하사 우리나라 만세..."

 ( 문자열 두 줄 이상 표기 올바른 방법 #1 )
 stringB = "동해물과 백두산이 마르고 닳도록
                하느님이 보우하사 우리나라 만세
                무궁화 삼천리 화려강산..."
  ' ∖'(역슬래시) 표시는 한글 자판에서는 '\'로 표시됩니다.
 역슬래시는 문자열뿐 아니라,  일반적인 수식이나 다른 코드의 작성 시에도 적용 가능합니다. 

한 줄 내려쓰기 역슬래시(\) 표기 방법

          
( 문자열 두 줄 이상 표기 올바른 방법 #2 )

 stringB = ''' 동해물과 백두산이 마르고 닳도록
                 하느님이 보우하사 우리나라 만세
                 무궁화 삼천리 화려강산... '''
   단 따옴표 3개를 앞뒤로 묶어주거나,  """  ....   """  큰따옴표 3개를 앞뒤로 묶어주면 됩니다.

- 스트링 머지 기능 (stringmerge) :  하나의 변수에 콤마로 구분되지 않은 문자열 묶음을 입력하면 합쳐집니다. 
  ex1) >>> A = "Korea" " Fighting" "2021"  
        >>> print ( A )
        KoreaFighting2021

  ex2) >>> B = ( "Korea"
                       " Fighting"
                       "2021"  )

        >>> print ( B )
        KoreaFighting2021

 ( 정수를 문자열로 변환 ) 
문자 "2021"을 정수로 바꿀 때는 int(2021)라고 설명을 드렸는데요,  반대로 정수를 문자열로 바꾸는 함수는 str(2021)를 사용하면 됩니다. 
  ex1) >>> A = "Korea" + str(2021)
        >>> print (A)
        Korea2021

※ 주의 사항 :  하나의 print( ) 함수 내에서는 문자열로만 출력하든지 int type과 같은 숫자 형태로만 구성 되어야 합니다. 
즉,  print("문자열..." + 정수 ) 와 같은 조합시 문법에러가 납니다. 
따라서 이럴때는 문자열 캐스팅 연산자('str( )')를 사용하여 문자열로 통일시켜 주면 됩니다. 
ex1) 



( 문자열 실수를 숫자 실수로 변환 )

int(  ) 함수는 문자열 실수 숫자를 소수점 이하를 버리고 숫자로 변환하기 때문에,  float (  ) 함수를 사용해야 합니다.
 그리고 (실수를 정수로 변환) 하는 방법도 아래 이미지를 참고해 주세요. 


(반올림 함수 사용하기 )

위 이미지에서 보듯 실수를 단순하게 int( ) 함수를 사용하여 변환할 경우 소수점 이하는 버려지게 되는데요,  
소수점 이하 반올림이 필요하게 될 경우 round ( ) 함수를 사용합니다. 

 

 ( 문자 코드 확인 함수 )     
  - 문자 코드 확인 함수 ord(  )와 chr( ) 함수 :   ord 함수는 아스키(ASCII) 문자뿐 아니라,  한글이나 한자와 같은 문자 변환 시에도 유니코드 값을 출력해 줍니다.  ( 3.x 버전부터 파이썬은 대부분의 유니코드 처리 가능한 언어이기 때문 )

 

 2) 리스트(list) 특징 :
- 리스트는 구조체의 특징을 가지고 있기 때문에,  정수나 실수 , 문자열 등을 [  ] 대괄호로 묶어 하나의 변수에 담아 놓을 수 있습니다. 
  ex)
  >>>  A = [ 1 , 2, 3, 4, 5] 
  >>>  B = [ 'a', 'b', 'abc', 'kt' ]
  >>>  C = [ 'a', 'b', 1 , 2, 3, 'abc', '12kt' ]
 - 리스트형은 배열의 특성도 지니고 있기 때문에,  특정 순서의 항목을 꺼내거나 삭제 추가 변경 등이 가능합니다.

- 리스트형 데이터의 연산(슬라이싱-Slicing 연산) :  리스트형을 대상으로 슬라이싱 연산이 가능한데요,  다음과 같은 자료의 추출이나 편집이 가능합니다. 
또한, 슬라이싱으로 값의 수정이나 추가 삭제도 가능합니다.

위 이미지를 보면,  값의 추가는 값을 변경하는 것으로 이해하면 됩니다. (A[2:3]은 3의 값을 3, 4로 바꾸는 것)
 즉,  A=[1, 2, 4, 5, 6, 7, 8, 9]  일 때, 2와 4 사이에 3을 추가하려고 한다면, 숫자 4를  3과 4로 바꾸는 것으로 이해해야 합니다.   이것이 슬라이싱을 이용한 추가 방법입니다.   [2:3] 에 인자로 사용된 2 : 3을 인덱스라 표현합니다. 
인덱스의 제일 처음 값인 0을 생략할 수 도 있습니다.
예를 들어  A [1, 2, 4, 5, 6, 7, 8, 9]  일때,
[ : 3 ]은 인덱스 값 처음부터 3 앞 까지를 의미 합니다.   즉,  [ 0 : 3 ]와  [ : 3 ] 은 같습니다. 
또한,  [ 4 : ]는 인덱스 값 4부터 끝까지를 의미합니다.  즉,  [ 4 :  ]와  [ 4 : 10 ] 은 같습니다.
그리고 [  :  ]는 리스트 전체를 의미하며,  따라서,  리스트 전체를 다른 것으로 변경할 수도 있습니다. 

또한,  아래처럼 슬라이싱의 인덱스 연산으로 리스트 값 전체 삭제도 가능합니다.  A [ : ] = [ ]

슬라이싱 인덱스 연산을 통해 데이터를 몇 칸씩 건너뛰며 출력하거나 변경하는 것도 가능합니다. 
또한,  인덱스 값 중에서 짝수 번째나 홀수 번째 자료를 출력하는 것도 가능합니다. 

A [0:15:2]에서 2는 1칸의 Step 값을 의미하며, 두 칸은 3,  세 칸이면 4로 하면 됩니다.

2) 리스트(list) 와 함수들 
  :  아래와 같은 기존 함수를 이용해서 리스트 연산 (추가 , 삭제 , 반환 ... 등 )을 수행 할 수 있습니다. 

함수명  (s 는 list 이름을 의미) 설 명  
s.append( x ) 리스트 s의 끝에  x를 추가
s.extend( t ) 리스트 s의 끝에 리스트 t의 내용 전부를 추가
s.clear( ) 리스트 s의 내용물 전부 삭제
s.insert( i , x ) s[ i ]에 x를 저장(삽입)
s.pop( i ) s[ i ]를 반환 및 삭제 
s.remove ( x ) 리스트 s에서 제일 앞에 등장하는 x를 하나만 삭제
s.count( x ) 리스트 s에 등장하는 x의 개수 반환
s.index( x ) 리스트 s에 처음 등장하는 x의 인덱스 값 반환


①  append 함수와 extend 함수  
 : append 와 extend 함수의 차이점은,   append 함수는 하나를 추가할 때 사용하고, extend 함수는 특정 리스트 전체를 추가할 때 사용함.  (아래 예시 참조)


②  insert 함수와 clear 함수 
 : insert 함수는 특정 위치(인덱스 값)에 추가하고자 하는 값을 추가합니다.  해당 인덱스에 있던 값이 덮어 써지거나, 없어지지 않고 모두 하나씩 뒤로 밀리게 됩니다.   (인덱스 값은 0 부터 시작입니다)
 : clear 함수는 리스트 안에 있던 내용을 모두 삭제함.


③  pop 함수와 remove 함수 
 : pop 함수는 표시한 인덱스(위치) 값을 삭제합니다.   remove 함수는 표시한 값을 list 함수에서 찾아 삭제합니다. 
 pop과 remove의 차이점은 pop함수는 인덱스(위치)를 기준으로 삭제한다는 점이며, remove 함수는 인덱스 기준이 아닌 list 안에 있는 '값'을 기준으로 삭제해 주는 것이 다릅니다.   또한 pop함수는 삭제된 값을 출력해 주는 특징이 있습니다.   만약 리스트에 없는 값을 삭제하려한다면,  에러를 출력합니다.


④  count 함수와 index 함수 
 : count 함수는 리스트 속에 찾는 값이 총 몇 번 등장하는지 합계하여 알려주며,  index 함수는 찾는 값이 처음 등장하는 인덱스(위치)값을 출력해 줍니다. 


⑤  len ( ) 함수와 min ( ) , max ( ) 함수 
 : 리스트 자료에서의 len( ) 함수는 자료에 포함된 전체 갯수를 알려줍니다.   min ( ) 함수는  리스트 중에서 제일 작은 수를 알려주고,  max ( ) 함수는 제일 큰 수를 알려줍니다.


문자열의 길이를 반환해 주며,  min( )은 알파벳 순서상 가장 앞에 있는 문자를 알려줍니다. 
max( ) 함수는 알파벳 순서상 가장 뒤에 있는 문자를 알려줍니다.  알파벳 순서에서 대문자가 소문자 보다 순서는 앞에 있습니다.  순서상으로 A, B, C, ...  X, Y, Z, a, b, c, ...  x, y, z  이런 순서로 됩니다.    아래 예시를 참고해 주세요.

 

⑥  기타 문자열 관련 함수들
 : 파이썬에서는 문자열도 리스트와 마찬가지로 객체(Object)로 인식합니다. 따라서 각각의 객체(문자열)를 컨트롤 할 수 있는 아래와 같은 함수를 사용할 수 있습니다. 

함수 사용 예시 str은 변수명 설명  
count( ) str.count("xx") 문자열(str)에 xx가 등장하는 횟수 반환한다.
lower( ) str.lower( ) 문자열(str)의 내용을 전부 소문자로 반환한다.
upper( ) str.upper( ) 문자열(str)의 내용을 전부 대문자로 반환한다.
strip( ) str.strip( ) 문자열(str) 앞, 뒤에 위치한 공백을 모두 제거한 문자열 반환
lstrip( ) str.lstrip( ) 문자열(str) 앞에(left) 위치한 공백을 모두 제거한 문자열 반환
rstrip( ) str.rstrip( ) 문자열(str) 뒤에(right) 위치한 공백을 모두 제거한 문자열 반환
replace( ) str.replace(old, new) 문자열(str)에서 old를 new로 교체하여 반환
split( ) str.split( ) 문자열(str)에서 공백등의 기준문자를 가지고 구분 후 리스트 에 담아서 반환
find( )
 또는 rfind ( )
str.find("xx")   ,   str.rfind("xx") 문자열에서 특정 문자"xx"를 찾아 그 위치값(인덱스)을 반환
isdigit ( ) str.isdigit( )  문자열 str이 숫자로만 이뤄져 있으면, True, 아니면 False반환
isalpha( ) str.isalpha( ) 문자열 str이 알파벳으로만 이뤄져 있으면, True, 아니면 False반환
startswith( ) str.startswith("aaa") 문자열 str이 "aaa"로 시작하면, True, 아니면 False 반환
endswith( ) str.endswith("bbb") 문자열 str이 "bbb"로 끝나면, True, 아니면 False 반환

1.  count ( ) 함수 사용예시
 : 문자열 속에 's' 문자의 수를 카운트하여 줌.


2.  lower ( )
: 문자열을 모두 소문자로 변환하여 특정 변수에 저장 하거나,  원래의 문자열에 바꾸어 대입시킬 수 있습니다.

3.  upper ( )
: 문자열을 모두 소문자로 변환하여 특정 변수에 저장 하거나,  원래의 문자열에 바꾸어 대입시킬 수 있습니다.

 

4.  strip ( ) 함수 
: 문자열 앞과 뒤에 있는 공백을 제거할 수 있는 함수입니다. (문자열 중간의 공백은 제거하지 않습니다)


5.  lstrip ( ) 함수 
: 문자열 앞(left)에 있는 공백을 제거할 수 있는 함수입니다. 

 

6.  rstrip ( ) 함수 
: 문자열 뒤(right)에 있는 공백을 제거할 수 있는 함수입니다.   (또한, strip , lstrip, rstrip 함수 모두 아래 예시처럼, 적용된 함수 결과를 원래의 변수에 대입시킬 수 있습니다)


7.  replace ( old, new ) 함수 
: 문자열에 속한 특정 문장을 다른 문장으로 바꿀수 있는 함수입니다. 
  (예시, replace("e", "a") 라고 할 때,  'e'라는 문자를 모두 'a'라는 문자로 바꾸어 주게 되며,  replace("e", "a", 1) 처럼, 만약 옵션에 숫자 1을 넣으면 앞에서부터 순서대로 하나만(숫자만큼) 빠꾸어 줄 수도 있습니다. ) 
아래 예시는, 문장속에 "Rasino" 문자열을, "Python" 문자열로 바꾸는 예시입니다.


8.  split ( ) 함수 
:  문자열에서 ' ' 공백이나 특정 문자를 기준으로 쪼개어 리스트라는 형식으로 담아 줍니다.


9.  find ( )  &  rfind ( ) 함수
문자열에서 특정 문자"xx"를 찾아 그 위치값(인덱스)을 반환합니다. (인덱스 값은 0부터 카운트 합니다)
  find ( ) 함수는 문장의 처음(좌측)부터 찾기 시작하고,  rfind ( )함수는 문장의 뒤(오른쪽)에서 부터 해당 문자"xx"를 검색합니다.   

 

10.  isdigit ( ) 함수  
 문자열 함수 str.isdigit( ) 에서  str이 모두 숫자로 이루어져 있을 경우, True를 반환하며, 그렇지 않을 경우 False를 반환.

11.  isalpha ( ) 함수  
 문자열 함수 str.isalpha( ) 에서  str이 모두 알파벳으로 이루어져 있을 경우, True를 반환하며, 그렇지 않을 경우 False를 반환. (문장속에 공백이나 특수 문자가 들어 있을 경우,  알파벳이 아니므로, False를 반환 하게 됩니다.)


 12. startswith ("aaa") 함수
: 문자열이 "aaa"로 시작하면 True를 반환하며,  그렇지 않을 경우 False를 반환.
 (예시는 아래 13번 예시와 함께 참조)

 13.  endswith ("bbb") 함수
: 문자열이 "aaa"로 시작하면 True를 반환하며,  그렇지 않을 경우 False를 반환.

 

이어서 if 조건문 등으로 이어지는 2편 링크를 클릭해 주세요.  (작업전입니다.)

 파이썬 기초#6파이썬기초 한방에정리하기!#2편    ←  클릭!

 

반응형
반응형

라즈베리Pi#20피에조 부저 사용하기!  with (파이썬 코드)
RaspberryPi Buzzer control with Python !

 안녕하세요 라즈이노 IoT 입니다.
이번 시간에는 라즈베리 Pi에서 부저를 사용해 보는 실습을 진행합니다.
GPIO 출력을 제어하여 부저를 울리는 방법을 설명드리며, 
주파수를 이용하여 음의 높낮이를 조절할 수 있기에, 실습5 에서는 간단한 동요를 출력해 보겠습니다.


1.  음계(Scale)와 옥타브(Octave)

  음계란, 음악에 쓰이는 음을 높이의 차례대로 배열한 음의 층계를 말합니다.   
음 높이는 Pitch.    

음계(Scale)

  "도, 레, 미, 파, 솔, 라, 시, 도" 의 8가지 음계를 옥타브라고 합니다.  즉, 옥타브는 어떤 음에서 완전 8도의 거리에 있는 음까지를 말하며, 물리학적으로는 주파수(진동수)가 두 배 차이나는 두 음 사이의 음정을 말하는데,  예를 들어, 음높이가 400Hz인 음과  800Hz인 음 사이의 음정은 옥타브라고 말하며, 인간의 귀는 이 두 음을 높이는 다르지만 서로 같은 음으로 인식합니다.  (예, 낮은 '도'와 높은'도',  낮은 '솔'과 높은 '솔')

옥타브
8 옥타브



2.  소리와 주파수 (음계 별 표준 주파수)


스피커나 부저를 통해서 듣게 되는 음도, 진동판의 떨림(주파수)에 의해 들을 수 있게 되는데요, 1초(Second)에 1회의 떨림을 1Hz라 부르며,  1초에 100회면 100Hz라 말합니다.  떨림(주파수)이 낮을수록 낮은음을 내게 되며, 높을수록 늪은 음을 내게 됩니다. 
음악에 사용되는 악기들의 종류는 매우 다양하고 많지만, 합주를 했을 때 음의 일치가 되는 이유는,  각각의 음 높이가 특정 주파수로 정리되었기에 가능합니다. 
아래가 각 음계 별 표준 주파수입니다.

이미지 참조 : control.cntc.ac.kr/cpu

 그럼, 이 번 실습에서 각 음계 별 주파수를 참고하여, 적당히 반올림한 수를 코드에 적용하면, 해당음의 소리를 출력할 수 있게 됩니다.   

 

 3. 부저의 종류와 특징 : 


    - Passive type : 전원만 가해서는 소리가 나지 않고, PWM 형태의 일정한 주파수일 때 소리가 나는 타입.
    - Active type : 전원만 연결해 주면 소리가 나는 타입.

위 이미지에서 녹색의 기판이 보이는 부저가 (좌) 패시브 타입이며,  PWM처리 회로를 내장하여 검은색으로 마감 처리한 부저가 (우) 액티브 타입 부저입니다.

  라즈베리 Pi의 포트에서 High 신호를 내보내어 직접 부저를 울릴 수도 있지만, 출력이 약할 수 있고, 포트를 통한 직접적인 출력을 제한하기 위해,  아래와 같은 Low level trigger 방식을 사용할 수 있습니다. 
이 방식은, GPIO 포트를 통한 직접적인 출력을 사용하지 않고, VCC 전원을 사용하게 함으로, 포트를 보호하게 되며, 부저에 충분한 전류를 공급할 수 있게 합니다. 

(Low level trigger 부저 연결회로도와 연결도)

 회로 연결을 보면, 입출력(I/O) 부분이 Low 신호가 되면, TR이 작동(스위치 On) 되어, VCC(+), Buzzer로 이어지는 전류가 E(에미터) - C(컬렉터)로 빠져나가면서, Buzzer를 울리게 됩니다.  그래서 이런 작동 형태를 '로우-레벨-트리거'(Low level trigger)라 말합니다.  
TR은 위 회로 기준으로,  가지고 있는 PNP타입의 TR 어떤 것이든 사용 가능합니다.
TR의 경우는  NPN 타입과 PNP타입으로 나뉘는데요,   PNP 타입도 제품 품번마다 E(에미터),  B(베이스),  C(컬렉터) 핀의  위치가 다르기 때문에  자신이 사용하는 TR의 스펙을 확인(검색 가능)해서 연결하면 됩니다. 

(좌)NPN 타입과  (우)PNP 타입 참고 이미지

즉,  같은 PNP 타입의 TR이라 하더라도, 위 이미지처럼, A1015품번의 경우 핀이 E C B의 순으로 되어 있지만,  
또 다른 PNP타입의 A9012 TR의 경우 핀 순서는 E B C로 되어 있습니다. (핀 배열 구분 주의!)   

또한 아래처럼,  액티브 타입 부저를 '로우-레벨-트리거' 방식으로 모듈화 한 제품도 있으니 참고하세요.
그림에 보면 TR과 저항이 내장되어 있습니다.(Low level trigger 방식)

모듈형 액티브 타입 부저

 

4.  라즈베리파이+부저 연결도 (실습을 위한 연결 도면)


 기본적으로 아래처럼 라즈베리 Pi 포트 출력으로 직접 부저를 작동시키는 연결을 하면 됩니다. 

또는 아래와 같이 TR과 저항을 이용한 Low level trigger 방식의 연결을 하여도 됩니다.  
이때, 사용한 TR은 PNP 타입의 A1015 품번을 사용했습니다. PNP타입의 다른 품번을 사용해도 되며, 이때는 ECB의 핀 배열이 다를 수도 있으니, 해당 TR의 스펙을 확인해 보세요.

 

또한 아래처럼, TR과 저항이 내장되어 모듈화 된 부저 모듈을 사용하여 간편하게 연결할 수도 있습니다.



부저를 이용한 실습

  (실습 1) 부저 1회 울리기

 : 아래 코드를 작성하여 동작시켜 보세요. 
부저가 1.5 동안 1회 울리고 종료됩니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import RPi.GPIO as GPIO
import time
 
buzzer = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer, GPIO.OUT)
GPIO.setwarnings(False)
 
pwm = GPIO.PWM(buzzer, 262) # '262'는 음의 높이에 해당하는 특정 주파수
pwm.start(50.0)
time.sleep(1.5) # 1.5초간 음이 울리도록 시간지연
 
pwm.stop()
GPIO.cleanup()
cs

 

 (실습 2) 부저로 '도, 레, 미' 음 3회 반복 울리기

 : 아래 코드를 작성하여 동작시켜 보세요. 
부저가 1.0초 간격으로 도, 레, 미 음을 3번 반복한 후 종료됩니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import RPi.GPIO as GPIO
import time
 
buzzer = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer, GPIO.OUT)
GPIO.setwarnings(False)
 
pwm = GPIO.PWM(buzzer, 1.0)  # 초기 주파수 설정을 1Hz로 함.
pwm.start(50.0)
 
for cnt in range(0,3):
    pwm.ChangeFrequency(262)   # 262는 4옥타브의 '도'에 해당되는 주파수 
    time.sleep(1.0)
    pwm.ChangeFrequency(294)   # 294는 4옥타브의 '레'에 해당되는 주파수 
    time.sleep(1.0)
    pwm.ChangeFrequency(330)   # 330은 4옥타브의 '미'에 해당되는 주파수 
    time.sleep(1.0)
 
pwm.ChangeDutyCycle(0.0)
 
pwm.stop()
GPIO.cleanup()
 
 
cs

 

 (실습 3) 부저로 '도레미파솔라시도' 음계 출력하기

 : 아래 코드를 작성하여 동작시켜 보세요. 
부저가 4옥타브 영역의 주파수인 '도, 레, 미, 파, 솔, 라, 시, 도' 음을 출력한 후 종료됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import RPi.GPIO as GPIO
import time
 
buzzer = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer, GPIO.OUT)
 
pwm = GPIO.PWM(buzzer, 1.0)   # 초기 주파수를 1Hz로 설정
pwm.start(50.0)               # 듀티비를 50%로 설정
 
scale = [262294330349392440494523]
 
for i in range(0,8):
    pwm.ChangeFrequency(scale[i])
    time.sleep(1.0)
 
pwm.stop()
GPIO.cleanup()
 
cs

 

(실습 4) 부저로 '도-레-미-파-솔-라-시- 도 -시-라-솔-파-미-레-도' 음계 출력하기

 : 아래 코드를 작성하여 동작시켜 보세요. 
부저가  '도, 레, 미, 파, 솔, 라, 시, 도' 음을 올리고 다시 내리는 형태로 출력합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import RPi.GPIO as GPIO
import time
 
buzzer = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer, GPIO.OUT)
 
pwm = GPIO.PWM(buzzer, 1.0)   # 초기 주파수를 1Hz로 설정
pwm.start(50.0)               # 듀티비를 50%로 설정
# 4옥타브 주파수 : 도(262)/레(294)/미(330)/파(349)/솔(392)/라(440)/시(494)/도(523)  
scale = [262294330349392440494523]
 
for i in range(0,8):
    pwm.ChangeFrequency(scale[i])
    time.sleep(1.0)
 
 
for i in range(7,-1,-1):
    pwm.ChangeFrequency(scale[i])
    time.sleep(1.0)
    
pwm.stop()
GPIO.cleanup()
 
cs

 

(실습 5) 부저로 '반짝반짝 작은 별' 동요를 출력해 봅니다.

 : 아래 코드를 작성하여 멜로디를 출력해 보세요.
부저가  '반짝 반짝 작은별' 계이름을 울리고 종료하도록 합니다. 
아래,  '작은 별' 악보를 참고하세요.  실습을 이해한 후, 다른 곡도 코딩하여 연습해 보세요.

작은 별 악보
작은 별 계이름
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import RPi.GPIO as GPIO
import time
 
buzzer = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer, GPIO.OUT)
 
pwm = GPIO.PWM(buzzer, 1.0# 초기 주파수를 1Hz로 설정
pwm.start(90.0) # 듀티비를 90%로 높여 설정함(음 구분이 더 잘되고 조금 더 부드럽게 들림)
 
# == 동요 : 반짝 반짝 작은별 계이름 ==
#도도솔솔라라솔파파미미레레도 솔솔파파미미레 솔솔파파미미레 도도솔솔라라솔파파미미레레도
 
# 4옥타브:도(1)/ 레(2)/ 미(3)/ 파(4)/ 솔(5)/ 라(6) / 시(7)  
scale = [ 262 , 294  , 330 ,  349 , 392 ,  440 ,   494 ]
twinkle = [ 11556654433221, \
            55443325544332, \
            11556654433221 ]
try :
    for i in range(0,42):
        pwm.ChangeFrequency(scale[twinkle[i]])
        if i==6 or i==13 or i==20 or i==27 or i==34 or i==41:
            time.sleep(1.0)   # 2분음표 부분을 모두 1초로 출력
        else :
            time.sleep(0.5)   # 기타 4분음표는 모두 0.5초로 출력함 
    pwm.stop()
 
finally :
    GPIO.cleanup()
 
cs

 

자, 어떠신가요?   비록 단순 부저여서 음질이 좋지는 못하지만, 음 고유의 주파수를 이용하여 동요나 가요의 멜로디를 얼마든지 연주할 수 있습니다.

그럼, 아래 전체 과정을 담은 동영상을 함께 보면서 실습해 보세요. 

라즈베리파이에 부저 사용하기 영상으로 학습하기

 

반응형
반응형

 파이썬 명령어 정리#1 파이썬 "String, 상수와 변수 & 연산자이스케이프 시퀜스(Escape Sequence)

이미지를 클릭하면 확대 됩니다

1) 파이썬 String, 상수와 변수 관련 함수

명령어 기능
print Text stream을 출력한다.
input Text string을 입력한다.
upper( ) String 내의 모든 문자를 대문자로 바꾼다.
lower( ) String 내의 모든 문자를 소문자로 바꾼다.
split(‘문자’) String을 주어진 문자를 기준으로 나눈다.
str(오브젝트) 오브젝트를 String으로 만든다.
len(오브젝트) 오브젝트의 길이를 구한다.
chr (정수) 0 ≤ x 255 범위의 숫자를 문자로 변환한다.
ord (문자) 문자의 code값을 숫자로 변환한다.
bytes(오브젝트) 오브젝트를 bytes로 변환한다.
float(오브젝트) 오브젝트를 실수로 변환한다.
int(오브젝트) 오브젝트를 정수로 변환한다.
hex(오브젝트) 오브젝트를 hexa string으로 바꾼다.
bin(오브젝트) 오브젝트를 binary string으로 바꾼다.
float.hex( ) 실수를 hexa string으로 바꾼다.
float.fromhex(오브젝트) 오브젝트를 실수로 변환한다.
bin(오브젝트) 오브젝트를 binary string으로 바꾼다.
bool(오브젝트) 오브젝트를 bool 값으로 바꾼다.
complex(오브젝트) 오브젝트를 복소수로 변환한다.
abs(오브젝트) 오브젝트의 절대값을 구한다.
isdigit( ) ‘0~9’ 사이의 문자로 만들어졌는지 확인한다.
math 수학 함수관련 모듈임.
eval( )

문자 혹은 문자열이 포함된 연산식(함수)을 계산하여 출력해준다
예 1) eval(“(3*2)/2”)
   3
예 2) eval( "max([1, 2, 3, 4, 5])" )
  》 5


2) 화면 제어코드 (Escape Sequence)
 (보통 한글 자판을 이용하기 때문에,  \는  \로 표시됩니다. )

Escape Sequence 표현되는 의미
Backslash(\)       백슬래시
\' single quote(')     단따옴표
\" double quote(")   이중 따옴표
\a ASCII Bell            벨 (Alarm) 음
\b ASCII Backspace(BS)   백스페이스
\f ASCII Formfeed(FF)    한 장 넘김
\n ASCII Linefeed(LF)      개 행(New line)
\r ASCII Carriage Return(CR)  행의 처음으로 되돌아감
\t ASCII Horizontal Tab (HT)  수평 탭
\v ASCII Vertical Tab (VT)      수직 탭
\0 ASCII Null                      널 문자

 

3) 연산자 

연산자 의미 사용예시
+ 덧셈 a + b
- 뺄셈 a - b
* 곱셈 a * b
** 거듭제곱 (지수) a ** b
/ 실수형 나눗셈 (결과 값은 실수) a / b
// 정수형 나눗셈 (결과 값은 정수) a // b
<< Left Shift a << b
>> Right Shift a >> b
% 모둘로(modulo),나눗셈 나머지 연산자 a % b
& bit 단위 and 연산자 a & b
| bit 단위 or 연산자
('|' 기호는 역슬래시() 키에 있음)
a | b
^ bit 단위 exclusive or 연산자 a ^ b
~ bit 단위 inverse ~a
not True ↔ False  반전 연산자 not a
< 작다 a < b
> 크다 a > b
== 같다 a == b
!= 같지 않다 a != b
>= 크거나 같다 a >= b
<= 작거나 같다 a <= b

 

4) String 연산 방법

연산 의미 사용예시
string [x] x+1번째 문자 (0부터 시작함) string 'abcdefg'의 [2]요소는 'c' 
string [x : y] x+1번째 문자 부터 y번째 문자까지 'abcdefg'의 [2 : 5]요소는 'cde'
string[ : y] y번째 문자 이전까지 모두  'abcdefg'의 [ : 3]요소는  'abc'
string[x : ] x+1번째 문자 이후 모두 'abcdefg'의 [ 3 : ]요소는  'defg'
len(string) string의 길이 len('abcdefg')   7
string1 + string2 string1 뒤에 string2가 이어 붙여짐 'abcd'+'efg' 'abcdefg'

 

5) 비트 연산자 

연산식
x | y x와 y의 비트 단위 논리합(OR)
x & y x와 y의 비트 단위 논리곱(AND)
x ^ y x와 y의 비트 단위 배타적 논리합(EOR)
(EOR: Exclusive OR이란 x와 y중 하나는 참이고 하나는 거짓으로 두 값이 같지 않을 때,  x ^ y의 결과가 참(True)이 되는 논리) 
~x x와 비트 단위 반전 (NOT)
x >> y x를 y비트 오른쪽으로 시프트,  빈 비트에는 '0'으로 채워짐
y << x x를 y비트 왼쪽으로 시프트,  빈 비트에는 '0'으로 채워짐

 

6) 복합 대입(할당) 연산자

연산식 식의 원형 의미
x += y x = x + y x + y의 결과를 x에 대입(저장)
x -= y x = x - y  x - y의 결과를 x에 대입
x *= y x = x * y x * y의 결과를 x에 대입
x /= y x = x / y x / y의 결과를 x에 대입
x %= y x = x % y x % y의 나머지를 x에 대입
x >>= y x를 y비트 만큼 오른쪽으로 시프트 후 x에 대입
x <<= y x를 y비트 만큼 왼쪽으로 시프트 후 x에 대입

 

반응형
반응형

특수 기호 문자 모음 특수기호 : 화살표 : 원문자  : 괄호문자 : 한자숫자 : 로마자 : 분수기호 : 화폐기호 : 단위기호 모음

 

【 한글 키보드에서 특수 문자 입력 방법 】

1. 한글 자음 + 한자키 + Tab

(만약, 한자키가 없는 키보드라면, 오른쪽 컨트롤키로 입력)

2. 한글 자음 + 오른쪽 컨트롤(Ctrl)키 + Tab

 단!)  한글 자음 입력 후 다른 키를 건드리지 않은 상태에서 바로 한자키(또는 Ctrl)를 눌러야 합니다. 

① ' ㅁ '  키로 입력할 수 있는 특수기호 (도형)

① ' ㄴ '  키로 입력할 수 있는 특수기호 (괄호)

③ ' ㅇ '  키로 입력할 수 있는 특수기호(원문자, 원숫자, 괄호문자,괄호숫자)

 

④ ' ㄹ '  키로 입력할 수 있는 특수기호(화폐, 도량단위)

 

⑤ ' ㅂ '  키로 입력할 수 있는 특수기호(선 긋기)

 

⑥ ' ㅈ '  키로 입력할 수 있는 특수기호(숫자, 로마자 숫자)

 

⑦ ' ㄷ '  키로 입력할 수 있는 특수기호(수식 수학식 기호)

 

⑧ ' ㄱ '  키로 입력할 수 있는 특수기호 ( 느낌표, 점, 등)

 

⑨ ' ㅋ '  키로 입력할 수 있는 특수기호(한글 자모음)

 

⑩ ' ㅌ '  키로 입력할 수 있는 특수기호(쌍 자모음)

 

⑪ ' ㅊ '  키로 입력할 수 있는 특수기호 (분수 기호)

 

⑫ ' ㅍ '  키로 입력할 수 있는 특수기호 (알파벳)

 

⑬ ' ㅃ '  키로 입력할 수 있는 특수기호 (일어 가타카나)

 

⑭ ' ㅁ '  키로 입력할 수 있는 특수기호(일어 히라가나)

 

⑮ ' ㄲ '  키로 입력할 수 있는 특수기호(유럽 특수문자)

 

(16) ' ㅎ '  키로 입력할 수 있는 특수기호 (키릴 자모-동유럽 문자)

 

(17)  ' ㅅ '  키로 입력할 수 있는 특수기호 (괄호 문자, 원 자모)

 

 

블로그 게시글, 인스타그램, 트위터, 페이스북 글 작성시 유용한 특수 문자 기호입니다. 

 

《 원문자,  괄호 문자 》
ㆍ  ⦁  ∎  ◦  ∘  ∙  ⋅  ▪  ▫  ■  ○  ▲  △  ▴  ▵  ▶  ▷  ▸  ▹  ►  ▻  ▼  ▽  ▾  ▿  ◀  ◁  ◂  ◃  ◄  ◅  ◆  ◇  ◈  ◉    

Ⓐ  Ⓑ  Ⓒ  Ⓓ  Ⓔ  Ⓕ  Ⓖ  Ⓗ  Ⓘ  Ⓙ  Ⓚ  Ⓛ  Ⓜ  Ⓝ  Ⓞ  Ⓟ  Ⓠ  Ⓡ  Ⓢ  Ⓣ  Ⓤ  Ⓥ  Ⓦ  Ⓧ  Ⓨ  Ⓩ

ⓐ  ⓑ  ⓒ  ⓓ  ⓔ  ⓕ  ⓖ  ⓗ  ⓘ  ⓙ  ⓚ  ⓛ  ⓜ  ⓝ  ⓞ  ⓟ  ⓠ  ⓡ  ⓢ  ⓣ  ⓤ  ⓥ  ⓦ  ⓧ  ⓨ  ⓩ

⑴  ⑵  ⑶  ⑷  ⑸  ⑹  ⑺  ⑻  ⑼  ⑽  ⑾  ⑿  ⒀  ⒁  ⒂  ⒃  ⒄  ⒅  ⒆  ⒇

⓪  ①  ②  ③  ④  ⑤  ⑥  ⑦  ⑧  ⑨  ⑩  ⑪  ⑫  ⑬  ⑭  ⑮  ⑯  ⑰  ⑱  ⑲ 
⑳ 
㉑  ㉒  ㉓  ㉔  ㉕  ㉖  ㉗  ㉘  ㉙  ㉚  ㉛  ㉜  ㉝  ㉞  ㉟  ㊱  ㊲  ㊳  ㊴

㊵  ㊶  ㊷  ㊸  ㊹  ㊺  ㊻  ㊼  ㊽  ㊾  ㊿

❶  ❷  ❸  ❹  ❺  ❻  ❼  ❽  ❾  ❿  ⓫  ⓬  ⓭  ⓮  ⓯  ⓰  ⓱  ⓲  ⓳  ⓴

㈀ ㈁ ㈂ ㈃ ㈄ ㈅ ㈆ ㈇ ㈈ ㈉ ㈊ ㈋ ㈌ ㈍ 
㉠ ㉡ ㉢ ㉣ ㉤ ㉥ ㉦ ㉧ ㉨ ㉩ ㉪ ㉫ ㉬ ㉭

㈎ ㈏ ㈐ ㈑ ㈒ ㈓ ㈔ ㈕ ㈖ ㈗ ㈘ ㈙ ㈚ ㈛
㉮ ㉯ ㉰ ㉱ ㉲ ㉳ ㉴ ㉵ ㉶ ㉷ ㉸ ㉹ ㉺ ㉻

㈠ ㈡ ㈢ ㈣ ㈤ ㈥ ㈦ ㈧ ㈨ ㈩
㊀ ㊁ ㊂ ㊃ ㊄ ㊅ ㊆ ㊇ ㊈ ㊉

㈪ ㈫ ㈬ ㈭ ㈮ ㈯ ㈰
㊊ ㊋ ㊌ ㊍ ㊎ ㊏ ㊐

㋀ ㋁ ㋂ ㋃ ㋄ ㋅ ㋆ ㋇ ㋈ ㋉ ㋊ ㋋

㏠ ㏡ ㏢ ㏣ ㏤ ㏥ ㏦ ㏧ ㏨ ㏩ ㏪ ㏫ ㏬ ㏭ ㏮ ㏯ ㏰ ㏱ ㏲ ㏳ ㏴ ㏵ ㏶ ㏷ ㏸ ㏹ ㏺ ㏻ ㏼ ㏽ ㏾

 

《 화폐기호 》

¢  £  ¥  ₩  ₠  ₡  ₢  ₣  ₤  ₥  ₦  ₧  ₨  ₩  ₪  ₫  €  ₭  ₮  ₯  ₰  ₱

 

《 로마자 》

Ⅰ  Ⅱ  Ⅲ  Ⅳ  Ⅴ  Ⅵ  Ⅶ  Ⅷ  Ⅸ  Ⅹ  Ⅺ  Ⅻ  Ⅼ  Ⅽ  Ⅾ  Ⅿ  ↀ  ↁ  ↂ

ⅰ  ⅱ  ⅲ  ⅳ  ⅴ  ⅵ  ⅶ  ⅷ  ⅸ  ⅹ  ⅺ    ⅻ  ⅼ    ⅽ  ⅾ   ⅿ

 

《 분수 》

¼  ½  ¾  ⅓  ⅔  ⅕  ⅖  ⅗  ⅘  ⅙  ⅚  ⅛  ⅜  ⅝  ⅞

 

《 원형 괄호 한자, 원형 일어(가타카나)  》

㈱  ㈲  ㈳  ㈴  ㈵  ㈶  ㈷  ㈸  ㈹  ㈺  ㈻  ㈼  ㈽  ㈾  ㈿  ㉀  ㉁  ㉂  ㉃

㊑  ㊒  ㊓  ㊔  ㊕  ㊖  ㊗  ㊘  ㊙  ㊚  ㊛  ㊜  ㊝  ㊞  ㊟  ㊠  ㊡  ㊢  ㊣  ㊤  ㊥  ㊦  ㊧  ㊨  ㊩  ㊪  ㊫  ㊬  ㊭  ㊮  ㊯  ㊰

㋐  ㋑  ㋒  ㋓  ㋔  ㋕  ㋖  ㋗  ㋘  ㋙  ㋚  ㋛  ㋜  ㋝  ㋞  ㋟  ㋠  ㋡  ㋢  ㋣  ㋤  ㋥  ㋦  ㋧  ㋨  ㋩  ㋪  ㋫  ㋬  ㋭  ㋮  ㋯  ㋰  ㋱  ㋲  ㋳  ㋴  ㋵  ㋶  ㋷  ㋸  ㋹  ㋺  ㋻  ㋼  ㋽  ㋾

 

《 화살표 》

←↑→↓↔↕↖↗↘↙↚↛↜↝↞↟↠↡↢↣↤↥↦↧↨↩↪↫↬↭↮↯↰↱↲↳↴↵↶↷↸↹↺↻↼↽↾↿⇀⇁⇂⇃⇄⇅⇆⇇⇈⇉⇊⇋⇌⇍⇎⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇚⇛⇜⇝⇞⇟⇠⇡⇢⇣⇤⇥⇦⇧⇨⇩⇪⇫⇬⇭⇮⇯⇰⇱⇲⇳

➔➘➙➚➛➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➰➱➲➳➴➵➶➷➸➹➺➻➼➽➾

⟰⟱⟲⟳⟴⟵⟶⟷⟸⟹⟺⟻⟼⟽⟾⟿⤀⤁⤂⤃⤄⤅⤆⤇⤈⤉⤊⤋⤌⤍⤎⤏⤐⤑⤒⤓

⤔⤕⤖⤗⤘⤙⤚⤛⤜⤝⤞⤟⤠⤡⤢⤣⤤⤥⤦⤧⤨⤩⤪⤫⤬⤭⤮⤯⤰⤱⤲⤳⤴⤵⤶⤷⤸⤹⤺⤻⤼⤽⤾⤿⥀⥁

⥂⥃⥄⥅⥆⥇⥈⥉⥊⥋⥌⥍⥎⥏⥐⥑⥒⥓⥔⥕⥖⥗⥘⥙⥚⥛⥜⥝⥞⥟⥠⥡⥢⥣⥤⥥⥦⥧⥨⥩⥪⥫⥬⥭⥮⥯⥰⥱⥲⥳⥴⥵⥶⥷⥸⥹⥺⥻⥼⥽⥾⥿

¬ ̄¦


《 수학 기호 연산자 》

∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝∞∟∠∡∢∣∤∥∦∧∨∩∪∫∬∭∮∯∰∱∲∳∴∵∶∷∸∹∺∻∼∽∾∿≀≁≂≃≄≅≆≇≈≉≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≛≜≝≞≟≠≡≢≣≤≥≦≧≨≩≪≫≬≭≮≯≰≱≲≳≴≵≶≷≸≹≺≻≼≽≾≿⊀⊁⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋⊌⊍⊎⊏⊐⊑⊒⊓⊔⊕⊖⊗⊘⊙⊚⊛⊜⊝⊞⊟⊠⊡⊢⊣⊤⊥⊦⊧⊨⊩⊪⊫⊬⊭⊮⊯⊰⊱⊲⊳⊴⊵⊶⊷⊸⊹⊺⊻⊼⊽⊾⊿⋀⋁⋂⋃⋄⋅⋆⋇⋈⋉⋊⋋⋌⋍⋎⋏⋐⋑⋒⋓⋔⋕⋖⋗⋘⋙⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩⋪⋫⋬⋭⋮⋯⋰⋱

⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿
- 플러스 마이너스 기호
±  

∂ 라운드D : 편미분기호
∇ 나블라 : 미분연산자기호
∬ 더블 인티그럴 : 중적분 기호
∮ 서큘라 인티그럴 : 선적분기호
σ : 소문자 시그마는 표준편차기호
Σ : 대문자 시그마는 합에 관한기호
i : 아이. 허수단위.
cosθ : 코사인쎄타
√ - 제곱근
∫ - 인테그랄 : 적분기호
∬ - 중적분 기호로, 이중적분
× - 곱하기
÷ - 나누기
∏ - 대문자 파이
≠ - 같지않다
∴ - 그러므로
∵ - 왜냐하면
≒ - 약: 근사값
≤ - 작거나 같다(좌항이 우항보다)
≥ - 크거나 같다(좌항이 우항보다)
<- 작다(좌항이 우항보다)
>- 크다(좌항이 우항보다)
dθ - 디쎄타 - 미분 기호
≡ - 합동 또는 모듈로(mod) 기호
∈ - (왼쪽이 오른쪽의) 원소
∋ - (오른쪽이 왼쪽의) 원소
⊂ - (왼쪽이 오른쪽의) 부분집합
⊃ - (오른쪽이 왼쪽의) 부분집합
∪ - 합집합
∩ - 교집합
∀ - 임의의
∃ - 존재한다(exist.)​
집합기호 : { }, ⊂,⊃,⊆,⊇,
명제기호 : ∧,∨,←,→,⇔,⇒,⇒
도형기호 : ∠(각),∽(닮음),≡(합동),?(평행),⊥(수직)
대소관계 : <, >, ≤,≥,
각종괄호 : (,),{,},[,]
적분기호 : ∫, ∬, ∮
미분기호 : ∂(편미분)
삼각함수 : sin, cos, tan, sec, cosec, cot, sinh, cosh, tanh, sech, cosech, coth,
arc : 역삼각함수
∞  : (무한대)
!   : (팩토리얼,factorial)

《 도량형 기호 단위 》

㎀  ㎁  ㎂  ㎃  ㎄  ㎅  ㎆  ㎇  ㎈  ㎉  ㎊  ㎋  ㎌  ㎍  ㎎  ㎏  ㎐  ㎑  ㎒  ㎓  ㎔  ㎕  ㎖  ㎗  ㎘  ㎙  ㎚  ㎛  ㎜  ㎝  ㎞  ㎟  ㎠  ㎡  ㎢  ㎣  ㎤  ㎥  ㎦  ㎧  ㎨  ㎩  ㎪  ㎫  ㎬  ㎭  ㎮  ㎯  ㎰  ㎱  ㎲  ㎳  ㎴  ㎵  ㎶  ㎷  ㎸  ㎹  ㎺  ㎻  ㎼  ㎽  ㎾  ㎿  ㏀  ㏁  ㏂  ㏃  ㏄  ㏅  ㏆  ㏇  ㏈  ㏉  ㏊  ㏋  ㏌  ㏍  ㏎  ㏏  ㏐  ㏑  ㏒  ㏓  ㏔  ㏕  ㏖  ㏗  ㏘  ㏙  ㏚  ㏛  ㏜  ㏝

 

《 특수기호 체크표시 》

엔터 기호 :  ↵  

㈜㉿〄

☎☏☐☑☒☓

♠♡♢♣♤♥♦

♲♳♴♵♶♷♸♹♺♻♼☢

♩♪♫♬♭♮♯♰♱

☼☀☽☾☁☂☃☄★☆☇☈☉☊☋☌☍

✓✔✕✖✗✘

✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋

‐‑‒–—―‖‗‘’‚‛“”„‟†‡•‣․‥…‧‰‱′″‴‵‶‷‸‹›※‼‽‾‿⁀⁁⁂⁃⁄⁅⁆⁇⁈⁉⁑

▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▐░▒▓▔▕

■□▢▣▤▥▦▧▨▩▬▭▮▯▰▱◊○◌◍◎●◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟◠◡◢◣◤◥◧◨◩◪◫◬◭◮◯

☖☗☚☛☜☝☞☟☠☡☣☤☥☦☧☨☩☪☫☬☭☮☯

☰☱☲☳☴☵☶☷

☸☹☺☻☿♀♁♂♃♄♅♆♇♈♉♊♋♌♍♎♏♐♑♒♓♔♕♖♗♘♙♚♛♜♝♞♟♧♨

✁✂✃✆✇✈✉✌✍✎✏✐✑✒❍❏❐❑❒❖❘❙❚❛❜❝❞❡❢❣❤❥❦❧

⦅⦆⦿⧺⧻⧼⧽⧾

⨀⨁⨂⨃⨄⨅⨆⨇⨈⨉

、。〃々〆〇〈〉《》「」『』【】〒〓〔〕〖〗〘〙〚〛〜〝〞〟〠〡〢〣〤〥〦〧〨

〩〪〱〲〳〴〵〶〷〸〹〺〻〼〽〾〿

゠ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネ

ノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶヷヸヹヺ・ーヽヾヿ

 

︰︱︲︳︴︵︶︷︸︹︺︻︼︽︾︿﹀﹁﹂﹃﹄﹅﹆﹇﹈﹉﹊﹋﹌﹍﹎﹏

 

《 그리스 문자 》


Α α →알파(ALPHA)
Β β →베타(BETA)
Γ γ →감마(GAMMA)
Δ δ →델타(DELTA)
Ε ε →입실론(EPSILON) 
Ζ ζ →제타(ZETA)
Η η →에타(ETA) 
Θ θ →쎄타(THETA)   (ex, cosθ 코싸인 쎄타)
Ι ι →이오타(IOTA)
Κ κ →카파(KAPPA)
Λ λ →람다(LAMBDA)
Μ μ →뮤(MU) 
Ν ν →뉴(NU)
Ξ ξ →크사이(XI)
Ο ο →오미크론(OMICRON)
Π π →파이(PI)
Ρ ρ →로우(RHO)
Σ σ →시그마(SIGMA)
Τ τ →타우(TAU)
Υ υ →웁실론(UPSILON)
Φ φ →퐈이(PHI)
Χ χ →카이(CHI)
Ψ ψ →프사이(PSI)
Ω ω →오메가(OMEGA)


《 기타 기호 》

μ(마이크로) - 10의 -6승. ( 1/1000000 )
℉ - 화씨
℃ - 섭씨
㎛(마이크로미터)
㎝(센티미터)
㎟(제곱밀리미터)

㎢(제곱키로미터)
㎣(세제곱밀리미터)
㎤(세제곱 센티미터)
㎥(세제곱 미터)
㎦(세제곱 키로미터)
㏈ - 데시벨
㎲ -마이크로세크(micro second)
∠  각 기호  

반응형
반응형

라즈베리Pi#19윈도 PC에서 라즈베리 Pi 원격 제어하기

 안녕하세요~ 이번 시간에는 윈도 PC에서 라즈베리 Pi를 원격 제어해 보는 실습을 진행합니다.

라즈베리Pi에 네트워크가 연결되어 있다면, 모니터 연결 없이 원격으로 제어할 수 있고 연결된 회로를 동작시킬 수 있습니다.
리눅스(라즈비안) 터미널에 접속하기 위한 Putty 프로그램을 먼저 설치하게 되며, 원격제어를 위해 서로 다른 OS 시스템인,  윈도↔라즈비안의 파일 시스템을 연결해주는 Samba Server 설치를 진행합니다.
아울러, 지난 시간 실습한 LED 밝기 조절 예제로 테스트를 해 보겠습니다.

※  본 계시 글의 모든 이미지는 클릭하면 선명한 이미지로 확대하여 볼 수 있습니다. 

 먼저, 라즈베리Pi에 초기 설정이 필요한데요, 모니터를 연결하고 부팅해 주세요. 
외부에서 라즈베리 Pi로 접속할 수 있도록, 'SSH' 통신 채널을 오픈해 주어야 합니다.

 라즈베리파이 라즈 비안 OS의 상단 메뉴에서 Preferences 》'Raspberry Pi Configuration'를 실행합니다.
Interfaces 탭에서 'SSH' 부분을 Enabled로 체크 후, 'OK'를 누르고 재부팅합니다.
그리고 현재 '라즈베리 Pi'가 접속한 IP주소를 확인해야 하는데요,


여기서 중요한 것은 라즈베리 Pi의 주소가 외부에서 접속이 되는 공인 IP의 경우는 문제없지만, 대부분의 경우 라우터에서 할당받은 사설 IP인 경우이므로,  원격 접속하려는 PC는 라즈베리 Pi와 동일한 내부망으로 접속해야 합니다.

또한, 일반적인 WiFi 공유기의 경우 WiFi 접속과 LAN선 접속을 함께 제공하는데요, 예를 들어 라즈베리 Pi는 WiFi에 접속되어 있고, LAN선으로 연결된 Pc에서의 접속은 가능합니다. (같은 내부망이라면, wifi ↔ wifi  ,  LAN ↔ LAN 모두 가능합니다)  대부분의 WiFi 공유기는 WiFi 망과 LAN선망이 같은 IP대역의 내부망으로 할당되기 때문입니다.

먼저 검색 엔진에 접속해서 'Putty'로 검색합니다.  그리고  Download 페이지를 클릭하세요.

Putty 프로그램이란?  

 


'here' 여기를 클릭하세요

 

설치하려는 운영체제에 맞는 버전을 선택합니다. 여기서는 'Windows,64bit'를 선택합니다.

다운로드한 파일을 클릭해서 설치해 주세요.

 Next를 눌러 계속 설치해주세요.  설치에 별다른 어려움 없을 거예요. 


그럼, 설치된 Putty를 실행하세요.

위 이미지의 붉은 네모 부분에 라즈베리 Pi가 할당받은 IP 주소를 입력해야 합니다.  
접속 포트는 '22' 기본 설정으로 두고,  SSH로 체크하세요.

(아래 이미지) 'Default Settings'을 선택하고 Save를 누르고 'Open' 버튼을 클릭하세요. 


(아래 이미지) 만약 Open을 눌렀는데, 이런 보안 경고창이 뜬다면, Yes를 눌러 주셔야 합니다.


아래 이미지와 같은 창이 떴을 때, 
라즈베리 Pi의 계정-비번을 건드리지 않았다면, 로그인 ID는 : pi , 비번은 : raspberry (모두 소문자)

로그인 ID와 패스워드는 아래 이미지를 참고하세요.

※ 만약! 여기 처럼 로그인 메뉴가 뜨지 않는 다면,  접속하려는 라즈베리파이가 외부에서 접속이 가능한 공인IP 인지?  혹은 공인IP에 링크된(포트포워딩 같은) IP 인지? 확인해 보세요.         
하지만  사설 IP에 연결 된 라즈베리파이라도, 동일한 라우터(네트웍, WiFi 공유기)에 접속된 기기일 경우 접속이 가능합니다. 

 

현재, 라즈베리 Pi 파일 시스템에 로그인된 상태이며, 간단한 리눅스 명령어를 입력해서 테스트해 보세요. 
- ls        : 현재 폴더 내의 리스트  ,  
- pwd    : 현재 작업 중인 디렉터리 경로 표시 , 
- mkdir  : 디렉토리 만들기   
- cd      : 디렉토리 바꾸기 (폴더 이동) 
- cd..     : 상위 디렉터리로 이동     
- clear   : 현재 화면 지우기

그럼, 삼바 서버를 설치해볼 텐데요, 

우선, 화면의 명령어로 apt 설치 프로그램 관리자 DB를 먼저 업데이트해주세요. 

DB 업데이트


업데이트되었다면, 지금 보이는 아래의 명령어로 삼바 프로그램을 설치해 주세요. 

삼바 프로그램 설치


아래 이미지처럼,  'Yes / No'를 묻는 창이 나온다면, 모두 'Yes'를 선택해 주세요.

Tab키나 화살표키로&nbsp; Yes를 선택하세요

마우스로는 선택이 안되며, 키보드 '← →' 키 혹은, <Tab> 키로 '<예>'를 선택할 수 있습니다.

삼바 서버 설치 모습

설치 완료 후에는, 아래의 명령어로, 삼바가 정상적으로 설치되었는지 확인할 수 있습니다

삼바 서버 설치 확인 명령어

 ' | ' 기호는 키보드 역슬래시 ' \ ' 또는 '₩' 키와 함께 있는 키에 있습니다.
네, 현재의 화면과 같이 나온다면, 설치가 잘 된 것입니다.

모든 이미지를 클릭하면 확대됩니다~

다음 명령어로 네트워크 연결 상태를 확인해 봅니다.

삼바 서버 네트워크 상태 확인 명령어

 

삼바 네트웍 설치 확인 명령어

라즈베리 Pi의 IP 주소가 보이고, 삼바 서버가 사용하는 445번 포트 번호도 보입니다.
이제 설치된 삼바 서버의 설정만 해주면 됩니다.
이제 , 라즈베리 pi 사용자의 파일 시스템을 윈도에서 접속할 수 있도록 설정합니다.
아래의 명령어를 입력하세요.

pi에 사용자 추가하는 명령어(nano 에디터 사용)

간단한 리눅스용 에디터인 'nano'를 가지고, 삼바 설정 파일에 pi 사용자를 추가해 주는 과정입니다.

위 이미지처럼, 설정 파일 문서가 열리면 커서의 위치를 잘 확인하면서 Page Down 키나 ↓화살표 키로 제일 아래 까지 내려옵니다.  그리고, [pi] 라고 되어 있는 6줄가량을 입력하세요. 
입력이 완료되었다면, 'Ctrl+X'를 눌러 저장할지를 물을 때, 'y'를 입력하고, 엔터키를 치세요. 
엔터키 이외의 다른 키를 잘못 누르거나 하면, 내용 수정이 안 되는 등의 오류가 생길 수 있으니 설명대로 해보세요.
추후에 로그인 접속 문제가 있다면, 방금 작업한 내용의 입력 내용에 오타가 없는지? 이 부분을 다시 살펴보세요.

그리고, 추가한 사용자에게 아래 이미지처럼, 공유 폴더 접근 가능한 비번을 부여해 줍니다.
비번은 기억하기 쉽도록 우선 'raspberry'로 할게요.  

사용자 추가시 등록한 아이디(pi)에 대한 비번(raspberry)예시

비번은 확인 비번까지, 두 번 입력하게 되고, 입력하는 과정이 화면에 표시되지 않으니, 당황하지 말고, 입력 후 엔터를 해주면 됩니다. 

비번 입력표시는 되지 않으니 참고하세요


 추후에 다른 사용자 추가도 이런 형태로 추가해 주면 됩니다.
이제 삼바 서버 설치와 모든 설정은 끝났습니다.
그럼, 이제 설정한 파일이 적용되려면, 다음 명령어로 삼바를 재 실행해야 합니다.

그럼, 같은 내부망으로 연결된 윈도 PC에서 네트워크로 접속해 볼게요.
아래 이미지는, 삼바 서버를 재시작했을 때, 표시되는 화면이며, 윈도 탐색 창으로 접속이 가능한 상태가 됩니다.
그리고서 윈도 실행창을 열어(윈도키 + R키), 라즈베리 pi의 ip 주소를 입력하는 모습입니다. 

 

아래처럼, 윈도 탐색 창이 열리면,  pi 드라이브를 클릭하고 열린 창에 추가해 주었던, 사용자 id와 패스워드를 입력해 줍니다.

이때, '내 자격 증명 기억'에 체크를 해 두면, 다음번에 패스워드를 다시 입력하지 않아도 됩니다.

네, 아래 이미지처럼, 라즈베리 pi에서 보았던, 폴더와 파일 목록이 그대로 뜨는 것을 볼 수 있습니다.

pi의 네트워크 드라이브를 윈도 탐색창으로 접속된 모습

그럼 여기서 잠시, NotePad++을 설치해 볼게요.  
notepad++은 윈도 기본 프로그램인 notepad처럼 가볍고, 가볍게 코딩하거나 편집하기에 정말 좋은 프로그램인데요,
화면처럼 검색해서 운영체제에 맞는 버전으로 다운로드해 설치하면 됩니다.  

노트패드++ 검색하여 설치하기

노트패드++은 코딩 전문 툴은 아니지만, 코드를 비교 분석할 수 있고, 가볍게 코딩하거나 편집하기에 정말 좋은 프로그램인데요, 아래 이미지처럼 검색해서 운영체제에 맞는 버전으로 다운로드해 설치하면 됩니다.

아래 이미지처럼, 노트패드++을 실행해주세요. 

실행시켜 보면 위 모습처럼 뜨며, 첫 화면에 뜬 change.log의 x를 눌러 닫고 새 파일을 작성하면 됩니다.
테스트를 위해 간단히, print("Hello Raspberry pi World")로 작성해보세요.

 작성한 파일을 'piWork'폴더나 적당한 곳에 'hello.py'이름으로 저장합니다.
그럼, 다시, 라즈베리 pi 접속창으로 가서, 방금 작성한 파일을 실행시켜 볼게요.
먼저, 파일을 저장한 경로로 이동합니다.

현재 라즈베리에 pi에는 파이썬 2.x대 버전과 3.x대 버전이 설치되어 있을 텐데요, 각각의 버전을 아래 이미지처럼, 확인할 수 있습니다.

위 이미지처럼, 각각의 버전으로 작성한 코드를 테스트해 보세요.
〔 2.x대 버전은 'python...'으로, 3.x대 버전은 'python3...'로 코드 실행합니다.〕

자, 이제 끝으로, 라즈베리 pi를 직접적으로 컨트롤할 수 있도록, 원격 데스크톱 연결을 해볼게요.
아래 이미지의 명령어를 입력하여, xrdp라는 프로그램을 설치해 주세요.

xrdp는 원격 접속할 때 그래픽 형태의 로그인을 지원하는 프로그램입니다.

설치가 되었다면, 윈도 검색에서 '원격 데스크톱 연결'을 검색하여 실행하세요.

위 이미지처럼, 컴퓨터 항목에, 라즈베리 pi 이름을 입력하고, 연결을 클릭하세요.
그리고, 아래와 같은 질문 창이 뜨면 (예)'(예) Y'를 클릭합니다.


그러면, 잠시 후에 아래와 같은 라즈베리 pi이 접속된 원격 데스크톱 화면이 뜨게 됩니다. 
그리고서,  좀 전에 pi 사용자로 추가해 주었던, id와 패스워드를 입력합니다.

드디어, '윈도 PC'에서 '라즈베리 pi 데스크톱 화면'이 열렸습니다   - 짝짝짝!!! - 

 SSH 관련 경고창은 닫아 주면 됩니다. 추후에 필요한 경우, Raspberri pi의 관리자 비번을 변경하면 경고창은 없어집니다.  다만, 변경 후 비번을 잘 기억해 두지 않으면, 시스템 접속이 불가할 수 있으니,  중요한 파일을 다루거나 하지 않거나, 학습용으로 사용한다면, 변경 없이 사용해도 될 것 같습니다. 

그럼, 라즈베리파이에 직접 로그인하지 않고, 이렇게 원격으로 접속된 상태에서의 파이썬 코드가 잘 실행이 되는지, 
아래처럼, 간단히 확인해 보세요. 

네, hello.py 코드 실행이 잘 되네요. 
그럼, 끝으로, 아래 이미지처럼, 지난 시간 라즈베리 pi에서 직접 pwm 예제를 실행했던 python IDE를 열어보겠습니다. 

Thonny Python IDE를 열고서,  지난 시간 PWM 회로에 사용한 코드나,  혹은 다른 코드를 올려서 라즈베리파이에 연결된 회로를 작동시켜 보세요. 

Run을 눌러 실행시켜 보면, 잘 작동하는 것을 볼 수 있습니다. 
중요한 것은,  지금 이 상황은, (멀리서?) 원격으로 라즈베리파이에 연결된 회로를 동작시킨 상황입니다.  
그래서, 이번 실습을 통해, 라즈베리 pi에 별도로 모니터 연결을 하지 않고, pi와 회로를 제어할 수 있으며,
또한,  라즈베리 pi를 이용해, NAS 서버나, 네트워크 드라이브 저장소와 같은 기능을 구축할 수 있습니다.
그럼, 다음 실습도 기대해 주세요.  감사합니다~

《 전 과정 영상으로 보기 》

 

반응형
반응형

라즈베리Pi#18HardWare PWM 사용하기!  with LED

『 선수학습 』
▶ 라즈베리Pi에 라즈비안 OS설치와 세팅, 그리고 PWM이전 기초실습 :
 【 라즈베리파이 】#01 라즈베리파이 설치하기   #01~#07까지 라즈비안OS 설치와 한글화 설정 등이 있습니다.
  
→  【 라즈베리파이 】#09 RaspberryPi 실습 ①   
→  【 라즈베리파이 】#10 RaspberryPi 실습 ②  
→  【 라즈베리파이 】#11 RaspberryPi GPIO   
→  【 라즈베리파이 】 #12 LED On Off 실습 with Switch   
→  【 라즈베리파이 】 #13 LED Fade In Out 실습 (소프트웨어 PWM) 
→  【 라즈베리파이 】 #14 타이밍 차트 활용한 LED 실습   
→  【 라즈베리파이 】 #15 LED SOS 신호와 동기신호 실습  
→  【 라즈베리파이 】 #16 State Diagram 구현 실습 
→  【 라즈베리파이 】 #17 4LED 순차 점멸 with Timing chart  

-------------------------------------------------------------------------------------------------------------------

안녕하세요~
라즈이노 IoT입니다.
라즈베리파이 베이직 학습 시리즈로 "하드웨어 PWM 사용하기"편을 준비해 봤습니다.

PWM은 디지털 출력을 가지고 아날로그처럼 동작할 수 있도록 해주는 기능이라고 보시면 되는데요,
(PWM : Pulse Width Modulation )
이번 실습에서 PWM 기능은 Led를 점점 밝게 또는 점점 어둡게 컨트롤해봄으로써 테스트해 볼 수 있습니다.

PWM 회로 연결은 아래와 같습니다.

LED는 연결할 때 + - 구분을 해주어야 합니다.

LED +- 극성구분

소프트웨어적인 PWM 기능은 입출력으로 사용되는 GPIO핀 어떤 핀이든 사용 가능한데요, 하지만 CPU에 과부하가 걸릴 수 있고 정밀 타이밍 제어가 필요한 곳에서는 오류가 날 수 있기에, 하드웨어적으로 동작하는 PWM 기능을 이용하게 되며, 그 핀은 정해져 있습니다.

화면 이미지에서 GPIO 18, 12번이 PWM0 로 사용되고, 13번 19번이 PWM1 채널로 사용됩니다.
채널별로 연동되기 때문에, 개별로 동작시킬 수 있는 핀은 실질적으로 두 개로 보시면 됩니다.
하드웨어 PWM기능은 오디오 출력 시에도 사용되기 때문에 동시에 사용할 수 없음을 주의하세요.

《주의 사항!》
1. GPIO 핀 출력 신호의 최대 전압은 3.3v이며,  각 핀당 약 18mA로 제한하며, 가급적 핀 전체 출력 전류가 50mA를 넘지 않도록 주의해 주세요. ( 전류값은 옴의 법칙인 I=V/R 으로 간단히 계산해 볼 수 있으며, 제한 값은 보드에 공급되는 전원과 소모 전력에 따라 달라질 수 있어요.)
2. 헤더 핀의 대부분은 Broadcom 메인 칩으로 직접 연결되어 있기 때문에, 잘못된 연결로 인하여 라즈베리 Pi를 영구적으로 손상시킬 수 있으니, 연결에 주의해 주세요!

실습에 사용된 환경과 준비 사항입니다

LED를 보호하는 저항 값은 220Ω~470Ω사잇값 중에 가지고 있는 것을 사용하면 됩니다.
영상에서는 라즈베리 Pi의 라즈비안 OS에서 직접 코드를 동작시키게 됩니다. 
다음번 영상에서는 윈도 PC에서 원격으로 접속하여 동작시켜 보겠습니다.

아래는 회로 동작에 사용한 파이썬 코드입니다.

《 회로 실행용 파이썬 코드 》

코딩에 사용된 프로그램은,  라즈베리 Pi 라즈비안OS에 기본 설치된 Thonny Python IDE 프로그램입니다. 
아래 이미지처럼, 실행과 디버그, Shell창이 함께 구성되어 있습니다. 

 동작 방식에는 몇 가지 있는데요, 여기서는 비교적 코드가 간단하고 이해하기 쉬운 RPi.GPIO라이브러리 모듈의 PWM 명령어를 사용했습니다.


LED의 밝기는 아래 이미지처럼, 출력 신호의 High와 Low신호의 비율(Duty Rate)로 결정됩니다.


ChangeDutyCycle(듀티비%) 함수로 0~100%의 값을 직접 입력해 넣어 주면 조절할 수 있습니다.

그리고, PWM 파형에는 주파수의 개념이 들어가는데요, 
주파수(Frequance)라는 것은 PWM 1주기의 신호가 1초에 몇 번 반복되는지를 의미합니다.

좌측 이미지처럼 1초에 1회 반복되면 1Hz라 하며, 우측 이미지처럼 1초에 3번 반복되는 형태이면 3Hz라 합니다.
만약 1초에 100번 반복되면 100Hz, 1000번 반복이면 1KHz(1000Hz)가 됩니다.
PWM 신호의 주파수는 LED에서는 신호의 깜빡임으로 나타나게 되며,  주파수가 낮으면 깜빡임이 확연하게 보이며, 주파수가 높으면 밝기 조절 때 더 자연스럽게 보입니다. 
다만, 사람의 눈은 잔상효과로 인하여 주파수가 낮더라도 깜빡임이 없는 것처럼 보일 수 있는데요, 디지털 눈인 카메라로 보면 그 차이를 쉽게 확인할 수 있습니다. 
(아래는 이미지여서 실제 깜빡 임의 차이는  맨 아래 전체 영상에서 확인 가능합니다.)


그럼 위 코드를 입력하고 Python IDE를 실행시켜 라즈베리 Pi에 연결된 LED를 동작시켜 보세요. 
코드를 살펴보면,  듀티비 값은 for 문에 의해 0~100% 증가/감소를 반복하며 밝기 조절이 되고 있습니다.
그럼 time.sleep( )의 delay 값을 0.1초에서 0.01초로 바꾸어 보면, 더 빠르게 Faid In / Faid Out이 되는 것을 볼 수 있습니다. 
주파수의 경우도, 주파수가 낮을수록 깜빡임이 심해지고, 일정 주파수가 이상 되면 깜빡임이 없는 자연스러운 Faid In/Out을 볼 수 있는데요,  옵션 값을  1000Hz, 100 Hz, 50Hz, 10Hz  이렇게 단계적으로 바꾸어 가며 실습해 보세요. 
특히 핸드폰 카메라 렌즈로 확인해 보면, 더 명확히 느끼실 수 있습니다. 

다음 영상에서는 라즈베리 Pi에 모니터를 연결하지 않고, 윈도 PC에서 원격 접속을 통해 라즈베리 Pi에 연결된 회로를 작동시켜 보는 실습을 진행합니다. 
라즈베리Pi에 라즈비안 OS설치와 세팅, 그리고 PWM이전 기초실습도 여기 블로그 【라즈베리파이 기초】 카테고리에 있으니, 필요하신 분은 함께 보면 도움이 되실 듯합니다. 

▶ 실습 전 과정 영상으로 학습하기

 

반응형
반응형

프로젝트#13손 안대고 손 소독하기!  자동 손 소독기 직접 만들어 봅시다!

 

 여러 사람이 이용하는 공동 장소에서는 손소독기가 있어도, 요즘 같은 시기에 직접 소독제를 만지기 꺼려하는 경우가 있게 되는데요,  이에 손 대지 않고 이용할 수 있는 자동 손소독기를 직접 만들어 보겠습니다.

1. 자동 손소독기 특징
 제작의 주안점은, 센서를 이용해 자동으로 작동하며, 소독액 리필 및 교환이 편리하도록 고려하였습니다.
또한, 전원 코드를 연결하지 않는 무선방식으로 충전식 배터리를 사용하였으며,  아두이노를 활용할 수도 있지만, 아두이노 없이 작동 가능하다면 전력 소모량이 적어지고, 비용도 낮아지는 장점이 있음을 반영했습니다. 
다만, 아두이노 사용하지 않는 펌프방식을 채택하다보니,  소독액이 어느정도 묽어야만 펌핑이 가능하기에, 액상 타입의 소독액만 사용 가능하고 겔타입 소독액은 사용이 어렵습니다.  하지만,  젤 타입도 식염수를 적당량의 비율로 섞어주면,  사용가능합니다.  이번 영상에 사용한 방법 또한 젤 용액과 식염수를 희석하여 사용하였습니다. 
 케이스는 3D 툴을 이용하여 3D 프린팅으로 출력해봤습니다.  물론, 종이 상자나 기존 상품 케이스 같은 것을 활용하셔도 좋습니다. 

본 게시글의 모든 이미지는 클릭시 자세히 확대 됩니다


2. 자동 손소독기 재료 준비

본 게시글의 모든 이미지는 클릭시 자세히 확대 됩니다

① 근접센서 :  FC-51 또는 TCRT-5000  1개,  기능은 동일하며, 적외선 LED 부착위치가 조금 다릅니다. 본 회로에서는 FC-51 사용.
② 파워 트랜지스터 (Power TR) : TIP32C 1개,  PNP 타입이며, 100V 3A까지 견딜수 있는 전력용 TR입니다.
③ 레귤레이터 : AMS1117(5v용) 1개 ,  5v 이상의 입력 전원을 정확히 5v 출력으로 유지시켜 주는 정전압 모듈이며, 5V로 동작되는 부품(근접센서, 샤플로 펌프)을 보호하는 역할도 합니다.  만약,  USB 전원(5V)을 사용한다면, 레귤레이터를 생략할 수 있습니다.
④ On/Off 전원스위치 :  스위치의 역할은 전원을 연결하거나 차단하는 역할로 사용 되기에 스위치의 종류에 크게 구애받지 않습니다.  록커(Rocker)스위치나,  토글스위치, 슬라이드 스위치 등 갖고 있는 스위치 중에 선택하면 되며, 본 회로에서는 록커 스위치 규격에 맞추어 케이스를 디자인 하였기에,  록커 스위치를 사용합니다.
⑤ 저항 (Resistor) :  저항은 본 글에서 사용한 펌프를 사용할 경우 100~300옴의 저항을 사용하며, 만약 더 작은 용량의 모터를 사용한다면, 1㏀ 이상의 저항을 사용해야 될 수 있습니다. 중요한 것은, 직접 테스트를 통해 본인이 갖고 있는 펌프가 원활히 잘 작동할 수 있는 저항 값을 찾아야 합니다. 

⑥ 다이오드 (Diode) : 1N4002~1N4007 사이의 다이오드는 모두 사용 가능 합니다.   마지막 숫자 2는 2A , 3은 3A, 7은 7A로, 최대 견딜 수 있는 허용 전류를 의미합니다.  다이오드는 모터의 역전류에 의한 회로 보호용으로 사용됩니다.
⑦ 전원잭 모듈 (DC005-Power Jack) :  리튬배터리 소켓 중에 배럴잭 타입의 소켓을 사용하게 될 경우, 전원잭 모듈을 사용하면, 연결이 편리합니다.  전원잭 모듈 없이 직접 선으로 연결하여도 무방합니다.
⑧ 리튬배터리 및 전용 소켓 : 18650 3.7v 2개 직렬 연결하여 7.4v로 출력이 되도록 직렬 소켓을 사용합니다. 
 회로가 정상 동작하기 위해서는 최소 5V이상의 전원이 입력되어야 하며, 모터가 들어간 회로에서는 전압보다, 전류가 더 중요한데요, 18650과 같은 전류의 세기가 좋은 배터리를 사용하는 것이 좋습니다.   하지만, 리튬이온 배터리는 합선에 의한 스파크 및 발화가 될 수 있으니 다루실 때 반드시 주의를 기울여야 합니다. (합선 주의! 충전시 장시간 자리이탈 금지! )
⑨ 미니 샤플로 펌프 (3v~5v) :  기어가 달린 모터 펌프로서, 내경-외경 크기가 3mm-5mm인 튜브를 사용하는 모터입니다.  실제 튜브 사용은 2mm-4mm 튜브를 사용했습니다.  만약, 모터가 잘 돌아가지 않는다면, 입력 전원이 특히 전류가 부족한 건 아닌지? 확인해 보시고, 기어 박스 속에 윤활제 같은 것을 발라 보세요.
⑩ 워터펌프용 튜브 : 내경-외경 2mm-4mm인 튜브(호수)를 사용 했습니다. 
⑪ 분사 노즐 :  형태 조절이 가능한 (Adjustable Oil Coolant Nozzle: 쿨란트 노즐)을 사용했는데요, 꼭 이런 노즐이 아니라도 되니 주변에서 쉽게 구할 수 있는 것으로 노즐을 대신 할 수 있습니다.

 

※ 주의! 만약, 사용하고자 하는 모터가 달라진다면, 튜뷰의 치수가 달라질 수 있으며, 동작을 시킬 수 있는 전압이 다를 수 있으니 이에 맞게 전원부 구성을 하셔야 합니다. 


3. 자동 손소독기 연결도 & 회로도

본 게시글의 모든 이미지는 클릭시 자세히 확대 됩니다

화면의 왼쪽이 실물 이미지로 된 연결도이고, 오른쪽이 회로도 입니다.  함께 참고해서 연결해 보세요

 :  회로 동작 원리 설명
근접센서에 물체가 접근하면 적외선 송신 LED에서 발사된 적외선이 물체에 반사되어, 수신LED로 입력되어 물체가 있음을 OUT 핀을 통해 HIGH(약 4.x V전압) 신호로 출력하게 됩니다.

근접센서 사용설명

이 신호 전압이 TR의 B(베이스) 단자로 입력되면, 스위칭 작용에 의해 E(에미터)에 연결된 5V의 전원이 C(콜렉터)로 빠져나가면서 모터를 구동하게 되는 원리입니다.

회로에 사용된 모터와 근접센서의 입력이 5V를 넘지 않아야 하기에, 5V레귤레이터를 연결했습니다.
만약, 5V USB전원을 사용할 경우, 레귤레이터가 필요 없기 때문에 바로 연결하면 됩니다.


4. 자동 손소독기 케이스 디자인

작품의 케이스를, 3D 프린팅으로 출력해서 제작했습니다.
먼저 세정액의 직경을 고려하고, 분사 노즐과 튜브의 직경, 스위치와 센서의 홀 사이즈를 결정합니다.
그리고, 배터리를 내장할 것이지 등에 따라, 전체적인 작품의 크기와 모양을 디자인하면 됩니다.
케이스는 3D 프린팅 출력을 고려하여 캡과 바디로 분리해서 작업 했습니다.
디자인은 라이노로 하였고, 편집 파일도 제공해드리니, 수정해서 사용해도 됩니다.
대부분의 3D 프린터에서 출력가능한, g-code 파일과 stl 파일도 제공해드립니다.

A- 캡 케이스 디자인
먼저, 캡 케이스의 디자인을 살펴 보세요.


자신이 가지고 있는 소독액 용기와 부품의 크기를 실측하여 홀의 크기를 결정하면 됩니다.
홀의 크기는 실제 실측치보다, 1~3mm 정도 조금 더 크게 디자인하는 것이 좋습니다.
라이노와 같은 3D 디자인 툴에서 작업한 결과물을 슬라이서 프로그램으로 넘기기 위해서는 보통 '.stl '파일로 저장하게 됩니다.
대표적인 슬라이서 프로그램인 큐라(Cura)에서 확장자 '.stl'로 저장한 파일을 연 모습입니다.

큐라에서는 보통 프린팅이 진행되면서 오류가 없을지? 사전 체크해 볼 수 있고, 벽을 몇%로 채울지? Support를 넣거나? 배드와 익스트루더 온도 등에 대한 옵션을 설정하게 되죠, 마지막으로 G-Code 파일로 저장하고 3D프린터로 옮겨 출력하면 됩니다.
아래는, 실제 3D 프린터로 출력한 결과 모습입니다.



B- 바디 케이스 디자인
아래는 바디케이스를 디자인한 모습입니다.

근접 센서가 부착되는 방향과 위치를 고려하였고, 배터리를 외부에 부착하기 위한 홀을 추가 했어요.

글자는 양각보다는 음각으로 하는 것이 출력하기에는 더 용이합니다.
그럼 이제, 바디 케이스를 슬라이서로 넘겨 보겠습니다.

 큐라(Cura)에서 모델링 파일을 불러 왔을 때, 3D툴에서 디자인한 기준점(C-PLAN)에 따라 모델링의 방향이 다르게 넘어 오는데요, 출력하기에 적합한 방향과 위치를 잡아줍니다.   기타 벽 채움(Infill) 밀도(%)와 지지대(Support) 사용 등 필요한 설정을 해주고서,  출력을 위한 G-Code 파일로 저장합니다. 
이어, 3D 프린팅을 합니다.

 

《 자동 손소독기 - 3D 프린팅 파일 다운로드 》  
   1. 디자인 뷰 파일( .png, .pdf )
   2. 라이노3D 디자인 작업 파일(.3dm)
   3. 슬라이서 편집가능 파일 (.stl)
   4. 3D 프린터 출력용 파일(.gcode)
 위와 같은 파일을 모두 압축하여 올립니다.  필요하신 분은 받아서 편집하거나 사용해 보세요.

3D_Printing File(자동 손소독기).zip
2.88MB

 


5. 자동 손소독기 작품 조립 제작


손 세정제 펌프캡은 가운데 부분을 뽑아내고 호수를 끼워 만들었습니다.

 오일 쿨란트 노즐에도 호수를 최대한 끝까지 밀어 넣는 것이 좋습니다.
이제 부터는 납땜으로 부품을 연결합니다.  그냥 선만 감아도 되지만 인두기를 이용하여 납땜을 해 놓으면, 더 안정적으로 작동합니다.
만약 브레드 보드를 사용하여 연결하려면, 본체 케이스를 좀 더 크게 만드는 것이 좋습니다.
주의해야 할 것은,  전기적으로 합선이 되면 안 되기에, 열수축 튜브나 테이프 등으로 감아 주면 좋습니다.

 아래,  이미지 처럼 근접센서 모듈에 있는 가변저항을 돌려 센싱을 원하는 거리를 맞추어 봅니다.

작동 거리가 너무 가까울 때는 가변저항을 반대쪽으로 돌려 작동거리를 늘려주세요.
처음엔 배터리를 내장할 계획이었으나, 넣을 공간이 부족하여 홀을 뚫어 외부에 부착하였습니다.

 작동이 제대로 된다면,  이제 부품들을 제대로 고정시켜 보겠습니다.
글루건은 부착도 쉽고, 탈착도 가능하기 때문에 적당히 고정시키기에 좋습니다.
글루건은 전기적으로 절연체이기 때문에 회로나 모듈에 방사되어도 큰 문제 없습니다.  다만, 열 배출이 잘 되도록 전부 덮어 씌우지는 마세요.


캡과 바디는 유격이 있기 때문에, 최종 조립이 다되면, 양면 테이프로 고정을 시켜주면 좋습니다.

아래가 완성된 이미지 입니다. 

 참고로 아래 전체 제작과정을 담은 영상을 참고해서,  여러분만의 자동 손소독기를 만들어 보세요~  ^^

《 전체 작업과정과 설명 영상으로 시청하기 》

반응형
반응형

【 아두이노모듈#31】 #1. 활용성 좋은 HC12 무선 모듈, 봉지 뜯은 김에 마스터해보기 


※ 모든 이미지는 클릭 시 확대되어 선명하게 보실 수 있습니다.


【 HC12 무선 개요 】

 ( Long Range RF Wireless Serial Module ) 
 HC-12 무선 모듈은 433MHz 대역을 사용하는 양방향 통신 무선 모듈이며,  1 대 1 (1 : 1) 통신뿐 아니라,  1 대 다(1 : N) 멀티채널 통신이 가능한 모듈입니다.  통신을 위해서는 최소한 2개의 모듈이 필요합니다. 
 통신주파수가 더 높은 고주파 대역을 사용하는 (예, 2.4 GHz) 무선기기들 보다 장애물에 좀 더 유연하며,  MCU를 내장하고 있어 직렬 포트를 통한 외부 장치와의 통신도 가능한 장점이 있습니다.
  전원을 넣으면 바로 연결이 되고, 응답성이 좋아, 다양한 사물기기간의 통신뿐 아니라,  무선조정 RC-Car와 같은 작품들을 만드는 데에도 활용하기 좋은 모듈입니다.  

 

〔 주요 특징 〕
- 장거리 무선 전송 ( 열린 공간에서 1,000 m의 거리를 5000 bps의 속도로 신호 전송 가능 , 저속 모드 시 1.8Km까지도 가능 )
- 모듈에 MCU가 내장되어 있어 모듈에 별도의 프로그래밍을 해줄 필요 없이 시리얼포트를 통한 AT 명령으로 전송 모드를 선택하거나 설정을 제어할 수 있습니다. 
- 절전모드(FU1), 초절전모드(FU2), 일반모드(FU3), 원거리통신모드(FU4) 등의 다양한 옵션을 제공해 줍니다.
- 100개의 채널을 활용할 수 있습니다. (작동 주파수 범위 : 433.4MHz ~ 473.0MHz , 400KHz 간격으로 100개)
- 시리얼(직렬) 포트를 통한 외부 장치와의 통신이 가능합니다.

〔 주요 사양 〕
- 작동 주파수 :  433.4MHz ~ 473.0MHz , 400KHz 간격으로 100개의 채널 사용가능
- 공급 전압    :  3.2V~5.5V
- 통신 거리    :  열린공간에서 1,000m  ,   저속모드 선택 시 1.8Km 가능,  외부 확장 안테나 연결단자 있음
- 시리얼 통신 속도 : 1200 bps / 2400 bps / 4800 bps / 9600 bps (default) / 19200 bps / 38400 bps / 57600 bps / 115200 bps
- 수신 감도    : -117dBm ~ -100dBm
- 전송 파워    : -1dBm ~ 20dBm
- 인터페이스 프로토콜 : UART / TTL
- 작동 온도    : -40℃ ~ +85
- 크  기         : 27.8mm x 14.4mm x 4mm

▶ HC-12 확장 안테나
(송신 거리 혹은 수신 감도를 높이기 위해 필요에 따라 아래와 같은 확장 안테나를 연결할 수 있습니다.  하지만 반드시 필요한 것은 아니며,  대부분의 경우 기본에 포함된 스프링 안테나를 이용하여도 충분합니다. )

확장 안테나
확장 안테나 연결 부위 확대 모습
확장안테나를 연결한 모습 (nRF24L용 안테나와 호환 가능)
스프링 안테나의 연결(납땜) 위치
스프링 안테나와 확장안테나 위치 표시

아래는 스프링 안테나와 핀의 납땜 모습입니다.  스프링은 세우지 않고 일자로 눕혀 납땜해도 상관없고,  핀도 90도 직각으로 꺾이는 핀을 따로 구해서 HC-12 모듈이 기판이나 브레드보드에 세워 꽂을 수도 있으니 참고하세요.


HC12의 스펙을 하나의 테이블로 보기 좋게 정리해보았습니다

 

 HC12의 FUx 모드 설정에 대한 상세 설명 

 

 HC12의 AT Commands 명령어 정리 


[HC12 모듈 간 통신 방식 설명]


HC12 모듈은 아래 이미지처럼, PC(시리얼 모니터)와 시리얼 방식으로 통신을 합니다.


그리고 HC-12 모듈 사이에 433 MHz 대역으로 RF 무선통신을 하게 됩니다.

 

【 HC12 모듈 실습 - 전체 과정 안내 】

 :  HC12 모듈을 구매하셨다면, 봉지를 뜯은 김에(?) 기초 실습부터 단계별로 진행하여 어느 정도 HC12 모듈을 잘 다룰 수 있는 실습까지 이 번에 모두 담아 보려 했습니다.   최종적으로 서보모터 2개를 동시에 무선으로 제어 해보는 실습까지 진행해 본다면, DC모터를 제어하는 것은 좀 더 쉽기 때문에 RC-Car와 같은  RC 기기류는 자유롭게 만들 수 있게 됩니다.  차기 콘텐츠에는 HC12모듈 활용 편으로 RC-Car를 진행할 예정이니 관심 있으신 분들은 이번 실습을 차근차근 진행해보면 많은 도움이 될 것으로 기대합니다.

《 실습 진행 순서 》
실습 #1에서는 HC12 모듈의 시리얼 통신 기능을 배워볼 텐데요, PC ↔ HC12를 시리얼 모니터를 이용한 시리얼 통신기능 학습입니다.

실습 #2에서는 HC12 모듈 간의 RF 통신 실습입니다. 회로를 1대 1,  또는 1대 2이상 구성한 다음, 시리얼 통신 기능을 이용해서 RF를 통해 문자를 주고받고, 받은 문자에 따라 LED를 켜보는 실습입니다. 

실습 #3은 AT-Command 통신 기능을 사용해보는 실습입니다. AT-명령어를 시리얼 모니터 창으로 입력하여 HC-12 모듈의 채널(주파수) 변경/전송 모드 변경/통신속도/통신 강도 변경 등을 실습합니다.

실습 #4에서는 RF 통신을 이용하여 AT-Command 기능을 활용해 보는 실습입니다.  푸시버튼스위치 2개를 이용하여, 무선통신으로 원격으로 HC12 모듈의 채널을 바꾸어 보는 실습입니다.  이번 실습 4를 이용하면, 채널(주파수) 변경뿐 아니라, 실습 3에서 해보았던, 전송 모드 변경/통신속도/통신 강도 변경 등도 할 수 있습니다. 

실습 #5가변저항을 돌려서 RF 통신으로 원격 회로의 LED 밝기를 조절해 보는 실습입니다. 이번 실습을 통해, 기본적인 데이터 주고받는 방법과 입·출력 포트 제어를 이해할 수 있습니다.

실습 #6은 조이스틱 모듈 하나로 원격의 서보모터 두 대를 제어해 보는 실습입니다.  보통 실습 2에서 처럼 무선으로 수신되는 데이터가 한 가지라면, 처리하기 쉽지만,  조이스틱 모듈에서 나오는 두 가지 데이터를 수신받아, 두 개의 서보모터(x, y) 데이터로 각각 분리하여 다루는 코딩 방법을 익히게 됩니다.  서보 모터를 다룰 수 있게 되면, DC 모터는 더 편하게 다룰 수 있습니다.

 앞 단계 실습이 쉬워 보이더라도, 가급적 순서대로 모든 실습을 직접 해보시길 추천드립니다. 
실습에 사용된 아두이노는 사이즈가 작고 별도의 USB to TTL 모듈이 필요치 않은 나노(Nano) 보드를 이용했습니다.
만약, 나노가 아닌 다른 보드를 사용하여도 되며,  특히 우노(Uno) 보드를 사용한다면, 회로의 연결이나 코딩의 변경 없이 거의 그대로 사용할 수 있습니다.


《 실습 재료 》

본 게시글의 모든 이미지는 클릭하면 선명하게 확대 됩니다

위의 실습재료는 실습 1~실습 6까지 전체 실습을 진행할 수 있는 최소한의 재료입니다. 
만약 실습 2에서와 같은 여러 대의 통신 실습을 진행하려면, ~개 이상이라고 표시된 부품들이 더 필요할 수 있으니 참고하세요.  기본적으로, 아두이노 나노(우노) 2대와 HC12 2개의 송수신 회로를 가지고, 연결을 바꾸어가며, 실습 1부터 실습 6까지 진행하실 수 있습니다.

【 실습  #1 】 나노 HC12회로 두 대를 이용한 시리얼 통신 실습

아래 회로 연결도를 구성해 주고 PC와 연결합니다.
▶ 회로 연결도 
(아두이노 나노와 RF 무선통신 모듈 HC12 연결도)
    ※ 아래와 같은 회로 두 개를 준비합니다.

 

《 콘덴서를 달아봅시다 》
바이패스(Bypass)/ 디커플링(Decoupling)  콘덴서란?
  HC12 모듈과 가까운(멀지 않은) 위치에 노이즈 제거 및 회로 전원 안정화를 위해 아래 회로처럼 콘덴서를 달아 주면 도움이 됩니다.  이런 용도의 콘덴서를 바이패스(Bypass) 콘덴서 또는 디커플링 콘덴서(Decoupling Capacitor)라고 칭합니다.  노이즈와 같은 신호는 때때로 하나의 제대로 된 신호로 인식하게 되고, 그래서 노이즈로 인해 오작동이나 결과에 영향을 주게 됩니다.  그리고 노이즈와 같은 신호는 주파수가 높아서 콘덴서를 통해 그라운드(GND)로 흘려버릴 수 있습니다(ByPass),
  그리고 바이패스/디커플링 콘덴서는 IC나, IC가 들어간 모듈 회로에 순간적으로 전류가 크게 흐르면 손상을 입을 수 있는데 이를 막아주는 역할도 합니다.  그리고 신호(직류 성분)에서 노이즈 성분(교류성분)만 GND로 통과시킨다고 하여 Bypass,  또는 신호(직류성분)에서 노이즈(교류 성분)를 분리해 낸다고 하여 디커플링이라 칭하고 있기 때문에,  기본적으로 같은 개념이며,  용어 또한 혼용해서 사용하고 있습니다. 

  또 한 가지 기능으로 각 부품이나 모듈에 순간적으로 전압(전류) 부족 현상이 생길 수 있는데, 콘덴서에 충전된 전압으로 인해 보충해 주는 역할도 하게 되어,   여러모로 도움이 될 수 있습니다.   여기에 사용되는 콘덴서로는, 무극성(극성 구분이 없는)의 세라믹 콘덴서와 이보다 용량이 큰 유극성의 전해 콘덴서를 주로 사용합니다. 
 굳이 콘덴서 구분을 하자면, 
  - 수백KHz~ 수십MHz의 높은 주파수 노이즈 바이패스 용도로  0.01~0.1uF 용량의 세라믹 콘덴서를 사용하며, 
  - 수Hz~ 수십KHz의 낮은 주파수 노이즈 바이패스 용도로 10~1000uF 용량의 전해 콘덴서를 사용하게 됩니다.
따라서 일부 노이즈에 취약한 특정 회로에서는 모든 노이즈 주파수에 대응하기 위해 세라믹과 전해 콘덴서 함께 사용하기도 합니다. 
  하지만 본 회로에서는 10uF 정도의 전해 콘덴서 하나 넣는 것으로 예시를 들었으며,   
이번 실험을 위해 반드시 달아야 하는 것은 아니니, 콘덴서 부품이 없으신 분들은 그냥 진행하시기 바랍니다. 

바이패스(Bypass)/디커플링/전원 안정화용 콘덴서 부착 회로 모습



▶ 실습 준비 
 - HC12 모듈은 구매 시 대부분 핀이나 안테나의 연결이 되어 있지 않은 상태입니다. 따라서 납땜을 위한 인두기가 필요할 수 있습니다.   납땜 작업 시, 핀의 납땜 방향과 안테나의 납땜 위치를 꼭 확인하고 진행하세요.  또한 납땜 과정에서 인두기로 인해 인접한 부품이 손상될 수 있으니 주의하세요.
 - 기본 제공되는 스프링과 연결핀 납땜한 모습 (작업 상황에 따라 'ㄱ자' 꺾인 핀을 사용하거나 안테나를 눕혀 납땜하여도 무방 합니다. 모두 안테나의 기능을 하는데 문제없습니다. )
 - 위 회로 두 개를 준비합니다.  (아두이노 X 2개,  HC12 모듈 X 2개 )
 - HC-12 모듈의 통신방식은 소프트웨어 시리얼을 이용합니다.  이번 실습에서 하드웨어 시리얼 통신단자(D0, D1)는 PC와의 시리얼 통신에 사용되어 지기 때문이며,  소프트웨어 시리얼 통신 단자는 D2 , D3 뿐 아니라 다른 디지털 단자를 연결하여도 됩니다. (코드 수정 필요)
 

▶ 아두이노 코드 
(아래 코드  아두이노 A / B 두 회로는  코드가 동일합니다.)

《아두이노 A 회로용 코드》 

// ###  'A'회로와 'B'회로 코드 ###  
// 시리얼 모니터를 통한 시리얼 통신 실습입니다.
// HC12모듈을 연결한 동일한 회로 두 개를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // 아두이노 2번을 HC-12 TX Pin에 연결, 3번을 HC-12 RX Pin에 연결.
void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도 
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12   통신속도 
  Serial.println("This is 'A' HC-12 Module");   // 2번째 아두이노 코드는 'B'로 변경 
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송  
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);
  } 
  delay (20);
}



《아두이노 B 회로용 코드》 

// $$$  'B' HC-12 모듈  $$$
// 시리얼 모니터를 통한 시리얼 통신 실습입니다.
// HC12모듈을 연결한 동일한 회로 두 개를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // 아두이노 2번을 HC-12 TX Pin에 연결, 3번을 HC-12 RX Pin에 연결.
void setup() { 
  Serial.begin(9600); // 시리얼포트 ↔ computer 
  HC12.begin(9600);   // 시리얼포트 ↔ HC12 
  Serial.println("This is 'B' HC-12 Module");
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);
  } 
  delay (20);
}


 《 위 코드 다운로드 》
아래 파일을 다운로드하여 압축을 풀어보면, 두 개의 파일이 나옵니다.  A 파일은 아두이노 회로 하나에 업로드하고, B 파일은 나머지 아두이노 회로에 업로드합니다.  하지만 실행되는 코드 내용은 같기 때문에 A나 B파일 하나만 가지고 양쪽 모두에 업로드해도 상관없습니다.  하지만, 실행 과정에서는 각각의 A, B 파일이 따로 존재해야 실습을 진행할 수 있습니다.

(실습 1) Serial Communication.zip
0.00MB


▶ 실행 방법 및 결과

: 코드를 업로드 후 아래 순서로 진행하세요. (HC12 모듈을 연결한 아두이노 회로 하나를 편의상 'A'회로라고 하고 동일한 나머지 아두이노 회로를 'B'회로라고 부를게요.)

1.  'A 회로'를 PC의 USB에 연결합니다.  인식된 포트를 확인하고  업로드할 때 사용하였던 A 아두이노 코드를 열고, 보드(나노) 정보를 선택한 다음, 아두이노 나노가 인식된 포트를 선택해 줍니다. 
2. 이어서, 'B 회로'를 PC의 USB에 연결합니다.  인식된 포트를 확인하고  B 아두이노 코드를 직접 클릭해서 여세요. 
보드(나노) 정보를 선택한다음, 아두이노 나노가 인식된 포트를 선택해 줍니다. 

※ 주의 : 일반적으로 윈도 PC에서 시리얼 포트로 아두이노를 두 개까지 포트를 구분해서 인식할 수 있습니다.  
즉, 장치 자체는 인식하고 코드 업로드도 가능하나, 서로 다른 포트로 할당받는 것은 두 개까지만 가능하다는 말입니다.

★☆★ 아두이노 두 개를 하나의 PC에서 서로 다른 시리얼 포트로 인식시키는 방법 ★☆★
 주의해야 할 것은,  A회로 코드를 열었던 아두이노 IDE의 파일 메뉴에서 '열기' 메뉴로 'B'아두이노 파일을 추가로 열게 되면 아두이노-IDE를 두 개 열어도 둘 다 하나의 포트 쪽으로만 인식이 되는 문제가 생길 수 있습니다.
 비록 화면에 뜬 아두이노 IDE 코드 파일은 두 개로 열려 있으나,  아두이노 회로 두 개를 같이 물려보면, 두 회로 모두 동일한 포트 번호로만 할당됩니다.   그러면, 포트 번호가 같기 때문에 아두이노 회로는 한 번에 하나씩만 동작되어서, 
하나의 PC에서 두 회로 간 통신 실험을 진행할 수 없게 됩니다.  따라서,  파일 탐색 창을 열고 'A 아두이노 파일'과 'B 아두이노 파일'을 각각 마우스 클릭으로 열어야 합니다.   그래서 아두이노 두 대를 연결해보면 서로 다른 포트로 할당받게 되고, PC 하나로 원격으로 이루어지는 것과 같은 시리얼 통신 실험을 해볼 수 있게 됩니다.  ( 두 대까지만 가능!  두 대 이상 연결 시에는 한 대를 제외한 나머지 보드는 같은 포트로 중복인식됨)

3.  아래 이미지처럼, 화면에 'A회로 시리얼 모니터 창'과  'B회로의 시리얼 모니터 창' 두 개를 나란히 여세요.
(반드시 포트 번호가 서로 다르게 되어 있는지 확인해 주세요)

이미지를 클릭하면 확대 됩니다

4. 각각의 시리얼 모니터 창을 여세요. 
(시리얼 모니터 창에 표시된 보드 레이트 Baud Rate가 코드와 같은 9600 bps로 되어 있는지 확인하세요)


(아두이노 연결)  두 개 이상은 같은 포트 번호로 할당받게 되어 구분이 되지 않게 됩니다. 
(동작 화면)  동작은 아래처럼 A-Nano 회로가 연결된 시리얼-모니터 입력창에 문자를 입력하면,  B-Nano 회로가 연결된 시리얼-모니터 화면으로 출력됩니다.   그리고,  양방향 통신이 가능한 모듈이고 코딩도 양방향이 되도록 해 두었기 때문에,  반대로 B-Nano 회로의 시리얼-모니터 입력창에 문자를 입력하면, A-Nano 회로가 연결된 시리얼-모니터 화면으로 출력되는 것을 볼 수 있습니다.

▶ 동작 영상
(본 글 제일 아래 전체 동영상을 참고해보세요 : 음성 설명 있음)

 

【  실습  #2 】 무선 RF로 여러 곳의 LED를 On/Off 하기

: 무선으로 멀리 떨어진 곳의 LED 들을 On/Off , 켜고 끄는 실습입니다.   지금은 LED를 예시로 들지만, 무선으로 LED를 제어할 수 있다는 뜻은 전등이 되었든 모터가 되었든 필요한 부가 장치만 달아주면 충분히 제어할 수 있음을 의미합니다.  예를 들어, 220V로 동작하는 전등을 무선으로 On/Off 하고 싶다면, 릴레이 모듈을 추가해주면 쉽게 해결할 수 있습니다.   

아래 회로 연결도를 구성해 주고 PC와 연결합니다.
▶ 회로 연결도 
(아두이노 나노와 RF 무선통신 모듈 HC12 연결도)
《 실습 2 :  A-Nano 기본회로 》

(실습2) A-Nano 기본회로

  
《 실습2 : B-Nano LED 회로 》

《 실습2 : B-Nano LED 회로 》

▶ 실습 준비 :
 위의 회로 두 가지를 준비해주세요.    LED의 색과 크기는 상관없으며, + , - 극성만 잘 구분해서 연결해주세요. 
저항 역시, 100옴~470옴 사이의 저항 값이면 어느 값이든 사용할 수 있습니다.  저항이 작을수록 LED 빛이 더 밝아지며, 저항 값이 클수록 조금 더 어두워지는 차이가 날 뿐입니다.   하지만, 1K옴이 넘어가게 되면 LED를 켤 수 있는 전류를 공급할 수 없어 LED의 동작 확인이 안 될 수 있습니다.
회로는 송신 회로 'A 하나'와,   수신 'LED 회로' 1개 또는 그 이상을 준비할 수 있습니다. 

▶ 아두이노 코드 
(아래 코드  아두이노 A와 / B회로의 코드를 각각 구분해서 업로드하세요.)

《아두이노 A 회로용 코드》 

// ###  'A' HC-12 모듈   ###
// 시리얼 통신실습 2편 - 시리얼 모니터 문자 입력으로 LED 제어하기!
// HC12모듈을 연결한 동일한 회로 두 개를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // 아두이노 2번을 HC-12 TX Pin에 연결, 3번을 HC-12 RX Pin에 연결.
void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도 
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12   통신속도 
  Serial.println("This is 'A' HC-12 Module");   
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송  
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);
  } 
  delay (20);
}


《아두이노 B , C , D 회로용 코드》 
B회로 하나만 가지고 실습할 수 있으며, 만약 C, D회로를 추가로 늘릴 경우에는 아래 코드에서 비교문 부분에
L1\r\n,   L2\r\n,   L3\r\n 과 같은 부분만 바꾸어서 업로드하면 됩니다.

// $$$  'L1' HC-12 모듈  $$$
// RasINO IoT : https://rasino.tistory.com/
#define LED_L1 5
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 

void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'L1' HC-12 Module");
  pinMode(LED_L1,OUTPUT);
  digitalWrite(LED_L1,LOW);  
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);    
    if ( input == "ON\r\n" || input == "L1\r\n" )  { //공백 구분함, line ending없음으로 설정(엔터구분) 
      for (int i=0;i<10;i++) {
        digitalWrite(LED_L1,HIGH);
        delay(200);        
        digitalWrite(LED_L1,LOW);        
        delay(200);        
      } 
    } 
  } 
  delay (20);
}

 《 위 코드 다운로드 》
아래 파일을 다운로드 해서 압축을 풀어보면 아래 파일 4개를 들어 있으며, 필요한 파일만 사용하면 됩니다.

(실습 2) RF 통신 with LED.zip
0.00MB
위 압축파일 속에 이와같은 4개의 파일이 있습니다

▶ 동작 실행(방법)
:  A회로의  아두이노-IDE의 시리얼 모니터 창을 열고 커맨드 입력란에 아래와 같이 입력해보세요.
 -  L1  입력   L1 회로(B회로)의 LED가 10회 깜빡입니다. 
 -  L2  입력 →   L2 회로(C회로)의 LED가 10회 깜빡입니다. 
 -  L3  입력 →   L3 회로(D회로)의 LED가 10회 깜빡입니다. 
 -  ON 입력 →   L1, L2, L3 회로의 모든 LED가 10회 깜빡입니다.


코드에서 중요한 부분을 설명드리면,   시리얼 모니터 입력창을 통해 입력한 문자는 L1  또는 ON이라는 문자만 입력되는 것이 아니라, 눈에는 보이지 않지만,  엔터키를 누르기 때문에(전송 버튼 누름도 마찬가지)  줄 바꿈에 해당하는 개행 문자가 입력되게 됩니다.   따라서 이 개행 문자도 함께 비교해 주어야 코드의 if 비교문이 제대로 작동합니다. 

엔터입력하면 개행문자(\r\n) 입력됨

 따라서  아래와 같은 코드 형태로 비교해 주어야 합니다. 
if ( input == "ON\r\n" || input == "L1\r\n" )   { ...  }

또한, 아래처럼, 시리얼 모니터창의 입력 옵션을 line ending 없음으로 해야,  개행 문자 처리가 중복으로 되지 않아 제대로 처리됩니다. 

 

 마지막으로 중요한 한 가지는, 아두이노와 같은 C/C++ 언어 프로그래밍에서 개행 문자의 처리가 운영체제 별로 다르다는 데 있습니다. 
최근에는 아두이노 코딩 환경을 윈도 환경에서 뿐 아니라, 리눅스나 맥 OS 환경에서 많이 하는 것을 볼 수 있는데요,
아래 운영체제 별 개행 문자 처리를 참고하여,  코드에 반영해 주어야 합니다.  ( '\' 표시는 역슬래시입니다)
 → Windows OS 개행 문자 :   \n\r
 → Mac OS 개행문자        :   \r
 → Linux 개행문자           :   \n

 

▶ 동작 영상
(본 글 제일 아래 전체 동영상을 참고해보세요 : 음성 설명 있음)

 

【 센서 실습  #3 】  LED의 밝기를 무선으로 조절하기(with VAR)

: 실습 #3에서는 가변저항 또는 볼륨으로 불리는 VAR(Variable resistor, 또는 Potentiometer)을 이용하여 원격지에 있는 회로의 LED의 밝기를 조절해 보는 실습입니다. 
 또한, VAR 쪽의 송신부에도 LED를 달아서 VAR 값의 변화가 제대로 되는지? 먼저 확인할 수 있도록 하였습니다

▶ 회로 연결도 (VAR이 연결된 회로와 LED 수신 회로 두 가지를 만드세요)
《 회로 1 :  VAR - Nano 송신 회로 》

《 회로 2 :  VAR - Nano 송신 회로 》


▶ 실습 준비 :
 위의 회로 두 가지를 준비해주세요.  가변저항은 여러 가지 종류가 있으며, 어떤 종류를 사용하더라도 사용이 가능합니다. 용량 또한,  1K옴~1M옴 사이의 용량이면 회로를 구성하는데 크게 문제없습니다. (권장, 1K옴~10K옴 사이)

여러가지 가변(반고정) 저항의 종류들

 본격적인 실습 전에,  가변저항의 역할과 활용에 대해 설명드립니다. 

- VAR의 ①번과 ③번 양단에 5V의 전압을 넣어 주면, ②번 단자로 전압이 나오게 되는데요,
VAR 조절 레버를 ①번 끝에서 ③번 끝까지 돌림에 따라, ②번으로 5V~0V 사이의 전압이 출력됩니다.
그리고, VAR의 ②번 단자 출력을 아두이노의 아날로그 입력 단자로 연결하였는데요,
아두이노 내부의 아날로그 입력 단자들에 연결된 AD Converter(Analog to Digital)에 의해 '0~5V'라는 아날로그 값이,  '0~1023'라는 디지털 수치로 변환되어 전달받게 됩니다.
나노(우노)에 내장된 ADConverter는 10bit의 분해능을 갖고 있어 최댓값은 2의 10승 값인 1024가 됩니다.
그리고 아두이노의 출력 단자는 디지털 단자여서 기본적으로 Low(0v)와 High(5v)의 값만 출력되는데요
LED의 밝기를 조절하려면, 0v~5v 사이의 아날로그 값이 필요합니다.

아두이노의 디지털 단자 중에서 아날로그와 같은  출력을 대신해 주는 단자가 PWM 출력 단자인데요.
High와 Low신호의 출력 비율(Duty Cycle)을 조절하여, 출력 전압이 조절되는 효과를 얻을 수 있습니다

아두이노에서는 디지털 단자의 숫자 옆에 '~'물결 기호가 붙어 있는 단자가 바로 PWM기능이 있는 디지털 단자입니다
( ※ Uno와 Nano의 PWM 단자: D3 ,D5, D6, D9, D10, D11 )

~ 물결무늬가 있는 핀이 PWM 출력 기능이 있는 핀입니다

아두이노의 아날로그 입력이 어떻게 디지털 값으로 변환되고 다시 아날로그 형태(디지털 PWM)로 출력되는지 아래 이미지와 함께 설명드리면, 
 나노(우노) 보드의 PWM 포트 출력은 8bit로 처리되기에, 2의 8승 값인, 0~255 사잇값으로 출력됩니다

그런데, A0로 입력된 값은 0~1023 값이고, 출력할 수 있는 최대 범위는 0~255이기 때문에, 입·출력의 매칭이 필요한데요, 아두이노 코드에서 맵핑 함수를 사용하면 간단히 해결할 수 있습니다

0~1023의 범위 값을 0~255값으로 맵핑하는 함수 사용

이렇게 해서 VAR가변저항을 돌려 변화되는 아날로그 입력 전압이(0~5V) 나노의 High(5V), Low(0v) 기능만 할 수 있던 디지털 출력 포트로 PWM 기능을 사용하여 0~5v의 변화되는 출력을 낼 수 있게 되어 LED의 밝기 조절이 가능해집니다. 


▶ 아두이노 코드 
( 아래의 코드 두 가지를 구분해서 각각 아두이노에 업로드해주세요. )
《 회로 1 : VAR 회로 코드 》

// VVVVV  HC-12 'VAR-side' 가변저항 회로 코드   VVVVV
// RasINO IoT : https://rasino.tistory.com/
#define LED_L1 5
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 

int Var = 0;

void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'VAR controller' HC-12 Module");
  pinMode(LED_L1,OUTPUT);
  digitalWrite(LED_L1,LOW);  
} 
void loop() { 
  Var = map(analogRead(A7), 0, 1023, 0, 255);
  analogWrite(LED_L1, Var);
  Serial.println(Var);  
  HC12.write(Var); // 주의! : 'print()'가 아닌, 'write()'를 사용합니다
  // ※ 'print()'는 숫자의 경우 ASCII값으로 변환하여 전송하기 때문에, 
  // 숫자값 그대로 전송하는 'write()'를 사용합니다
}


《 회로 2 : LED 회로 코드 》

// ### HC-12 'LED-side' 가변저항(LED) 회로 코드   ###
// RasINO IoT : https://rasino.tistory.com/
#define LED_L1 5
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 
void setup() { 
  Serial.begin(9600); // computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'LED' Side HC-12 Module"); 
  pinMode(LED_L1,OUTPUT);
  digitalWrite(LED_L1,LOW);  
} 
void loop() { 
  while (HC12.available()) { 
    int input = HC12.read();
    Serial.println(input);
    analogWrite(LED_L1, input);    
  }   
}


《 위 코드 다운로드 》

(실습 3) Var-LED.zip
0.00MB

▶ 동작 실행(방법)
:  VAR이 연결된 나노 회로의 VAR을 한쪽 끝에서 다른 쪽 끝으로 돌려보면 RF 신호를 수신한 LED 회로의 LED의 밝기가 조절됩니다.  이때 보조배터리와 같은 외부 전원만으로도 동작시킬 수 있으며, PC에 연결해서 실습을 진행할 경우 시리얼 모니터 창을 띄우면, 변환되는 0~255 값을 함께 확인할 수 있습니다.

▶ 동작 모습

▶ 실행 영상
(제일 아래 전체 설명 동영상 참고)

【 실습  #4 】
시리얼 통신#1 (AT-커맨드 명령어 사용하기)

: 실습 #4에서는 AT-커맨드 명령어를 사용하여 HC-12 모듈의 설정을 바꾸어 보겠습니다.  이번 실습 4는 #1편과 #2편으로 구분되어 있습니다.
PC와 연결하고 아두이노-IDE의 시리얼 모니터를 사용하여 AT-통신 명령어를 입력하면, HC-12의 '통신 채널 변경', 'Bauds Rate', '통신 모드'와 같은 설정을 변경할 수 있습니다.  AT-명령어 모드로 진입하기 위해서는, HC12 모듈의 SET 단자가 GND(Low)로 연결되어 있어야 합니다.  

▶ 실습 준비 : 회로는 하나만 준비하면 됩니다.  상호 통신이 아니라 PC와 연결하여 AT  명령어를 이용한 HC-12 모듈의 설정 변경 실습이기 때문에, 회로는 하나를 준비하고,  실습은 2가지로 진행합니다. 

▶ 회로 연결도
《 실습 4-1의 회로 :  Set 핀 - GND 연결된 회로 》

▶ 아두이노 코드 
( 아래의 코드를 업로드해주세요. )
《 실습4-1 회로 코드 》

// ###  'AT-Command'  실습     ###
// AT-명령어를 통하여 HC12의 채널/속도/모드... 등을 변경해 보는 실습
// HC12모듈을 연결한 회로를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3);

void setup() 
{
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도 
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12 통신속도 
}
void loop() 
{   
  while (Serial.available()) {
    HC12.write(Serial.read());
  }
  while (HC12.available()) {
    Serial.write(HC12.read());
  }
}

《 위 코드 다운로드 》

HC12_AT-Change_CH.zip
0.00MB

▶ 동작 실행(방법)
 :  회로를 구성하고 PC와 연결하여 아두이노-IDE의 시리얼 모니터창을 띄우면, AT-명령어 입력 모드 상태가 됩니다.
AT-명령어 모드로 진입하기 위해서는, HC12 모듈의 SET 단자가 GND(Low)로 연결되어 있어야 합니다.

아래, 많은 시간을 들여 직접 정리한 AT-명령어 표를 참고하여 테스트해보세요. 

- '시리얼-모니터' 입력창에 대문자로 'AT '라고 입력하세요.
  'OK'라는 응답 신호가 나온다면, AT-Command 모드 진입에 성공한 것입니다. 

- 'AT+RX'를 입력하면 현재의 주요 설정값을 한 번에 보여줍니다.
- 그리고,  현재 RC001로 '채널 1'로 설정되어 있는 것을 '채널 2'로 바꾸어 보세요.

- 'FUx'모드 설정을 통해 좀 더 특수한 환경에서 동작할 수 있도록 동작 모드를 변경할 수도 있습니다.
만약, FU2와 FU4 모드를 선택한다면, 시리얼 포트 통신속도는 제한된 속도로 자동 변경됩니다.

만약, FU2와 FU4 모드를 선택한다면, 위 이미지의 FUx 모드 상세 설명에서 처럼, 시리얼 포트 통신속도는 제한된 속도로 자동 변경됩니다.
- 송신 파워 설정도 변경해 보세요.


- 'AT+DEFAULT' 명령어로 바뀐 설정을 한 번에 복구할 수 있습니다

- 마지막으로 HC12 모듈의 셋업 설정이 마무리 하였다면,   SET핀을 GND에 연결하였던 선을 제거해야, 
HC12모듈의 통신이 가능하다는 것을 기억하세요.

 

시리얼 통신#2 (AT-커맨드 명령어 사용하기)

이번 실습 4-1는 셋업을 직접 손으로 SET-GND 핀을 연결하지 않고, 프로그램 코딩으로 아두이노의 아웃풋 출력 단자를  LOW / High 출력으로 조절하여 설정하는 실습입니다.   손이 아닌, 코드로 셋업을 조절하게 되면, 채널 변경이나, 모드 변경 등과 같은 기능들을 코드나, 스위치 조작 등 더 다양하게 활용할 수 있게 됩니다. 
▶ 회로 연결도

《 실습 4-2의 회로 :  Set 핀 - 디지털 입출력 핀 연결된 회로 》

SET 핀의 아두이노 포트 연결은 아무 디지털 출력 포트로 선택하면 됩니다.  여기서는 D6번 핀으로 하였고, 코드에도 6번으로 되어 있으니 변경하려 한다면, 코드의 핀 번호를 수정하세요.

▶ 아두이노 코드 
( 아래의 코드를 업로드해주세요. )
《 실습 4-1 회로 코드 》

// ###  'AT-Command'  실습     ###
// HC12 모듈의 Setup Pin을 활용한 HC12의 채널/속도/모드... 변경 실습 
// HC12모듈을 연결한 회로를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3);
#define setPin 6  // HC12 모듈의 SET 핀에 연결될 아두이노 핀 번호 정의 함

void setup() 
{
  Serial.begin(9600);
  HC12.begin(9600);
  pinMode(setPin,OUTPUT);
  digitalWrite(setPin,LOW);  //  AT command mode 진입
  delay(100);                // 명령어 전달되는 시간을 기다려 줌 
  HC12.write("AT");          // AT 명령어 입력 ( "OK" 문자 응답)
  delay(300);                // 명령어 전달되는 시간을 기다려 줌 
  HC12.write("AT+C003");       // 현재 HC12의 설정 정보를 보여달라는 명령
  delay(300);                // 명령어 전달되는 시간을 기다려 줌   
  HC12.write("AT+FU2");       // 현재 HC12의 설정 정보를 보여달라는 명령
  delay(300);                // 명령어 전달되는 시간을 기다려 줌   
  digitalWrite(setPin,HIGH); // AT-mode 빠져나옴(data 전송모드)
}

void loop() 
{ 
  while (HC12.available()) {
    Serial.write(HC12.read());
  }  
  while (Serial.available()) {
    HC12.write(Serial.read());
  }

}

《 위 코드 다운로드 》

HC12_AT-Use_Setup_pin.zip
0.00MB

▶ 동작 실행(방법)
 :  회로를 아래와 같이 구성하고 PC와 연결하여 아두이노 코드를 업로드하면, 코딩 루틴에 의해 자동으로 채널이 001번 채널에서 002번 채널로 변경되게 됩니다.  

 그럼, 코딩에 의해 자동으로 채널이 변경된 것인지? 확인하기 위해,  그래서 AT 모드로 진입하기 위해 다시 아래처럼, 6번 핀에 연결된 SET-핀을 뽑고,  직접 GND에 연결해 주세요. 

그리고, 아두이노-IDE의 시리얼 모니터 창을 열어 AT+RX 명령어로, 설정 상태를 확인해보면, 채널이 002번 채널로 변경되어 있는 것을 확인할 수 있게 됩니다.
▶ 동작 모습

그럼, 코드를 수정해서, 다른 AT-명령어도 넣어서 적용해 보세요.  (아래는 예시입니다)


이렇게, SET핀을 아두이노 포트로(코드로) 제어하게 되면, 이어지는 실습에서처럼, 버튼으로 채널을 변경하거나, 통신 모드 변경과 같은 것을 쉽게 구현할 수 있습니다.

【 실습  #5 】  무선 버튼으로 통신채널 변경하기

: 실습 #5에서는 '버튼 1'을 누르면, 통신채널 1번으로 동기화되고, '버튼 2'를 누르면, 통신채널 2번으로 동기화되는 실습입니다.  실습#4를 응용한 실습인데요, 버튼 수를 늘려서 변경되는 채널 수를 늘릴 수도 있고, 통신 모드 변경이나 파워 설정 같은 AT모드상에서 변경할 수 있는 것들을 이번 실습을 통해 쉽게 적용시킬 수 있습니다.  

▶ 실습 준비 : 회로는 두 가지를 준비합니다.  버튼(스위치) 2개가 들어간 1번 회로와,  신호를 수신하여 적용되었다는 것을 알 수 있도록 LED를 연결한 2번 회로로 구성됩니다.    또한, 무선 RF의 장점인 채널이 일치하면 1대 N의 통신이 가능함을 보여드립니다.  이 때는 똑같이 적용된 2번 회로가 2개 이상 필요합니다.  기본적으로, 2번 회로 하나만 있어도 실습 5의 학습은 가능합니다. 

[ 회로에 사용된 푸시버튼스위치(PB-SW) 설명 ] 
 아두이노에서 PB-SW는 보통 High 신호와 Low 신호를 입력하고자 할 때 사용하게 되는데요, 
스위치 한쪽을 GND로 연결하고, 나머지 한쪽은 저항을 통하여 VCC로 연결하게 되는데요, 
버튼을 누를 때는 GND로 연결되기 때문에, Low 신호가 아두이노 포트에 입력되며,
버튼을 누르지 않았을 때는 GND와 분리되고, 저항을 통해 VCC로 연결되기 때문에 High 신호가 입력됩니다. 
이때, 저항의 역할은 기본적으로 스위치를 누를 때 GND와 VCC가 합선(Short)되는 것을 방지하고, 누르지 않았을 때는, 확실한 High 신호를 입력되게 하는 역할로 사용되며, 이런 저항의 역할을 바로 풀업(Pull UP) 저항이라 합니다. 
이와 반대되는 개념의 저항을 풀다운(Pull Down) 저항이라 합니다. 

외부 풀업저항 연결

위, 이미지에서 스위치를 닫으면 GND(그라운드, 혹은 0V)에 연결되어 Low 신호가 아두이노의 D5번 포트로 입력되게 되며, 스위치를 오픈하면, 5V의 High 신호가 저항을 타고 D5로 입력되는 구조입니다.    여기서  만약에 저항을 연결하지 않고 직접 5V 전원을 D5로 연결시킬 경우, 스위치를 닫을 때, GND와 5V가 직접적으로 맞닿아 합선(Short)되어 문제가 생기게 되어 저항이 필요하며,   만약 저항과 5V 연결 자체를 하지 않게 될 경우, 스위치를 닫을 때는 확실한 Low신호가 입력되나, 스위치를 오픈할 경우에는 확실한 High 신호가 입력되지 않아 불안정해집니다.  따라서, 이런 이유 때문에 스위치와 함께 사용하게 되는 저항을 일컫어,  확실하게 +전원(5V, VCC)으로 끌어올린다(당긴다)하여, Pull UP 저항이라 칭합니다.   마찬가지로, 아래와 같은 연결의 저항을 풀 다운 저항이라 칭합니다. 

풀 다운(Pull Down) 저항과 스위치의 연결

그런데,  아두이노를 설계할 때, 각 포트마다 스위치를 연결할 경우 필요한 풀업 저항의 연결을 최소화하고자 하는 목적으로 내부 풀업 저항이 설계되어 있습니다. 

따라서, 외부에 별도의 풀업용 저항을 연결할 필요 없으니 회로 구성을 더욱 간단히 할 수 있어 편합니다. 
그럼, 풀업 저항의 기능을 활성화하기 위해서는 아두이노 코드에서,  해당 포트의 입력을 풀업 기능으로 설정만 해주면 됩니다. 
일반 적으로 아두이노 코드에서 예를 들어, D5번 포트를 입력으로 설정할 경우에는, 
pinMode ( 5, INPUT );   이렇게 작성하나,    풀업 기능의 입력을 사용할 경우에는 
pinMode ( 5, INPUT_PULLUP );   이라고 설정해주면 됩니다. 

▶ 회로 연결도(VAR이 연결된 회로와 LED 수신 회로 두 가지를 만드세요)
《 회로 1 :  버튼스위치(PB-SW) Nano 회로 》
회로 1에서도 버튼을 눌렀을 때, 눌러졌다는 것을 알기 위해 LED를 연결해 놓았습니다.

《 회로 2 :  LED - Nano 회로 》

▶ 아두이노 코드 
( 아래의 코드를 업로드해주세요. )
《 실습 5  버튼 스위치 1번 회로 코드 》

/* 《 버튼으로 통신채널 변환하기 》 --- 1번 Nano (버튼 회로) ---  
 * AT명령어를 수정하면 통신속도(거리)/ 동작(통신)모드 / 슬립모드 / 송신파워 등의 설정이 가능함 
 * 회로의 상세자료 및 설명은 게시글 참조 : https://rasino.tistory.com/326
*/

#include <SoftwareSerial.h>  //소프트웨어 시리얼 연결은 2번, 3번 이외의 비어있는 다른 디지털 핀을 사용해도 됨
SoftwareSerial HC12(2, 3);   // (HC12의 TX Pin, HC12의 RX Pin)을 연결할 아두이노 포트 지정 (2번, 3번)
#define setPin 6    // HC12의 SetPin 연결 (AT모드 진입에 사용되는 핀)  
#define btn1 5      // '버튼 1' 연결
#define btn2 9      // '버튼 2' 연결 
#define led 12      // 버튼을 누를 때 확인하기 위한 LED 연결

byte incomingByte;        // 수신 데이터를 바이트 단위로 저장하는 변수 선언
String readBuffer = "";   // 송·수신 데이터 저장을 위한 문자열 변수 선언
int btn1_State = 0;       // 버튼 1의 상태
int btn1_Pressed = 0;     // 버튼 1의 눌러짐 체크 변수
int btn2_State = 0;       // 버튼 2의 상태  
int btn2_Pressed = 0;     // 버튼 2의 눌러짐 체크 변수

void setup() {
  Serial.begin(9600);           // PC와의 시리얼 통신 포트 열기(시작)
  HC12.begin(9600);             // HC12의 시리얼 포트 열기(시작)
  pinMode(setPin, OUTPUT);      // HC12의 AT 모드 진입을 위한 아두이노 연결핀 출력설정
  pinMode(btn1, INPUT_PULLUP);  // 버튼 1을 저항 연결 없이 내부 풀업을 사용하여 연결함
  pinMode(btn2, INPUT_PULLUP);  //     2를 
  pinMode(led, OUTPUT);         // 버튼 입력 표시를 위한 LED 연결  
  digitalWrite(setPin, HIGH);   // HC-12를 일반적인 전송 모드로 설정함 (LOW 일경우 AT 커맨드 모드로 진입함)
  digitalWrite(led,LOW);        // LED OFF로 디폴트 설정
  Serial.println("This is ** Nano1 ** , i'm ready!");
}

void loop() {
  // 문자열 변수 버퍼에 HC12의 수신 데이터 저장
  while (HC12.available()) {             // HC12에 데이터가 있다면
    incomingByte = HC12.read();          // HC12로 부터 바이트(byte) 단위로 읽어 byte타입 변수에 저장
    readBuffer += char(incomingByte);    // 각각의 읽은 바이트를 문자열 변수에 저장 (예시, 'A' 'T' '+' 'R' 'X' → "AT+RX")
  }
  delay(100);
  // 시리얼 데이터가 있을 경우 HC12(1번 nano)의 데이터를 외부 다른 HC12(2번 nano)로 발신
  while (Serial.available()) {
    HC12.write(Serial.read());
  }

// 〔 #####  버튼1이 눌러지면, HC12의 채널을 '001'로 설정하는 루틴의 시작 ##### 〕

  btn1_State = !digitalRead(btn1);    // 버튼의 하드웨어 연결이 누르면 LOW, 떼면 HIGH 입력되므로, '!'로 반전 값 저장함
  if (btn1_State == HIGH & btn1_Pressed == LOW) {   // 만약 버튼1이 눌러지고, 버튼1 눌러짐 체크 변수가 LOW 였다면
    btn1_Pressed = HIGH;            // 버튼1 눌러짐 체크 변수를 HIGH로 함                 
    delay(20);
  }
  if (btn1_Pressed == HIGH) {            // 만약 버튼1 눌러짐 체크 변수가 HIGH 라면,    
    digitalWrite(led, HIGH);             // LED를 켜고  
    HC12.print("AT+C001");               // 다른(nano_2번) HC12모듈에 채널 1로 변경하는 신호 발신
    delay(100);                          // 신호 발신 시간 기다려줌
    // AT 명령어 모드로 진입하는 루틴 시작 (nano_1번)
    digitalWrite(setPin, LOW);           // HC12의 Set핀에 LOW를 입력하여, AT 커맨드(명령어) 모드로 진입함
    delay(100);                          // 시간 딜레이
    HC12.print("AT+C001");               // 채널 1로 변경하는 AT 명령어 보냄
    delay(200);                          // 명령어 적용되는 시간 딜레이
    while (HC12.available()) {           // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 데이터를 시리얼 모니터로 전송
    }
    Serial.println("btn 1 pressed, changing Channel 《 No.1 》");
    digitalWrite(setPin, HIGH);          // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    digitalWrite(led, LOW);              // 버튼을 누를때 켰던 LED를 끔
    btn1_Pressed = LOW;                  // 버튼 눌러짐 체크 변수를 LOW로 함 
  }
// ######################################
  
// 〔 $$$$$  버튼2가 눌러지면, HC12의 채널을 '002'로 설정하는 루틴의 시작 $$$$$ 〕
  btn2_State = !digitalRead(btn2);
  if (btn2_State == HIGH & btn2_Pressed == LOW) {
    btn2_Pressed = HIGH;
    delay(100);
  }
  if (btn2_Pressed == HIGH) {       // 만약 버튼2 눌러짐 체크 변수가 HIGH 라면,  
    digitalWrite(led, HIGH);        // LED를 켜고
    HC12.print("AT+C002");          // 다른(nano_2번) HC12모듈에 채널 2로 변경하는 신호 발신
    delay(100);
    // AT 명령어 모드로 진입하는 루틴 시작 (nano_1번)
    digitalWrite(setPin, LOW);      // HC-12의 Set핀에 LOW가 입력되면, AT 커맨드(명령어) 모드로 진입함
    delay(100);                    
    HC12.print("AT+C002");          // 채널 2로 변경하는 AT 명령어 보냄
    delay(200);
    while (HC12.available()) {      // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());    // 데이터를 시리얼 모니터로 전송
    }
    
    Serial.println("btn 2 pressed, changing Channel 《 No.2 》");
    digitalWrite(setPin, HIGH);     // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    digitalWrite(led, LOW);         // 버튼을 누를때 켰던 LED를 끔
    btn2_Pressed = LOW;
  }
  checkATCommand();                // AT 명령 응답신호 체크함수 호출 
  readBuffer = "";                 // 버퍼를 비움
}

// 시리얼모니터를 통해 AT 명령어를 잘 전달 받았는지, 체크하는 서브함수
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // 버퍼에 'AT'로 시작되는 문자열이 있는지 확인
    digitalWrite(setPin, LOW);           // HC-12를,  AT 커맨드 모드로 진입
    delay(100);                          // 시간 딜레이
    HC12.print(readBuffer);              // 버퍼에 있는 내용을 HC12로 보냄
    delay(200);                          // 시간 딜레이
    while (HC12.available()) {           // HC12에 AT-응답 신호가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 시리얼 모니터로 전송
    }
    digitalWrite(setPin, HIGH);          // AT 명령어 모드를 빠져나옴
  }
}

《 위 코드 다운로드 》

btn_SW_One.zip
0.00MB


《 실습5  LED 2번 회로 코드 》

/* 《 버튼으로 통신채널 변환하기 》 --- 2번 Nano (LED 회로) ---  
 * AT명령어를 수정하면 통신속도(거리)/ 동작(통신)모드 / 슬립모드 / 송신파워 등의 설정이 가능함 
 * 회로의 상세자료 및 설명은 게시글 참조 : https://rasino.tistory.com/326
*/

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3);  // (HC12의 TX Pin, HC12의 RX Pin)을 연결할 아두이노 포트 지정 (2번, 3번)
#define setPin 6     // HC12의 SetPin 연결 (AT모드 진입에 사용되는 핀)
#define led 5        // 채널이 변경 되었음을 표시하기 위해 LED를 연결함

byte incomingByte;          // 수신 데이터를 바이트 단위로 저장하는 변수 선언
String readBuffer = "";     // 송·수신 데이터 저장을 위한 문자열 변수 선언

void setup() {
  Serial.begin(9600);         // PC와의 시리얼 통신 포트 열기(시작)
  HC12.begin(9600);           // HC12의 시리얼 포트 열기(시작)
  pinMode(setPin, OUTPUT);    // HC12의 AT 모드 진입을 위한 아두이노 연결핀 출력설정
  pinMode(led, OUTPUT);       // 버튼 입력 표시를 위한 LED 연결 
  digitalWrite(setPin, HIGH); // HC-12를 일반적인 전송 모드로 설정함 (LOW 일경우 AT 커맨드 모드로 진입함)
  digitalWrite(led,LOW);      // LED를 OFF로 디폴트 설정  
  Serial.println("This is $$ Nano2 $$ , i'm ready!");
}

void loop() {
  // 문자열 변수 버퍼에 HC12의 수신 데이터 저장
  while (HC12.available()) {             // HC12에 데이터가 있다면
    incomingByte = HC12.read();          // HC12로 부터 바이트(byte) 단위로 읽어 byte타입 변수에 저장
    readBuffer += char(incomingByte);    // 각각의 읽은 바이트를 문자열 변수에 저장 (예시, 'A' 'T' '+' 'R' 'X' → "AT+RX")
  }
  delay(100);
  // 시리얼 데이터가 있을 경우 HC12로 발송
  while (Serial.available()) {
    HC12.write(Serial.read());
  }
  
  // ### nano1번의 버튼1이 눌러질 때 전송받은 데이터가 "AT+C001"이라면, 여기 Nano2에서 HC12의 채널을 '001'로 설정하는 루틴  ###
  
  if (readBuffer == "AT+C001") {         // 만약 버퍼에 저장된 데이터가 "AT+001"이라면,
    digitalWrite(led, HIGH);             // LED를 켜고, 
    digitalWrite(setPin, LOW);           // HC12의 Set핀에 LOW를 입력하여, AT 커맨드(명령어) 모드로 진입함
    delay(100);                          // 시간 딜레이
    HC12.print(readBuffer);              // 버퍼에 있는 데이터로(채널 1로 변경하는 "AT+C001") AT 명령어 보냄
    delay(200);                          // 명령어 적용되는 시간 딜레이
    while (HC12.available()) {           // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 데이터를 시리얼 모니터로 전송
    }
    Serial.println("Channel successfully changed, 《 No.1 》");
    digitalWrite(led, LOW);              // LED를 끔 
    digitalWrite(setPin, HIGH);          // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    readBuffer = "";                     // 버퍼를 비움 
  }
  
// ### nano1번의 버튼2가 눌러질 때 전송받은 데이터가 "AT+C002"이라면, 여기 Nano2에서 HC12의 채널을 '002'로 설정하는 루틴  ###
  if (readBuffer == "AT+C002") {        // 만약 버퍼에 저장된 데이터가 "AT+001"이라면, 
    digitalWrite(led, HIGH);            // LED를 켜고
    digitalWrite(setPin, LOW);          // HC12의 Set핀에 LOW를 입력하여, AT 커맨드(명령어) 모드로 진입함
    delay(100);                         // 시간 딜레이
    HC12.print(readBuffer);             // 버퍼에 있는 데이터로(채널 2로 변경하는 "AT+C002") AT 명령어 보냄
    delay(200);                         // 명령어 적용되는 시간 딜레이
    while (HC12.available()) {          // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여
      Serial.write(HC12.read());        // 데이터를 시리얼 모니터로 전송
    }
    Serial.println("Channel successfully changed, 《 No.2 》");
    digitalWrite(led, LOW);             // LED를 끔
    digitalWrite(setPin, HIGH);         // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    readBuffer = "";                    // 버퍼 비움 
  }
  checkATCommand();                     // AT 명령 응답신호 체크함수 호출
  readBuffer = "";                      // 버퍼를 비움
}

// 시리얼모니터를 통해 AT 명령어를 잘 전달 받았는지, 체크하는 서브함수
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // 버퍼에 'AT'로 시작되는 문자열이 있는지 확인
    digitalWrite(setPin, LOW);           // HC-12를,  AT 커맨드 모드로 진입
    delay(100);                          // 시간 딜레이
    HC12.print(readBuffer);              // 버퍼에 있는 내용을 HC12로 보냄
    delay(200);                          // 시간 딜레이
    while (HC12.available()) {           // HC12에 AT-응답 신호가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 시리얼 모니터로 전송
    }
    digitalWrite(setPin, HIGH);          // AT 명령어 모드를 빠져나옴
  }
}


《 위 코드 다운로드 》

LED_Two.zip
0.00MB

 

▶ 동작 실행(방법)
 :  SW1을 누르면 채널 1로 설정되고,  SW2를 누르면 채널 2로 설정됩니다.   이때, 코드가 작동되면서 회로 1과 회로 2에 연결된 LED가 점멸하게 됩니다.   아래 이미지처럼, 시리얼 모니터 상에도 채널이 변경된 정보가 뜨도록 처리했습니다.

아래 동작 이미지는 수신 회로 2개를 더 추가하여, 동시에 수신 회로 3개의 채널을 변경되는 것을 보여드리고 있습니다. 

만약, 일부의 채널이 잘 변경되지 않을 경우에는 코드의 delay( )값을 잘 조절해 보거나,   바뀌지 않는 회로의 HC12 모듈의 채널을 확인해 보시기 바랍니다.  채널 변경 실험 과정 등에서, 1 채널 혹은 2 채널이 아닌 아예 다른 채널로 변경되는 경우가 있으니,  이럴 때는, AT통신용 코드를 업로드하여 AT-커맨드 모드에서 채널 확인해보고, 다시 채널을 1번으로 변경하거나, AT+DEFAULT 디폴트로 바꾸어 놓으면 됩니다. 


【 실습  #6 】  RF 무선 조이스틱으로 서보모터 제어하기

: 실습 #6에서는 조이스틱을 이용하여 서보모터 2 개를 무선으로 제어해 보는 실습입니다. 
무선으로 모터 하나를 제어하는 것은 하나의 데이터만 처리하면 됨으로 비교적 쉽지만,  모터 2개를 제어하는 것은 쉽지 않은데요,  시리얼 형태로 날아오는 데이터를 받아서 A 모터 데이터와 B모터 데이터를 구분해서 처리하는 코드 스킬이 필요하기 때문입니다. 
  이번 실습을 통해서 이런 코드 스킬을 익혀둔다면, 다른 작품에도 동일하게 적용할 수 있으니 매우 유익할 것으로 기대됩니다. 



▶ 실습 준비 :   
 회로는 두 가지를 준비합니다.  조이스틱이 연결된 1번 송신 회로와,  서보 모터 2개로 구성된 2번 수신 회로입니다.
서보모터는 SG-90이라는 모터를 사용하였으나, 다른 종류의 서보모터 사용도 가능합니다.
조이스틱의 경우, 제조사에 따라 핀 배열이 본 게시글에서 사용한 것과다를 수 있으니, 갖고 계신 조이스틱의 핀 배열을 확인하고 연결하세요. 


  [ 회로 동작 원리 ] 
조이스틱을 좌우로 움직일 때, VRx로, 전압값(0v~5v)이 나오면, 이를 아두이노의 A0포트로 입력시키고, 
조이스틱을 위아래로 움직일 때, VRy로, 전압값(0v~5v)이 나오면, 이를 아두이노의 A1포트로 입력시키게 됩니다.
그럼, 실습#3 과정에서 설명했듯이, 나노(우노)에서는 10bit의 분해능을 가진 AD Converter에 의해, 아날로그 전압값은(0v~5v) 디지털 값(0~1023)으로 변환되어,  아두이노 코드에서 'analogRead(A0)' 함수를 통해 변환된 데이터를 읽어서 처리할 수 있게 됩니다. 

서보모터 회로에서는 PWM 기능이 있는 포트를 서보모터의 제어선(노란색 데이터선)과 연결하게 되며, 
<Servo.h>라는 라이브러리를 사용하면 servo.write(각도) 형태로 모터의 회전 위치를 제어할 수 있게 되는 원리입니다.

▶ 회로 연결도 (조이스틱이 연결된 송신 회로 1번과,  서보모터 2개가 연결된 수신 회로 2번 두 가지를 만드세요)
《 회로1 :  조이스틱 Nano 회로 》

 조이스틱을 연결할 때는 아래 이미지처럼, 보통 '암-수' 형태의 점퍼 케이블로 연결하게 됩니다. 

하지만, 여기서는 좀 더 간결한 회로를 만들기 위해, 조이스틱의 있는 핀을 구부려서 브레드보드에 직접 연결하였는데요, 
작업 과정에서 핀이 부러지거나 손상될 수 있으니,  조이스틱의 여유 개수가 있는 분만 시도해 보시기 바랍니다. 
방법은 아래 이미지를 보세요, 조이스틱의 핀은,  아래 분홍색 박스의 이미지와 같은 핀헤더로 납땜되어 있습니다. 
그럼, 핀헤더를 고정하고 있는 플라스틱 부분을 니퍼로 사이사이를 잘라내면,  플라스틱 조각은 빠져나오게 되고,  핀의 길이가 구부려도 여유 있는 상태가 됩니다.   그럼, 브레드보드에 밀착시켜서 꽂을 수 있게 됩니다. 



《 회로 2 :  서보모터 Nano 회로 》

서보모터는 회로도처럼 그냥 2개를 연결시켜 놓기만 해도 되지만, 기왕이면, 아래 이미지와 같은 서보모터 틸트 거치대 같은 것을 활용해서 만들어 보면, 곧바로 응용해볼 수도 있고 해서 좋을 것 같네요. 
예를 들어 틸트 위에 소형 아두이노 카메라 모듈이나, ESP32-CAM과 같은 모듈을 부착해서 활용할 수 있겠네요.

그리고, 위 틸트 거치대의 노란색 화살표 부분을 보면, SG90 서보모터에 같이 동봉된 하얀색 핀과  틸트 거치대 홈의 길이가 딱 맞지 않기 때문에 하얀색 핀을 일부 잘라내어야 합니다. 

그리고, 서보모터 커넥터 핀의 기본 스타일은 암놈 형태의 핀으로 되어 있기 때문에,  브레드 보드에 서보모터 커넥터를 연결하려면, 아래 그림과 같은 핀헤더 연결핀이 필요할 수 있습니다. 

만약, 이미지와 같은 핀헤더가 없다면,  굵은 전선(전선 한 가닥으로 된 단선)을 잘라 꽂거나, 혹은  저항이나 LED와 같은 부품의 리드선(다리)을 잘라서 활용해도 됩니다. 

▶ 아두이노 코드 
( 아래의 코드를 각각의 회로에 업로드해주세요. )
《 실습 6 : 조이스틱 1번 회로 코드 》

// === HC-12 'Joystick' Control 회로 코드   ===
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 
int Jox=0, Joy=0;

void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송
  Jox = map(analogRead(A0),0,1023,0,180);
  Joy = map(analogRead(A1),0,1023,0,180);
  Serial.print(Jox);
  Serial.print("\t");
  Serial.println(Joy);
  // 아래 X 문자를 아스키 값으로 변환되지 않고 그대로 전송하기 위해 write( )함수 사용
  HC12.print(Jox); HC12.write("X"); // 조이스틱 X축 값을 보내고 이어 "X"문자를 전송  
  HC12.print(Joy); HC12.write("Y"); // 조이스틱 Y축 값을 보내고 이어 "Y"문자를 전송
  delay(50);   // 전송 시간 확보를 위한 딜레이   
}

《 위 코드 다운로드 》

HC12_LED_L3_Joy.zip
0.00MB


《 실습6 : 서보모터 2번 회로 코드 》

// ###  HC-12 '서보 x 2 연결 회로 코드'   ###
// RasINO IoT : https://rasino.tistory.com/326

#include <Servo.h>
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 
Servo servo1, servo2;
int servo1Pin=5;  // 1번 서보모터 연결된 아두이노 핀
int servo2Pin=9;  // 2번 서보모터 연결된 아두이노 핀
byte incomingByte;  // 0~255 값 저장할 수 있는 byte변수 선언
String readBuffer = "";
String readBufferX = "";
String readBufferY = "";
int Jox = 0;
int Joy = 0;
int i = 0;
bool x_ready = false;
bool y_ready = false;
bool x_passed = false;
bool data_received = false;

void setup() { 
  Serial.begin(9600); // computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'A-Servo Motor' HC-12 Module"); 
}  

void loop() { 
  while (HC12.available() > 0) { 
    incomingByte = HC12.read();   // 수신 데이터를 byte 단위로 저장
    readBuffer += char(incomingByte); // 수신되는 데이터를 문자형으로 캐스팅하여 문자열 변수(readBuffer)에 쌓아 둠
  }
  delay(70);  // 송신측 전송 delay(50) 타임보다 최소 같거나 더 높이 설정해 주어야 함.
// 송신측(코드)에서 X joy 값을 보내고 "X" 문자를 보낸 후 ,  Y joy값을 보내고 "Y"문자를 보낸 것을 기억하세요.
  while (i <= sizeof(readBuffer)) {
    if (readBuffer[i] == 'X') {
      x_ready = true;
    }
    if (readBuffer[i] == 'Y') {
      y_ready = true;
    }
    if (!x_ready) {
      readBufferX = readBufferX + (readBuffer[i]);
    }
    if (x_passed && !y_ready){
      readBufferY = readBufferY + (readBuffer[i]);
    }
    if (x_ready) {
      x_passed = true;
    }
    i = i+1;
  }
  data_received = true;  
  Jox = readBufferX.toInt();  //문자열로 저장된 X 데이터 값을 정수형으로 변환하여 저장.
  Joy = readBufferY.toInt();  //문자열로 저장된 Y 데이터 값을 정수형으로 변환하여 저장.
  if (data_received) {
    // 데이터 버퍼 변수 들을 리셋.
    readBuffer = "";  
    readBufferX = "";
    x_ready = false;
    x_passed = false;
    readBufferY = "";
    y_ready = false;
    i=0;
  }
  data_received =false;
  servo1.attach (servo1Pin);
  servo2.attach (servo2Pin);  
  servo1.write(Jox);      
  servo2.write(Joy);      
  delay(26); 
  servo1.detach();
  servo2.detach();
  delay(15);   
  Serial.print(Jox);
  Serial.print("\t");
  Serial.println(Joy); 
}

《 위 코드 다운로드 》

HC12_LED_A_Servo.zip
0.00MB


▶ 동작 실행(방법)
 :  전원을 연결하면,  예를 들어 조이스틱을 상하로 움직이면, 1번 서보모터가 상하로 움직이며,   조이스틱을 좌우로 움직이면, 2번 서보모터가 좌우로 움직이게 됩니다. 
그런데, 제가 올린 영상에 보면, 기본적인 서보모터 제어 코드로 제어하게 되면, 대부분의 경우 서보모터 떨림 현상을 겪게 됩니다.   그렇다고 제어가 안 되는 것은 아니고, 제어되기는 하지만, 조이스틱을 움직이지 않을 때는 더욱 심하게 상하 좌우로 떨게 되어, 작품의 완성도가 상당히 떨어지게 됩니다. 
원인은 몇 가지가 있을 수 있겠지만,  지난번에 올린 서보모터 떨림 개선이라는 게시글을 참고해보세요.  떨림 원인과 개선에 대한 자세한 설명되어 있습니다.  (자료 링크 : 
【 아두이노에러해결#4】 서보모터 떨림, 불안정 현상 해결! )
아무튼 본 게시글의 아두이노 코드에는 attach( )함수와, detatch( )함수를 사용한 개선된 코드로 올려져 있으니 떨림이 거의 없게 동작할 거예요.   그럼에도 모터의 떨림이 생길 수 있는데요, 이럴 때는 아래에 표시된 delay( ) 함수의 시간 값을 조금씩 앞뒤로 조절해 보세요. 

 

그리고 당연한 이야기지만, PC 연결에 의존하지 않고, 보조배터리(5V) 연결로도 무선통신이 되며, 잘 작동이 됩니다. 

 

그럼, 끝으로 HC-12 모듈의 주요 장점을 정리해 드리며, 마치도록 하겠습니다. 
본 게시글 끝에 있는 HC-12 모듈에 대한 풀코스 학습 영상과 꼭 같이 보면서 실습을 한다면, 실습을 진행하는데 별 어려움 없이 완료할 수 있을 것으로 생각됩니다. 
감사합니다~ 
그럼, 오늘도 좋은 하루 보내세요~  &^^ 

 

【 HC-12 모듈 풀 코스 학습 영상 】

 아래 영상을 클릭해보세요.

 

 

반응형