ARM TechCon 2016 전시회 참관 후기

Posted by 카이젠8501 카이젠8501
2016.11.03 16:55 IT 개발/기타

ARM TechCon 2016 전시회 참관 후기

전시회장에는 크게 ARM 부스와 mbed 부스로 나누어져 있었고, 나머지 기업들의 부스는 작게 분포 되어 있었습니다. mbed 부스에는 WIZwiki-W7500ECO가 전시되어 있었습니다.
(가장 아랫줄 4번째에 위치해 있는 WIZwiki-W7500ECO 보드)

Techcon_01

전시회는 ARM과 협력하는 업체들로 구선되어 있었는데, 크게 SoC(Cadence, Synopsis 등), 소프트웨어 IDE(IAR 등), ARM 코어로 칩을 제작하는 회사(NXP, Renesas) 그리고 OS 및 클라우드(WIND River 등) 업체가 주를 이루었고 기타 대리점(Mouser)들이 있었습니다.

Multitech

우리가 중점적으로 주목한 곳은 mbed 부스였습니다. 먼저 커다란 화분 같이 생긴 부스가 눈에 띄었고 해당 부스로 발걸음을 옮겼습니다. 아래 그림에 있는 WaterBit이라는 이름의 제품은 Multitech라는 업체에서 mbed 플랫폼을 사용하여 만든 Prototype 제품이었습니다. 본 제품은 스마트 화분이고 Multitech에서 만든 게이트웨이와 클라우드 서비스를 이용하여 서비스를 제공합니다. 게이트웨이는 LoRa부터 Ethernet까지 각종 토신들을 원하는 대로 교체 장착 할 수 있게 되어 있었습니다.

Techcon_02

기타 mbed 부스

그리고 나서 옆에 mbed 부스들을 돌아보았는데, 전체적으로 우리가 지금까지 해왔던 펜타코드들과 크게 다르지 않았습니다. IoT 솔루션이라고 부르는 것들 모두 센서 그리고 클라우드 서비스로의 연결 범주를 벗어나지 않았습니다. 하지만 mbed에서 내세우고 강조하는 것은 mbed OS이며 이 OS 기반으로 모든 서비스와 어플리케이션이 가능하다는 점을 강조하는 것을 알수 있었습니다. 우리가 mbed 플랫폼을 제대로 이용하고 mbed Eco system과 융화 되기 위해서는, mbed OS는 선택이 아닌 필수가 될지도 모르겠다는 생각이 들었습니다. mbed 클라우드 또한 mbed OS 기반이었고 TLS 등의 Security 관련한 것들 또한 마찬가지였습니다.

다음은 mbed 전시회를 둘러보며 인상적이었던 것들을 소개 하겠습니다.

아래 그림의 Hexiwear는 NXP에서 나온 Smart Multimedia 개발 킷으로, 메인 제품에 도킹보드를 가지고 여러 가지 도킹 쉴드를 장착해 Wearable 기기들을 개발 할 수 있습니다. 초기에는 FreeRTOS와 Kinetics SDK로 개발환경이 구성되었지만 지금은 mbed Os 5로 변경되었다고 합니다.

Techcon_11

OpenAIS와 mbed-client, mbed OS를 이용하여 만든 원격으로 불을 On/Off 하는 Prototype과 스마트 팩토리 관련 Prototype 입니다.

Techcon_12

아래 그림은 작은 오락기( Tiny Arcade)이며, mbed 클라우드를 체험해 볼 수 있는 부스도 마련되어 있었습니다.

Techcon_13

저희 회사에 반가운 아두이노 부스도 볼 수 있었습니다. 아무래도 최근 아두이노 진영에서도 Cortex 계열 및 Linux를 위한 보드들이 많아 지면서 ARMTech Con에서 홍보를 하는게 아닌가라는 생각을 하였습니다. 오른쪽 사진은 Snap4Arduino라는 프로그램으로, 저희가 아는 스크래치 프로그램과 유사한 프로그램으로 소프트웨어 뿐 아니라 하드웨어 컨트롤이 가능하도록 개발된 프로그램입니다. Snap 쥬얼 프로그래밍 언어를 사용하여 쉽게 아두이노 보드를 컨트롤 할 수 있도록 개발된 것으로, 거의 모든 아두이노 보드를 지원하며 자동 환경 구성을 제공합니다. ( 참고로 무료이며, 한국어 지원이 가능합니다. )

Techcon_14

WindRiver

전시회장을 둘러보고 마지막으로 WindRiver 부스에 방문하였습니다. 아래 글은 WindRiver 기업을 소개하기 위한 페이지에 있는 글입니다. 글에 따르면 인텔의 자회사로 네트워크, 디지털 가전, 산업 및 자동화, 항공우주 및 방위산업, 모바일, 자동차 관련 부분 등 임베디드 관련 분야를 사업영역으로 하며 RTOS와 임베디드 리눅스 분야에서 인정 받고 있는 기업이라고 합니다.

임베디드 및 모바일 소프트웨어 분야에서 세계 시장을 선도하고 있는 윈드리버는 인텔의 자회사로 네트워크, 디지털 가전, 산업 및 자동화, 항공우주 및 방위산업, 모바일, 자동차 관련 부분 등 임베디드 기술이 필요한 거의 모든 분야를 사업 영역으로 하고 있습니다. 1981년부터 지난 30년간 임베디드 장비 내부의 컴퓨팅 환경 개선을 위해 노력해 왔으며 그 기술은 5억 개 이상의 제품에 적용되어 왔습니다.
 임베디드 소프트웨어 중에서도 OS분야에 있어서 강한 두각을 나타내고 있는 윈드리버는 글로벌 시장 조사 기관인 VDC 리서치 그룹이 발표한 2012년 “임베디드/실시간 운영 시스템”보고서에서 시장을 주도해 온 리더 기업으로 선정된 바 있습니다. 이 보고서에 따르면 윈드리버는 실시간 운영 시스템, RTOS 분야에 있어서 ‘VxWORKS’관련 제품 및 서비스를 통해 전세계 시장 매출의 40%이라는 기록적인 점유율을 달성했으며, 리눅스 플랫폼 및 관련 솔루션으로 전체 시장 매출액의 50 % 이상을 차지하면서 임베디드 리눅스 시장에서도 연속 4년째 리더 기업으로 인정받아 왔습니다. 윈드리버의 이와 같은 경이로운 시장 점유율은 2위 기업의 2배에 달하는 것으로 나타나 독보력인 리더십을 증명했다고 할 수 있습니다. 
또한 최근 주목 받고 있는 안드로이드 분야에서도 매우 활발한 활동을 벌이고 있는데, 윈드리버는 구글의 OHA(Open Handset Alliance) 창립 멤버로서 고객들이 실제적으로 시장에 영향력있는 모바일 제품을 출시할 수 있도록 강력한 안드로이드 서비스 비즈니스를 성공적으로 구축해 왔습니다. 뿐만 아니라 영향력 있는 다양한 오픈 소스 프로젝트 참여를 비롯해 모바일 기술 발전에도 많은 공헌을 하고 있습니다. 
아울러 윈드리버는 GENIVI 연합의 창립멤버로 GENIVI 플랫폼과 안드로이드 등 다양한 리눅스 기반의 자동차 플랫폼 분야에서도 영향력을 발휘하고 있습니다.

ARM TechCon 부스에서는 VxWORKS라는 RTOS와 HELIX라는 클라우드 시스템을 소개 하고 있었습니다. VxWORKS는 Cortex A, M, R에서 동작 할 수 있다고 설명 되었으나, CortexM0/M0+급의 MCU에서는 WindRiver Rocket이라는 RTOS를 사용하라고 권유 받았습니다. 현재 WindRiver Rocket은 Zephyr라는 새로운 이름의 프로젝트로 서비스 하고 있습니다.

Techcon_15

WindRiver의 서비스들을 이용하기 위한 SDK를 제공하고 있었으며, 아래 그림과 같이 특정 플랫폼에 대한 템플릿 예제와 온라인 컴파일러들을 제공함으로써 마치 ARM mbed와 같은 생태계를 만들려고 하는 것 처럼 보였습니다. 현재 SDK List에는 대부분 리눅스급의 퍼포먼스를 요구하는 디바이스들이 등록되어 있고, Cortex계열은 Freescale Freedom K64F 가 유일합니다. 하지만 이 보드 역시 Cortex M4 급으로 우리 칩 W7500/W7500P이 해당 SDK 리스트에 등록 가능한지는 조금 더 검토가 필요 할 것 같습니다.

Techcon_16

현재는 WindRiver 담당자에게 연락처를 남겨 놓은 상태이고, 해당 담당자를 통해 저희 보드가 WindRiver SDK 리스트에 등록하기 위해서는 어떤 절차가 필요한지 문의 해 놓은 상태 입니다


저작자 표시
신고
이 댓글을 비밀 댓글로

mbed connect 2016 참관 후기

Posted by 카이젠8501 카이젠8501
2016.11.03 16:42 IT 개발/기타

mbed connect

mbed connect 일정동안 keynote 발표를 들으면서, ARM이 강조하고 싶은 2 Keyword는 mbed os, Security 라는 생각이 들었습니다.

