반응형

아이가 유치원에서 너무나 예쁜 스탠드를 만들어 왔습니다.. AAA 건전지가 들어가는 예쁜 스탠드.

스텐드 옆면에 예쁘게 그림을 그려서 본인이 자는 방에 가져다 두고는

"오늘부터 얘가 나를 지켜줄꺼야~"

ㅎㅎ

너무나 귀엽지 않습니까?

 

저녁이 되어 불을 켜보니 

ㄷㄷㄷ 오던 잠도 깰것 같은 블루라이트가 펑펑

헐랭

정말 오던 잠도 달아날 것 같은 푸르스름한 조명이더군요.

그래서 바꿔주기로 하였습니다.

  • 일단 조명 색상은 따뜻한 색상으로 
  • 밤새 켜져 있지 않도록 자동으로 소등될 것

요렇게 간단한 요구사항을 작성한뒤에 바로 실행에 들어갑니다.

 

필요한 재료는 간단합니다.

  • Attiny85 (아두이노를 사용하기는 아깝잖아요?)
  • 1W LED (5000K 미만)
  • 50uf 전해 콘덴서 (작은걸로)
  • 전선 조금.

 

간단하죠?

우선 자동으로 소등이 되어야 하고 소등이 될때는 서서히 어두워 지는 것이 좋을 것 같아 먼저 테스트를 해보기로 하였습니다.

우선 Attiny 에 대하여 간단히 알아 보아야 하는데요. attiny 는 아주 작은 마이크로프로세서로 칩안에 부트로더, 디지털핀, 아날로그핀, PWM 핀을 모두 갖춘 환상적인 부품입니다. 전압만 적당히 주면 칩하나로도 왠만한 동작이 가능한 녀석입니다. 나중에 이녀석을 이용한 작품들을 좀 소개해 드리겠습니다.

 

소스코드를 업로드 하기 위하여 별도의 프로그래머가 필요하긴 하지만 아두이노를 이용하여 간단하게 프로그래머로 사용할 수 있는 방법이 있으니 걱정마시고 진행하시면 됩니다.

저는PWM 핀에 일정 시간이 지나면 서서히 전압을 감소 시킨뒤 0V 까지 떨어지면 Attiny85를 sleep 모드로 진입시켜 초절전상태가 되도록 할 계획입니다. 

 

 

아두이노 ISP 만들기

아두이노를 ISP 와 같이 사용하여 Attiny85 를 프로그래밍 할 건데요. 간단합니다.

아두이노 예제에 있는 ArduinoISP 를 열어 주세요.

아두이노 기본 예제에 들어있는 ArduinoISP 소스

해당 소스를 본인의 아두이노 설정에 맞게 세팅한 뒤 업로드를 합니다. 

그런 다음 10uf 전해 콘덴서를 하나 준비해주시고

Arduino reset --  콘덴서의 + ,
Arduino GND -- 콘덴서의 - 를

연결한 뒤 Arduino 와 Attiny85의 각 핀을 아래와 같이 연결합니다.

  • Arduino 5V   --  ATTiny85 Pin 8 (Vcc)
  • Arduino GND -- ATTiny85 Pin 4 (GND)
  • Arduino Pin 13 -- ATTiny85 Pin 8 (SCK)
  • Arduino Pin 12 -- ATTiny85 Pin 7 (MISO)
  • Arduino Pin 11 -- ATTiny85 Pin 6 (MOSI)
  • Arduino Pin 10 -- ATTiny85 Pin 1 (Slave Reset)

attiny85 핀 맵

전 브래드 보드에 매번 연결하는 것이 귀찮아서 간단한 보드를 하나 만들었습니다.

arduino isp for attiny85

위 사진과 같이 만들어서 소켓에 아두이노 나노와 attiny85 를 끼웠다 뺐다 할 수 있게 했습니다.

참고로 사진에 보이는 attiny85 는 smd 타입으로 dip 타입보다 작고 가격도 조금 저렴합니다. 저는 smd 타입에 8핀 보드를 붙여서 사용하고는 합니다.

 

일단 이러면 코드 테스트를 위한 준비가 완료 되었습니다.

 

 

코딩을 해보자!

// this code for enter sleep mode
#include <avr/sleep.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

//setting variables
int ledPin = 0;    // LED connected to digital pin 9
float timer = 2400;
float maxBrightness = 255.0;
float a = 0;
float curX = 0;
float curY = 0;

void setup() {
  // 그래프의 기울기 값 계산
  a = maxBrightness / (timer*timer);
}

void loop() {
  curX++;
  curY = a * (curX*curX);
  
  analogWrite(ledPin, maxBrightness - curY);
  
  if (maxBrightness - curY < 1 )
  {
    analogWrite(ledPin, 0);
    system_sleep(); // sleep 모드 진입
  }
  delay(1000);
}

  void system_sleep()
  {
    cbi(ADCSRA, ADEN);                    // switch Analog to Digitalconverter OFF
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // sleep mode is set here
    sleep_enable();
    sleep_mode();                         // System sleeps here
    sleep_disable();                      // System continues execution here when watchdog timed out 
    sbi(ADCSRA, ADEN);                    // switch Analog to Digitalconverter ON
  }

 

