Brise

자작 후미등 - 코드편 본문

DIY/자작 후미등

자작 후미등 - 코드편

naudhizb 2015. 9. 24. 17:36
반응형


--


자작 후미등을 MCU를 이용하여 만들었기 때문에 코드를 이용하여 후미등을 제어할 수 있다.


때문에, 이 제어를 어떻게 할 것인지 명세를 먼저 하고 코드 작업을 들어가야한다.






전체적인 상태 구조는 위와 같다.


Init 부분에서 핀 아웃풋, 인풋 / 타이머 및 인터럽트 초기화 / 모드 및 타이머 함수 초기화를 진행하고


모드 0으로 진입하며 전력 절약모드에 들어간다.


스위치를 누를 때마다 깨어나 모드를 바꾸거나 주기를 바꾼다. 


타이머 인터럽트를 통해 위와 독립적으로 각 led배열 값을 이용하여 led를 표시한다.


여기서 led와 mode는 서로 concurrent하게 동작하며 상호간의 consistency를 맞춰주기 위하여 조작하는 부분은 임계영역(critical section)에서 실행된다. 



작성한 소스코드들의 의존관계는 다음과 같다.






그리고 위 코드를 구현한 내용은 아래와 같다. 


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
30
31
32
33
34
35
 
/*******************************************************************************
common.h
07-13-2015 Made by naudhizb
 매크로,매크로 함수와 함수들 선언
*******************************************************************************/
 
/*** include guard ***/
#ifndef _COMMON_H_
/*** define macro ***/
#define _COMMON_H_
 
 
////Define Macro Function
 
//MACRO FUNCTION
#define constrain(value,min,max) ((value-min)>=0)?((value-max)<=0)?value:max:min
#define map(value,i_min,i_max,o_min,o_max) o_min+(value-i_min)/(i_max-i_min)*(o_max-o_min)
 
//PORT CONTROL
#define gbi(PORTX,bitX) ((PORTX & (1<<bitX))>>bitX)
#define tbi(PORTX,bitX) PORTX ^= (1<<bitX)
#define sbi(PORTX,bitX) PORTX |= (1<<bitX)
#define cbi(PORTX,bitX) PORTX &= ~(1<<bitX)
#define bi(bitX) (1<<bitX)
 
//// HW indep한 헤더 include
#include <stdio.h>
#include <stdint.h>
#include <math.h>
 
 
/*** include guard end ***/
#endif 
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
/*******************************************************************************
atmega8.h
07-13-2015 Made by naudhizb
 HW dep 헤더 선언
*******************************************************************************/
 
#define F_CPU 8000000UL // CPU CLOCK RATE DEFINE
 
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <util/atomic.h>
//#include <util/setbaud.h>
#include <util/twi.h>
 
cs


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
30
31
32
33
34
35
 
/*******************************************************************************
atmega8_timer.h
07-13-2015 Made by naudhizb
 타이머 선언
*******************************************************************************/
 
 
#ifndef _H_TIMER_
#define _H_TIMER_
 
 
#include "common.h"
#include "atmega8.h"
 
typedef enum _clock_prescaler {
    NO_CLOCK_SOURCE,
    PRESCALE_D1, //31250
    PRESCALE_D8, //3906
    PRESCALE_D64,//488
    PRESCALE_D256,//122
    PRESCALE_D1024 //30.5
} clock_prescaler;
 
enum timer_interrupt_flags {
    INTERRUPT_DISABLE,
    INTERRUPT_ENABLE
} ;
 
 
void timer0_set(uint8_t PRESCALE, 
                uint8_t INTERRUPT_FLAG);
    
#endif
 
cs


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
 