특히 아래 그림에서 볼 수 있듯이, ARM에서는 TrustZone 기능이 추가/보완 된 ARM-v8M 아키텍쳐 기반의 H/W를 사용하고 그 위에 mbed os 를 S/W로 사용하면 보안에 강력한 임베디드 디바이스를 구성 할 수 있다고 설명하고 있습니다.

01_mbedconnect

Security

현재 보안이 매우 중요해지고 있음에도 불구하고, 소형 임베디드 디바이스는 제한적인 보호 상태이거나, 개발자에게 높은 전문 기술 지식을 요구하는 소프트웨어 관리 보안 시스템에만 의존하고 있는 상황이라고 합니다. 이에 마이크 뮬러(Mike Muller) ARM 최고기술책임자(CTO)는 ARMv8-M에 구현된 하드웨어 아키텍처 보안을 적용시킴으로써 훨씬 더 쉽게 보안을 구축하고 효율적으로 실행할 수 있도록 도울 수 있다고 설명하였습니다.

ARMv6-M & ARMv7-M 대비 ARMv8-M의 특징은 아래와 같습니다. 아직까지는 ARMv8-M 아키텍처 기반의 Core(예, Cortex-M0,M0+ ….)는 존재하지 않으나, Cortex-M0,M0+와 대응되는 제품군을 ARMv8-M baseline으로 Cortex-M3,M4,M7과 대응되는 제품군을 ARMv8-M mainline으로 전환 할 것으로 보입니다.

02_mbedconnect

기존 아키텍처(ARMv6-M,ARMv7-M)와 가장 큰 특징적인 차이는 ARM TrustZone 기능의 추가 이며, TrustZone은 여러 방식으로 변이되는 소프트웨어 공격 및 일반 하드웨어 공격을 막아 낼 수 있는 향상된 기술을 저렴한 비용으로 구현하기 위해 개발 되었다고 합니다.
TrustZone은 아래 그림과 같이 Non-secure state(RTOS와 Application)와 암호화 및 Key 매지니먼트, 무결성 검사와 같은 민감한 작업을 처리하는 Secure state 사이에 독립성을 제공합니다.

03_mbedconnect

이 아키텍처의 가장 큰 핵심은 별도의 보안 구역(trusted)을 만들어 이 안에서 작업을 한 후 정보를 박스에 넣고 열쇠를 채워 비신뢰 보드로 넘기게 되는데, 이 비신뢰 모드에서는 이 박스가 어떻게 생겼고 열쇠가 어떻게 잠겼으며 그 안에 어떤 내용이 채워져 있는지 볼 수 없게 하는 방식 입니다.

간단하게 정리하면, ARM은 ARMv8-M 아키텍처를 사용하여 SoC 레벨에서 Security를 위한 기능을 제공하고 있으며 기존 Software 레벨에서 제공하는 보안 기술(ex, SSL/TLS)와 같이 사용하여 보다 더 강화된 보안을 보다 더 쉽게 사용 할 수 있다고 강조 하고 있습니다.

하지만 아직 ARMv8-M 아키텍처를 이용한 Core가 시중에 나와 있지 않은 관계로, 위즈네트에서는 조금 더 시간을 가지고 ARMv8-M 아키텍처를 사용한 Core들의 동향을 지켜 봐야 할 것 같습니다.

mbed OS

이전 mbed OS 2(“Classic”), mbed OS 3 (“Eventing OS”)와 비교하여 가장 큰 차이점은, mbed OS 5에는 RTOS, connectivity, security component가 maintenance core로 포함되었다는 것입니다. 이전에는 분리 되어 있던 Network Stack과 mbed cloud client가 포함되고, 보안을 위한 mbed TLS, Security APIs(mbed uVisor)가 추가 된 것을 볼 수 있습니다.
Network Stack에는 Ethernet, BLE, Wi-Fi, 6LoWPAN, Thread 등이 있습니다.

05_mbedconnect

mbed OS 또한 Security를 강조하고 있으며, 이를 반영하기 위해 mbed OS의 구조를 조금씩 업그레이드 하고 있음을 확인 하였습니다. 앞에서 설명한 내용은 Hardware(SoC) 측면에서 보안 기술을 적용하는 반면, mbed OS는 mbed TLS, mbed uVisor를 이용하여 Software 측면에서 보안 기술을 개발하고 적용하였습니다.

04_mbedconnect

mbed OS에서는 Security code compartment, Communication security, Lifecycle security로 나누어서 IoT 단말의 보안을 관리 합니다.

06_mbedconnect

Security code compartment ( uVisor )

먼저 Security code compartment를 위해서는 uVisor라는 기술을 사용하는데, mbed uVisor는 OS에서 가장 하위 계층에 위치하며, MPU(Memory Protection Unit)을 통해 Cortex-M3, M4, M7 Core 상에 ‘boxes’라고 명 명하는 격리된 보안 영역(예, 샌드박스)을 생성하는 일종의 하이퍼바이저 로써 기기 자체 보호 기능 입니다.

uVisor의 주요 기능은 ACLs(Access Control Lists)이며, 아래 그림을 보면 ACLs의 개념을 쉽게 이해 할 수 있습니다. User는 uVisor를 통해 Application 혹은 Task를 Box로 묶어서 관리 할 수 있고, 해당 Box만 접근 할 수 있는 MCU의 Peripheral 들을 지정 할 수 있습니다. 예를 들어 User가 Box1이라고 지정한 Application에서는 Timer와 UART만 사용할 수 있도록 설정해 놓았는데, Flash나 I2C와 같은 Peripheral을 사용하려면 Memory Fault와 같은 Error를 발생시켜 OS 내에 악성코드나 외부의 공격 코드로부터 훼손된 시스템 컴퍼넌트, 드라이버로 부터 Box를 보호 할 수 있다는 개념입니다.

08_mbedconnect

Communication Security

SSL은 안전하지 않은 데이터를 암호화 하여 안전하게 전달하기 위해 사용 합니다. SSL 버전 1은 실제로 발표 되지 않았었고, SSL 버전 2가 공개 적으로 발표되었는데 많은 보안 취약점이 있었다고 합니다. 그래서 그것을 보완한 버전이 SSL 버전 3이며 공식적으로 표준화 한 이름이 TLS 입니다. 이를 같이 묶어서 SSL/TLS라고 부릅니다.
mbed에서는 mbedTLS를 지원 함으로써 데이터를 암호화 하여 송/수신 할 수 있는 기능을 제공하고 있습니다.

Lifecycle Security

mbed cloud client에서는 Key Value, Device ID 및 특정 설정 값들을 이용하여 Device의 상태를 관리 하거나 제어 할 수 있는 기능을 제공합니다. 또한 Device의 Firmware도 원격에서 Upgrade 및 Downgrade 하는 기능도 제공합니다.

Conculution

mbed OS를 사용하여 mbed에서 추구하는 보안 기능을 사용하기에는 W7500, W7500P의 한계를 확인 할 수 있었습니다. 우선 Cortex M0/M0+에서는 MPU(Memory Protected Unit)을 지원하지 않기 때문에 Secure code를 보장하기 위한 uVisor 기능을 사용할 수 없습니다.
또한 W7500, W7500P는 RAM size가 부족하여 mbed TLS와 같은 Communication Security의 사용도 어려운 것으로 판단 됩니다.

IoT 서비스가 활성화 되면서 경량 기기에 대한 다양한 기능적 요구가 증가함에 따라 OS 운영이 불가피하게 되었고, 인터넷 연결 특성으로 인한 보안 위협에 대한 대비도 강조되고 있습니다. 이에 위즈네트는 mbed OS와 mbed Security 및 mbed 이외의 다른 RTOS 및 Security를 사용할 수 있을 만큼의 퍼포먼스를 가진 MCU 라인업을 구축 하기 위한 방안을 장기적으로 고려 해 봐야 될 것 같습니다.

그래도 Connectivity 쪽으로 접근하면 희망적으로 WIZnet과 ARM mbed가 공생할 수 있는 포인트들이 있다고 생각합니다. 예를 들어, ST, Freescale 등 다른 회사의 MCU에 mbed OS를 사용하고 Wi-Fi 및 Ethernet Interface를 사용하고 싶은 경우 WizFi250/WizFi310 및 WIznet의 Ethernet Module들을 활용 할 수 있도록 가이드 할 수 있습니다.

단, 위의 모듈들이 mbed OS를 활용하는 고객들을 만족시키기 위해서는, WIZnet 모듈에 대한 mbed OS 라이브러리 지원 및 유지 보수 작업에 지금 보다 더 많은 시간을 투자 해야 한다고 생각합니다.
( *참고 : 이미 WizFi250과 Ethernet Module을 mbed platform 에서 사용할 수 있도록 라이브러리나 드라이버가 준비되어 있지만, 이는 상위 버전(ex, mbed OS5)과 호환이 안됨. 즉, mbed OS5를 위한 갱신된 라이브리 필요. )


참고자료 

- http://aqwerf.tistory.com/12

- http://www.insightsemicon.com/news/article.html?no=128289