코드 위아래에 좀 눈에 익지 않은 코드가 있죠? 그 부분이 바로 sleep 모드 진입을 시키기 위한 코드입니다. attiny85 는 슬립 모드에 진입하면 놀라울 만큼 전기를 먹지 않기 때문에 아주 유용한 기능이 아닐 수 없습니다. sleep 모드에서 깨우기 위하여는 reset pin 에 GND 를 스위치 등으로 순간 연결해 주거나 전원을 껏다가 켜면 다시 최초 상태로 실행이 됩니다.

위에 타이머 부분이 전체 조명이 켜져있는 시간이되겠습니다. 다만 정확한 시간 조정은 안되고 대충 감으로 잡아야 하더군요. 현재 설정은 2400 초 인데요. 대략 40분 내외의 시간이 흐르면 소등됩니다. (한 30분 지나면 점점 어두워집니다)

loop 의 아래쪽에 현재 아날로그 출력값이 1보다 작아지면 sleep 모드로 진입하는 코드가 있고요.

그게 전부입니다. ㅋ

이제 attiny85 에 업로드를 해야하는데요. 

먼저 라이브러리가 없다면 추가를 해주어야 겠죠?

구버전용 라이브러리는 직접 받으셔야 하고요. 신버전은 json 을 추가해주고 설치를 하면 됩니다.

아래 경로에서 라이브러리 설치에 대한 내용을 확인하시면 됩니다.

highlowtech.org/?p=1695

 

Programming an ATtiny w/ Arduino 1.6 (or 1.0)

This tutorial shows you how to program an ATtiny45, ATtiny85, ATtiny44 or ATtiny84 microcontroller using the Arduino software. These are small, cheap ($2-3) microcontrollers that are convenient for…

highlowtech.org

 

보드는 attiny > attiny85 1Mhz 로 선택해 주시고요.

ISP 는 Arduino as ISP 를 선택해 주시면 됩니다.

그리고 업로드 고고

 

 

Hardware 개조 타임

이제 조명을 뜯어서 기존의 LED 를 떼어내고 Attiny 와 LED 를 부착해줄 차례 입니다.

먼저 배터리 를 제거한다.

당연한 이야기지만 먼저 배터리를 제거해 줍니다.

 

상단 뚜껑 및 케이스 분해

상단의 흰색 갓은 위로 잡아 당기면 그냥 빠집니다. 꽉 끼워져 있기는 한데 본드로 붙어있는 것은 아니더군요. 

아래쪽 나사를 모두 풀어주고 분리하면 위와 같은 상태입니다. 심플하네요.

스프링이 도망가지 않게 살살 열어 줍니다.

 

거의 8000K 인 듯한 LED. 덩치도 크다.

어쨌든 문제의 LED는 제거합니다.

크기도 엄청 크네요.

 

LED 를 잘라낸 모습

스위치에 붙어 있는 저항도 필요 없으니 떼어낼겁니다.

 

Attiny 에 콘덴서를 하나 달아주었다.

Attiny 에 배터리 (약 4.5v) 를 연결하니 전압이 불안정한지 동작이 원하는데로 되지 않아 굴러다니는 전해 콘덴서를 하나 붙여 주었습니다. 저는 50uf 를 달아 주었는데요. 적당히 아무거나 달아도 될 듯 합니다. 크기가 작아 소켓보드 아래에 쏙 들어가네요. ㅎㅎ

 

 

LED 는 1W(??) cree 제품. 

예전에 사두었던 LED 가 적당해 보여 달아주었습니다. 불빛도 너무 노랗지도 않고 방열판도 있으니 적당하다 생각되었습니다.

본딩을 해서 붙인뒤 고정을 위해 일단 테이프로 붙여 둡니다.

 

최종 단계 진입. 스위치에 저항을 떼어내고 결선을 위한 전선을 매달기 직전

자 이제 거의 다 되었습니다.

스위치에 있는 저항을 테어내고 전선을 연결할 겁니다. 스위치로 - 가 연결되고 스위치의 다른 한쪽이 attiny 의 GND 에 연결되면 됩니다.

빨간선은 + 이므로 attiny 의 5V 에 연결합니다.

테스트 성공

쨔잔~ 네 예쁘게 잘 들어옵니다.

Attiny 는 3M 양면 테이프로 붙여주면 완성입니다.

 

배선 확인용 사진

참고로 위와 같이 배선하시면 안됩니다. 잘못 배선한 사진인데요. LED 로 가는 굵은 빨간선이 사진상 오른쪽 맨 아래 핀에 연결이 되어야 합니다. ㅜㅜ

아래 사진에는 다시 제자리에 납땜을 했습니다.

납땜까지 완료된 모습

자 이제 완성입니다.

배선에 약간 오류가 있기는 했지만 간단한 문제로 바로 해결하였습니다.

 

최종 결과물은?

DIY 가 완료 되었으나 처음과 똑같은 모습

ㅋㅋ 처음과 똑같네요. 다시봐도 그림이 너무 예쁩니다. 

어쨌든 이제 아이방에 놔주기만 하면 됩니다.

 

따뜻하고 예쁜 조명으로 다시 태어나다.

음~ 마음에 드는군요.

아이도 좋다며 매일 켜고 자고 있습니다. ㅎㅎ

자동으로 소등이 되니 배터리도 많이 먹지 않고요. 

만약 사용해보고 배터리를 많이 먹는다 싶으면 저항을 하나 달아줄 계획입니다. 저항은 아주 작은 용량의 저항이면 됩니다. 

 

 

스탠드 조명 튜닝 완료

