이번에는 꽤 유용한 콤포넌트가 PSOC5에 추가되었다.

DMA 를 사용해서 CPU에 부담이 없이, LED 메트릭스를 Dynamic Scan 방식으로 제어가능하다.
또한 PWM으로 LED 밝기 조절 기능까지 들어있고, 7-SEGMENT 와 심지어 14,16 SEGMENT 도 콘트롤할 수 있다.

저는 7-SEGMENT 와 LED 비트제어 만, 제공되는 여러 함수를 이용해서 사용해 봤는데,
14,16-SEGMENT 는 써 본적이 없네요.

아뭏든 LED를 더 많이 제어하려면, MCU 중에서 다리가 많고 싼놈으로 고르시기 바랍니다.
이 콤포넌트는 seg out 이 24개까지, com out이 8개까지 가능해서,
동시에 출력 가능한 최대 LED 갯수는 24 x 8 = 192개이다.

예전에 LED 드라이브 IC 를 4천원에 SPI/I2C 방식으로 MCU에 붙여서 사용했었는데,
포트가 좀 필요하지만 LED 드라이브 IC를 안 써도 된다. 
대신 TR을 포트 갯수 만큼 달아 줘야 하지만 가격 대 성능비는 괜찮은 것 아닌가? (IC 크기가 문제없는 곳이라면)

프로그램에서는, 제공되는 함수로 디스플레이를 바꾸고 싶을 때 한번만 레지스터를 써 주면 끝이다.
계속 타이밍에 맞춰서 출력해 줘야하는 수고스러움 없이, 관심 끄고 다른 프로그램 코딩하면 되겠다.

다음은 PSOC5 에 연결할 COMMON-Cathode 타입의 7-SEGMENT 회로도 중, 
전류를 증폭하기 위해서 사용한 TR 회로 입니다.
PNP TR 출력에 연결된 저항을 바꿔서 최대 밝기를 조절해 줄 수 있다. 
다이나믹 스캔 방식이라 저항을 너무 크게 달지 않는 것이 좋다. (크면 어둡다)
대략 51 옴 정도 달면 적당할 듯 하다. (전류가 너무 많이 흐르게 했을까요? 다시한번 확인을 해 봐야겠네요.)
오렌지 색 1608 LED가 전압강하 2.2V 이네요.
따라서 전원을 3.3V 사용시 LED를 통해 흐르는 전류를 20mA로 만들려면,
1.1V(3.3V-2.2) / 0.02 = 55 옴 으로, 전력은 55*0.02*0.02(R x I x I) = 0.022W 입니다.
즉 1/45 W 네요. ^^.

51옴 정도 달면 되겠습니다.




다음은 TR 에 연결되는 FND 와 LED 회로 입니다.



위와같이 회로는 준비 됐고, PSOC5 의 새로 생긴 콤포넌트인 LED Segment and Matrix Driver [v1.10] 을 살펴보자.
TopDesign.cysch 에, 일단 제가 다 만들어 놓은 콤포넌트를 보겠습니다.
세그먼트 출력 8개, 코먼 출력 8 개로 7-SEGMENT 7개와 8개의 LED를 제어하도록 구성했습니다.



다음은 다리가 많은 모델로 고른 PSOC5 IC 입니다. 다리는 많은데 가격은 좀 비싼 놈입니다. 제가 열전대 값을 읽으려고 20-비트 ADC가 있는 놈으로 고르다 보니 가격이 비싸져버렸네요.
저와 같은 용도가 아니면 다리가 좀 많고 가격이 싼 PSOC5를 고르는 게 좋습니다.



다음은 콤포넌트 설정입니다. 여러가지를 설정할 수 있는데, 최대 출력 개수는 segment 24, common 8개 이고,
스캔 주기도 조정할 수 있습니다. 적당히 테스트하면서 조정하면 됩니다. 
나머지 설정들은 보면 아시겠죠? (common Cathode/Anode 에 따라 드라이브 타입을 조정해 주시면 되고, 내부 클럭으로 돌릴지 외부 클럭으로 돌릴지, 밝기 조절을 할지 말지.. 등이 있습니다)



이렇게 설정을 마치고 나면 자동으로 LED 드라이브 파일이 생성되고, 우와 함수 참 다양하죠?
테스트용으로는 몇 개 안쓸 것입니다. ^^