- http://m.autoelectronics.co.kr/article/articleView.asp?idx=1904

- https://gigglehd.com/zbxe/newsreport/13542447

- http://blog.daum.net/_blog/BlogTypeView.do?blogid=0Idbt&articleno=7593753&categoryId=404972&regdt=20151005145502




저작자 표시
신고
이 댓글을 비밀 댓글로

W7500 mbed SDK Porting Guide (6/6)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:04 IT 개발/mbed

W7500 mbed SDK Porting Guide

ADC Porting

예제 코드

#include "mbed.h"

int main() {

    Serial pc(USBTX, USBRX); // tx, rx
    pc.baud(115200);
    AnalogIn ain(A0); //is ADC0_0: must be channel 0 of ADC0 or ADC1

    pc.printf("Starting program...\r\n");

    while(1)
    {
        pc.printf("percentage: 3.3f\r\n", ain.read() * 100.0f);
        pc.printf("normalized: 0x%04X\r\n", ain.read_u16());
        wait(1);
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.

  • api/AnalogIn.h

targets/hal/TARGET_WIZNET/TARGET_W7500x/analogin_api.c

특이사항
  • WIZWiki Board의 ADC Pin은 ADC_CH0, ADC_CH1, ADC_CH2, ADC_CH3, ADC_CH4, ADC_CH5만 사용함
  • analogin_read 함수는 출력되는 analog 값을 0 ~ 1 사이의 값으로 modulation 함
  • analgoin_read_u16 함수는 출력되는 analog 값을 16bit로 읽어 옴

ADC_TypeDef * AdcHandle;

int adc_inited = 0;

void analogin_init(analogin_t *obj, PinName pin)
{
    // Get the peripheral name from the pin and assign it to the object
    obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);

    MBED_ASSERT(obj->adc != (ADCName)NC);

    // Configure GPIO
    pinmap_pinout(pin, PinMap_ADC);

    // Save pin number for the read function
    obj->pin = pin;

    // The ADC initialization is done once
    if (adc_inited == 0) {
        adc_inited = 1;

        ADC_Init();
    }
}

static inline uint16_t adc_read(analogin_t *obj)
{
    ADC_CH adc_ch;

    switch (obj->pin) {
        case PC_15:
            adc_ch = ADC_CH0;
            break;
        case PC_14:
            adc_ch = ADC_CH1;
            break;
        case PC_13:
            adc_ch = ADC_CH2;
            break;
        case PC_12:
            adc_ch = ADC_CH3;
            break;
        case PC_11:
            adc_ch = ADC_CH4;
            break;
        case PC_10:
            adc_ch = ADC_CH5;
            break;
        default:
            return 0;
    }

    ADC_ChannelSelect(adc_ch);
    ADC_Start();

    // Wait end of conversion and get value
    while(ADC_IsInterrupt());
    return ADC_ReadData();
}

uint16_t analogin_read_u16(analogin_t *obj)
{
    uint16_t value = adc_read(obj);
    // 12-bit to 16-bit conversion
    return value;
}

float analogin_read(analogin_t *obj)
{
    uint16_t value = adc_read(obj);

    return (float)value * (1.0f / (float)0xFFF); // 12 bits range
}


저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

How to use pyOCD for new target MCU like W7500  (0) 2015.10.08
WIZwiki_W7500 CMSIS-DAP Porting  (0) 2015.10.08
W7500 mbed SDK Porting Guide (6/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed SDK Porting Guide (5/6)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:03 IT 개발/mbed

W7500 mbed SDK Porting Guide

I2C Master Porting

예제 코드

선택 영역_027.png

int main() {
    int address = 0xA0;
    char tx_data[27] = {0x00, 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,
                        0x08, 0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
                        0x10, 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18};
    char rx_data[22]={0};

    I2C i2c(I2C_SDA, I2C_SCL);

    i2c.start();
    i2c.write(address,tx_data,9);

    wait(1);

    i2c.start();
    i2c.write(address,0x00,1,true);

    i2c.read(address,rx_data,27);

    for(int i=0;i<22;i++)
    {
        //pc.printf("Data[%d]: %x\r\n",i, rx_data[i]);
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.

  • api/I2C.h
  • common/I2C.cpp

targets/hal/TARGET_WIZNET/TARGET_W7500x/i2c_api.c

  • i2c 초기화 및 frequency 설정을 위한 함수
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
{
    // Determine the I2C to use
    I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
    I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);

    obj->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
    MBED_ASSERT(obj->i2c != (I2CName)NC);

    // Enable I2C1 clock and pinout if not done
    if ((obj->i2c == I2C_0) && !i2c0_inited) {
        i2c0_inited = 1;
        // Configure I2C pins
        pinmap_pinout(sda, PinMap_I2C_SDA);
        pinmap_pinout(scl, PinMap_I2C_SCL);
        pin_mode(sda, OpenDrain);
        pin_mode(scl, OpenDrain);
    }

    // Enable I2C2 clock and pinout if not done
    if ((obj->i2c == I2C_1) && !i2c1_inited) {
        i2c1_inited = 1;
        // Configure I2C pins
        pinmap_pinout(sda, PinMap_I2C_SDA);
        pinmap_pinout(scl, PinMap_I2C_SCL);
        pin_mode(sda, OpenDrain);
        pin_mode(scl, OpenDrain);
    }

    // Reset to clear pending flags if any
    i2c_reset(obj);

    // I2C configuration
    i2c_frequency(obj, 100000); // 100 kHz per default
    obj->is_setAddress = 0;
}

void i2c_frequency(i2c_t *obj, int hz)
{
    MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    // wait before init
    I2C_ConfigStruct conf;

    conf.mode = I2C_Master;
    conf.master.timeout = LONG_TIMEOUT;

    // Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0
    switch (hz) {
        case 100000:
            conf.master.prescale  = 0x61;      // Standard mode with Rise Time = 400ns and Fall Time = 100ns
            break;
        case 400000:
            break;
        case 1000000:
            break;
        default:
            break;
    }

    // I2C configuration
    I2C_Init(I2cHandle, conf);
}
특이사항
  • W7500 I2C 구조적인 차이로 i2c_start 시, i2c start signal을 내보내지 않음.
    • W7500은 I2C start signal을 설정하기 전에 Slave Address를 미리 저장하고 있어야 함.
  • 위 문제를 해결하기 위해, read/write 함수에서 Slave Address의 유/무를 확인하여 I2C Start Signal을 송신 함.
inline int i2c_start(i2c_t *obj)
{
    obj->is_setAddress = 0;

    return 0;
}

inline int i2c_stop(i2c_t *obj)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    // Generate the STOP condition
    I2C_Stop(I2cHandle);
    I2C_Reset(I2cHandle);
    obj->is_setAddress = 0;

    return 0;
}

int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);
    int count;
    int value;

    if(!obj->is_setAddress)
    {
       if( I2C_Start(I2cHandle, address, I2C_READ_SA7) == ERROR )
        {
            return -1;
        }
       obj->is_setAddress = 1;
       obj->ADDRESS = address;
    }
    else
    {
        I2C_Restart_Structure(I2cHandle, address, I2C_READ_SA7);
        obj->ADDRESS = address;
    }

    // Read all bytes
    for (count = 0; count < (length-1); count++) {
        if( (value = i2c_byte_read(obj, 0)) == -1) return value;
        data[count] = (char)value;
    }

    if(stop){
        if( (value = i2c_byte_read(obj, 1)) == -1) return value;
        data[count] = (char)value;
    }
    else{
        if( (value = i2c_byte_read(obj, 0)) == -1) return value;
        data[count] = (char)value;
    }

    return count;
}

int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);
    int count;

    if(!obj->is_setAddress)
    {
       if( I2C_Start(I2cHandle, address, I2C_WRITE_SA7) == ERROR )
        {
            return -1;
        }
       obj->is_setAddress = 1;
       obj->ADDRESS = address;
    }
    else
    {
        I2C_Restart_Structure(I2cHandle, address, I2C_WRITE_SA7);
        obj->ADDRESS = address;
    }

    for (count = 0; count < length; count++) {
        i2c_byte_write(obj, data[count]);
    }

    // If not repeated start, send stop
    if (stop) {
        i2c_stop(obj);
    }

    return count;
}

int i2c_byte_read(i2c_t *obj, int last)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    return I2C_ReceiveData(I2cHandle, last);
}

int i2c_byte_write(i2c_t *obj, int data)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);
    return I2C_SendDataAck(I2cHandle,(uint8_t)data);
}

void i2c_reset(i2c_t *obj)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    I2C_Reset(I2cHandle);
}


저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