자 간단한 작업으로 싸구려 같은 장난감에서 고급스러운 조명 색상에 타이머 기능까지 있는 멋진 조명으로 탈바꿈 하였습니다. 여러분도 한번 도전해 보시면 어떨까요?

 

그럼 오늘의 포스팅을 마칩니다. ~

 

2022.01.31 - [DIY/Arduino] - [아두이노]NRF24L01을 이용하여 무선으로 mpu6050 신호 전달하기

 

[아두이노]NRF24L01을 이용하여 무선으로 mpu6050 신호 전달하기

자 어느새 목표했던 RC headtracking FPV 만들기의 종착역을 다가가고 있습니다. 앞서 소개해 드렸던 2축 서보마운트 제작 및 서보컨트롤과 mpu6050 을 이용하여 2축 서보모터를 제어하는 내용은 잘 보

diy-dev-design.tistory.com

2019/10/13 - [DIY] - [DIY] 아이방 수면등 만들기 (feat. 아이그림)

 

[DIY] 아이방 수면등 만들기 (feat. 아이그림)

아이들은 창의적이다. 시키지도 않았던 생각치도 않았던 아무 많은 그림을 시도 때도 없이 시간과 장소 불문, 심지어는 종이를 불문하고 마구마구 그려댄다. 그래서 A4 용지를 내주었더니 그럴

diy-dev-design.tistory.com

 

2020/05/17 - [DIY] - [재활용] 고장난 LED 바 수리하기 > 화장대 조명 만들기

 

[재활용] 고장난 LED 바 수리하기 > 화장대 조명 만들기

저의 보물창고 바로 폐 배터리, 형광등 수거함 입니다. 지나는 길에 기웃거려 보니 LED 바가 버려진게 있더군요. LED 바 금액 자체가 비싼건 아니지만 사실 일부러 돈주고 살만큼 효과적인 조명기

diy-dev-design.tistory.com

 

2020/03/23 - [DIY/Arduino] - Arduino(아두이노) 무작정 시작하기

 

Arduino(아두이노) 무작정 시작하기

아두이노, Arduino 여기저기서 많이 들었을 겁니다. 이걸 해야 된다는 말이 귀에 못이 박히도록 이야기 합니다. 대충 뭔지는 알겠는데 개발자도 아닌 내가 과연 이걸로 뭘 할 수 있을까 싶기도 하

diy-dev-design.tistory.com

 

2020/10/29 - [DIY] - [DIY] 오래된 다목적 랜턴 LED 램프, 충전식으로 교체하기

 

[DIY] 오래된 다목적 랜턴 LED 램프, 충전식으로 교체하기

처갓집 구석에서 재미있는 물건을 하나 발견했습니다. 마침 캠핑 전용 랜턴이 하나 있었으면 하는 차에 이게 왠 떡인가요 ㅋ 언제부터 처갓집에 있었는지는 모르겠지만 사용하지 않는 것이 분

diy-dev-design.tistory.com

 

반응형
반응형

아두이노로 통합(만능) 리모콘 만들기 3/3 이라 쓰고 왠지 이번 포스트에서 끝나지 않을 것 같은 느낌이 강하게 듭니다. 지난 포스트에서 아두이노 IR 센서를 이용하여 신호를 해킹하고 또 필요한 신호를 따서 기록하는 것까지 소개해 드렸는데요.  해당 포스트는 아래 링크를 참고해 주세요.

