비눗방울 장난감을 고퀄리티 LED 요술봉으로 개조하기 마지막입니다.
앞 글들을 읽고 오시는 걸 추천드립니다.
오늘 글에서는 어떤 동작을 할지 결정후, 코딩을 하고, 동작되는 최종 형태까지 확인하도록 하겠습니다.
먼저 동작은 다음과 같이 계획했습니다.
버튼을 누르면, 전원이 켜짐과 동시에 1번 이미지가 출력됩니다.
다시 버튼을 누를 때마다 이미지가 바뀌고, 4번째 버튼을 누를 때 종료됩니다.
매우 간단하지요.
제가 개발해야 하는 모든 시스템이 이렇게 간단하기만 하면 행복하겠습니다 ㅎ
출력하는 이미지를 몇 가지로 할까 고민하다가 너무 많으면 지겨울 까봐 딱 3개만 하기로 했어요.
먼저 두 가지는 알록달록 무지개 색을 하고, 하나는 잔상효과를 이용한 이미지 출력을 해볼까 해요.
이제 빛의 색상이 혼합되는 가산 혼합에 의해 그 색을 정합니다.
RGB 컬러 이기 때문에 색상은 24Bit로 출력되며 R, G, B, 더미 데이터(FF)의 순으로 32Bit 데이터로 배열을 만들어 사용합니다.
예를 들어 RED를 출력하고자 한다면, 0xFF0000FF 가 되고, Green 은 0x00FF00FF, Blue 는 0x0000FFFF 가 됩니다.
그림의 좌측은 물감을 섞을 때 나오는 감산 혼합이고, 우측이 빛을 섞을 때 만들어지는 가산 혼합입니다.
우리는 LED 빛으로 색을 만들기 때문에 가산 혼합에 속하지요.
이미지는 아이들이 좋아하는 알록달록 색으로 만들어 줄 거예요.
또 출력되는 색상이 가만히 있으면 재미없으니 흐르듯이 옆으로 움직임도 넣을 거예요.
이미지의 형태는 총 3가지인데. 각각 아래와 같아요.
1번과 2번 이미지는 24개의 LED에 해당하는 배열 하나로 해결이 가능하지만, 아래 3번 이미지는 잔상효과로 나타낼 것이기 때문에 가로 32, 세로 24개의 2중 배열을 만들어 한순간에 한 라인 출력해야 해요.
하지만 저 색상들을 일일이 HEX 값으로 변환하는 것은 너무나 고된 막노동 입니다.
그래서 변환하는 툴들이 있지요.
물론 이미지 1, 2는 직접 계산해서 했지만, 아래 3번 이미지는 이미지 파일을 C 에레이 형태로 변환해주는 사이트를 통해서 얻은 것입니다.
사실 사용해 보니 그대로 쓰기에는 조금 무리가 있고요, 적절히 사용 가능하도록 수정이 필요하긴 합니다.
https://littlevgl.com/image-to-c-array
3번 이미지는 내용이 너무 크다 보니 제외하고, 1번, 2번 이미지 어레이는 아래와 같아요.
/*****************************************************************************************
* @file : images.h
* @author : [EMC] r2adve(sungtae sun)
* @date : 2020.4.09
* @brief :
******************************************************************************************/
uint32_t img1[24]={
0xFF0000FF,0x00FF00FF,0x0000FFFF,0xFFFF00FF,0x00FFFFFF,0xFF00FFFF,0xFFFFFFFF,
0xFF0000FF,0x00FF00FF,0x0000FFFF,0xFFFF00FF,0x00FFFFFF,0xFF00FFFF,0xFFFFFFFF,
0xFF0000FF,0x00FF00FF,0x0000FFFF,0xFFFF00FF,0x00FFFFFF,0xFF00FFFF,0xFFFFFFFF,
0xFF0000FF,0x00FF00FF,0x0000FFFF};
uint32_t img2[24]={
0x2000A0FF,0x400080FF,0x600060FF,0x800040FF,0xA00020FF,0xC00000FF,0xE00000FF,0xFF2000FF,
0xE04000FF,0xC06000FF,0xA08000FF,0x80A000FF,0x60C000FF,0x40E000FF,0x20FF20FF,0x00E040FF,
0x00C060FF,0x00A080FF,0x0080A0FF,0x0060C0FF,0x0040E0FF,0x0020FFFF,0x0000E0FF,0x0000C0FF};
이제 저 배열을 비트 별로 쭉~ 밀어 넣는 로직을 만들어야 해요.
이번 시리즈의 앞부분에서 말했듯이 3색 LED를 제어하는 드라이버 IC의 타이밍도에 맞게 데이터를 밀어 넣도록 만들어야 합니다.
/*******************************************************************************************
* @file : display.c
* @author : [EMC] r2adve(sun sungtae)
* @date : 2020, 04, 09
* @brief :
*******************************************************************************************/
#include "stdio.h"
#include "string.h"
#include "string_utils.h"
#include "printf.h"
#include "stm32f0xx.h"
#include "stm32f0xx_gpio.h"
#include "func.h"
#include "delay.h"
#include "gpio.h"
#include "images.h"
//----------------------------------------------------------------------------------------
// 기능 : 1번 이미지 출력
// 주의 :
//----------------------------------------------------------------------------------------
void img_out_1(void)
{
uint32_t tmp = 0;
uint32_t i,k;
uint32_t mask = 0x8000000;
uint32_t rgb = 0;
for(i=0; i<24; i++)
{
rgb = img1[i];
mask = 0x80000000;
for(k=0;k<24;k++)
{
if(rgb & mask)
{
udelay(5);
GPIOB->BSRR = 0x0001; // PB0 ON
__ASM volatile("NOP");
GPIOB->BRR = 0x0001; // PA0 OFF
udelay(1);
}
else
{
udelay(5);
GPIOB->BSRR = 0x0001; // PB0 ON
GPIOB->BRR = 0x0001; // PA0 OFF
udelay(1);
}
mask = mask>>1;
}
}
mdelay(20);
tmp = img1[0];
for(i=0; i<23; i++)
{
img1[i]= img1[i+1];
}
img1[23] = tmp;
}
위 코드는 1번 이미지를 출력 하는 함수 인데요, 이미지 배열을 20msec 간격으로 한칸씩 아래로 이동하면서 출력 하는 형태 입니다.
2번 이미지, 3번 이미지도 출력하는 로직을 만들어줍니다.
하나의 함수로 이미지를 변경하는 것이 효율적이긴 하지만, 셋다 아예 다른 동작을 하도록 만들고 싶어서 함수를 따로 만들었어요.
3번 이미지 출력은 잔상효과를 보여주기 위해서 2중 배열을 출력 해요.
//----------------------------------------------------------------------------------------
// 기능 : 잔상효과 출력
// 주의 :
//----------------------------------------------------------------------------------------
void after_img_out(void)
{
uint32_t i,j,k;
uint32_t mask = 0x8000000;
uint32_t rgb = 0;
for(i=0; i<32; i++)
{
for(j=0; j<24; j++)
{
rgb = images[j][i];
mask = 0x80000000;
for(k=0;k<24;k++)
{
if(rgb & mask)
{
udelay(5);
GPIOB->BSRR = 0x0001; // PB0 ON
__ASM volatile("NOP");
GPIOB->BRR = 0x0001; // PA0 OFF
udelay(1);
}
else
{
udelay(5);
GPIOB->BSRR = 0x0001; // PB0 ON
GPIOB->BRR = 0x0001; // PA0 OFF
udelay(1);
}
mask = mask>>1;
}
}
mdelay(1);
}
}
3개의 이미지 출력 코드가 비슷해 보이는 이유는 24개의 LED 각각에 값을 밀어 넣는 로직이 같기 때문이고, 다른 점은 이미지가 움직이는 방향과 속도가 다르고, 특히 3번의 경우는 2중 배열을 출력하기 떄문에 for 루프가 한번 더 있다는 겁니다.
어쨌든 이미지 3개의 출력에 대한 로직이 완성되었어요.
이제 버튼을 누르면 다음 이미지가 켜지고, 3개가 모두 지나가면 꺼지는 코드를 만들면 됩니다.
//----------------------------------------------------------------------------------------
// 기능 : 버튼 입력 처리
// 주의 :
//----------------------------------------------------------------------------------------
uint8_t check_sw(void)
{
if(!sys_info.flag_button)
return 0;
sys_info.mode++;
sys_info.flag_button = 0;
if(sys_info.mode > _END_)
{
display_off();
power_off();
}
return 0;
}
//----------------------------------------------------------------------------------------
// 기능 : 모드에 따라 출력
// 주의 :
//----------------------------------------------------------------------------------------
void display(void)
{
switch (sys_info.mode)
{
case _DISPLAY_1 :
img_out_1();
break;
case _DISPLAY_2 :
img_out_2();
break;
case _DISPLAY_3 :
after_img_out();
break;
default :
break;
}
}
스위치를 눌러서 동작 모드를 바꾸고, _END_ 보다 값이 커지면 끄도록 했어요.
그리고 display에서는 해당 모드에 대한 이미지를 출력하도록 했고요.
이제 main 함수에서 이들을 반복적으로 호출만 해주면 땡입니다.
//****************************************************************************************
// 기능 : 메인 함수
// 주의 :
//****************************************************************************************
int main(void)
{
//제품의 동작을 위한 주변장치들을 초기화 한다.
sys_peripheral_init();
//시스템 정보 출력
print_system_info();
//시스템 초기화
sys_init();
while(GET_PWR_SW)
;
sys_info.flag_button = 0;
while(1)
{
check_sw();
display();
}
}
맨 마지막의 while 루프에서 스위치와 display를 반복하고 있는 것이 보입니다.
아주 간단명료하지요 ~
사실 위에서 보인 코드가 전부는 아니에요.
일부분이지만 그래도 전체적 로직을 보여주기에는 충분하다고 생각합니다.
이제 실제 동작이 되는지 확인해 볼 차례입니다.
딸내미가 받고 좋아서 오버하는 모습을 올리고 싶긴 한데.. 내복을 이상하게 입고 있어서 올리질 못하겠네요. 딸내미의 이미지 관리 차원에서 ㅎㅎ
어쨌든 개조를 성공적으로 마쳤어요.
이 작품의 장점이라면, 제가 직접 만들었기 때문에 언제든지 다른 이미지로 바꿀 수 있다는 거죠 ~
참고로 이거 들고 어두울 때 밖에 나가면 어마어마합니다.
시간 날 때 하나 더 조립해서 쌍칼을 만들어줘야겠어요.
날아라 슈퍼보드에서 이상한 여자애가 등에 쌍칼을 들고 나오는 바람에 요새 우리 집 강아지도 닌자 한다고 길쭉한 것만 보이면 무조건 두 개씩 등에 꼽고 있거든요 ㅎㅎ
다음에는 또 뭘 만들어볼까 ~ 하고 고민해 봅니다.
파트너스 활동으로 수수료를 받을 수 있음.
'아빠가 개발자면 생기는 일' 카테고리의 다른 글
10포트 USB 충전기 만들기 (1) | 2020.04.16 |
---|---|
탄약 장착식 고무줄총 만들기 (0) | 2020.04.13 |
왕스틱 비누방울 버블봉을 LED 요술봉으로 개조하기 #4/5 (0) | 2020.04.08 |
왕스틱 비누방울 버블봉을 LED 요술봉으로 개조하기 #3/5 (0) | 2020.04.07 |
시크릿쥬쥬 셀카폰 USB 충전식으로 개조하기 #5/5(마무리) (24) | 2020.04.07 |
댓글