WIZwiki_W7500 CMSIS-DAP Porting  (0) 2015.10.08
W7500 mbed SDK Porting Guide (6/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed SDK Porting Guide (4/6)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:02 IT 개발/mbed

W7500 mbed SDK Porting Guide

wait Dealy Porting

예제 코드

#include "mbed.h"

int main()
{
    Serial pc(USBTX, USBRX);
    DigitalOut myled(LED1);

    pc.baud(115200);
    pc.printf("TEST Start\r\n");

    myled = 0;
    while(1){
        pc.printf("LED ON\r\n");
        myled = 1; // LED is ON
        wait(1); // 1 sec
        pc.printf("LED OFF\r\n");
        myled = 0; // LED is OFF
        wait(1); // 1 sec
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.
GPIO Porting시 사용하는 아래 파일들은 수정할 필요가 없다.

  • api/wait_api.h
  • common/wait_api.c

common/wait_api.c

  • 아래 함수를 수정 할 필요는 없으나 wait 함수 동작을 위해 함수 구현부를 정리 하였다.
  • wait_us()에서는 PWM의 Counter 값을 읽고 함수가 시작했을 때의 Counter 값의 차이가 원하는 Delay 시간이 될 때 까지 Polling으로 기다림
void wait(float s) {
    wait_us(s * 1000000.0f);
}

void wait_ms(int ms) {
    wait_us(ms * 1000);
}

void wait_us(int us) {

    uint32_t start = us_ticker_read();
    while ((us_ticker_read() - start) < (uint32_t)us);
}

targets/hal/TARGET_WIZNET/TARGET_W7500x/us_ticker.c

  • 1us의 counter를 사용하기 위해 PWM을 아래와 같이 설정 함
// 32-bit timer selection
#define TIM_MST PWM_CH7

//static TIM_HandleTypeDef TimMasterHandle;
static PWM_TimerModeInitTypeDef TimMasterHandle;
static int us_ticker_inited = 0;

void us_ticker_init(void)
{
    if (us_ticker_inited) return;
    us_ticker_inited = 1;

    TimMasterHandle.PWM_CHn_PR = (GetSystemClock() / 1000000) -1;
    TimMasterHandle.PWM_CHn_LR = 0xFFFFFFFF;
    TimMasterHandle.PWM_CHn_PDMR = 1;

    PWM_TimerModeInit(TIM_MST, &TimMasterHandle);
    PWM_CHn_Start(TIM_MST);
}

uint32_t us_ticker_read()
{
    if (!us_ticker_inited) us_ticker_init();

    return TIM_MST->TCR;
}


저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

W7500 mbed SDK Porting Guide (6/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 1/6 )  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed porting Guide ( 3/6 )

Posted by 카이젠8501 카이젠8501
2015.10.08 15:01 IT 개발/mbed

W7500 mbed SDK Porting Guide

Serial Porting

예제 코드

#include "mbed.h"

int main()
{
    Serial pc(USBTX, USBRX);

    pc.baud(115200);
    pc.printf("TEST Start\r\n");

    while(1){
        pc.printf("LED ON\r\n");
        wait(1); // 1 sec
        pc.printf("LED OFF\r\n");
        wait(1); // 1 sec
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.
GPIO Porting시 사용하는 아래 파일들은 수정할 필요가 없다.

  • api/Serial.h
  • api/SerialBase.h
  • common/Serial.cpp
  • common/SerialBase.cpp

targets/hal/TARGET_WIZNET/TARGET_W7500x/TARGET_WIZwiki_W7500/PeripheralPins.c

  • UART 사용 시 필요한 RX, TX Pin 정보를 저장
  • 상위 어플리케이션에서는 PA_14라는 Pin 정보만 줘도 아래 PinMap으로 UART0의 TX Pin을 설정 할 수 있음
//*** SERIAL ***
const PinMap PinMap_UART_TX[] = {
    {PA_14, UART_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {PC_2,  UART_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {NC,    NC,     0}
};

const PinMap PinMap_UART_RX[] = {
    {PA_13, UART_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {PC_3,  UART_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {NC,    NC,     0}
};

targets/hal/TARGET_WIZNET/TARGET_W7500x/serial_api.c

  • Serial 객체 생성 및 사용 시, Serial.cpp와 SerialBase.cpp를 통해 아래 코드 수행
static void init_uart(serial_t *obj)
{
    UART = (UART_TypeDef *)(obj->uart);
    UART_InitStructure.UART_BaudRate            = obj->baudrate;
    UART_InitStructure.UART_WordLength          = obj->databits;
    UART_InitStructure.UART_StopBits            = obj->stopbits;
    UART_InitStructure.UART_Parity              = obj->parity;
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;


    if (obj->pin_rx == NC) {
        UART_InitStructure.UART_Mode = UART_Mode_Tx;
    } else if (obj->pin_tx == NC) {
        UART_InitStructure.UART_Mode = UART_Mode_Rx;
    } else {
        UART_InitStructure.UART_Mode = (UART_Mode_Rx | UART_Mode_Tx);
    }

    UART_Init(UART,&UART_InitStructure);
}

void serial_init(serial_t *obj, PinName tx, PinName rx)
{
    // Determine the UART to use (UART_1, UART_2, ...)
    UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
    UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);

    // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
    obj->uart = (UARTName)pinmap_merge(uart_tx, uart_rx);

    MBED_ASSERT(obj->uart != (UARTName)NC);

    // Enable USART clock
    if (obj->uart == UART_0) {
        obj->index = 0;
    }

    if (obj->uart == UART_1) {
        obj->index = 1;
    }

    // Configure the UART pins
    pinmap_pinout(tx, PinMap_UART_TX);
    pinmap_pinout(rx, PinMap_UART_RX);
    if (tx != NC) {
        pin_mode(tx, PullUp);
    }
    if (rx != NC) {
        pin_mode(rx, PullUp);
    }

    // Configure UART
    obj->baudrate = 9600;
    obj->databits = UART_WordLength_8b;
    obj->stopbits = UART_StopBits_1;
    obj->parity   = UART_Parity_No;

    obj->pin_tx = tx;
    obj->pin_rx = rx;


    init_uart(obj);

    // For stdio management
    if (obj->uart == STDIO_UART) {
        stdio_uart_inited = 1;
        memcpy(&stdio_uart, obj, sizeof(serial_t));
    }
}

void serial_baud(serial_t *obj, int baudrate)
{
    obj->baudrate = baudrate;
    init_uart(obj);
}

void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
{
    if (data_bits == 7) {
        obj->databits = UART_WordLength_7b;
    } else {
        obj->databits = UART_WordLength_8b;
    }

    switch (parity) {
        case ParityOdd:
        case ParityForced0:
            obj->parity = UART_Parity_Odd;
            break;
        case ParityEven:
        case ParityForced1:
            obj->parity = UART_Parity_Even;
            break;
        default: // ParityNone
            obj->parity = UART_Parity_No;
            break;
    }

    if (stop_bits == 2) {
        obj->stopbits = UART_StopBits_2;
    } else {
        obj->stopbits = UART_StopBits_1;
    }

    init_uart(obj);
}


/******************************************************************************
 * READ/WRITE
 ******************************************************************************/

int serial_getc(serial_t *obj)
{
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);
//    while(!serial_readable(obj));
    while(uart->FR & UART_FR_RXFE);

    return (uart->DR & 0xFF);
}

void serial_putc(serial_t *obj, int c)
{
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);

    uart->DR = (uint32_t)(c & (uint16_t)0xFF);
    while(uart->FR & UART_FR_BUSY);
}

int serial_readable(serial_t *obj)
{
    int status;
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);
    // Check if data is received
    status = ((uart->FR & UART_FR_RXFE) ? 0: 1);
    return status;
}

int serial_writable(serial_t *obj)
{
    int status;
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);
    // Check if data is transmitted
    status = ((uart->FR & UART_FR_BUSY) ? 0: 1);
    return status;
}
저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 1/6 )  (0) 2015.10.08
mbed rpc interfacing with Python  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed porting Guide ( 2/6 )

Posted by 카이젠8501 카이젠8501
2015.10.08 15:00 IT 개발/mbed

W7500 mbed SDK Porting Guide

GPIO Porting

예제 코드

#include "mbed.h"

////MBED Example 1 LED CONTROL AND Serial Output
int main()
{
    DigitalOut myled(LED1);

    myled = 0;
    while(1){
        myled = 1; // LED is ON
        wait(1); // 1 sec
        myled = 0; // LED is OFF
        wait(1); // 1 sec
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.
GPIO Porting시 사용하는 아래 파일들은 수정할 필요가 없다.

  • api/DigitalOut.h
  • common/gpio.c
  • hal/gpio_api.h

targets/hal/TARGET_WIZNET/TARGET_W7500x/TARGET_WIZwiki_W7500/PortNames.h

typedef enum {
    PortA = 0,
    PortB = 1,
    PortC = 2,
    PortD = 3,
} PortName;

targets/hal/TARGET_WIZNET/TARGET_W7500x/TARGET_WIZwiki_W7500/PinNames.h

  • W7500 Chip의 Pin 정보를 mbed SDK를 위한 형태로 변경
  • PinName 규칙 (AF[9:8] + PORT[5:4] + PIN[3:0])
    • ex) PC_10 = 0x32A, // 0xx:U_TXD2, 1xx:GPIOC_10, 2xx:PWM2, 3xx:AIN5
// See W7500x_hal_gpio.h for values of MODE, PUPD and AFNUM
#define WIZ_PIN_DATA(MODE, PUPD, AFNUM)  ((int)(((AFNUM) << 8) | ((PUPD) << 4) | ((MODE) << 0)))
#define WIZ_PIN_MODE(X)       (((X) >> 0) & 0x0F)
#define WIZ_PIN_PUPD(X)       (((X) >> 4) & 0x0F)
#define WIZ_PIN_AFNUM(X)      (((X) >> 8) & 0x0F)
#define WIZ_MODE_INPUT              (0)
#define WIZ_MODE_OUTPUT             (1)
#define WIZ_MODE_AF                 (2)

#define WIZ_GPIO_NOPULL             (0)   /*!< No Pull-up or Pull-down activation  */
#define WIZ_GPIO_PULLDOWN           (1)   /*!< Pull-down activation                */
#define WIZ_GPIO_PULLUP             (2)   /*!< Pull-up activation                  */
#define WIZ_GPIO_OPEN_DRAIN         (3)   /*!< Open Drain activation               */


#define WIZ_AFNUM(X)(((uint32_t)(X) >> 8) & 0xF)    // AF number   (0=AF0, 1=AF1, 2=AF2, 3=AF3)
#define WIZ_PORT(X) (((uint32_t)(X) >> 4) & 0xF)    // port number (0=A, 1=B, 2=C, 3=D)
#define WIZ_PIN(X)  ((uint32_t)(X) & 0xF)           // pin number


typedef enum {
    PIN_INPUT,
    PIN_OUTPUT
} PinDirection;


typedef enum {
    // W7500x Pin Names (AF[9:8] + PORT[5:4] + PIN[3:0])

    PA_0  = 0x000,
    PA_1  = 0x001,
    PA_2  = 0x002,
    PA_3  = 0x003,
    PA_4  = 0x004,
    PA_5  = 0x005,
    PA_6  = 0x006,
    PA_7  = 0x007,
    PA_8  = 0x008,
    PA_9  = 0x009,
    PA_10 = 0x00A,
    PA_11 = 0x00B,
    PA_12 = 0x00C,
    PA_13 = 0x00D,
    PA_14 = 0x00E,
    PA_15 = 0x00F,

    PB_0  = 0x010, //SSEL1/SD_SEL
    PB_1  = 0x011, //SCLK1/SD_CLK
    PB_2  = 0x012, //MISO1/SD_MISO
    PB_3  = 0x013, //MOSI1/SD_MOSI
    PB_4  = 0x014,
    PB_5  = 0x015,
    PB_6  = 0x016,
    PB_7  = 0x017,
    PB_8  = 0x018,
    PB_9  = 0x019,
    PB_10 = 0x01A,
    PB_11 = 0x01B,
    PB_12 = 0x01C,
    PB_13 = 0x01D,
    PB_14 = 0x01E,
    PB_15 = 0x01F,

    PC_0  = 0x120,  // 0xx:U_CTS1, 1xx:GPIOC_0, 2xx:PWM0
    PC_1  = 0x121,  // 0xx:U_RTS1, 1xx:GPIOC_1, 2xx:PWM1
    PC_2  = 0x022,
    PC_3  = 0x023,
    PC_4  = 0x124,  // 0xx:SDA1, 1xx:GPIOC_4, 2xx:PWM4
    PC_5  = 0x025,
    PC_6  = 0x026,
    PC_7  = 0x027,
    PC_8  = 0x128,  // 0xx:PWM0,   1xx:GPIOC_8,  2xx:SCL0,  3xx:AIN7
    PC_9  = 0x129,  // 0xx:PWM1,   1xx:GPIOC_9,  2xx:SDA0,  3xx:AIN6

    PC_10 = 0x32A,  // 0xx:U_TXD2, 1xx:GPIOC_10, 2xx:PWM2,  3xx:AIN5
    PC_11 = 0x32B,  // 0xx:U_RXD2, 1xx:GPIOC_11, 2xx:PWM3,  3xx:AIN4
    PC_12 = 0x32C,  // 0xx:AIN3,   1xx:GPIOC_12, 2xx:SSEL0, 3xx:AIN3
    PC_13 = 0x32D,  // 0xx:AIN2,   1xx:GPIOC_13, 2xx:SCLK0, 3xx:AIN2
    PC_14 = 0x32E,  // 0xx:AIN1,   1xx:GPIOC_14, 2xx:MISO0, 3xx:AIN1
    PC_15 = 0x32F,  // 0xx:AIN0,   1xx:GPIOC_15, 2xx:MOSI0, 3xx:AIN0

    PD_0  = 0x030,
    PD_1  = 0x031,
    PD_2  = 0x032,
    PD_3  = 0x033,
    PD_4  = 0x034,


    // Arduino connector namings
    A0          = PC_15,            // AIN0
    A1          = PC_14,            // AIN1
    A2          = PC_13,            // AIN2
    A3          = PC_12,            // AIN3
    A4          = PC_11,            // AIN4
    A5          = PC_10,            // AIN5
    D0          = PA_14,            // U_TXD0
    D1          = PA_13,            // U_RXD0
    D2          = PC_1,            // GPIOC_1, EXTI
    D3          = PC_0,            // GPIOC_0, EXTI
    D4          = PA_2,            // GPIOA_2,
    D5          = PA_1,            // GPIOA_1,
    D6          = PA_0,            // GPIOA_0,
    D7          = PC_6,            // GPIOC_6, EXTI
    D8          = PC_7,            // GPIOC_7, EXTI
    D9          = PC_4,            // GPIOC_4, EXTI
    D10         = PA_5,            // SSEL0
    D11         = PA_8,            // MOSI0
    D12         = PA_7,            // MISO0
    D13         = PA_6,            // SCLK0
    D14         = PA_10,            // SDA0
    D15         = PA_9,            // SCL0

    // Generic signals namings
    LED_RED      = PC_8,
    LED_GREEN    = PC_9,
    LED_BLUE     = PC_5,

    LED1        = LED_RED,
    LED2        = LED_GREEN,
    LED3        = LED_BLUE,
//    USER_BUTTON = PC_13,
    SERIAL_TX   = PC_2,            // U_TXD1
    SERIAL_RX   = PC_3,            // U_RXD1
    USBTX       = SERIAL_TX,
    USBRX       = SERIAL_RX,
    I2C_SCL     = PA_9,         // SCL0
    I2C_SDA     = PA_10,        // SDA0
    SPI_MOSI    = PA_8,         // MISO0
    SPI_MISO    = PA_7,         // MOSI0
    SPI_SCK     = PA_9,         // SCL0
    SPI_CS      = PA_5,         // SSEL0
    SD_SEL      = PB_0,         // SSEL1
    SD_CLK      = PB_1,         // SCL1
    SD_MISO     = PB_2,         // MOSI1
    SD_MOSI     = PB_3,         // MISO1
//    PWM_OUT     = PC_7,

    // Not connected
    NC = (int)0xFFFFFFFF
} PinName;

targets/hal/TARGET_WIZNET/TARGET_W7500x/gpio_object.h

  • PinNames.h에 정의한 Pin 정보들을 이용하여 GPIO pin을 read, write 하기 위한 Function 구현
typedef struct {
    PinName  pin;
    uint32_t mask;

    __IO uint32_t *reg_data_in;
} gpio_t;


extern uint32_t Get_GPIO_BaseAddress(uint32_t port_idx);


static inline void gpio_write(gpio_t *obj, int value) {
    MBED_ASSERT(obj->pin != (PinName)NC);

    uint32_t port_index = WIZ_PORT(obj->pin);
    uint32_t pin_index  = WIZ_PIN(obj->pin);

    uint32_t gpio_add = Get_GPIO_BaseAddress(port_index);
    GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add;

    if (value)
    {
        HAL_GPIO_SetBits(gpio,(0x01 << pin_index));
    }
    else
    {
        HAL_GPIO_ResetBits(gpio,(0x01 << pin_index));
    }
}

static inline int gpio_read(gpio_t *obj) {
    MBED_ASSERT(obj->pin != (PinName)NC);

    return ((*obj->reg_data_in & obj->mask) ? 1 : 0);
}

static inline int gpio_is_connected(const gpio_t *obj) {
    return obj->pin != (PinName)NC;
}

targets/hal/TARGET_WIZNET/TARGET_W7500x/pinmap.c

  • Pin들을 설정하기 위한 함수 구현
    • Output,Input,Alternative Fuction을 설정 할 수 있음.
    • Pin Mode 설정을 위한 함수 구현 —> Pull up, Pull down, Open Drain
  • 실질적인 pin을 Control 하기 위한 기능들이 구현되어 있음
// GPIO mode look-up table
// It have to same with PinMode index in "PinNames.h"
static const uint32_t gpio_pupd[4] = {
    GPIO_NO_PUPD,           //  PullNone
    GPIO_PuPd_DOWN,         //  PullDown
    GPIO_PuPd_UP,           //  PullUp
    GPIO_OD                 //  OpenDrain
};

uint32_t Get_GPIO_BaseAddress(uint32_t port_idx)
{
    uint32_t gpio_add = 0;
    switch(port_idx)    {
        case PortA:
            gpio_add = GPIOA_BASE;
            break;
        case PortB:
            gpio_add = GPIOB_BASE;
            break;
        case PortC:
            gpio_add = GPIOC_BASE;
            break;
        case PortD:
            gpio_add = GPIOD_BASE;
            break;
        default:
            error("Pinmap error: wrong port number.");
            break;
    }
    return gpio_add;
}


/**
 * Configure pin (input, output, alternate function or analog) + output speed + AF
 */

void pin_function(PinName pin, int data) {
    MBED_ASSERT(pin != (PinName)NC);
    // Get the pin informations
    uint32_t mode  = WIZ_PIN_MODE(data);
    uint32_t pupd  = WIZ_PIN_PUPD(data);
    uint32_t afnum;

    if( mode == WIZ_MODE_AF )
        afnum = WIZ_PIN_AFNUM(data);
    else
        afnum = WIZ_AFNUM(pin);

    uint32_t port_index = WIZ_PORT(pin);
    uint32_t pin_index  = WIZ_PIN(pin);


    uint32_t gpio_add = Get_GPIO_BaseAddress(port_index);
    GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add;

    // Configure Alternate Function
    // Warning: Must be done before the GPIO is initialized
    switch (afnum) {
        case 0:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF0);
            break;
        case 1:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF1);
            break;
        case 2:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF2);
            break;
        case 3:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF3);
            break;
        default:
            break;
    }

    if(mode == WIZ_MODE_AF)
        return;

    // Configure GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin       = (uint32_t)(1 << pin_index);
    GPIO_InitStructure.GPIO_Mode      = mode;
    GPIO_InitStructure.GPIO_Pad       = gpio_pupd[pupd];
    HAL_GPIO_Init(gpio, &GPIO_InitStructure);
}