2019/11/10 - [DIY/Arduino] - [DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3

 

[DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3

도대체 영화 한편 보려면 몇개의 리모콘을 사용하는지... TV 전원을 켜기위해 TV 리모컨을 찾아야 하고 안드로이드 TV 셋톱을 켜기위해 안드로이드 TV 리모콘을 역시 찾아야 하며 막상 틀었더니 소

diy-dev-design.tistory.com

2019/11/10 - [DIY/Arduino] - [DIY] 아두이노로 통합(만능) 리모콘 만들기 2/3

 

[DIY] 아두이노로 통합(만능) 리모콘 만들기 2/3

먼저 포스트에서 아두이노를이용하여 다양한 리모콘의 신호를 해킹하는 방법을 알아 보았습니다. https://diy-dev-design.tistory.com/65 [DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3 도대체 영화 한편 �

diy-dev-design.tistory.com

 

이번 포스트에서는 본격적으로 SW 를 설계하고 HW 를 만들어가는 과정을 소개해 드릴까 합니다.

먼저 조사했던 여러가지 기능을 모두 소화하기에 아두이노의 입력핀은 너무 적기 때문에 기기 전환 버튼같은 기능을 두어서 버튼은 동일한 레이아웃을 가지고 아두이노의 동일한 핀으로 입력 신호가 들어가더라도 실제 출력해주는 IR  신호는 다르게 보내주는 방식으로 구현을 할 계획입니다.

 

필요한 재료

  • 3cm x 7cm 양면 만능기판 (2.54mm 규격) x 2EA
  • 아두이노 나노
  • Attiny85
  • SW-200D 진동/틸트 스위치 양쪽 다리형
  • Push switch (2pin) x 14 EA
  • LED (red, SMD) x 4EA
  • LED (green, SMD) x 1EA
  • 5V DCDC Converter, Step Up Power Supply 보드
  • TP4056 18650 charge module
  • 0.1F 전해콘덴서 (슈퍼콘덴서??) 꼭 필요한지 모르겠음
  • 대충 33옴 정도되는 저항, 낮아도 별 상관 없음 (SMD LED 연결용)
  • IR LED (송신용) x 1EA
  • 18650 배터리 1EA

 

 

 

SW 를 대충 설계해보자.

먼저 아두이노의 인풋, 아웃풋 키와 함께 각각의 기능을 매칭하는 테이블을 만들어야겠습니다. 아무래도 여러가지 기능이 동작되어야 하므로 나중에 실수하지 않으려면 각각의 입력핀에 연결될 버튼과 기능을 정의하는게 중요합니다.

4개의 제품의 동작별로 기록한 신호와 기능명칭들 가장 오른쪽은 아두이노의 핀번호

위와 같이 각각의 기능을 테이블로 만들어 보았습니다. 가장 우측의 비고에 해당하는 열이 아두이노의 핀번호가 되겠으며 9~12번은 4개의 제품에 해당되는 LED 를 켜주기 위한 출력핀입니다. 18번은 제품전환용 버튼 입력핀이 됩니다.

제일 좌측에 S01~S14까지 번호가 있는데요. 이번호들은 각각 아래와 같은 형태로 배치할 계획입니다.

리모컨 버튼부 레이아웃

저는 양면 만능기판을 사용할 계획이고요. 만능기판의 끝부분에 단자용도로 사용할 수 있는 납이 붙어있어 그부분까지 일단 납땜을 하여 연결해 보기로 합니다. 중앙 상단의 네게의 흐릿한 동그라미가 LED 1234 와 연결이 되는 것이죠.

14개의 버튼은 모두 1개의 그라운드핀과 연결되며 나머지 한쪽 다리를 아래쪽 단자에 순차적으로 매칭을 시켜줍니다.

LED 역시 그라운드를 모두 한꺼번에 연결하고 아래쪽 LED 핀은 아두이노 디지털 출력핀과 연결해주어 선택된 제품에 불이 켜지도록 하겠습니다.

 

만능기판에 버튼을 실장한 사진은 아래와 같습니다.

총 14개의 버튼이 위와같이 배치된다.

총 14개의 버튼이 위와 같이 아름답게 배치됩니다. 만능기판의 크기를 생각해보면 아주 아담한 리모컨이 만들어 질 것 같네요.

 

 

 

 

아두이노 나노와 전원 공급 모듈

전원 입력은 3.7V 리튬이온 18650 배터리를 이용할 계획인데요. 아두이노가 5V 이상의 전압이 필요하기 때문에 5V 로 승압을 해주는 보드를 하나 장착이 필요하고요, 이 제품을 연속으로 사용하지 않을 경우 자동으로 전원 공급이 중단되도록 할 필요가 있을듯 하여 attiny85 를 이용하여 일정 시간이 지나면 전원 공급이 중단되도록 할 계획입니다. atiny는 sleep 모드라는 것을 지원하는데 sleep 모드로 들어가면 거의 전기를 먹지않는 놀라운 기능을 수행하게 됩니다.

다시 동작할때는 reset 핀에 GND 를 입력해주면 다시 동작을 시작하게 되는데 틸트 스위치를 이용하여 움직임을 감지하여 물리적으로 움직임이 발생되면 attiny85의 reset핀으로 신호를 보내줌으로써 attiny 가 전원 공급을 시작하는 것이죠. 이번 제작하는 리모컨 자체가 전류를 거의 사용하지 않기 때문에 문제는 없을 듯 하지만 그래도 attiny 의 디지털 출력핀이 충분한 전기를 공급할 수 있을지는 미지수입니다.

그래서 0.1F 정도의 콘덴서를 전원 공급용으로 하나 달아 보았습니다. ( 사실 전기/전자 지식이 매우 얕아서 저렇게 하면 되는지는 잘 모르겠어요)

 

그렇게 만들어진 보드가 바로 아래와 같이 만들어졌습니다.

 

위에서 설명드린 것처럼 우측 상단에 attiny85 가 자리잡고 있고요. (SMD 버전입니다) 중간에 검은 통이 틸트 스위치입니다. 약간 기울여서 달아주어야 평소에 눕혀져 있을때 신호가 끊어지기 때문에 기울여서 부착을 했고요, 아래 검은 네모박스가 0.1F 전해 콘덴서 입니다. 어디서 떼어낸건지는 기억이 안나는데 버리는 가전제품에서 떼어낸 부품입니다.

실제 아두이노 나노로 입력되는 전원은 전해콘덴서와 연결이 되어 있어 attiny 가 sleep 모드로 들어가더라도 일정시간 전원을 공급하여 주는 역할을 하게 됩니다.

우측의 단자부분은 이미 납땜이 마구 되어 있는데요, 위에 소개해드린 버튼부분과 연결이 되게 됩니다.

 

 

 

 

 

고난의 시작 ! 인정사정 없이 납땜시작

정말 납땜하다가 정신병 걸리는 줄 알았습니다.

왼쪽은 아두이노 나노를 포함한 메인 컨트롤 부, 오른쪽은 버튼 조작부와 LED 되겠습니다. LED 는 우측 끝에 매달려 있는데 잘 안보이시죠? 작은 회로기판 같은데 신호용으로 아주아주 작은 SMD 타입의 LED가 붙여 있는 것을 보셨을 텐데요, 고 녀석들을 떼어내서 부탁을 해주었습니다. 일부러 구입할일은 없으니까요.

각각의 선들은 위에서 설계한 것처럼 연결을 해주었는데 설계할때는 이게 이렇게나 복잡할거라고는 생각을 못했습니다.

위쪽에 보이는 작은 초록색 기판이 3.7 --> 5V 승압회로 , 그사이에 아주 작게 보이는 파란색 보드가 USB 전원을 이용하여 3.7V 배터리를 충전할 수 있는 충전 보드 입니다. 

이렇게 하면 완전한 하나의 제품에 해당되는 부품을 모두 제작한 셈이 되겠네요.

두 보드는 이렇게 접어서 조립할 예정입니다.

위에서 보았던 두개의 보드는 위 사진처럼 접어서 조립할 계획입니다. 안쪽역시 매우 지저분하네요. 저렇게 만들어진 배선이 과연 잘 붙어있을까 궁금합니다.

두개의 보드 중간에는 절연을 위하여 얇은 실리폰 패드를 하나 넣어줄 계획입니다.

 

전원 입력!

전원이 들어오게 되면 위사진과 같이 불이 켜집니다. 계획에는 LED가 4개였지만 메인 전원이 들어왔는지 여부를 판단하기 위하여 연두색 SMD LED를 하나 추가하였습니다. 

 

 

 

코딩 시작!

자 순서가 좀 바뀐것 같지만 이제부터는 지루한 SW 코딩 부분입니다.

SW 구현할때 다음의 것들이 동작해야 하는 것이 중요합니다.

  • 하나의 버튼에 의해 주어진 신호는 4개의 제품에 대한 신호를 보낼 수 있어야 한다.
  • 마지막으로 사용한 제품을 기억했다가 다시 동작할때 세팅해준다.
  • 신호가 한번에 입력이 안될 경우를 대비하여 연속으로 n번 보낼 수 있도록 구성한다.

뭐 별건 없습니다만 두번째에 해당되는 부분은 제가 처음해보는 관계로 저도 공부를 좀 했습죠.

 

 

 

EEPROM 을 사용해보자!

아두이노 나노에 사용되는 Atmega328 칩에는 무려 1kb 라는 비 휘발성 저장공간이 존재합니다. EEPROM 이라고 부르는데요, 프로그램이 저장되는 공간 외에 사용자가 데이터를 저장할 수 있는 공간말입니다.

무려 1kb 요.

-_-;;

1kb 라니.. 장난하냐..

 

 

 

싶겠지만 있는게 어딥니까?

이 저장공간을 이용하여 우리는 마지막 동작했던 제품의 정보를 기억할 건데요. 따지고 보면 차고도 넘치는 양이지요.

자 그럼 EEPROM 에 데이터는 어떻게 저장하고 읽어 들이는지 볼까요?

#include <EEPROM.h>

int sw_02;
int productIdx = 0; //0 : TV / 1: TV BOX / 2: BTV / 3: SPK
bool chkon = false;

//LED
const int L00 = 9;    // TV
const int L01 = 10;   // TV BOX
const int L02 = 11;   // BTV
const int L03 = 12;   // LONPOO SPEAKER

void setup()
{
    pinMode(s02, INPUT_PULLUP);
    productIdx = EEPROM.read(0); // EEPROM 에 저장된 제품의 번호를 불러오는 부분
}

void loop() {

  sw_02 = digitalRead(s02);

   // change product
  if (sw_02 == HIGH) {
    chkon = true; // 연속으로 눌리는 것을 방지하기 위하여 on 상태일때만 기기 변경이 되도록 한다.
    ledON(productIdx);
  }else{
    if (chkon)
    {
      productIdx++;
      if (productIdx > 3) productIdx = 0;
      EEPROM.write(0, productIdx); // 이부분이 EEPROM 에 현재 제품의 번호를 저장하는 부분
      chkon = false;
    }
    
    ledON(productIdx);
}

void ledON (int idx) // 선택된 인덱스에 맞게 LED 를 켜주는 함수
{
  digitalWrite(L00, LOW);
  digitalWrite(L01, LOW);
  digitalWrite(L02, LOW);
  digitalWrite(L03, LOW);
  switch (idx) {
  case 0:
    digitalWrite(L00, HIGH);
    break;
  case 1:
    digitalWrite(L01, HIGH);
    break;
  case 2:
    digitalWrite(L02, HIGH);
    break;
  case 3:
    digitalWrite(L03, HIGH);
    break;
  default:
    break;
  }
}

어렵지 않죠? 제일 위에 해당 라이브러리를 불러들여 주고요,

Setup 시에 저장되어 있는 값을 불러옵니다.

버튼은 눌렀을때 LOW 가 되도록 하고 항상 HIGH 한 상태를 만들어 줍니다. HIGH 한 상태가 되면 chkon 이 true 가되고 버튼이 눌렸을때 기기의 인덱스를 변경한 뒤 EEPROM 에 값을 저장하고 chkon 을 false 로 만들어 다음 신호를 기다리게 됩니다. 이렇게 하면 버튼을 연속으로 누르고 있어도 신호는 한번만 가게 되겠죠. 마지막으로 사용한 제품도 저장이 됩니다.

 

 

 

 

버튼 하나로 4개의 제품은 어떻게 제어를 할까요?

//setup, 변수 선언 등은 생략합니다.

void loop() {

if (sw_03 == HIGH) {    //s03 은 전원 버튼입니다.
  }else{    
    digitalWrite(13, HIGH);
    press_S03(productIdx);
  }
  // 생략
}


void press_S03 (int idx) // power
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF10EF,32);   // tv power
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F02FD,32);   // tv box power
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE807F,32);   // Btv power1 
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF807F,32);   
    break;
  default:
    // statements
    break;
  }
}