/*******************************************************************************
atmega8_timer.c
07-13-2015 Made by naudhizb
 타이머 구현
*******************************************************************************/
 
 
#include "atmega8_timer.h"
 
 
void timer0_set(uint8_t PRESCALE, 
                uint8_t INTERRUPT_FLAG) {
    
    TCCR0     = PRESCALE; //CPU ?대씫
    
    if(INTERRUPT_FLAG==INTERRUPT_ENABLE){
        sbi(TIMSK,TOIE0);
        sbi(TIFR,TOV0);
    }
    else {
        cbi(TIMSK,TOIE0);
    }
    
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
/*******************************************************************************
button.h
07-13-2015 Made by naudhizb
 버튼 init 및 getter 선언
*******************************************************************************/
 
 
#ifndef _H_BUTTON
#define _H_BUTTON
 
#include "common.h"
#include "atmega8.h"
 
 
 
void button_init (void);
 
uint8_t button_read (void);
 
#endif
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*******************************************************************************
button.c
07-13-2015 Made by naudhizb
 버튼 init 및 getter 구현
*******************************************************************************/
 
 
#include "button.h"
 
 
void button_init(void) {
    cbi(DDRD,DDRD2);
    sbi(PORTD,PORTD2);
    
}
 
uint8_t button_read(void) {
    return gbi(PIND,PIND2);
}
 
cs


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
30
31
 
/*******************************************************************************
ext_int.h
07-13-2015 Made by naudhizb
ext_int init 선언
*******************************************************************************/
 
 
#ifndef _H_EXT_INT
#define _H_EXT_INT
    
#include "common.h"
#include "atmega8.h"
 
enum interrupt_flags {
    EXT_INTERRUPT_DISABLE,
    EXT_INTERRUPT_ENABLE
};
 
enum interrupt_modes {
    INTERRUPT_LOW_LEVEL,
    INTERRUPT_LOGIC_CHANGE,
    INTERRUPT_F_EDGE,
    INTERRUPT_R,EDGE
};
 
void ext_interrupt_init (char INTERRUPT_FLAG,
                    char INTERRUPT_MODE);
                    
#endif
 
cs


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
30
31
32
33
 
/*******************************************************************************
ext_int.h
07-13-2015 Made by naudhizb
ext_int init 구현
*******************************************************************************/
 
 
#include "ext_int.h"
 
 
void ext_interrupt_init (char INTERRUPT_FLAG,
                        char INTERRUPT_MODE) {
    if(INTERRUPT_FLAG == EXT_INTERRUPT_ENABLE)
    {
        sbi(GICR, INT0);
        sbi(GIFR, INTF0);
    } else {
        cbi(GICR, INT0);
        cbi(GIFR, INTF0);
    }
                        
    if(gbi(INTERRUPT_MODE,ISC00))
        sbi(MCUCR,ISC00);
    else
        cbi(MCUCR,ISC00);
    
    if(gbi(INTERRUPT_MODE,ISC01))
        sbi(MCUCR,ISC01);
    else
        cbi(MCUCR,ISC01);
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
/*******************************************************************************
led.h
07-13-2015 Made by naudhizb
led init 및 setter 선언
*******************************************************************************/
 
 
#ifndef _H_LED
#define _H_LED
 
#include "common.h"
#include "atmega8.h"
 
void led_control (    uint8_t led_channel,
                    uint8_t led_set);
 
void led_set(uint8_t led_arr);
void led_init(void);
 
void led_debug(uint8_t swi);
#endif
cs


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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*******************************************************************************
led.c
07-13-2015 Made by naudhizb
led init 및 setter 구현
*******************************************************************************/
 
 
#include "led.h"
 
/*
(PORTD,PORTD5)
(PORTD,PORTD6)
(PORTD,PORTD7)
(PORTB,PORTB2)
(PORTB,PORTB1)
(PORTB,PORTB0)
(PORTC,PORTC5) // for debug
*/
 
void led_control (uint8_t led_channel,uint8_t led_set) {
    switch(led_channel) {
        
        case 0:
            if(led_set)
                sbi(PORTD,PORTD5);
            else
                cbi(PORTD,PORTD5);
        break;
        
        case 1:
            if(led_set)
                sbi(PORTD,PORTD6);
            else
                cbi(PORTD,PORTD6);
            break;    
            
            case 2:
            if(led_set)
                sbi(PORTD,PORTD7);
            else
                cbi(PORTD,PORTD7);
            break;
            
            case 3:
            if(led_set)
                sbi(PORTB,PORTB2);
            else
                cbi(PORTB,PORTB2);
            break;
        
            case 4:
            if(led_set)
                sbi(PORTB,PORTB1);
            else
                cbi(PORTB,PORTB1);
            break;
        
            case 5:
            if(led_set)
                sbi(PORTB,PORTB0);
            else
                cbi(PORTB,PORTB0);
            break;
        
            case 6:
            if(led_set)
                sbi(PORTC,PORTC5);
            else
                cbi(PORTC,PORTC5);
            break;
            
            default:
            break;
    }
}
 
void led_set(uint8_t led_arr) {
    for(int i=0;i<7;i++)
        led_control(i,gbi(led_arr,i));        
}
 
void led_init(void) {
 
    sbi(DDRD,DDRD5);
    sbi(DDRD,DDRD6);
    sbi(DDRD,DDRD7);
    sbi(DDRB,DDRB2);
    sbi(DDRB,DDRB1);
    sbi(DDRB,DDRB0);
    sbi(DDRC,DDRC5);
}
 
void led_debug(uint8_t swi) {
    led_control(6,swi);
}
cs


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
30
31
/*******************************************************************************
mode.h
07-13-2015 Made by naudhizb
mode init 및 iterator  선언
*******************************************************************************/
 
 
#ifndef _H_MODE
#define _H_MODE
 
#include "common.h"
#include "atmega8.h"
#include "atmega8_timer.h"
#include "led.h"
 
 
typedef struct _led_mode {
    uint8_t num_of_mode;
    clock_prescaler freq_set;
    char *plight_mode_arr;
    uint8_t length;
} led_mode;
 
 
void mode_init(void);
void mode_change(void);
void freq_change(void);
void led_iterator (void);
#endif
 
 
cs


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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
 
/*******************************************************************************
mode.c
07-13-2015 Made by naudhizb
mode init 및 iterator 구현 및 mode 명세
*******************************************************************************/
 
 
#include "mode.h"
 
const char mode_off[] = {0x00};
const char mode_full[] = {0x3F};
const char mode_half[] = {0x3F,0x3F0x00,0x00};
const char mode_onethird[] = {0x3F,0x3F0x000x00,0x00,0x00};
const char mode_serial[] = {0x010x01,0x02,0x020x040x040x10,0x100x20,0x200x10,0x100x04,0x040x02,0x02};
const char mode_cross[] = {0x080x08,0x14,0x14};
const char mode_light[] = {0x08};
const char mode_halflight[] = {0x08,0x08,0x00,0x00};
 
led_mode mode_arr[] = {
    {
        0,
        NO_CLOCK_SOURCE,
        (char *)&mode_off[0],
        sizeof(mode_off)/sizeof(char)
    },
    {
        1,
        NO_CLOCK_SOURCE,
        (char *)&mode_full[0],
        sizeof(mode_full)/sizeof(char)
    },
    {
        2,
        PRESCALE_D64,
        (char *)&mode_half[0],
        sizeof(mode_half)/sizeof(char)
    },
    {
        3,
        PRESCALE_D64,
        (char *)&mode_onethird[0],
        sizeof(mode_onethird)/sizeof(char)
    },
    {
        4,
        PRESCALE_D1024,
        (char *)&mode_serial[0],
        sizeof(mode_serial)/sizeof(char)
    },
    {
        5,
        PRESCALE_D1024,
        (char *)&mode_cross[0],
        sizeof(mode_cross)/sizeof(char)
    },
    {
        6,
        NO_CLOCK_SOURCE,
        (char *)&mode_light[0],
        sizeof(mode_light)/sizeof(char)
    },
    {
        7,
        PRESCALE_D64,
        (char *)&mode_halflight[0],
        sizeof(mode_halflight)/sizeof(char)
    }
};
 
/*
    NO_CLOCK_SOURCE,
    PRESCALE_D1, //31250
    PRESCALE_D8, //3906
    PRESCALE_D64,//488
    PRESCALE_D256,//122
    PRESCALE_D1024 //30.5
    */
 
 
 
led_mode * p_mode_arr;
char mode_cursor_max;
char mode_cursor=0;
 
char * plight_arr;
char light_cursor_max;
char light_cursor;
clock_prescaler current_freq=0;
 
 
void notify_number (int number) {
    for(int i=0; i<number;i++) {
        led_control(6,1);
        _delay_ms(100);
        led_control(6,0);
        _delay_ms(100);
    }
}
void mode_init(void) {
    
    mode_cursor_max = sizeof(mode_arr)/sizeof(led_mode);
    p_mode_arr = &mode_arr[0];
    mode_cursor_max = sizeof(mode_arr)/sizeof(led_mode);
    plight_arr = p_mode_arr->plight_mode_arr;
    light_cursor_max = p_mode_arr->length;
    light_cursor = 0;
    current_freq = 0;
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
 
void mode_change(void) {
    // change mode cursor
    //exception handling
    if(++mode_cursor >=mode_cursor_max) {
        mode_cursor = 0;
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    } 
    // change mode ptr
    p_mode_arr = &mode_arr[mode_cursor];
    
    // change light ptr
    plight_arr = p_mode_arr->plight_mode_arr;
    light_cursor_max = p_mode_arr->length;
    
    // reset light ptr cursor
    light_cursor = 0;
    
    set_sleep_mode(SLEEP_MODE_IDLE);
    
    // change timer
    current_freq = p_mode_arr->freq_set;
    timer0_set(current_freq,INTERRUPT_ENABLE);
    
    led_iterator();
    // notify mode number
    notify_number(p_mode_arr->num_of_mode);
}
 
void freq_change(void) {
    current_freq += 1;
    if(current_freq >=8)
        current_freq = 3;
    
    // notify freq number
    
    timer0_set(current_freq, INTERRUPT_ENABLE);
    notify_number(current_freq);
}
 
void led_iterator (void) {
    // exception handling
    if(++light_cursor>=light_cursor_max)
        light_cursor = 0;
    
    led_set(*(plight_arr+light_cursor));
    
}
 
 
cs


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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
 
/*******************************************************************************
main_function.c
07-13-2015 Made by naudhizb
메인 알고리즘 및 sleep 구현
*******************************************************************************/
 
 
#include "common.h"
#include "atmega8.h"
#include "led.h"
#include "atmega8_timer.h"
#include "mode.h"
//#include "iterator.h"
#include "button.h"
#include "ext_int.h"
 
////Include Header
 
/* VARIABLE */
 
/** FOR ISR FUNCTION **/
extern char * plight_arr;
extern char light_cursor_max;
extern char light_cursor;
 
/** FUCTION **/
void into_sleep_mode(void) {
    sleep_enable();
    sleep_cpu();
    sleep_disable();
}    
 
 
/** MAIN FUNCTION **/
int main(void)
{
 
    led_init();
    led_debug(1);
    mode_init();
    button_init();
 
    ext_interrupt_init(EXT_INTERRUPT_ENABLE,
                        INTERRUPT_LOW_LEVEL);
 
                        timer0_set(    NO_CLOCK_SOURCE,
                INTERRUPT_ENABLE);
    _delay_ms(500);
    led_debug(0);
    sei();
 
    while(1)
    {
    into_sleep_mode();
    }
 
    return 0;
}
 
 
 
 
 
 
/** ISR SECTION **/
volatile unsigned int cnt=0;
 
ISR(INT0_vect) // enable low
{
    led_debug(1);
    cnt=0;
    while(!button_read()) {
        cnt++;            
    _delay_ms(100);        
    if(cnt>=6)
        led_debug(0);
    }
    if(cnt <=1); // exception handling (prevent chattering)
    else if(cnt<=5) { // short press --> mode change
        mode_change();
    }
    else if(cnt<=10) { // long press --> freq change
        freq_change();
    }
    led_debug(0);
}
 
ISR(TIMER0_OVF_vect) // iterate led
{
    led_iterator();
}
 
cs




--




반응형

'DIY > 자작 후미등' 카테고리의 다른 글

자작 후미등 - 기구편  (0) 2015.09.24
자작 후미등 - 회로편  (0) 2015.09.24
자작 후미등 Specification  (0) 2015.09.01
Comments