/**
 * Configure pin pull-up/pull-down
 */
void pin_mode(PinName pin, PinMode pupd)
{
    MBED_ASSERT(pin != (PinName)NC);

    P_Port_Def *px_pcr;

    uint32_t port_index = WIZ_PORT(pin);

    switch(port_index)    {
        case PortA:
            px_pcr = PA_PCR;
            break;
        case PortB:
            px_pcr = PB_PCR;
            break;
        case PortC:
            px_pcr = PC_PCR;
            break;
        case PortD:
            px_pcr = (P_Port_Def*)PD_PCR;
            break;
        default:
            error("Pinmap error: wrong port number.");
            return;
    }

    px_pcr->Port[port_index] &= ~(Px_PCR_PUPD_DOWN|Px_PCR_PUPD_UP|Px_PCR_DS_HIGH| \
                                  Px_PCR_OD | Px_PCR_IE | Px_PCR_CS_SUMMIT);
    px_pcr->Port[port_index] |= gpio_pupd[pupd];
}

targets/hal/TARGET_WIZNET/TARGET_W7500x/gpio_api.c

  • pinmap.c에 구현한 함수를 이용하여 gpio 설정을 변경
extern uint32_t Get_GPIO_BaseAddress(uint32_t port_idx);

uint32_t gpio_set(PinName pin)
{
    MBED_ASSERT(pin != (PinName)NC);

    pin_function(pin, WIZ_PIN_DATA(WIZ_MODE_INPUT, WIZ_GPIO_NOPULL, 0));

    return (uint32_t)(1 << ((uint32_t)pin & 0xF)); // Return the pin mask
}