바로 Switch 문을 이용하여 입력되는 idx 에 따라 각각 다른 신호를 보내주는 것이지요. 

아래 press_S03 버튼이 바로 전원을 켜고 끄는기능을 담당하는 함수가 되는 것이죠.

저런 식으로 버튼 개수만큼 함수를 만들어 주면 됩니다. 좀더 효율적으로 코딩할수도 있겠지만 초보인 저에게는 저렇게 쉽게 코딩하는게 나중에 뜯어 고치지도 좋을 것 같아 이란 저런 방식으로 작성을 하였습니다.

 

 

 

포스트가 점점 길어지네요.. 

자 이제 전체 소스 갑니다.

중요한 내용은 위에 다 설명 드렸고 이전 포스트를 참고하시면서 내용 확인해 보시면 되고요. 꼭 저와 동일하게 만들 필요는 없으니 참고만 해주시면 됩니다.

 

길이가 대단하니 조심하세요~ ㅋ

#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <EEPROM.h>
/*
 * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
 * An IR LED must be connected to Arduino PWM pin 3.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 */
/*
 * tv (NEC)
 * power :      0x2DF10EF, 32
 * input :      0x2DFD02F, 32
 * chnnel up :  0x2DF00FF, 32
 * chnnel dn :  0x2DF807F, 32
 * volumn up :  0x2DF40BF, 32
 * volumn dn :  0x2DFC03F, 32
 * OK :         0x2DF22DD, 32
 * sw up :      0x2DF02FD, 32
 * sw dn :      0x2DF827D, 32
 * sw left :    0x2DFE01F, 32
 * sw right :   0x2DF609F, 32
 * 
 * android tv (NEC)
 * power :      0x807F02FD, 32
 * sw up :      0x807F6897, 32
 * sw dn :      0x807F58A7, 32
 * sw left :    0x807F8A75, 32
 * sw right :   0x807F0AF5, 32
 * sw OK :      0x807FC837, 32
 * back :       0x807F9867, 32
 * volumn up :  0x807F18E7, 32
 * volumn dn :  0x807F08F7, 32
 * 
 * 
 * lonpoo speaker
 * power :      0x40BF807F, 32
 * volumn up :  0x40BF50AF, 32
 * volumn dn :  0x40BFD02F, 32
 * bt :         0x40BFA05F, 32
 * bt esc :     0x40BF906F, 32
 * opt :        0x40BF20DF, 32
 * 
 * 
 * LED
 * tv :     9
 * tv box : 10
 * btv :    11
 * spk :    12
 * 
 * input
 * s01 
 * 
 * 
 * 
 * 
 */