다음은 제가 만든 코드 예제 입니다.
7개의 7-SEGMENT 에 1,2,3,4,5,6,7 이 켜지고 , LED 8개가 다음과 같이 켜질 것입니다.
실제 7-SEGMENT 와 LED가 켜진 사진을 못 올리는 것이, 맡겨 놓은 회사에서 회로를 잘못 바꿔서 최종으로 

Common-Anode 타입으로 만들어 와서 지금 설명하는 내용과 좀 다릅니다. 이해 바랍니다.





다음은 main.c 파일에 있는, 테스트용으로 제가 만든 예제 소스코드입니다. (아주 간단하게~~^^)

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
/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "project.h"
 
int main(void)
{
    LED_Driver_1_Start();
    
    CyGlobalIntEnable; /* Enable global interrupts. */
 
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    LED_Driver_1_PutChar7Seg('1',0);
    LED_Driver_1_PutChar7Seg('2',1);
    LED_Driver_1_PutChar7Seg('3',2);
    LED_Driver_1_PutChar7Seg('4',3);
    LED_Driver_1_PutChar7Seg('5',4);
    LED_Driver_1_PutChar7Seg('6',5);
    LED_Driver_1_PutChar7Seg('7',6);
    LED_Driver_1_SetDisplayRAM(0x55,7);
    
    for(;;)
    {
        /* Place your application code here. */
    }
}
 
/* [] END OF FILE */
cs



마지막으로 위의 내용에서 설명드린 것과 그대로 동작하는 프로젝트 파일을 첨부합니다.

fnd_com_K.Bundle01.zip


이전 글에 TR(MMBT3904)의 내부 다이오드를 이용해서 오도 측정하는 방법 중, 

H/W 상의 설명은 충분하다고 생각이 됩니다.
(사실 저도 정확하게 잘 모릅니다. 그냥 실제로 써 먹을 수만 있으면 된다고 생각하고 있습니다. ^^)

다이오드 온도 센싱을 위해 수학함수 쓰다가 컴파일러 오류 나서 고치고,
온도 값을 받아서 UART 에 floating point 로 출력하다가 컴파일러 오류나서 고치다 보니 한동안 멍~하네요.

이제 겨우 본론으로, 간단하게(저도 잘 모르는 관계로) 다이오드 온도측정과 열전대 온도측정에 관해서 말씀 드리겠습니다.
일단 동작은 모두 잘 됩니다.

다이오드(TR 내부의 다이오드) 온도센싱의 회로도와 열전대 회로도를 다시 한번 올려 보겠습니다.