void gpio_init(gpio_t *obj, PinName pin)
{
    obj->pin = pin;
    if (pin == (PinName)NC) {
        return;
    }

    uint32_t port_index = WIZ_PORT(pin);

    GPIO_TypeDef *gpio = (GPIO_TypeDef *)Get_GPIO_BaseAddress(port_index);

    // Fill GPIO object structure for future use
    obj->mask    = gpio_set(pin);
    obj->reg_data_in    = &gpio->DATA;
}

void gpio_mode(gpio_t *obj, PinMode mode)
{
    pin_mode(obj->pin, mode);
}

void gpio_dir(gpio_t *obj, PinDirection direction)
{
    MBED_ASSERT(obj->pin != (PinName)NC);
    if (direction == PIN_OUTPUT) {
        pin_function(obj->pin, WIZ_PIN_DATA(WIZ_MODE_OUTPUT, WIZ_GPIO_NOPULL, 0));
    } else { // PIN_INPUT
        pin_function(obj->pin, WIZ_PIN_DATA(WIZ_MODE_INPUT, WIZ_GPIO_NOPULL, 0));
    }
}
저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 1/6 )  (0) 2015.10.08
mbed rpc interfacing with Python  (0) 2015.10.08
mbed RPC Library porting guide for WIZwiki-W7500  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed porting Guide ( 1/6 )

Posted by 카이젠8501 카이젠8501
2015.10.08 14:58 IT 개발/mbed

W7500 mbed porting Guide

현재 회사에서 W7500 Peripheral Library Firmware 구현과 mbed에 등록하기 위한 Porting 작없을 진행하고 있다.
본 포스팅에서는 W7500을 mbed에 등록하기 위한 Porting 작업을 진행하는 방법과 기술적인 이슈들을 정리 한다.

mbed SDK Porting 개요

mbed Porting의 궁극적인 목적은 mbed에서 제공하는 아래와 같은 코드를 W7500에서 동작 할 수 있도록 Interface Code를 구현하는 것이다.

#include "mbed.h"

////MBED Example 1 LED CONTROL AND Serial Output
int main()
{
    Serial pc(USBTX, USBRX);
    DigitalOut myled(LED1);

    pc.baud(115200);
    pc.printf("TEST Start\r\n");

    myled = 0;
    while(1){
        pc.printf("LED ON\r\n");
        myled = 1; // LED is ON
        wait(1); // 1 sec
        pc.printf("LED OFF\r\n");
        myled = 0; // LED is OFF
        wait(1); // 1 sec
    }
}

mbed SDK Porting을 위한 코드 및 자세한 정보는 아래 주소에서 얻을 수 있다.
http://developer.mbed.org/handbook/mbed-SDK-porting

mbed SDK 폴더 구조

mbed SDK의 폴더 구조는 크게 api, common, hal, targets 으로 구분 된다. 각 폴더에 대한 간략한 설명은 아래와 같다.

api

api 폴더에는 아래 그림과 같은 파일들이 존재 하며, 각 파일들은 User가 Application을 구현 할 때 필요한 API 들의 프로토타입들이 존재 한다.

선택 영역_017.png

common

api 폴더에서 선언한 프로토타입들을 구현한 파일들이 존재 한다.
common 폴더의 구현부에서 Chip에 종속적인 함수들을 호출 할 때는 Hal 폴더에 정의된 함수들을 이용한다.

선택 영역_018.png

hal

Chip에 종속적인 기능을 사용 하기 위한 Interface API들의 프로토타입들이 존재 하며, common 폴더의 함수들은 hal에 정의되어 있는 함수들을 이용하여 Chip에 종속적인 기능을 이용한다.

선택 영역_019.png

targets

targets 폴더는 cmsis와 hal로 나뉜다.

targets/cmsis

targets/cmsis는 chip을 구동하기 위해 필요한 startup code와 linker script 들이 존재 하며, verdor에 따라서는 Chip을 제어하기 위한 Library Code 들을 보관 한다.

선택 영역_024.png

targets/hal

hal 폴더에서 정의한 프로토타입들의 실제 구현 코드들을 보관하며, common 폴더의 함수들이 Chip에 종속적인 기능을 사용하기 위해서는 targets/hal 폴더에 정의된 함수들을 호출한다.

선택 영역_026.png

저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 1/6 )  (0) 2015.10.08
mbed rpc interfacing with Python  (0) 2015.10.08
mbed RPC Library porting guide for WIZwiki-W7500  (0) 2015.10.08
mbed RPC  (0) 2015.10.08
이 댓글을 비밀 댓글로

How to make Wi-Fi oil checker using Axeda

Posted by 카이젠8501 카이젠8501
2015.10.08 14:50 IT 개발/DIY 프로젝트

How to make WiFi oil check using Axeda cloud

Axeda

Axeda는 세계 각지의 기계와 센서 데이터를 수집하고 체계화하기 위한 IoT 솔루션을 제공하는 기업이다. 150개 이상의 고객사를 향해 매일 수억 개의 규모의 데이터를 처리하고 있으며, 크게 3가지 서비스를 제공하고 있다.

  1. ‘Axeda Machine Cloud Service’는 기기간 통신(M2M) 및 IoT 연결 서비스 소프트웨어 에이전트 툴킷으로 구성되어 있으며, 기업의 제품과 클라우드 보안 연결을 거의 모든 통신 방법(이동통신 네트워크, 인터넷, 무선 LAN, 위선통신 등)에서 제공한다.
  2. ‘Axeda Connected Content Application’은 대량의 연결된 제품에 콘텐츠 전송을 안전하고 확실하고 효율적으로 실현하고 소프트웨어 업데이트 및 보안 패치의 원격 설치를 자동화 한다.
  3. ‘Axeda Connected Service Application’은 PTC의 서비스 라이프 사이클 관리(SLM) 솔루션을 보완하고 Axeda 플랫폼에 연결된 장치의 문제를 원격으로 확인, 진단, 수리하는 다양한 툴과 Web 기반의 그래픽 인터페이스를 현장 서비스 및 기술 지원 부서에 제공한다.