#include <IRremote.h>

const int s01 = 0;
const int s02 = 18;   // select sw 
const int s03 = 1;
const int s04 = 2;
const int s05 = 19;
const int s06 = 4;
const int s07 = 5;
const int s08 = 6;
const int s09 = 7;
const int s10 = 8;
const int s11 = 14;
const int s12 = 15;
const int s13 = 16;
const int s14 = 17;
//LED
const int L00 = 9;    // TV
const int L01 = 10;   // TV BOX
const int L02 = 11;   // BTV
const int L03 = 12;   // LONPOO SPEAKER

//
// define sw value
int sw_01;
int sw_02;
int sw_03;
int sw_04;
int sw_05;
int sw_06;
int sw_07;
int sw_08;
int sw_09;
int sw_10;
int sw_11;
int sw_12;
int sw_13;
int sw_14;

// 
int productIdx = 0; //0 : TV / 1: TV BOX / 2: BTV / 3: SPK

int addr = 0;
bool chkon = false;
IRsend irsend;

void setup()
{
  pinMode(s01, INPUT_PULLUP);
  pinMode(s02, INPUT_PULLUP);
  pinMode(s03, INPUT_PULLUP);
  pinMode(s04, INPUT_PULLUP);
  pinMode(s05, INPUT_PULLUP);
  pinMode(s06, INPUT_PULLUP);
  pinMode(s07, INPUT_PULLUP);
  pinMode(s08, INPUT_PULLUP);
  pinMode(s09, INPUT_PULLUP);
  pinMode(s10, INPUT_PULLUP);
  pinMode(s11, INPUT_PULLUP);
  pinMode(s12, INPUT_PULLUP);
  pinMode(s13, INPUT_PULLUP);
  pinMode(s14, INPUT_PULLUP);
  
  pinMode(L00, OUTPUT);
  pinMode(L01, OUTPUT);
  pinMode(L02, OUTPUT);
  pinMode(L03, OUTPUT);
  
  pinMode(13, OUTPUT);
  
  productIdx = EEPROM.read(0);
}