[#1 다이오드 온도측정 회로도]





[#2 열전대 온도측정 회로도]




추가로 이번에 안 사실인데, 열전대를 거꾸로 달면 온도가 올라갈수록 전압이 낮아져서 온도가 떨어지는 것처럼 동작하더군요.
주의 : 열전대는 방향이 있습니다. 


다음은 PSOC5 의 콤포넌트를 배치하는 Topdesign.cysch 입니다.



다른 MCU와 좀 색다른 프로그램 환경이지만, 
1. Differential 20-Bit ADC 5ch 사용하고, 
2. current mode DAC 1개 , 
3. 칩내부 온도 센싱 (프로그램에서는 사용 안했음),
4. 열전대 온도 테이블 계산 콤포넌트,
5. UART 1개
를 사용했습니다.

[첨부한 예제 프로그램 설명]
Diode 로 측정된 온도를 프로그램에서는 Cold Junction Temperature 라고 부르고,
열전대로 측정한 온도를 Hot Junction Temperature 라고 부르더군요.
2개의 온도를 측정해서(물론 여러가지 처리를 합니다. sw 노이즈 필터, 열전대 테이블 보상 등등),
서로 더해주면 최종 열전대로 측정된 온도가 나옵니다.
이것을 UART로 출력 합니다.

이정도면 됐을까요? 이해 안되시면 댓글에 질문하시고, 저도 잘 모르지만 한번 해 본 것밖에 차이는 없습니다. ^^

예제 파일 첨부합니다. 


아~ 놔.. 열통 터지네. 이번에는 sprintf 함수에 아무리 float 값을 써도 이상하게 나와서 찾아보니,

이것도 컴파일러 문제일 듯 하네요. 또 라이브러리쪽에 뭘 써 넣어야 하는군요.

다음과 같이 수정하면 printf/sprintf 함수에서 floating point 값을 표시할 수 있습니다.

1. 프로젝트를 클릭하고, 다시 마우스 우클릭한 다음 Build Setting 을 클릭.




2. Linker 의 Use newlib-nano Float Format 을 True 로 고치고, 
command line 의 Custom Flags 에 -u _printf_float 라고 써 넣음.


열전대의 온도를 측정하기 위해, 다이오드로 열전대의 콘넥션 부분의 온도를 측정해야 한다.


열전대는 두 선의 상대적인 온도차를 측정하는 것이기 때문에 현재 온도값이 필요하므로,
현재 TR(MMBT3904) 안에 있는 다이오드로 온도를 측정하도록 회로를 구성하고 프로그램을 만들었다.

그런데, 다이오드 온도측정에 필요한 함수 중에 log() 라는 수학함수가 있다.
이 함수를 쓰려면 #include <math.h> 만 추가해 주면 에러가 났다.

이유야 어떻든 불편하긴 한데, 컴파일러의 문제로 생각된다.
사용자의 기술적인 문제는 아니므로, 원인을 알 필요는 없다.

이 문제를 해결하려면, 다음과 같이 하면 된다.

1. 프로젝트를 클릭하고, 다시 마우스 우클릭한 다음 Build Setting 을 클릭.




2. 아래 그림처럼 Linker 를 클릭하고 Additional Libraries 에 m 이라고 써준다.




PSOC5 는 EEPROM 테스트 관련 글이 없어서 약간 시간을 내서 글을 올려 봅니다.


물론 예제에서도 참고할 수 있는데, 예제가 너무 복잡해 보이네요.
또한 제가 사용할 때는, EEPROM 을 따로 Erase를 할 필요가 없었는데.. 
예제에서는 항상 Erase를 하고 Write를 하는게 좀 이상했습니다.

이번에 테스트한 보드는, Cypress에서 많이 파는 CY8CKIT-059 로 진행했습니다.
사용한 콤포넌트는 Port 입력 1개(TACT Switch)와 UART 만 사용했습니다.

byte(unsigned char) 타입 데이터 2개와 uint(unsigned 16 bit) 타입 데이터 2개를 스위치를 1번 누를 때마다,
1씩 증가하도록 하고 EEPROM 에 저장을 했습니다.
그리고 리셋 버튼을 누르면 EEPROM에 저장된 값을 UART 로 출력해서 EEPROM의 동작을 확인했습니다.

보드의 외형과 사용하는 포트들은 다음과 같습니다.




다음은 PSOC Creeator 의 컴포넌트 설계도입니다. (TopDesign.cysch)



다음은 실제 PSOC5 IC의 사용하는 포트입니다.






다음은 프로그램 테스트 과정입니다.

1. 처음 프로그램을 다운로드하고 UART 로 출력되는 내용 (EEPROM에 저장되는 값들을 초기화하여 Write 한다)




2. 스위치를 3번 눌러서 값을 3증가시켜서 저장하고 UART로 출력. 리셋 버튼을 눌러 EEPROM 값을 읽어 확인.




3. 전원을 OFF --> ON 해서 정말로 데이터가 남아 있는지도 확인.





psoc 소스 코드 첨부합니다.

eeprom_test.Bundle01.zip


안녕하세요, 

이 글은 예정에는 없었지만, 카페에 올린줄 알았는데 없어서 글을 쓰게 되었습니다.

PSOC5에서 micro SD-Card 를 사용하는 방법인데, PSOC5은 SDIO 가 없어서 SPI 방식만 지원합니다.
속도는 24Mhz 입니다.
제가 보기에는 현재까지 PSOC5가 MCU 중에서 가장 사용자 친화적으로 잘 만들어 진 것 같은데,
패키지가 다양하지 않고 후속 모델(PSOC6)이 안나오며, PSOC4만 계속 손데고 있어서 매우 불만이 많습니다.
가격은 요새 좀 내려간 듯 한데, STM32F4xx 에는 가성비가 못미치네요.
PSOC5 이대로 죽는겐가? ㅜㅜ

아.. 헛소리를 많이 했군요. 
그럼 다시 PSOC5에서 SPI 방식으로 SD Card 제어하는 방법을 알아보겠습니다.
PSOC Creator 의 TopDesign.cysch 에 emFile SPI Mode[V1.20] 콤포넌트를 배치하고 
emfile 콤포넌트의 Datasheet를 보면 여기서 설명하려는 내용이 영문으로 나와 있습니다.


1. PSOC Creator 내부에 File System 라이브러리가 없기 때문에 먼저 File System 라이브러리를 다운로드 받아야 합니다.

여기(링크)에서 다운로드 받으시면 됩니다.





2. 받은 파일을 압축을 풀어서 적당한 위치에 놓으십시요. (저는 프로젝트 폴더 옆에 놓았습니다)




3. 콤포넌트 창에서 Communication->FileSystem->emFile 을 TopDesign.cysch 으로 끌고 와서 배치합니다.




4. 왼쪽 Workspace Explorer 의 Project 를 우클릭하여 Build Setting 을 클릭합니다.




5. Include Directory 를 추가




6. 라이브러리 이름 추가. 직접 타이핑해 줍니다.
emf32noslfn 를 타이핑 하고, 이 의미는 No OS , Long File Name 의 의미입니다.




7. 다음은 라이브러리가 있는 디렉토리를 추가합니다.




8. 라이브러리 파일을 추가합니다.




9. 회로를 보고 핀을 배치합니다. (PSOC5는 이것이 장점 : 핀을 맘대로 옮길 수 있습니다.)
디버깅용으로 USB Serial 포트도 하나 넣었습니다.




10. micro-SD 카드 회로도는 다음과 같습니다. 신호에 굳이 풀업저항은 필요 없었습니다.
혹시나 해서 테스트 해 봤는데 잘 되네요.




11. SD 카트에서 데이터를 읽어서 뿌려볼라고 하는데, 구글링해서 "영문 텍스트 소설" 검색하니 해리포터 불의잔이 있네요. ^^
다운받아서 SD Card에 넣습니다.




12. 제작한 기판에 SD Card를 끼웁니다. 회사에서 만든 기판은 다음과 같습니다.





이제 프로그램만 짜면 되는데 불의잔을 읽어서 USB Serial로 터미날에 5000 바이트만 뿌려 보겠습니다.
먼저 결과를 올려 보겠습니다.

잘 읽히네요. 불의 잔. ^^

소스코드는 main.c 에만 코드를 추가했고, SD Card 읽기만 테스트 해 봤습니다.
나머지는 현재까지 읽기 이외의 작업이 필요없었던 관계로 회원 여러분이 찾아서 해 보십시요. ^^
프로젝트 압축해서 첨부합니다. 그런데 emfile 라이브러리는 PSOC Creator에서 한번에 압축을 안해 주네요.
아마도 4~8 과정을 회원분들께서 다시 해 주셔야 될 것 같습니다.

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
#include "project.h"
#include <stdio.h>
#include <FS.h>
 
#define BUFFER_LEN  64u
 
struct tagFILE
{
    uint8 accmd;
    uint32 sz;
    FS_FILE* fp;
    char tFileName[64];
};
 
static struct tagFILE   tFILE;
char8 *parity[] = { "None""Odd""Even""Mark""Space" };
char8 *stop[] = { "1""1.5""2" };
 
void ready_USB_UART_tx(void);
 
int main(void)
{
    uint8_t buffer[5000];
    uint16_t i;
    char usb_tx[BUFFER_LEN];
    
    
    FS_Init();
    FS_Mount(0);
    FS_FAT_SupportLFN();
    
    CyGlobalIntEnable; /* Enable global interrupts. */
 
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    
    CyDelay(500);
    
    FS_DIR*     pDir;
    USBUART_1_Start(0u, USBUART_1_3V_OPERATION);
    ready_USB_UART_tx();
 
    pDir = FS_OpenDir("");
    sprintf(tFILE.tFileName,"Harry_potter_Goblet_of_Fire.txt");
    tFILE.fp = FS_FOpen(tFILE.tFileName, "rb");
    tFILE.sz = FS_GetFileSize (tFILE.fp);
 
    sprintf(usb_tx,"File size : %5lu\n\r",tFILE.sz);
    while(USBUART_1_CDCIsReady() == 0u);    /* Wait till component is ready to send more data to the PC */ 
    USBUART_1_PutString(usb_tx);       /* Send data back to PC */
    
    FS_FSeek(tFILE.fp,0,0);
    FS_Read(tFILE.fp, buffer, 5000);
    for (i=0;i<5000;i++)
    {
        while(USBUART_1_CDCIsReady() == 0u);    /* Wait till component is ready to send more data to the PC */ 
        USBUART_1_PutChar(buffer[i]);       /* Send data back to PC */
    }
    //proc_USB_UART();
 
    for(;;)
    {
        /* Place your application code here. */
    }
}
 
void ready_USB_UART_tx(void)
{
    uint16 count;
    uint8 state,led_st=0,cnt_USB_UART_con=0;;
    uint8 buffer[BUFFER_LEN];
    char tx_buffer[BUFFER_LEN];
   /* Main Loop: */
    for(;;)
    {
        if(USBUART_1_IsConfigurationChanged() != 0u) /* Host could send double SET_INTERFACE request */
        {
            if(USBUART_1_GetConfiguration() != 0u)   /* Init IN endpoints when device configured */
            {
               /* Enumeration is done, enable OUT endpoint for receive data from Host */
                USBUART_1_CDC_Init();
            }
        }         
        if(USBUART_1_GetConfiguration() != 0u)    /* Service USB CDC when device configured */
        {
            if(USBUART_1_DataIsReady() != 0u)               /* Check for input data from PC */
            {   
                count = USBUART_1_GetAll(buffer);           /* Read received data and re-enable OUT endpoint */
                if(count != 0u)
                {
                    while(USBUART_1_CDCIsReady() == 0u);    /* Wait till component is ready to send more data to the PC */ 
                    USBUART_1_PutData(buffer, count);       /* Send data back to PC */
                    /* If the last sent packet is exactly maximum packet size, 
                    *  it shall be followed by a zero-length packet to assure the
                    *  end of segment is properly identified by the terminal.
                    */
                    if(count == BUFFER_LEN)
                    {
                        while(USBUART_1_CDCIsReady() == 0u); /* Wait till component is ready to send more data to the PC */ 
                        USBUART_1_PutData(NULL, 0u);         /* Send zero-length packet to PC */
                    }
                }
            }  
            
            state = USBUART_1_IsLineChanged();              /* Check for Line settings changed */
            if(state != 0u)
            {  
                if(state & USBUART_1_LINE_CODING_CHANGED)   /* Show new settings */
                {
                    sprintf(tx_buffer,"BR:%4ld,DB:%d\n\r",USBUART_1_GetDTERate(),(uint16)USBUART_1_GetDataBits());
                    sprintf(tx_buffer,"SB:%s,Parity:%s\n\r", stop[(uint16)USBUART_1_GetCharFormat()], \
                                                         parity[(uint16)USBUART_1_GetParityType()]);
                }
 
                if(state & USBUART_1_LINE_CONTROL_CHANGED)  /* Show new settings */
                {   
                    state = USBUART_1_GetLineControl();
                    sprintf(tx_buffer,"DTR:%s,RTS:%s\n\r",  (state & USBUART_1_LINE_CONTROL_DTR) ? "ON" : "OFF", \
                                                        (state & USBUART_1_LINE_CONTROL_RTS) ? "ON" : "OFF");
                    cnt_USB_UART_con++;
                    
                    if (cnt_USB_UART_con > 1)
                        break;
                }
            }
        }
    }   
}
 
cs


emFile_V322c.zip

sd_card_test.zip


안녕하세요.


회사를 옮기면서 쓰게될 프로세서를 소개합니다.

이 프로세서(Psoc-5LP)는 ARM Cortex-M3계열로서,
특이점은 OP-AMP 와 ADC, ASIC을 Microcontroller와 조합해서 사용한다는 점입니다. 
This type of system is different from most mixed-signalembedded systems, which use a combination of amicrocontroller unit (MCU) and external analog and digitalperipherals, such as opamps, ADCs, and applicationspecificintegrated circuits (ASICs). 

다른 일반적인 MCU는 정해진 핀의 기능중 선택해서 사용하는 방식이나, 이 MCU(psoc 5LP)는 ASIC 회로를 꾸미고 핀에 붙이고 조합해서 씁니다. 예를 들어 디지탈 필터니 카운터, 디지탈 플립플롭들을 ASIC하듯이 회로도처럼 설계하여 MCU핀에 붙이면
외부에 Logic IC를 쓴 것과 같은 효과가 있습니다.
이 점이 저한테는 굉장히 특이하더군요.

컴파일러는 Cypress에서 제공하는 Psoc Creator 3.1을 사용합니다.
현재 공부를 진행 중인데, 왠만한 기능들이 라이브러리화되어 제공되고 라이브러리에서
회로도 툴(Orcad 와 비슷)처럼 부품을 빼서 그리면 기본 소스 코드가 생성됩니다.

공부를 진행하면서 시리즈로 올려볼까 합니다.

현재는 아직 프로그램 다운로드나 컴파일도 서툽니다. ^^





+ Recent posts