참고 PTC, 액세다(Axeda) 인수 완료…사물인터넷 사업 강화

Go to the staging page on your Axeda Toolbox account

toolbox.axeda.com에 회원 가입 후, 아래 그림과 깉이 AXEDA READY 아이콘을 선택하고 mbed LPC1768 Device를 선택한다.

toolbox_landing_page mbedselect

본 포스팅 예제에서는 WIZwiki-W7500 Board를 사용하지만, 아직 Axeda에는 WizWik-W7500 Board가 없는 관계로 LPC1768의 ToolBox를 사용한다.

원하는 Device Name을 입력하고 Go 버튼을 누르면 아래 그림과 같은 화면을 볼수 있다.
Serial Number는 Axeda Example Code를 수행 할 때 필요하므로 메모장 같은 곳에 복사 해두길 바란다.

yourdevicepage

Materials

아래 하드웨어에 대한 자세한 내용은 아래 링크를 참고 하기 바란다.
Link

WIZwiki-W7500 ( MCU Platform)

wizwiki-w7500_main

WizFi250-EVB ( Wi-Fi Module )

ShopDtl_1203_20140918154919

Sensor Shield

TB2wSGHaFXXXXcLXXXXXXXXXXXX_!!33841454

Hardware Configuartion

20150626_151253

WizFi250-EVB Sensor Shield WIZwiki-W7500
RX-TX RXD TXD
TX-RX TXD RXD
CTS-RTS CTS D8
RTS-CTS RTS D7
WizFi250-RESET JP10-2 PA12

Compile AxedaGo-WizFi250 Example onto Wizwiki-W7500 Board

아래 주소에 접속하면 WizFi250 Axeda Example Code를 이용 할 수 있다.
Link for AxedaGo-WizFi250 Example

20150626_151744

AxedaGo-WizFi250 Example을 컴파일 하기 전, Axeda Tool box 에서 얻은 Serial Number를 아래 코드에 추가한다.

line19serial

코드를 컴파일 한 후, 생성된 바이너리를 WIZwiki-W7500 Board에 Upload 한다.

Source Code

#include <stdio.h>
#include "mbed.h"
#include "WizFi250Interface.h"

#define SECURE WizFi250::SEC_AUTO
#define SSID "ssid"
#define PASS "key"


#if defined(TARGET_WIZwiki_W7500)
    WizFi250Interface wizfi250(D1,D0,D7,D8,PA_12,NC,115200);
    Serial pc(USBTX,USBRX);
#endif

AnalogIn pot1(A0);
TCPSocketConnection sock;

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

int main() 
{
    char *MODEL = "mbed";
    char *SERIAL_NUM = "serial number"; 
    float DEADBAND = 0.03;

    int http_cmd_sz=800;
    char http_cmd[http_cmd_sz];
    int buffer_sz=300;  
    char buffer[buffer_sz];  
    int returnCode = 0;

    led1 = 1;
    led2 = 1;
    led3 = 1;
    led4 = 1;

    pc.baud(115200);

    wizfi250.init();
    returnCode = wizfi250.connect(SECURE, SSID, PASS);

    if ( returnCode == 0 )
    {
        printf(" - WiFi Ready\r\n");
        printf("IP Address is %s\r\n", wizfi250.getIPAddress());
        led1 = returnCode;
    }
    else
    {
        printf(" - Could not initialize WiFi - ending\r\n");
        return 0;
    }

    float oil_level = 0.0;
    float oldPotVal = -2.0;

    while(1) {
        oil_level = pot1.read();

        if ( abs(oil_level - oldPotVal) < DEADBAND)
        {
            continue;   
        }
        else
        {
            oldPotVal = oil_level;
            printf("Sending Value for well1 %.2f\n\r", oil_level);
            sock.connect("toolbox-connect.axeda.com", 80);

            snprintf(http_cmd, http_cmd_sz,  "POST /ammp/data/1/%s!%s HTTP/1.1\r\nContent-Type: application/json\r\nContent-Length: 65\r\n\r\n{\"data\":[{\"di\":{\"oil_level\":%.2f}}]}\r\n\r\n", MODEL, SERIAL_NUM, oil_level);
            sock.send_all(http_cmd, http_cmd_sz-1);

            while ( (returnCode = sock.receive(buffer, buffer_sz-1)) > 0)
            {
                buffer[returnCode] = '\0';
                printf("Received %d chars from server:\n\r%s\n", returnCode, buffer);
            }

            sock.close();
        }
     }
}

Test Result

Send data to the demo application

위 코드를 수행하면, WIZwiki-W7500은 WizFi250을 이용하여 Axeda Tool box에 센싱된 데이터를 송신한다. Axeda Tool box는 Device가 송신한 데이터를 가지고 아래 그림과 같이 Mbed Widget을 만들어 준다. Sensor Shield의 A0의 Switch를 돌리면 Axeda의 mbed Widget도 변하는 것을 확인 할 수 있다.

20150626_16013820150626_154710

Log message on Serial Terminal

[WizFi250: INFO]AT+MMAC=?
[WizFi250: INFO][OK]

[WizFi250: INFO]AT+WSET=0,wizohp
[WizFi250: INFO][OK]

[WizFi250: INFO]AT+WSEC=0,,wiznet218
[WizFi250: INFO][OK]

[WizFi250: INFO]AT+WJOIN
[WizFi250: INFO][OK]

[WizFi250: INFO]AT+WSTATUS
[WizFi250: INFO][OK]

[WizFi250: INFO]IP      : 192.168.13.29
[WizFi250: INFO]Gateway : 192.168.13.1
[WizFi250: INFO]WizFi250 is successfully join to AP
 - WiFi Ready
IP Address is 192.168.13.29
Sending Value for well1 0.54
[WizFi250: INFO]AT+FDNS=toolbox-connect.axeda.com,1000
[WizFi250: INFO][OK]

[WizFi250: DBG]216.34.120.52
[WizFi250: INFO]AT+SCON=O,TCN,216.34.120.52,80,,0
[WizFi250: INFO][OK]

[WizFi250: INFO]AT+SSEND=0,,,799
[WizFi250: INFO][OK]

[WizFi250: INFO]POST /ammp/data/1/mbed!nlr__kaizen8501_gmail_com___6245114 HTTP/1.1
Content-Type: application/json
Content-Length: 65

{"data":[{"di":{"oil_level":0.54}}]}



[WizFi250: DBG]receive readable : 1

Received 36 chars from server:
HTTP/1.1 200 
Content-Length: 0

Demo Video


저작자 표시
신고
이 댓글을 비밀 댓글로

Remote Temperature/Humidity Checker using TTS

Posted by 카이젠8501 카이젠8501
2015.10.08 14:44 IT 개발/DIY 프로젝트

Remote Temperature/Humidity Checker & LED controller

앞에서 설명한 mbed RPC Library와 Python Interface를 활용한 예제를 만들어 보려고 하다 보니 제목이 거창해 진거 같다.

간단하게 말하자면, 본 예제는 아래와 같은 기능을 수행한다.

  • mbed platform의 3색 LED 제어 ( On/Off )
  • mbed platform의 현재 LED 상태 확인 ( Smartphone의 TTS 기능을 이용하여 Green,Blue,Red 인지 상태 확인 기능 )
  • mbed platform으로 부터 온도, 습도 정보를 확인 ( Smartphone의 TTS 기능을 이용하여 온/습도 정보를 확인 가능)

본 예제에서는 mbed RPC를 이용하여 스마트폰에서 mbed platform을 제어하고 있으며, 스마트폰의 Application은 python 기반의 kivy 라이브러리를 사용하였다.

20150727_132817

mbed HTTP RPC Server

본 장에서는 위에서 설명한 동작을 수행하기 위한 mbed code를 구현하는 방법에 대해 설명한다. 아래 코드는 mbed rpc와 HTTP Server 등을 구동하기 위한 코드이며, 사용된 라이브러리는 아래와 같다. mbed platform에 아래 코드를 컴파일해서 Upload 하면, 외부에서 HTTP Data를 이용하여 mbed platform을 제어 할 수 있다.

  • DHT : 온/습도 센서를 제어 하기 위한 라이브러리
  • HTTPServer : HTTP Server를 위한 라이브러리
  • mbed-rpc : mbed RPC를 위한 라이브러리
  • WIZnetInterface : 별도의 Software stack 없이 Ethernet을 사용하기 위한 라이브러리

Example Code는 아래 경로에서 다운로드 할 수 있다.
RPC_HTTP_WIZnetInterface

#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPServer.h"
#include "mbed_rpc.h"
#include "DHT.h"

RpcDigitalOut led1(D9,"led1");
RpcDigitalOut led2(D10,"led2");
RpcDigitalOut led3(D11,"led3");

//RPCVarialbe<float> RPCTemperature(&GetTemperature, "Temperature");
//RPCVarialbe<float> RPCHumidity(&GetHumidity, "Humidity");
void Get_Temp_and_Humidity(Arguments * input, Reply * output);

RPCFunction Temp_and_Humidity_Finder(&Get_Temp_and_Humidity, "Temp_and_Humidity_Finder");