void loop() {

  digitalWrite(13, LOW);
  
  sw_01 = digitalRead(s01);
  sw_02 = digitalRead(s02);
  sw_03 = digitalRead(s03);
  sw_04 = digitalRead(s04);
  sw_05 = digitalRead(s05);
  sw_06 = digitalRead(s06);
  sw_07 = digitalRead(s07);
  sw_08 = digitalRead(s08);
  sw_09 = digitalRead(s09);
  sw_10 = digitalRead(s10);
  sw_11 = digitalRead(s11);
  sw_12 = digitalRead(s12);
  sw_13 = digitalRead(s13);
  sw_14 = digitalRead(s14);
  
  // change product
  if (sw_02 == HIGH) {
    chkon = true;
    ledON(productIdx);
  }else{
    if (chkon)
    {
      productIdx++;
      if (productIdx > 3) productIdx = 0;
      EEPROM.write(0, productIdx);
      chkon = false;
    }
    
    ledON(productIdx);
  }
  
  if (sw_01 == HIGH) {    
  }else{    
    digitalWrite(13, HIGH);
    press_S01(productIdx);
  }
  if (sw_03 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S03(productIdx);
  }
  if (sw_04 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S04(productIdx);
  }
  if (sw_05 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S05(productIdx);
  }
  if (sw_06 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S06(productIdx);
  }
  if (sw_07 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S07(productIdx);
  }
  if (sw_08 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S08(productIdx);
  }
  if (sw_09 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S09(productIdx);
  }
  if (sw_10 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S10(productIdx);
  }
  if (sw_11 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S11(productIdx);
  }
  if (sw_12 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S12(productIdx);
  }
  if (sw_13 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S13(productIdx);
  }
  if (sw_14 == HIGH) {    
  }else{
    digitalWrite(13, HIGH);
    press_S14(productIdx);
  }
	
	delay(75); //5 second delay between each signal burst
}

void press_S14 (int idx) // vol -
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DFC03F,32);   // tv vol -
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F08F7,32);  // tv box vol -
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE42BD,32);  // BTV box vol -
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BFD02F,32);  //  spk vol -
    break;
  default:
    // statements
    break;
  }
}

void press_S13 (int idx) // chnl -
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF807F,32);   // tv chnl -
    break;
  case 1:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F18E7,32);  // tv box vol +
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE827D,32);   // Btv chnl -
    break;
  case 3:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF50AF,32);  //  spk vol +
    break;
  default:
    // statements
    break;
  }
}

void press_S12 (int idx) //vol +
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF40BF,32);   // tv vol +
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F18E7,32);  // tv box vol +
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FEC23D,32);   // Btv vol +
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF50AF,32);  //  spk vol +
    break;
  default:
    // statements
    break;
  }
}

void press_S11 (int idx) // chnl +
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF00FF,32);   // tv chnl +
    break;
  case 1:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F58A7,32);  // tv box
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE02FD,32);   // Btv chnl +
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF906F,32);  //  spk bt esc
    break;
  default:
    // statements
    break;
  }
}

void press_S10 (int idx) // down
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF827D,32);   // tv down
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F58A7,32);  // tv box down 
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE52AD,32);   // Btv down
    break;
  case 3:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF20DF,32);  //  
    break;
  default:
    // statements
    break;
  }
}

void press_S09 (int idx) // right
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF609F,32);   // tv right
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F0AF5,32);  // tv box right 
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE32CD,32);   // Btv right
    break;
  case 3:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF20DF,32);  // tv box up 
    break;
  default:
    // statements
    break;
  }
}
void press_S08 (int idx) // ok
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF22DD,32);   // tv ok
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807FC837,32);  // tv box ok 
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE629D,32);   // Btv ok
    break;
  case 3:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF20DF,32);  // tv box up 
    break;
  default:
    // statements
    break;
  }
}

void press_S07 (int idx) // arrow left
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DFE01F,32);   // tv left
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F8A75,32);  // tv box left 
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FED22D,32);   // Btv left
    break;
  case 3:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF20DF,32);  // tv box up 
    break;
  default:
    // statements
    break;
  }
}
void press_S06 (int idx)
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF02FD,32);   // tv back
    break;
  case 1:
    //for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F9867,32);  // tv box back 
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE728D,32);   // Btv back
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF20DF,32);  // spk OPT 
    break;
  default:
    // statements
    break;
  }
}

void press_S05 (int idx) // arrow up
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF02FD,32);   // tv up
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F6897,32);  // tv box up 
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE926D,32);   // Btv up
    break;
  case 3:
    //irsend.sendNEC(0x40BFA05F,32);  
    break;
  default:
    // statements
    break;
  }
}

void press_S04 (int idx)
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DFD02F,32);   //외부입력
    break;
  case 1:
    //irsend.sendNEC(0x2DF10EF,32);   
    break;
  case 2:
    //irsend.sendNEC(0x2DF10EF,32);   
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BFA05F,32);   // blue tooth
    break;
  default:
    // statements
    break;
  }
}

void press_S03 (int idx) // power
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF10EF,32);   // tv power
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F02FD,32);   // tv box power
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE807F,32);   // Btv power1 
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF807F,32);   
    break;
  default:
    // statements
    break;
  }
}
void press_S01 (int idx) //  S01
{
  switch (idx) {
  case 0:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x2DF10EF,32);   
    break;
  case 1:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x807F02FD,32);   
    break;
  case 2:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x1FE807F,32);   
    break;
  case 3:
    for (int i = 0; i < 1; i++) irsend.sendNEC(0x40BF807F,32);   
    break;
  default:
    // statements
    break;
  }
}
void ledON (int idx)
{
  digitalWrite(L00, LOW);
  digitalWrite(L01, LOW);
  digitalWrite(L02, LOW);
  digitalWrite(L03, LOW);
  switch (idx) {
  case 0:
    digitalWrite(L00, HIGH);
    break;
  case 1:
    digitalWrite(L01, HIGH);
    break;
  case 2:
    digitalWrite(L02, HIGH);
    break;
  case 3:
    digitalWrite(L03, HIGH);
    break;
  default:
    // statements
    break;
  }
}

 

