이번 글에서는 프로그램이 시작되는 시점의 현재 시간을 맞춰 주거나 시간 경과에 따라 시간 오차가 발생할 때, 이를 보정해주기 위하여 사용자가 푸쉬버튼을 눌러 주어 시간과 분에 해당되는 값을 조정하는 방법에 대해서 구현해 보도록 하겠다.시간 단위 조정을 위하여 푸쉬버튼 하나를 이용하고, 분단위 값을 조정하기 위하여 푸쉬버튼을 하나 더 이용하기로 한다.시간을 조정하기 위하여 사용자가 언제 푸쉬버튼을 누를지 알 수 없기 때문에, 버튼을 누르는 순간 즉각 이를 알아내기 위하여 external interrupt를 사용하여야 한다. AVR에는 두가지 종류의 external interrupt를 제공하는데, 하나는 위의 그림에서 초록색 박스로 표시된 INT# 라고 되어 있는 각 핀별로 인터럽트를 발생할 수 있는 방법과..
이번 글에서는 빛의 세기에 따라 저항값이 달라지는 Cds(Photo cell)을 이용하여 빛의 밝기를 측정하는 방법에 대해서 설명하도록 하겠다.회로 구성을 보면 ATtiny85의 7번 핀에 Cds가 연결되어 있는것을 볼 수 있다. Cds의 한쪽은 VCC에 연결되어 있고, 다른 쪽은 10K옴 저항을 통하여 GND에 연결되게 된다.Cds는 빛이 세기가 강해 질 수록 저항값이 감소하게 된다. 당연히 어두워지면 저항값이 증가한다. 빛이 밝아지면 Cds의 저항값이 감소하게 된다는 의미는 10K 저항에 걸리는 전압이 증가한다는 것이고, 이를 ATtiny85의 ADC로 측정하게 되면 큰 값이 읽히게 된다. 반대로 주위가 어두워지면 Cds의 저항값이 증가하고 10K 저항에 걸리는 전압은 상대적으로 낮아지게 된다. 결과..
이번 글에서는 디지털 시계 만들기 프로젝트의 핵심이라고 할 수 있는 타이머 설정에 대해서 설명하도록 하겠다.ATtiny85의 Timer/Counter0을 이용하여 일정한 시간 간격으로 타이머를 동작 시키도록 할 것이다.입문 과정에서 설명하였던 타이머/카운터 - PWM(CTC Mode)을 참고하여 원하는 시간에 인터럽트가 발생되도록 설정해준다. 하드웨어 타이머를 사용하면 CPU 동작과 무관하게 일정한 시간 간격으로 이벤트를 제공하므로 비교적 정확한 시계로 동작될 수 있게된다.enum timer_mode { NORMAL, PHASE, CTC, FAST }; enum timer_prescaler { DIV_NO, DIV_0, DIV_8, DIV_64, DIV_256, DIV_1024, EXT_FALLING, ..
이번 글에서는 TM1637을 제어하여 4자리 숫자를 표시해 보도록 하겠다. 이전 글에서 간단하게 언급하였지만 MCU와 TM1637간의 연결은 CLK, DIO 이렇게 2개의 시그널을 이용한다. 동작 원리는 I2C와 비슷하다는것도 앞에서 설명하였다.TM1637 datasheet에 설명되어 있는 방법중 "Write SRAM data in a fixed address mode"라는 동작을 이용하여 숫자를 표시하게 된다.CLK, DIO가 high 상태에서 DIO가 low가 되면 start 된다는 것을 의미한다. CLK 신호가 low에서 high 상태로 변경되는 시점의 DIO 값이 TM1637로 전달된다. 데이터가 나가는 순서는 LSB부터 나가도록 되어있는데 datasheet에는 이 부분이 정확히 설명되어 있지 않..
이번 프로젝트는 ATtiny85를 사용하여 아주 간단한 디지털 시계를 만들어 보는 것이다.ATtiny85는 위의 그림에서 보는것처럼 외부로 나오는 핀이 모두 8개인 아주 작은 MCU이다.ATtiny85의 핀 구성은 위의 그림과 같다. 이번 프로젝트에서는 VCC, GND, /RESET 핀을 제외한 5개의 핀 모두를 사용하도록 하겠다.이번에 만들어 보는것이 디지털 시계이므로 시간을 숫자로 표시해 주기위하여 7-세그먼트 디스플레이 모듈을 사용하겠지만, MCU의 I/O 핀을 직접 7세그먼트에 연결하는 것이 아니고 TM1637 칩이 들어있는 4핀짜리 디스플레이 모듈을 이용할 것이다. 위의 그림을 자세히 보면 TM1637칩이 실장되어 있고 CLK, DIO, GND, 5V 이렇게 4개의 핀이 연결될 수 있다는 것을 ..
앞의 글에서 설명한 대로 송신 기능을 구현하여 동작시켜 놓은 상태이므로, 송신기에서는 주기적으로 16비트 카운트 값을 내 보내주고 있다.이번에는 이 데이터를 수신하여 콘솔창에 출력함으로써 데이터 송신과 수신 과정이 정상적으로 수행되고 있음을 확인해 보도록 하겠다. static uint8_t tranceiver_addr[ADDR_WIDTH] = {0x12, 0x34, 0x56, 0x78, 0x90}; void nrf24_init(void) { ce_low(); cs_high(); _delay_ms(10); nrf24_close_pipe(NRF_ALL); nrf24_open_pipe(NRF_PIPE0); nrf24_crc_mode(NRF_CRC_16BIT); nrf24_auto_retr(15, 500); n..
nRF24L01을 이용한 무선 통신nRF24L01 register 읽어보기 nRF24L01의 내부 레지스터들을 정상적으로 읽어 오는 것을 확인하였으면 다음 과정으로 송신 기능을 구현해 보도록 하겠다.static uint8_t tranceiver_addr[ADDR_WIDTH] = {0x12, 0x34, 0x56, 0x78, 0x90}; void nrf24_init(void) { ce_low(); cs_high(); _delay_ms(10); nrf24_close_pipe(NRF_ALL); nrf24_open_pipe(NRF_PIPE0); nrf24_crc_mode(NRF_CRC_16BIT); nrf24_auto_retr(15, 500); nrf24_addr_width(NRF_AW_5BYTES); nrf24..
지금까지는 OLED 디스플레이 모듈과의 통신을 위하여 SPI버스를 이용하였지만, 이번에는 I2C 버스를 이용하여 원하는 데이터를 출력하는 방법에 대해서 설명하도록 하겠다.SPI 버스 방식은 모두 7개의 연결이 필요하였지만, I2C버스의 경우 전원 포함 4개의 연결만 필요하므로 훨씬 단순한 연결방식이라고 할 수 있겠다.SSD1306 datasheet 문서에서 I2C 버스의 경우에 어떻게 데이터를 보내야하는지는 위의 그림과 같이 설명되어 있다.I2C의 경우 device address가 필요한데 SSD1306의 경우에는 0x3C의 값을 가진다. 필요한 경우 칩의 D/C# 핀을 1로 연결하면 device address가 0x3D로 변경할 수 있다. 이번 프로젝트에서 사용하는 모듈은 0x3C의 주소를 가지고 있다..
예전에 설명하였던 LCD1602나 LCD12864의 경우 글자를 출력하기 위한 기능이 디스플레이 내부에 들어 있었지만, SSD1306은 그런 기능이 없기 때문에 글자를 표현하기 위해서 직접 점들을 조합하여야 한다.이번 프로젝트에서는 5x7 픽셀의 점들을 이용하여 ASCII code를 출력하는 방법에 대해서 설명하겠다.예를 들어 대문자 'A'를 출력하기 위한 표시는 위의 그림과 같다. 가로로 5칸, 세로로 7칸의 조합으로 표시하며, 좌,우,상,하 글자와 구분하기 위하여 아래로 한칸, 오른쪽에 한줄의 공백을 두어야 한다. SSD1306 datasheet 문서를 보면 Page내에서 위쪽에 있는 점이 D0에 해당되고 가장 아래쪽에 있는 점이 D7에 해당된다. 그러므로, 'A'의 첫번째 행을 이진수로 표현하면 '..
앞의 글들을 통해서 기본적인 SSD1306의 동작 원리를 설명하였으므로 이를 응용하여 화면에 원하는 위치에 점 하나를 표시하는 방법을 구현해 보도록 하겠다.점 하나만을 표시하고자 할때 주의할 점은 위의 그림을 보면 알겠지만, column의 위치는 특정 SEG위치를 지정해 줌으로써 원하는 위치를 직접 지정해 줄수 있지만, row의 위치는 Page단위, 즉, 1바이트 크기만큼씩 지정해 줄수밖에 없는 구조에 대해 고려해 주어야 한다는 것이다.만약, 18번째 줄의 어딘가에 점하나를 출력하고자 원한다면, PAGE2의 D1비트의 값을 1로 설정해 주면 된다. 하지만 이때 나머지 비트값들은 그대로 유지해 주어야한다. 그렇지 않으면, D1비트값만 켜지고 나머지 줄들의 데이터는 모두 0이 되므로 꺼지게 되는 것이다.따라..