EthernetInterface eth;  
HTTPServer svr;

DHT sensor(D4, DHT11);

void Get_Temp_and_Humidity(Arguments * input, Reply *output){
    int error = 0;
    float h = 0.0f, c = 0.0f;
    char arg[100];

    error = sensor.readData();
    if (0 == error) {
        c   = sensor.ReadTemperature(CELCIUS);
        h   = sensor.ReadHumidity();
        sprintf(arg,"Temperature in Celcius: %4.2f, Humidity is %4.2f",c, h);

        output->putData(arg);
    }
}

int main() {
  //Turn the LEDs off
  uint8_t mac_addr[6] = {0x00, 0x08, 0xDC, 0x32, 0x23, 0x42}; 
  led1.write(0);
  led2.write(0);
  led3.write(0);

  RPC::add_rpc_class<RpcDigitalOut>();

  printf("Setting up...\n");
  eth.init(mac_addr);
  int ethErr = eth.connect();
  if(ethErr < 0)
  {
    printf("Error %d in setup.\n", ethErr);
    return -1;
  }
  svr.addHandler<HTTPRpcRequestHandler>("/rpc");

  //attach server to port 80
  printf("Listening...\n");
  svr.start(80, &eth);

  Timer tm;
  tm.start();
  //Listen indefinitely
  while(true)
  {
    svr.poll();
    if(tm.read()>.5)
    {
      tm.start();
    }
  }
}
  • 7~8 : 3색 LED를 위한 GPIO를 RPC에 등록
  • 15 : 온/습도를 얻어 오기 위한 Custom 함수를 RPC에 등록
  • 22~35 : Custom 함수의 구현 부
    • mbed RPC client로 부터 요청이 들어오면 온/습도를 추출한 후, Temperature in Celcius : … “ 데이터를 RPC client에게 송신 한다.
  • 54 : HTTPRPC Request 등록

Smartphone Simple Application

본 장에서는 Smartphone에서 mbed device를 제어하기 위한 간단한 Application을 만드는 방법을 설명한다. 본 예제는 python으로 구현 하였으며, UI를 위해 kivy 라이브러리를 사용하였다. 본 예제를 구현 및 구동하기 위해서는 아래와 같은 절차를 수행 해야 한다.

Download Qpython

Android 폰에서 python을 구동하기 위해서는 Qpython 이라는 프로그램이 필요 하며, 다운로드 경로는 아래와 같다.
QPython Download

20150727_140513

앞에서 설명한 것과 같이 python으로 UI를 만들기 위해서는 kivy 라이브러리가 필요하며, 스마트폰의 TTS(Text to Speach) 기능을 사용하기 위해서는 AndroidHelper 라이브러리가 있어야 한다. 각각의 라이브러리는 아래 그림과 같은 절차를 수행하면 설치 할 수 있다.

20150727_140920 20150727_141000 20150727_141026

20150727_141051 20150727_141110 20150727_141151 20150727_141247

Edit Source Code

스마트폰 앱으로 소스코드를 작성하는 일은 매우 불편하다. 다행히도 QPython은 미리 작성한 코드를 FTP로 핸드폰에 저장하는 기능을 지원하고 있다.
나는 이 기능을 이용해서 PC에서 미리 구현해 놓은 프로그램을 스마트폰에 복사 한 후 실행하는 절차로 코드를 구현 및 디버깅 했다. ( 이 또한 매우 불편 하였다. )

Setting for FTP

아래 그림과 같은 절차를 수행하면 Qpython의 FTP 기능을 사용 할 수 있다.

20150727_143112 20150727_143133 20150727_143156

Upload Source Code to Smartphone

아래 그림들은 PC에서 QPython의 FTP Server에 접속해서 미리 작성한 코드를 업로드 하는 방법을 나타낸다.

20150727_143344

FTP 접속에 성공하면 아래와 같이 Qpython의 폴더 트리를 볼 수 있다. 폴더 트리에 나오는 폴더를 하나 선택하여 미리 작성한 코드를 업로드 하면 된다.

20150727_143413

나는 project3/RPC_TTS 폴더를 만들고 kivy.py와 mbedRPC.py를 복사 해서 사용한다.
mbedRPC.py는 앞에서 설명한 mbed python RPC library이며, kivy.py는 Application의 UI 및 동작을 구현한 파일이다.

20150727_143443

Source code of kivy.py

#-*-coding:utf8;-*-
#qpy:2
#qpy:kivy

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from mbedRPC import *
import androidhelper

class CommandScreen(GridLayout):
    def __init__(self, **kwargs):
        super(CommandScreen, self).__init__(**kwargs)
        self.cols = 2
        self.row = 2
        self.row_force_default=True
        self.row_default_height=200

        self.add_widget(Label(text='Device IP'))
        self.m_text_device_ip = TextInput(multiline=False,text="192.168.18.121")
        self.add_widget(self.m_text_device_ip)

        self.m_button_init = Button(text="Init")
        self.m_button_init.bind(on_press=self.mbedInit)
        self.add_widget(self.m_button_init)

        self.m_button_GetTemp = Button(text="Get Temp")
        self.m_button_GetTemp.bind(on_press=self.GetTemp)
        self.add_widget(self.m_button_GetTemp)

        self.btn_onLed1 = Button(text="Turn On",background_color=(1,0,0,1))
        self.btn_onLed1.bind(on_press=self.TurnOnLed1)
        self.add_widget(self.btn_onLed1)

        self.btn_offLed1 = Button(text="Turn Off",background_color=(1,0,0,1))
        self.btn_offLed1.bind(on_press=self.TurnOffLed1)
        self.add_widget(self.btn_offLed1)

        self.btn_onLed2 = Button(text="Turn On",background_color=(0,1,0,1))
        self.btn_onLed2.bind(on_press=self.TurnOnLed2)
        self.add_widget(self.btn_onLed2)

        self.btn_offLed2 = Button(text="Turn Off",background_color=(0,1,0,1))
        self.btn_offLed2.bind(on_press=self.TurnOffLed2)
        self.add_widget(self.btn_offLed2)

        self.btn_onLed3 = Button(text="Turn On",background_color=(0,0,1,1))
        self.btn_onLed3.bind(on_press=self.TurnOnLed3)
        self.add_widget(self.btn_onLed3)

        self.btn_offLed3 = Button(text="Turn Off",background_color=(0,0,1,1))
        self.btn_offLed3.bind(on_press=self.TurnOffLed3)
        self.add_widget(self.btn_offLed3)

        self.btn_getLedStatus = Button(text="LED Status")
        self.btn_getLedStatus.bind(on_press=self.GetLedStatus)
        self.add_widget(self.btn_getLedStatus)

        self.btn_getA0Status = Button(text="Get A0 Status")
        self.btn_getA0Status.bind(on_press=self.GetA0Status)
        self.add_widget(self.btn_getA0Status)


    def mbedInit(self,event):
        self.droid = androidhelper.Android()

        self.mbed = HTTPRPC(self.m_text_device_ip.text)
        self.led1 = DigitalOut(self.mbed,"led1")
        self.led2 = DigitalOut(self.mbed,"led2")
        self.led3 = DigitalOut(self.mbed,"led3")
        self.temp_humidity = RPCFunction(self.mbed,"Temp_and_Humidity_Finder")

        box = BoxLayout(orientation='vertical')
        box.add_widget(Label(text='Init Complete'))
        button_close = Button(text='Close me!')
        box.add_widget(button_close)

        popup = Popup(title='message', content=box,
                      size_hint=(None,None),size=(400,400), auto_dismiss=False)

        button_close.bind(on_press=popup.dismiss)
        popup.open()


    def GetTemp(self,event):
        resp = self.temp_humidity.run("")
        self.droid.ttsSpeak(resp)

    def TurnOnLed1(self,event):
        self.led1.write(1)

    def TurnOffLed1(self,event):
        self.led1.write(0)

    def TurnOnLed2(self,event):
        self.led2.write(1)

    def TurnOffLed2(self,event):
        self.led2.write(0)

    def TurnOnLed3(self,event):
        self.led3.write(1)

    def TurnOffLed3(self,event):
        self.led3.write(0)

    def GetLedStatus(self,event):
        if( self.led1.read()[0] == '1' ): self.droid.ttsSpeak("Turn on red.")
        if( self.led2.read()[0] == '1' ): self.droid.ttsSpeak("Turn on green.")
        if( self.led3.read()[0] == '1' ): self.droid.ttsSpeak("Turn on blue.")

    def GetA0Status(self,event):
        print ''

class MyApp(App):
    def build(self):
        return CommandScreen()        

if __name__ == '__main__':
    MyApp().run()
  • 15 ~ 65 : App Button 및 UI 초기화
  • 68 ~ 86 : mbed RPC library 초기화
  • 89 : mbed platform으로 부터 온/습도 데이터를 수신 후 TTS로 출력
  • 93 ~ 109 : LED1/2/3 On/Off
  • 111 ~ 114 : 현재 mbed platform의 LED 색깔을 확인 후 TTS로 출력

Result after run

20150727_130822

Demo Video

저작자 표시
신고
이 댓글을 비밀 댓글로