자 이렇게 해서 프로그램까지 마쳤습니다.

원래 3편에 걸쳐 포스팅을 완료하려고 하였으나 너무 길어져서 최종 케이스제작과 동작 테스트는 다음 포스트로 미루도록 하겠습니다. 죄송합니다.

또 얼마가 걸릴지 모르겠네요. 

 

어쨌든 핵심이 되는 내용은 이번 편까지인것 같고 하드웨어 구성은 여러분께서 마음껏 하셔도 될 것 같습니다. 기능도 변경해보시고요, 좀 고민해보면 더 많은 기능을 구성하는 것도 가능할 수도 있습니다.

이번 프로젝트로 무려 4개의 리모컨을 1개로 통합하는 작업을 해보았는데요, 사실 제가 생각했던것과 아주 유사한 제품이 판매되는 제품도 있습니다. 가격이 아주 비싼것도 아니고요. 다만 이런것을 직접 해봄으로 해서 우리는 또 많은 것을 배울 수 있지 않겠습니까?

저는 이번 프로젝트에서 EEPROM 과 IR 신호를 제어하는 것을 배울 수 있는 좋은 기회였던 것 같습니다.

 

자 그럼 케이스 까지 완성되는 그날을 기대하며 ~

 

완성된 리모컨 구경하려면?

2022.08.16 - [DIY/Arduino] - [DIY] 아두이노로 통합(만능) 리모콘 만들기 (최종)

 

[DIY] 아두이노로 통합(만능) 리모콘 만들기 (최종)

만능 리모컨을 만들기로 해놓고 정말 많은 시간이 흘렀습니다. 2019.11.10 - [DIY/Arduino] - [DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3 2019.11.10 - [DIY/Arduino] - [DIY] 아두이노로 통합(만능) 리모콘..

diy-dev-design.tistory.com

 

뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 
도움이 되었다 생각되시면  클릭!!  부탁드려요~

 

IR 리모컨 제작 관련 링크는?

2019/11/10 - [DIY/Arduino] - [DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3

 

[DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3

도대체 영화 한편 보려면 몇개의 리모콘을 사용하는지... TV 전원을 켜기위해 TV 리모컨을 찾아야 하고 안드로이드 TV 셋톱을 켜기위해 안드로이드 TV 리모콘을 역시 찾아야 하며 막상 틀었더니 소

diy-dev-design.tistory.com

2019/11/10 - [DIY/Arduino] - [DIY] 아두이노로 통합(만능) 리모콘 만들기 2/3

 

[DIY] 아두이노로 통합(만능) 리모콘 만들기 2/3

먼저 포스트에서 아두이노를이용하여 다양한 리모콘의 신호를 해킹하는 방법을 알아 보았습니다. https://diy-dev-design.tistory.com/65 [DIY] 아두이노로 만능 (통합) 리모콘 만들기 1/3 도대체 영화 한편 �

diy-dev-design.tistory.com

 

다른 아두이노 예제는?

 

2020/05/26 - [DIY/Arduino] - 0.96 inch OLED 디스플레이 구동하기

 

0.96 inch OLED 디스플레이 구동하기

가끔 아두이노로 무엇인가를 만들어 보려고 하다보면 디스플레이가 있으면 하는 생각이 들때가 있습니다. 아두이노는 작은 컴퓨터이기는 하지만 모름지기 컴퓨터라 한다면 입력장치 - 중앙처��

diy-dev-design.tistory.com

2019/10/29 - [DIY/Arduino] - [DIY] 아두이노를 이용한 수경재배 시스템

 

[DIY] 아두이노를 이용한 수경재배 시스템

아두이노는 정말 놀라운 하드웨어가 아닐수 없죠. 우리가 생각하는 이런건 자동으로 해주는거 없나? 이런게 자동으로 되면 좋을텐데... 이런걸 왜 자동으로 안하는거야?? 같은 대부분의 자동화 �

diy-dev-design.tistory.com

2019/06/27 - [DIY/Arduino] - 아두이노를 이용한 간단한 화분 자동 물주기 시스템

 

아두이노를 이용한 간단한 화분 자동 물주기 시스템

얼마뒤면 베트남으로 가족 여행을 떠날 예정입니다. 7박이나 하고 올 예정이므로 집을 비우기 전 준비해야 할 것들이 많습니다. 이것저것 여행준비를 하던 찰나 베란다에 내어 둔 화분이 걱정이

diy-dev-design.tistory.com

2020/03/23 - [DIY/Arduino] - Arduino(아두이노) 무작정 시작하기

 

Arduino(아두이노) 무작정 시작하기

아두이노, Arduino 여기저기서 많이 들었을 겁니다. 이걸 해야 된다는 말이 귀에 못이 박히도록 이야기 합니다. 대충 뭔지는 알겠는데 개발자도 아닌 내가 과연 이걸로 뭘 할 수 있을까 싶기도 하��

diy-dev-design.tistory.com

2020/06/29 - [DIY/Arduino] - C# 에서 아두이노로 시리얼 통신 하기

 

C# 에서 아두이노로 시리얼 통신 하기

카테고리를 c# 으로 해야 할지 Arduino 로 해야할지 조금 고민이 되는 포스트 입니다. 음.... arduino 로 하는게 좋겠네요. 따지고 보면 C# 으로 만든 어플이 중요한게 아니라 아두에노에서 시리얼 통신

diy-dev-design.tistory.com

 

반응형

+ Recent posts