micro:bit - Servo(SG-90) 모터 제어

OS/micro:bit 2018.01.28 19:10 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : lampbotics: mbed Servo Control - 0 to 180º fix - Thomas Murphy
BLENano_SimpleControls - SimpleControls works with the BLEController iOS/Android App. | Mbed
Servo - A class to control a model R/C servo, using a PwmOut | Mbed
Input/Output Pins — BBC micro:bit MicroPython 0.0.1 documentation
Visual Bastic.Net Serial 통신 - Create a basic BBC Micro:Bit Air Mouse – Hardware Hacks
micro:bit IoT In C - Pulse Width Modulation, Servos And More

micro:bit - Servo(SG-90) 모터 제어

micro:bit를 이용한 서보모터중에 가장 저렴한 SG-90을 제어하는 예제를 구현해보았습니다.

Servo.h

#ifndef _SERVO_H
#define _SERVO_H

#include "mbed.h"

class Servo
{
public:
    Servo(PinName pin);
    ~Servo(void);
    
    void write(unsigned char degree);

private:
    void convert(unsigned char degree);
    
    PwmOut _servo;
    unsigned int pulse;
};

#endif

Servo.cpp

#include "Servo.h"

Servo::Servo(PinName pin) : _servo(pin)
{
    _servo.period_ms(20);
}

Servo::~Servo(void)
{
    
}

void Servo::write(unsigned char degree)
{
    convert(degree);
    _servo.pulsewidth_us(pulse);
}

void Servo::convert(unsigned char degree)
{
    // 0~180 degree correspond to 500~2500
    pulse = degree * 11 + 500;
}

main.cpp

#include "MicroBit.h"
#include "Servo.h"

/*
PwmOut servo(P0_1);
int main() {
    servo.period(0.020);          
    while (1) {
        for(float offset=0.0003; offset<0.003; offset+=0.0001) {
            servo.pulsewidth(offset); 
            wait(0.25);
        }
    }
}
*/

#define SERVO_PIN P0_1

Serial pc(USBTX, USBRX);
Servo myservo(SERVO_PIN);

int main() 
{  
    int degree = 0;
    int direction = 1;
    
    while(1)
    {
        
        pc.printf("degree=%d \n\r",degree);
        myservo.write(degree);
            
        if(direction==1)
        {
            degree = degree + 5;
        }
            
        if (direction==2)
        {
            degree = degree - 5; 
        }
            
        if(degree>180)
        {
            degree = 180;
            direction = 2;
        }
        if(degree<0)
        {
            degree = 0;
            direction = 1;
        }
            
        wait(0.05);
    }
}

실행

setServoValue 함수를 사용하는 방법

출처 : micro:bit IoT In C - Pulse Width Modulation, Servos And More

#include "MicroBit.h"
MicroBit uBit;

int main() {
    uBit.init();
    for (;;) {
        uBit.io.P0.setServoValue(0);
        uBit.sleep(1000);
        uBit.io.P0.setServoValue(90);
        uBit.sleep(1000);
        uBit.io.P0.setServoValue(180);
        uBit.sleep(1000);
    }
    release_fiber();
    return 0;
}

아나로그 output을 이용하는 방법

출처 : micro:bit IoT In C - Pulse Width Modulation, Servos And More

#include "MicroBit.h"
MicroBit uBit;

int main() {
    uBit.init();
    uBit.io.P0.setAnalogValue(0);
    uBit.io.P0.setAnalogPeriod(20);

   for (;;) {
    uBit.io.P0.setAnalogValue(52 * 0 / 180 + 920);
    uBit.sleep(1000);
    uBit.io.P0.setAnalogValue(52 * 90 / 180 + 920);
    uBit.sleep(1000);
    uBit.io.P0.setAnalogValue(52 * 180 / 180 + 920);
    uBit.sleep(1000);
  }
  release_fiber();
  return 0;
}


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - Arduino - LED 끄고 켜기

OS/micro:bit 2018.01.28 14:18 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : [Micro:Bit]C 언어 + Arduiono IDE|작성자 쿠루쿠루

micro:bit - Arduino - LED 끄고 켜기

쿠루쿠루님의 블로그를 통해서 micro:bit에서 Arduino IDE를 이용해서 개발이 가능한것을 알게 되었습니다. 보드추가 방법은 쿠루쿠루님의 블로그가 잘 나와있으니 참고 하시고, Arduino IDE를 이용해서 LED를 끄고 켜는 예제를 만들어 보았습니다.

보드 추가

메뉴 [파일] - [환경설정]을 선택하시면 아래와 같이 [환경설정]창을 나옵니다.
이 [환경설정]창에서 [추가적인 보드 메니저 URLs]에 https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json 값을 설정합니다.

메뉴 [툴] - [보드] - [보드 메니저] 선택, [보드 메니저]창에서 nRF5로 검색하고 Nordic Semiconductor nRF5 Boards by Sandeep Mistry 선택하고 하단에 [설치]버튼을 눌러서 설치합니다.

메뉴 [툴] - [보드] - [BBC micro:bit] 설택

메뉴 [툴] - ]Softdevice] - [S110] 선택

메뉴 [툴] - [포트] - 해당 포트 설정

소스

int led = 16; // P0_16

void setup() {
  pinMode(led, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

실행

마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - Pong Game

OS/micro:bit 2018.01.27 08:27 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Arduino Pong Game - OLED Display: 5 Steps (with Pictures)

micro:bit - Pong Game

Arduino로 SSD1331이용해서 만들어진 간단한 PONG 게임을 micro:bit에서 구동 되도록 만들어 보았습니다. micro:bit에 내장된 좌우 버튼으로 좌버튼을 누르면 올라가고, 우버튼을 누르면 내려가도록 했습니다.

  

main.cpp - pong_game_source_2.7z

#include "MicroBit.h" 
#include "ssd1331.h"
 
// Color definitions
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

#define LOW 0

const unsigned long PADDLE_RATE = 33;
const unsigned long BALL_RATE = 20;
const uint8_t PADDLE_HEIGHT = 24;
int MAX_SCORE = 3;

int CPU_SCORE = 0;
int PLAYER_SCORE = 0;


// You can use any (4 or) 5 pins 
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8

// MOSI is Data pin on display breakout
// ssd1331(PinName cs_pin, PinName rst_pin, PinName a0_pin, PinName mosi_pin, PinName miso_pin, PinName sclk_pin);
ssd1331 display(P0_16, P0_18, P0_10, P0_21, P0_22, P0_23); // cs, res, dc, miso(nc), sck (KL25z)

void drawCourt();
void gameOver();
void loop();
void showScore();

uint8_t ball_x = 64, ball_y = 32;
uint8_t ball_dir_x = 1, ball_dir_y = 1;

bool gameIsRunning = true;
bool resetBall = false;

static const unsigned char pong [] = {
0xff,0xe0,0x0,0x3f,0x80,0x7,0xe0,0x7,0xc0,0x3,0xfc,0x0,
0xff,0xf8,0x1,0xff,0xe0,0x7,0xf0,0x7,0xc0,0x1f,0xff,0x0,
0xff,0xfc,0x3,0xff,0xf0,0x7,0xf0,0x7,0xc0,0x3f,0xff,0x0,
0xff,0xfe,0x7,0xff,0xf8,0x7,0xf8,0x7,0xc0,0xff,0xff,0x0,
0xf8,0x7f,0xf,0xff,0xfc,0x7,0xfc,0x7,0xc0,0xff,0xff,0x0,
0xf8,0x3f,0xf,0xe0,0xfe,0x7,0xfc,0x7,0xc1,0xfc,0x7,0x0,
0xf8,0x1f,0x1f,0x80,0x7e,0x7,0xfe,0x7,0xc3,0xf8,0x1,0x0,
0xf8,0x1f,0x1f,0x0,0x3e,0x7,0xfe,0x7,0xc3,0xf0,0x0,0x0,
0xf8,0x1f,0x3f,0x0,0x3f,0x7,0xdf,0x7,0xc7,0xe0,0x0,0x0,
0xf8,0x1f,0x3e,0x0,0x1f,0x7,0xdf,0x87,0xc7,0xc0,0x0,0x0,
0xf8,0x3f,0x3e,0x0,0x1f,0x7,0xcf,0x87,0xc7,0xc1,0xff,0x80,
0xf8,0x7e,0x3e,0x0,0x1f,0x7,0xc7,0xc7,0xc7,0xc1,0xff,0x80,
0xff,0xfe,0x3e,0x0,0x1f,0x7,0xc7,0xe7,0xc7,0xc1,0xff,0x80,
0xff,0xfc,0x3e,0x0,0x1f,0x7,0xc3,0xe7,0xc7,0xc1,0xff,0x80,
0xff,0xf8,0x3e,0x0,0x1f,0x7,0xc1,0xf7,0xc7,0xc0,0xf,0x80,
0xff,0xe0,0x3f,0x0,0x3f,0x7,0xc1,0xf7,0xc7,0xe0,0xf,0x80,
0xf8,0x0,0x1f,0x0,0x3e,0x7,0xc0,0xff,0xc3,0xe0,0xf,0x80,
0xf8,0x0,0x1f,0x80,0x7e,0x7,0xc0,0x7f,0xc3,0xf0,0xf,0x80,
0xf8,0x0,0x1f,0xc0,0xfc,0x7,0xc0,0x7f,0xc3,0xfc,0xf,0x80,
0xf8,0x0,0xf,0xff,0xfc,0x7,0xc0,0x3f,0xc1,0xff,0xff,0x80,
0xf8,0x0,0x7,0xff,0xf8,0x7,0xc0,0x3f,0xc0,0xff,0xff,0x80,
0xf8,0x0,0x3,0xff,0xf0,0x7,0xc0,0x1f,0xc0,0x7f,0xff,0x80,
0xf8,0x0,0x1,0xff,0xe0,0x7,0xc0,0xf,0xc0,0x3f,0xff,0x0,
0xf8,0x0,0x0,0x7f,0x0,0x7,0xc0,0xf,0xc0,0x7,0xf8,0x0
};

static const unsigned char game [] ={
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xff,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc3,0xff,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xc3,0xff,0x80,
0x0,0x0,0x0,0x0,0x3,0xe0,0xf,0xc3,0xe0,0x0,
0x0,0x0,0x0,0x0,0x7,0xf0,0x1f,0xc1,0xe0,0x0,
0x0,0x0,0x0,0xf8,0x7,0xf0,0x1f,0xc1,0xe0,0x0,
0x0,0xfc,0x1,0xfc,0x7,0xf8,0x1f,0xc1,0xe0,0x0,
0x7,0xfc,0x1,0xfc,0x3,0xf8,0x1f,0xe1,0xff,0x80,
0x1f,0xfc,0x1,0xde,0x3,0xbc,0x3d,0xe1,0xff,0x80,
0x3f,0xfe,0x1,0xde,0x3,0xbc,0x39,0xe1,0xff,0x80,
0x7e,0x0,0x3,0xdf,0x3,0xde,0x39,0xe1,0xfc,0x0,
0x7c,0x0,0x3,0xcf,0x3,0xde,0x39,0xe1,0xe0,0x0,
0xf8,0x0,0x3,0xcf,0x3,0xcf,0x39,0xe1,0xf0,0x0,
0xf8,0x0,0x3,0x87,0x83,0xcf,0x79,0xe0,0xf0,0x0,
0xf0,0x7f,0x7,0x87,0x83,0xc7,0xf1,0xe0,0xf0,0xe0,
0xf0,0xff,0x7,0x83,0xc3,0xc7,0xf1,0xe0,0xff,0xe0,
0xf0,0xff,0x7,0xff,0xc1,0xc3,0xf1,0xf0,0xff,0xe0,
0xf0,0xff,0x7,0xff,0xe1,0xc3,0xf0,0xf0,0xff,0xe0,
0xf8,0xf,0xf,0xff,0xe1,0xc1,0xe0,0xf0,0xe0,0x0,
0xf8,0xf,0x8f,0x1,0xf1,0xe1,0xe0,0xf0,0x0,0x0,
0x7c,0xf,0x8f,0x0,0xf1,0xe1,0xe0,0x0,0x0,0x0,
0x7f,0x1f,0x8f,0x0,0xf9,0xc0,0x0,0x0,0x0,0x0,
0x3f,0xff,0x9f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x1f,0xff,0x1f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x7,0xfc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

unsigned long ball_update;
unsigned long paddle_update;

const uint8_t CPU_X = 12;
uint8_t cpu_y = 16;

const uint8_t PLAYER_X = 85;
uint8_t player_y = 16;

uint64_t millis() { return us_ticker_read() / 1000; }
void delay(uint32_t delay) { wait_ms(delay); }

uint8_t random(uint8_t min, uint8_t max) {
	return (rand() % (max - min + 1) ) + 1;
}

DigitalIn UP_BUTTON(MICROBIT_PIN_BUTTON_A);
DigitalIn DOWN_BUTTON(MICROBIT_PIN_BUTTON_B);

int main() { 
 
  display.cls(); // clear screen to black
  display.drawBitmap(3,0,pong,89,24,GREEN);
  display.drawBitmap(10,30,game,75,26,RED);
  while(UP_BUTTON && DOWN_BUTTON) {
    wait_ms(100);
  }

  unsigned long start = millis();

    
  display.fillScreen(BLACK);
  drawCourt();

  while(millis() - start < 2000);
  ball_update = millis();
  paddle_update = ball_update;
  ball_x = random(25,65); 
  ball_y = random(3,63);
  
  while(1) {
  	loop();
  }
  
  release_fiber();   
}

void loop() {

    unsigned long time = millis();    
    static bool up_state = false;
    static bool down_state = false;
    
    up_state |= (UP_BUTTON == LOW);
    down_state |= (DOWN_BUTTON == LOW);

    if(resetBall)
    {
      ball_x = random(25,70); 
      ball_y = random(3,63);
      
      /*
      do
      {
      	ball_dir_x = random(-1,2);
      }while(ball_dir_x==0);

       do
      {
      	ball_dir_y = random(-1,2);
      }while(ball_dir_y==0);
      */
      
      ball_dir_x = 1;
      ball_dir_y = 1;
      
      resetBall=false;
    }

    if(time > ball_update && gameIsRunning) {
        uint8_t new_x = ball_x + ball_dir_x;
        uint8_t new_y = ball_y + ball_dir_y;

        // Check if we hit the vertical walls
        if(new_x == 0) //Player Gets a Point
        {
            PLAYER_SCORE++;
            if(PLAYER_SCORE==MAX_SCORE)
            {
              gameOver();
            }else
            {
              showScore();
            }
        }

         // Check if we hit the vertical walls
        if(new_x == 95) //CPU Gets a Point
        {
            CPU_SCORE++;
            if(CPU_SCORE==MAX_SCORE)
            {
              gameOver();
            }else
            {
              showScore();
            }
        }

        // Check if we hit the horizontal walls.
        if(new_y == 0 || new_y == 63) {
            ball_dir_y = -ball_dir_y;
            new_y += ball_dir_y + ball_dir_y;
        }

        // Check if we hit the CPU paddle
        if(new_x == CPU_X && new_y >= cpu_y && new_y <= cpu_y + PADDLE_HEIGHT) {
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;
        }

        // Check if we hit the player paddle
        if(new_x == PLAYER_X
           && new_y >= player_y
           && new_y <= player_y + PADDLE_HEIGHT)
        {
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;
        }

        display.drawPixel(ball_x, ball_y, BLACK);
        display.drawPixel(new_x, new_y, WHITE);
        ball_x = new_x;
        ball_y = new_y;

        ball_update += BALL_RATE;

    }

    if(time > paddle_update && gameIsRunning) {
        paddle_update += PADDLE_RATE;

        // CPU paddle
        display.drawFastVLine(CPU_X, cpu_y,PADDLE_HEIGHT, BLACK);
        const uint8_t half_paddle = PADDLE_HEIGHT >> 1;
        if(cpu_y + half_paddle > ball_y) {
            cpu_y -= 1;
        }
        if(cpu_y + half_paddle < ball_y) {
            cpu_y += 1;
        }
        if(cpu_y < 1) cpu_y = 1;
        if(cpu_y + PADDLE_HEIGHT > 63) cpu_y = 63 - PADDLE_HEIGHT;
        display.drawFastVLine(CPU_X, cpu_y, PADDLE_HEIGHT, RED);

        // Player paddle
        display.drawFastVLine(PLAYER_X, player_y,PADDLE_HEIGHT, BLACK);
        if(up_state) {
            player_y -= 1;
        }
        if(down_state) {
            player_y += 1;
        }
        up_state = down_state = false;
        if(player_y < 1) player_y = 1;
        if(player_y + PADDLE_HEIGHT > 63) player_y = 63 - PADDLE_HEIGHT;
        display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, GREEN);
    }
}

void drawCourt() {
  display.drawRect(0, 0, 96, 64, WHITE);
}

void gameOver()
{
  gameIsRunning = false;
  display.fillScreen(BLACK);
  drawCourt();
  if(PLAYER_SCORE>CPU_SCORE)
  {
    display.setCursor(5,4);
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.printf("You Won");
  }else
  {
    display.setCursor(5,4);
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.printf("CPU WON");
  }

  display.setCursor(20,30);
  display.setTextColor(RED);
  display.setTextSize(3);
  display.printf("%d", CPU_SCORE);

  display.setCursor(60,30);
  display.setTextColor(GREEN);
  display.setTextSize(3);
  display.printf("%d",PLAYER_SCORE);
  
  delay(2000);

  while(UP_BUTTON && DOWN_BUTTON)  
  {
    delay(100);
  }
  gameIsRunning = true;
  
  CPU_SCORE = PLAYER_SCORE = 0;
  
  unsigned long start = millis();
  
	display.Scrollstop(); // stop scroll
  delay(100);
  
	display.fillScreen(BLACK);
	drawCourt();
	while(millis() - start < 2000);
	ball_update = millis();    
	paddle_update = ball_update;
	gameIsRunning = true;
	resetBall=true;
	
	display.Scrollstop(); // stop scroll
  wait(1);
}

void showScore()
{
  gameIsRunning = false;
  display.fillScreen(BLACK);
  drawCourt();
  
  display.setCursor(15,4);
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.printf("Score");

  display.setCursor(20,30);
  display.setTextColor(RED);
  display.setTextSize(3);
  display.printf("%d",CPU_SCORE);

  display.setCursor(60,30);
  display.setTextColor(GREEN);
  display.setTextSize(3);
  display.printf("%d",PLAYER_SCORE);

	delay(2000);
	unsigned long start = millis();
	
	display.Scrollstop(); // stop scroll
  delay(100);

	display.fillScreen(BLACK);
	drawCourt();
	while(millis() - start < 2000);
	ball_update = millis();    
	paddle_update = ball_update;
	gameIsRunning = true;
	resetBall=true;
}

실행 - pulse-combined.hex


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - 버튼 이벤트

OS/micro:bit 2018.01.25 09:32 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : UARTService - micro:bit runtime - GitHub Pages

micro:bit - 버튼 이벤트

micro:bit에는 두개의 버튼이 내장 되어 있습니다. 이 버튼의 이벤트를 리스너를 등록해서 버튼 이벤트가 발생시 메소드가 동작하는 예제를 만들어 보았습니다.

main.cpp

#include "MicroBit.h" 
 
MicroBit uBit;

void onButtonA(MicroBitEvent e)
{
  uBit.display.scroll("A");
}

void onButtonB(MicroBitEvent e)
{
  uBit.display.scroll("B");
}

void onButtonAB(MicroBitEvent e)
{
  uBit.display.scroll("AB");
}
 
int main() { 
  uBit.init(); 
  uBit.display.scroll("Button Test"); 

  // listen for user button interactions
  uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButtonA);
  uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonB);
  uBit.messageBus.listen(MICROBIT_ID_BUTTON_AB, MICROBIT_BUTTON_EVT_CLICK, onButtonAB);
  
  release_fiber();   
}

실행


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - BLE - FireMonkey(Delphi) 연동

OS/micro:bit 2018.01.24 23:57 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Blog Yamasho: Delphi 10.2.2:Bleで Microbitと通信する。
googlesamples/android-BluetoothLeGatt - GitHub
ButtonService - micro:bit runtime
microbit-samples/source/examples/bluetooth-services/main.cpp - GitHub
https://github.com/lancaster-university/microbit-dal/issues/337
Advanced - micro:bit runtime - GitHub Pages
Send/Receive Data Using BLE and MBED | BBC:Microbit - Instructables

micro:bit - BLE - FireMonkey(Delphi) 연동

micro:bit에서 지원하는 BLE 서비스와 Delphi의 크로스 컴파일인 FireMonkey로 BLE 연동 하는 예제를 구현했습니다. FireMonkey는 아이폰도 지원하지만 실행 영상은 안드로이드 실행 영상을 올립니다.

컴파일 환경 - config.json

{
    "microbit-dal": {
        "bluetooth": {
            "enabled": 1,
            "pairing_mode": 1,
            "private_addressing": 0,
            "open": 1,
            "security_level": "SECURITY_MODE_ENCRYPTION_NO_MITM",
            "whitelist": 1,
            "advertising_timeout": 0,
            "tx_power": 7,
            "dfu_service": 0,
            "event_service": 1,
            "device_info_service": 1
        },
        "gatt_table_size": "0x600"
    }
}

소스 - main.cpp

#include "MicroBit.h"
#include "MicroBitUARTService.h"

MicroBit uBit;
MicroBitUARTService *uart;

// we use events abd the 'connected' variable to keep track of the status of the Bluetooth connection
void onConnected(MicroBitEvent)
{
    uBit.display.print("C");
    
    // 종료 문자열
    ManagedString eom(":");

    while(1) {
    	//ManagedString msg = uart->read(1);
        ManagedString msg = uart->readUntil(eom);
        uBit.display.scroll(msg);
    }
}

void onDisconnected(MicroBitEvent)
{
    uBit.display.print("D");
}

int main()
{
    // Initialise the micro:bit runtime.
    uBit.init();

    // Services/Pairing Config/Power Level
    uBit.display.scroll("BLE ABDILMT/P/0");

    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnected);
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnected);
    
    //new MicroBitAccelerometerService(*uBit.ble, uBit.accelerometer);
    new MicroBitButtonService(*uBit.ble);
    //new MicroBitIOPinService(*uBit.ble, uBit.io);
    //new MicroBitLEDService(*uBit.ble, uBit.display);
    //new MicroBitMagnetometerService(*uBit.ble, uBit.compass);
    //new MicroBitTemperatureService(*uBit.ble, uBit.thermometer);
    
    // Note GATT table size increased from default in MicroBitConfig.h
    // #define MICROBIT_SD_GATT_TABLE_SIZE             0x500
    uart = new MicroBitUARTService(*uBit.ble, 32, 32); 
    uBit.display.scroll("UART ready");
    
    // If main exits, there may still be other fibers running or registered event handlers etc.
    // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
    // sit in the idle task forever, in a power efficient sleep.
    release_fiber();
}

Delphi 화면 디자인

Delphi 소스 - Main.pas

unit Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Objects, FMX.Edit, FMX.Controls.Presentation, System.Bluetooth,
  System.Bluetooth.Components, FMX.Layouts, FMX.ListBox;

const
 UUID_BUTTON_SERVICE          : TBluetoothUUID  = '{E95D9882-251D-470A-A062-FA1922DFA9A8}';
 UUID_BUTTON1_CHARACTERRISTIC : TBluetoothUUID  = '{E95DDA90-251D-470A-A062-FA1922DFA9A8}';
 UUID_BUTTON2_CHARACTERRISTIC : TBluetoothUUID  = '{E95DDA91-251D-470A-A062-FA1922DFA9A8}';

 UUID_UART_SERVICE            : TBluetoothUUID  = '{6E400001-B5A3-F393-E0A9-E50E24DCCA9E}';
 UUID_UART_TX_CHARACTERRISTIC : TBluetoothUUID  = '{6E400003-B5A3-F393-E0A9-E50E24DCCA9E}';

type

  TForm42 = class(TForm)
    Connect: TButton;
    Edit1: TEdit;
    Send: TButton;
    ButtonA: TCircle;
    Label1: TLabel;
    BTLableA: TLabel;
    ButtonB: TCircle;
    BtLabelB: TLabel;
    BluetoothLE1: TBluetoothLE;
    ListBox1: TListBox;
    StyleBook1: TStyleBook;
    procedure BluetoothLE1CharacteristicRead(const Sender: TObject;
      const ACharacteristic: TBluetoothGattCharacteristic;
      AGattStatus: TBluetoothGattStatus);
    procedure BluetoothLE1EndDiscoverDevices(const Sender: TObject;
      const ADeviceList: TBluetoothLEDeviceList);
    procedure BluetoothLE1EndDiscoverServices(const Sender: TObject;
      const AServiceList: TBluetoothGattServiceList);
    procedure ConnectClick(Sender: TObject);
    procedure SendClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ListBox1ItemClick(const Sender: TCustomListBox;
      const Item: TListBoxItem);
  private
    { private 먬뙻 }
  public
    { public 먬뙻 }
  end;

var
  Form42: TForm42;
  GBleDevice         : TBluetoothLEDevice;
  BackColor          : TColor;

implementation

{$R *.fmx}
{$R *.iPhone55in.fmx IOS}

procedure TForm42.BluetoothLE1CharacteristicRead(const Sender: TObject;
  const ACharacteristic: TBluetoothGattCharacteristic;
  AGattStatus: TBluetoothGattStatus);
begin
  if(ACharacteristic.UUID = UUID_BUTTON1_CHARACTERRISTIC) then
  begin
    if  ACharacteristic.GetValueAsInt8(0) <> 0 then
        ButtonA.Fill.Color := TAlphaColorRec.Red
    else
        ButtonA.Fill.Color := BackColor;
  end
  else
  if(ACharacteristic.UUID = UUID_BUTTON2_CHARACTERRISTIC) then
  begin
    if  ACharacteristic.GetValueAsInt8(0) <> 0 then
        ButtonB.Fill.Color := TAlphaColorRec.Red
    else
        ButtonB.Fill.Color := BackColor;
  end;
end;

procedure TForm42.BluetoothLE1EndDiscoverDevices(const Sender: TObject;
  const ADeviceList: TBluetoothLEDeviceList);
var
i : uint32;   // ARM 궶궻궳띍밙돸
device : TBluetoothLEDevice;
begin

  ListBox1.Clear;
  for i := 0 to ADeviceList.Count-1 do begin
    device := ADeviceList.Items[i];
    ListBox1.Items.AddObject(device.DeviceName +'/' + device.Address, device);
  end;

  {
  if ADeviceList.Count > 0 then begin
    for i := 0 to Pred(ADeviceList.Count) do begin
      if Pos('BBC micro:bit', ADeviceList[i].DeviceName) > 0 then begin
        Label1.Text := ADeviceList[i].DeviceName ;// ' (' + ADeviceList[i].Address + ')';
        BluetoothLE1.CancelDiscovery;
        GBleDevice  :=  ADeviceList[i];
        GBleDevice.DiscoverServices;
        exit;
      end;
    end;
  end;
  }
end;

procedure TForm42.BluetoothLE1EndDiscoverServices(const Sender: TObject;
  const AServiceList: TBluetoothGattServiceList);
var
  i : uint32;   // ARM 궶궻궳띍밙돸
  LGattService   : TBluetoothGattService;
begin
  LGattService := BluetoothLE1.GetService(GBleDevice, UUID_BUTTON_SERVICE);
  if LGattService <> nil then
  begin
    for i := 0 to Pred(LGattService.Characteristics.Count) do
    begin
        if LGattService.Characteristics[i].UUID = UUID_BUTTON1_CHARACTERRISTIC then
        begin
           GBleDevice.SetCharacteristicNotification(LGattService.Characteristics[i], True);
        end
        else
        if LGattService.Characteristics[i].UUID = UUID_BUTTON2_CHARACTERRISTIC then
        begin
           GBleDevice.SetCharacteristicNotification(LGattService.Characteristics[i], True);
        end;
    end;
  end;

end;

procedure TForm42.ConnectClick(Sender: TObject);
begin
  if( not BluetoothLE1.Enabled ) then
  begin
    BluetoothLE1.Enabled := True;
    BluetoothLE1.DiscoverDevices(1000);  // 10뷳
    Connect.Text := 'Disconnect';
    Label1.Text  := '';
  end
  else
  begin
    ListBox1.Clear;
    BluetoothLE1.CancelDiscovery;
    BluetoothLE1.Enabled := False;
    GBleDevice           := NIL;
    Connect.Text := 'Connect';
  end;
end;

procedure TForm42.FormCreate(Sender: TObject);
begin
    BackColor :=  ButtonA.Fill.Color;
end;

procedure TForm42.ListBox1ItemClick(const Sender: TCustomListBox; const Item: TListBoxItem);
var
  BLEDevice : TBluetoothLEDevice;
begin
  BLEDevice := Item.Data as TBluetoothLEDevice;
  Label1.Text := BLEDevice.DeviceName ;// ' (' + ADeviceList[i].Address + ')';
  BluetoothLE1.CancelDiscovery;
  GBleDevice  :=  BLEDevice;
  GBleDevice.DiscoverServices;
end;

procedure TForm42.SendClick(Sender: TObject);
var
  i : uint32;   // ARM 궶궻궳띍밙돸
  LGattService : TBluetoothGattService;
  LCharact     : TBluetoothGattCharacteristic;
begin
  if GBleDevice             = NIL   then exit;
  if GBleDevice.IsConnected = false then exit;

  LGattService := BluetoothLE1.GetService(GBleDevice, UUID_UART_SERVICE);
  if  LGattService   = NIL   then exit;
//  LCharact     :=  LGattService.GetCharacteristic(UUID_UART_TX_CHARACTERRISTIC);
  for i := 0 to Pred(LGattService.Characteristics.Count) do
  begin
    if LGattService.Characteristics[i].UUID = UUID_UART_TX_CHARACTERRISTIC then
    begin
       LGattService.Characteristics[i].SetValueAsString(Edit1.Text+':', True);
       GBleDevice.WriteCharacteristic(LGattService.Characteristics[i]);
       exit;
    end;
  end;
end;

end.

실행

예제 파일 컴파일 (참고용)

(workspace) D:\tmp>git clone https://github.com/lancaster-university/microbit-samples.git
(workspace) D:\tmp>cd microbit-samples
(workspace) D:\tmp\microbit-samples>yotta target bbc-microbit-classic-gcc
(workspace) D:\tmp\microbit-samples>copy source\examples\bluetooth-services\main.cpp source
(workspace) D:\tmp\microbit-samples>copy source\examples\bluetooth-services\config.json .
(workspace) D:\tmp\microbit-samples>yotta clean
(workspace) D:\tmp\microbit-samples>yotta build


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - OLED Display SSD1331 제어

OS/micro:bit 2018.01.24 23:50 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : ssd1331 - SSD1331 Oled driver library for 96x64 colour Oled display. Demo included in .h file | Mbed

micro:bit - OLED Display SSD1331 제어

micro:bit로 oled 모듈인 ssd1331 제어하는 예제를 C++로 만들어 보았습니다. 라이브러리 소스(출처 : ssd1331 - SSD1331 Oled driver library for 96x64 colour Oled display. Demo included in .h file | Mbed)를 받아서 사용했습니다.

소스 - ssd1331.h

라이브러리 소스 파일 -  ssd1331_lib.zip

#ifndef __ssd1331_H__
#define __ssd1331_H__

#include "mbed.h"

// Screen Settings
#define width   96-1        // Max X axial direction in screen
#define height  64-1        // Max Y axial direction in screen
#define Set_Column_Address  0x15
#define Set_Row_Address     0x75
#define contrastA           0x81
#define contrastB           0x82
#define contrastC           0x83
#define display_on          0xAF
#define display_off         0xAE

// Internal Font size settings
#define NORMAL  0
#define WIDE    1
#define HIGH    2
#define WH      3
#define WHx36   4
#define X_width 6 
#define Y_height 8 


// GAC hardware acceleration commands
#define GAC_DRAW_LINE           0x21    // Draw Line
#define GAC_DRAW_RECTANGLE      0x22    // Rectangle
#define GAC_COPY_AREA           0x23    // Copy Area
#define GAC_DIM_WINDOW          0x24    // Dim Window
#define GAC_CLEAR_WINDOW        0x25    // Clear Window
#define GAC_FILL_ENABLE_DISABLE 0x26    // Enable Fill
#define SCROLL_SETUP            0x27    // Setup scroll
#define SCROLL_STOP             0x2E    // Scroll Stop
#define SCROLL_START            0x2F    // Scroll Start

// Basic RGB color definitions         RED GREEN BLUE values                         

#define Black           0x0000      //   0,   0,   0 
#define LightGrey       0xC618      // 192, 192, 192 
#define DarkGrey        0x7BEF      // 128, 128, 128 
#define Red             0xF800      // 255,   0,   0 
#define Green           0x07E0      //   0, 255,   0 
#define Cyan            0x07FF      //   0, 255, 255 
#define Blue            0x001F      //   0,   0, 255 
#define Magenta         0xF81F      // 255,   0, 255 
#define Yellow          0xFFE0      // 255, 255,   0 
#define White           0xFFFF      // 255, 255, 255 

class ssd1331 : public Stream {
public:
    // constructor
    ssd1331(PinName cs_pin, PinName rst_pin, PinName a0_pin, PinName mosi_pin, PinName miso_pin, PinName sclk_pin);
    
    void Init(void);
    void pixel(uint8_t x,uint8_t y, uint16_t color); // place a pixel x,y coordinates, color
    void rect(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint16_t colorline); // draw rectangle, start x,y end x,y, color
    void fillrect(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint16_t colorline,uint16_t colorfill); // fill rectangle start x,y, end x,y, outline color, fill color.
    void line(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint16_t color); // draw line start x,y, end x,y, color
    void circle (uint8_t radius, uint8_t x, uint8_t y,uint16_t color,uint16_t fill); // draw circle radius, position x,y, color
    void Fill_Screen(uint16_t color); // fill screen with any colour
    void foreground(uint16_t color); // set text color
    void background(uint16_t color); // set background color
    void SetFontSize(uint8_t); // set internal font size NORMAL, HIGH, WIDE, WH (high and wide), WHx36 (large 36x36 pixel size)
    void on();  // display on
    void off(); // display off
    void cls(); // clear screen to black screen
    void dim();  // flip dim/normal on each call
    void contrast(char value); //0~9 low~high
    void locate(uint8_t column, uint8_t row); // text start position x,y
    uint16_t toRGB(uint16_t R,uint16_t G,uint16_t B);   // get color from RGB values 00~FF(0~255)
    uint8_t row(); // set row position (in pixels)
    uint8_t column(); // set column position (in pixels)
    void ScrollSet(int8_t horizontal, int8_t startline, int8_t linecount, int8_t vertical , int8_t frame_interval); // set up scroll function
    void Scrollstart(); // start scrolling
    void Scrollstop(); // stop scrolling
    void Copy(uint8_t src_x1,uint8_t src_y1,uint8_t src_x2,uint8_t src_y2, uint8_t dst_x,uint8_t dst_y); // GAC function to copy/paste area on the screen
    void character(uint8_t x, uint8_t y, uint16_t c); // Print single character, x & y pixel co-ords.
    void set_font(unsigned char* f); // set external font. Use oled.set_font(NULL) to restore default font
    void Bitmap(const uint8_t *bitmap, uint8_t x, uint8_t y, uint8_t w, uint8_t h, unsigned char color); // load mono bitmap from flash
    void Bitmap16(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *bitmap); // load bitmap from flash
    
    int Bitmap16RAM(uint8_t x, uint8_t y, unsigned char *Name_BMP); // copy image to RAM, uses up to 12.288k RAM, Fast but need plenty of RAM
    int Bitmap16FS(uint8_t x, uint8_t y, unsigned char *Name_BMP); // load from fielsystem, uses 96b RAM, slower, will work on any MCU
    // use GIMP to generate images, open image, select image-scale image, set width/height(max 96x64), select File-Export As
    // select Windows BMP image, Name it with .BMP extension, select export, select Compatability Options- check 'Do Not write colour space'
    // select Advanced Options- check '16bit R5 G6 B5', select export. Copy the file to a SD card or to the local file system. 
    // image maximum size 96x64, smaller images can be placed anywhere on screen setting x,y co-ords but must fit within boundaries
    // example:
    // oled.Bitmap16FS(0,0,(unsigned char *)"/sd/image.bmp"); full size 96x64 image
    // oled.Bitmap16RAM(20,20,(unsigned char *)"/sd/image.bmp"); place smaller image starting x-20, y-20
   
protected:
    // Stream implementation functions
    virtual int _putc(int c);
    virtual int _getc();
private:
    void RegWrite(unsigned char Command);
    void RegWriteM(unsigned char *Command, uint8_t count);
    void DataWrite(unsigned char c);
    void DataWrite_to(uint16_t Dat);
    void FontSizeConvert(int *lpx, int *lpy);
    void PutChar(uint8_t x,uint8_t y,int a);
    void PutCharInt(uint8_t x,uint8_t y,uint16_t a);
    void putp(int colour);
    unsigned char* font;
    uint16_t Char_Color;    // text color
    uint16_t BGround_Color; // background color
    void window(uint8_t x, uint8_t y, uint8_t w, uint8_t h);
    void Maxwindow(); // reset display window to full size
    // pixel location
    uint8_t _x;
    uint8_t _y;
    
    // window location
    uint8_t _x1;
    uint8_t _x2;
    uint8_t _y1;
    uint8_t _y2;
    uint8_t char_x;
    uint8_t char_y;
    uint8_t chr_size;
    uint8_t cwidth;       // character's width
    uint8_t cvert;        // character's height
    uint8_t externalfont;
    DigitalOut  CS,  RES,  DC;
    SPI spi; // mosi, miso, sclk    
};

#endif

소스 - main.cpp

#include "MicroBit.h" 
#include "ssd1331.h" 
 
MicroBit uBit;

// ssd1331(PinName cs_pin, PinName rst_pin, PinName a0_pin, PinName mosi_pin, PinName miso_pin, PinName sclk_pin);
ssd1331 oled(P0_16, P0_26, P0_20, P0_21, P0_22, P0_23); // cs, res, dc, miso(nc), sck (KL25z)

char Time[50],Date[50];
void gettime();
 
int main() { 
  uBit.init(); 
  uBit.display.scroll("ssd1331"); 
  
  while(1){
      
    oled.Fill_Screen(oled.toRGB(255,0,0)); //red
    wait_ms(500);
    oled.Fill_Screen(oled.toRGB(0,255,0)); //green
    wait_ms(500);
    oled.Fill_Screen(oled.toRGB(0,0,255)); //blue
    wait_ms(500);
    oled.Fill_Screen(oled.toRGB(255,255,255)); //white
    wait_ms(500);
    
    oled.cls(); // clear screen to black

    oled.circle (20, 40, 30 ,oled.toRGB(0,0,255) , 1);      //fill circle
    oled.circle (20, 40, 30 ,oled.toRGB(255,255,255) , 0);  //circle 
    oled.circle (20, 60, 40 ,oled.toRGB(255,0,0) , 0);      //circle
    oled.line( 0, 0, width, height, oled.toRGB(0,255,255)); //line
    oled.line( width, 0, 0, height, oled.toRGB(255,0,255)); //line
    oled.rect(10,10,90,60,oled.toRGB(255,255,0));      //rectangle
    oled.fillrect(20,20,40,40,oled.toRGB(255,255,255),oled.toRGB(0,255,0)); //fillrectangle
    
    for(int y = 9; y >= 0; y--) {
			oled.contrast(y);  // set contrast level
			oled.foreground(oled.toRGB(255,255,255)); // set text colour
			oled.locate(1, 10); // set text start location
			oled.printf("%d",y); // std printf
			wait_ms(300);
    } 
    
    wait_ms(1000);
    oled.contrast(9); // set contrast to maximum
    wait_ms(2000);
    oled.cls();

    oled.SetFontSize(HIGH); // set tall font
    oled.foreground(oled.toRGB(0,255,0)); // set text colour
    oled.locate(0, 10);
    oled.printf( "HIGH 12345");  
    
    oled.SetFontSize(WIDE); // set text to wide
    oled.foreground(oled.toRGB(0,0,255));
    oled.locate(0, 28);
    oled.printf( "WIDE 123");  
    
    oled.SetFontSize(WH); // set text to wide and tall
    oled.foreground(oled.toRGB(255,0,0));
    oled.locate(0, 40);
    oled.printf( "WH 123");
    
    oled.SetFontSize(NORMAL); // set text to normal
    oled.foreground(oled.toRGB(255,255,255));      
            
    oled.ScrollSet(0,8,18,1,0); // set scroll function
    oled.Scrollstart(); // start scroll
   
    gettime();wait(1);gettime();wait(1);gettime();wait(1);      
    oled.ScrollSet(0,8,18,-2,0);
    oled.Scrollstart();       
    gettime();wait(1);gettime();wait(1);gettime();wait(1);
    
    oled.ScrollSet(0,8,18,3,0);
    oled.Scrollstart();
    
    gettime();wait(1);gettime();wait(1);gettime();wait(1);
    
    oled.ScrollSet(0,8,18,-4,0);
    oled.Scrollstart();
   
    gettime();wait(1);gettime();wait(1);gettime();wait(1);
    
    oled.Scrollstop(); // stop scroll
    wait(1);
  }        
  
  uBit.display.scroll("bye");
  release_fiber();   
}

void gettime() {  
  time_t seconds = uBit.systemTime();
  strftime(Time,40,"%H:%M:%S %a", localtime(&seconds));
  strftime(Date,40,"%d-%b-%Y", localtime(&seconds));
  oled.locate(0, 0);
  oled.printf(Time); 
}

실행


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - LED 켜기/끄기

OS/micro:bit 2018.01.24 02:38 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Arduino Pong Game - OLED Display: 5 Steps (with Pictures)

micro:bit - LED 켜기/끄기

micro:bit 자체에 LED가 내장되어 있지만 디지탈 pin을 이용해서 LED 켜고, 끄기 예제를 C++로 구현해보았습니다.

소스

#include "MicroBit.h" 
 
MicroBit uBit;
DigitalOut myled(P0_16);
 
int main() { 
  uBit.init(); 
  uBit.display.scroll("LED TEST");
  
  while (1) {
		myled = 1;
		wait(0.5);
		myled = 0;
		wait(0.5);
  }
  
  release_fiber();   
}

실행


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - Bluetooth(HC-06) Serial 통신

OS/micro:bit 2018.01.24 02:37 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Bluetooth_HC-06 - Bluetooth HC-06 Hello world | Mbed
Pighixxx Esp32 Pinout Microbit ~ wiring diagram components

micro:bit - Bluetooth(HC-06) Serial 통신

micro:bit는 블루투스 4.0인 BLE를 지원하지만, 앱인벤터는 BT통신(블루투스 2.0)만 지원하고 있어서, micro:bit에 HC-06을 사용해서 앱인벤터와 BT 통신하는 예제를 구현해보았습니다. 예제는 앱인벤터에서 r 문자를 보내면 micro:bit에서 r를 LED에 출력하고 Hello World를 전달하면 다시 앱인벤터에서는 전달받은 문자열을 TextView에 보여주고, 다시 q 를 micro:bit에 전달하면 micro:bit는 while을 빠져 나와서 bye를 LED에 출력하고 프로그램을 종료합니다.

micro:bit pin 배열

이미지 출처 : Pighixxx Esp32 Pinout Microbit ~ wiring diagram components

배선

소스 - main.cpp

pulse-combined.hex

#include "MicroBit.h"
 
MicroBit uBit;
Serial HC06(P0_17,P0_12); // tx, rx,
 
int main() { 
  uBit.init(); 
  uBit.display.scroll("HC-06"); 
  
  HC06.baud(9600);
  while (1) {
    char c = HC06.getc();
    if(c == 'r') {
      HC06.printf("Hello World\n");
      //
      uBit.display.scroll(c); 
    } else if(c == 'q') {
    	break;
    }
  }
  
  uBit.display.scroll("bye");
  release_fiber();   
}

app inventor

microbit_hc06_3.apk


실행


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit - C++ 오프라인 hex 빌드

OS/micro:bit 2018.01.15 15:39 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Offline C/C++ Development With The Micro:bit - I Programmer
在 Windows/MacOS X 平台安裝 NetBeans IDE (for C++程式開發@BBC micro:bit) - 曾令燊Davis@Blog部落格

micro:bit는 기본적으로 microsoft block, microsot touch, javascript, python을 지원지만, c++도 지원하는데, 온라인 상태의 편집기가 아닌 오프라인에서 컴파일해서 hex 파일을 만들 수 있습니다. 온라인 상태에서 가능한 mbed은 다음에 알아보도록 하고 오프라인에서 hex 파일을 생성하는 방법을 알아보겠습니다.

yotta 설치

파이썬 OpenSSL 패키지 설치

pip install pyopenssl

srecord 설치

srecord 다운로드(https://sourceforge.net/projects/srecord/files/latest/download?source=files) 받아서 C:\yotta 폴더에 압축풀기

개발환경 만들기

(workspace) D:\>mkdir pulse
(workspace) D:\>cd pulse
(workspace) D:\pulse>yotta init
(workspace) D:\pulse>yotta target bbc-microbit-classic-gcc
(workspace) D:\pulse>yotta install lancaster-university/microbit

yotta init

yotta target bbc-microbit-classic-gcc

yotta install lancaster-university/microbit

main.cpp

#include "MicroBit.h" 
 
MicroBit uBit;  
 
int main() { 
  uBit.init(); 
  uBit.display.scroll("http://bluexmas.tistory.com"); 
  release_fiber(); 
}

빌드 - hex 파일 생성

실행

pulse-combined.hex 파일 마이크로 비트에 복사


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

micro:bit 개봉기

OS/micro:bit 2018.01.13 20:55 Posted by 파란크리스마스

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Features | micro:bit

아이씨뱅크에서 micro:bit 체험 이벤트에 선정되어서 micro:bit를 접하게 되었는데, 처음에는 아두이노 짝퉁 정도로 생각되었는데, 스펙이나 확장면에서 많은 부분 아우이노와 비교되지 않은 정도로 기본적으로 가지고 있는 센서와 인터페이스을 가지고 있습니다.

micro:bit 개봉기

택배 박스

택배 박스 개봉

내용물 - 안내장과 비닐 포장

micro:bit 내용물

간단한 설명서 2장(한글은 없네요), AAA건전지 1.5v 2개,  AAA건전지 홀더, micro:bit 기본 보드, 마이크로 5핀 케이블

micro:bit 스펙

이미지 출처 : Features | micro:bit

LEDs

5x5 25개의 LED가 있어서 간단한 영문 텍스트나 숫자, 이미지를 표현

Buttons

좌우 2개의 버튼이 있어서 버튼 클릭 이벤트를 받을 수 있음

Pins

출처 : BBC micro:bit Pins

Light Sensor

전면의 LED를 입력모드로 변경하면, 전면 LED가 광 센서로 작동하여 주변 광을 감지 할 수 있음

온도센서 - Temperature Sensor

이 센서를 통해 micro:bit는 주변의 온도를 감지

가속도 센서 - Accelerometer

가속도 센서는 흔들림, 기울기 및 자유 낙하 등이 있음(향후 드론도 만들 수 있을 것으로 예상)

나침반 - Compass

나침반 기능이 있어서 동서남북 측정

Radio

WIFI나 블루투스보다 송수신 거리가 길어서 드론에서 많이 사용하는 통신 수단으로 라디오 송수신 기능 제공

Bluetooth

BLE (Bluetooth Low Energy) 통신 신호를 송수신하거나 프로그램 업로드 가능

USB Interface

PC와 연결해서 전원 공급과 동시에 프로그램 업로드가능한 마이크로 5핀 커넥터 제공

개인적인 평가

micro:bit는 아두이노와 다르게 기본적으로 제공되는 센서가 많아서 micro:bit 하나만으로도 충분히 많은 아이디어를 구현 할 수 있는 기기로 프로그램 개발 언어도 초보자가 개발가능한 Microsoft Block이나 Microsoft Touch를 지원하고 있고, 조금 더 전문적인 언어로 JavaScript, python도 지원합니다. 아직까지 지원 모듈이 없지만 드론제작울 염두 해두고 만든것 처럼 가속도 센서나, 드론에서 많이 사용하는 배터리도 호환되고, 통신방식으로 라이오 송수신까지 지원합니다. 

프로그램 업로드는 USB이용해서 PC에서 가능하고, 블루투스를 이용해서 모바일 폰에서도 업로드가 가능합니다. 

마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

Orange Pi Zero Plus2

OS/Orange PI 2018.01.06 00:28 Posted by 파란크리스마스

Orange Pi Zero Plus2

출처 : 스터디메이크 :: 오렌지파이 제로 보드 간단 사용기
Xunlong Orange Pi Zero

 

 

OS 설치

OS 다운로드 - Orange Pi Zero 2+ H5

부팅후 계정 설정

Ubuntu 16.04.3 LTS orangepizeroplus2 ttyS0
 
orangepizeroplus2 login: root
Password: [1234]
You are required to change your password immediately (root enforced)
Changing password for root.
(current) UNIX password: [1234]
Enter new UNIX password: [orangepi]
Retype new UNIX password: [orangepi]
  ___  ____  _   _____                ____  _             ____
 / _ \|  _ \(_) |__  /___ _ __ ___   |  _ \| |_   _ ___  |___ \
| | | | |_) | |   / // _ \ '__/ _ \  | |_) | | | | / __|   __) |
| |_| |  __/| |  / /|  __/ | | (_) | |  __/| | |_| \__ \  / __/
 \___/|_|   |_| /____\___|_|  \___/  |_|   |_|\__,_|___/ |_____|
 
 
Welcome to ARMBIAN 5.34.171121 nightly Ubuntu 16.04.3 LTS 4.13.14-sunxi64
System load:   0.42 0.12 0.04   Up time:       0 min
Memory usage:  8 % of 482MB     IP:
CPU temp:      27°C
Usage of /:    4% of 29G
 
[ General system configuration (beta): armbian-config ]
 
New to Armbian? Check the documentation first: https://docs.armbian.com
 
 
You are using an Armbian nightly build meant only for developers to provide
constructive feedback to improve build system, OS settings or user experience.
If this does not apply to you, STOP NOW!. Especially don't use this image for
daily work since things might not work as expected or at all and may break
anytime with next update. YOU HAVE BEEN WARNED!
 
This image is provided AS IS with NO WARRANTY and NO END USER SUPPORT!.
 
Creating a new user account. Press <Ctrl-C> to abort
 
Please provide a username (eg. your forename): pi
Trying to add user pi
Adding user `pi' ...
Adding new group `pi' (1000) ...
Adding new user `pi' (1000) with group `pi' ...
Creating home directory `/home/pi' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: [orangepi]
Retype new UNIX password: [orangepi]
passwd: password updated successfully
Changing the user information for pi
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n]
 
 
 
Dear pi, your account pi has been created and is sudo enabled.
Please use this account for your daily work from now on.
 
root@orangepizeroplus2:~#

Wifi 설정

armbian 와이파이 설정

출처 : 오렌지파이 제로 무선인터넷 설정 1.2 암비안 와이파이 설정

$ sudo nmtui

eMMC os 설치

출처 : #Test: Orange Pi Plus 2e: unpacking and installing Armbian on eMMC memory • DIY Projects

$ sudo nand-sata-install

JDK 설치

출처 : Install Java 8 on Armbian (Orange Pi Lite or higher) • DIY Projects

저장소 추가

$ sudo add-apt-repository ppa:webupd8team/java

추가한 저장소 반영

$ sudo apt-get update

JDK 설치

$ sudo apt-get install oracle-java8-installer

JAVA_HOME 환경변수 추가

$ sudo vi /etc/profile

내용 추가 export JAVA_HOME=/usr/lib/jvm/java-8-oracle

export JAVA_HOME=/usr/lib/jvm/java-8-oracle

JDK 설치 확인

$ $JAVA_HOME/bin/java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) Client VM (build 25.151-b12, mixed mode)

SD 추가

출처 : Setting up the bootable SD card - Orange Pi

디스크 확인

$ sudo fdisk -l
Disk /dev/mmcblk2: 7.3 GiB, 7818182656 bytes, 15269888 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2e3d2df2
 
Device         Boot Start      End  Sectors  Size Id Type
/dev/mmcblk2p1       8192 15117183 15108992  7.2G 83 Linux
 
 
Disk /dev/mmcblk2boot1: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
 
 
Disk /dev/mmcblk2boot0: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
 
 
Disk /dev/zram0: 60.3 MiB, 63270912 bytes, 15447 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
 
 
Disk /dev/zram1: 60.3 MiB, 63270912 bytes, 15447 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
 
 
Disk /dev/zram2: 60.3 MiB, 63270912 bytes, 15447 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
 
 
Disk /dev/zram3: 60.3 MiB, 63270912 bytes, 15447 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
 
 
Disk /dev/mmcblk0: 29.7 GiB, 31914983424 bytes, 62333952 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x67c048bb
 
Device         Boot Start      End  Sectors  Size Id Type
/dev/mmcblk0p1       8192 61710591 61702400 29.4G 83 Linux

기존 파이션 삭제 및 파티션 생성

pi@orangepizeroplus2:~$ sudo fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): d
Partition number (1,2, default 2): [Enter]

Partition 2 has been deleted.

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): [Enter]

Using default response p.
Partition number (1-4, default 1): [Enter]
First sector (2048-62333951, default 2048): [Enter]
Last sector, +sectors or +size{K,M,G,T,P} (2048-62333951, default 62333951): [Enter]

Created a new partition 1 of type 'Linux' and of size 29.7 GiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

pi@orangepizeroplus2:~$ 

디스크 포맷

$ sudo mkfs.ext4 /dev/mmcblk0p1
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done                            
Creating filesystem with 7791488 4k blocks and 1949696 inodes
Filesystem UUID: 620c3235-2471-45b6-bd2e-5ead5fc11350
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
        4096000
 
Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done 

마운트

$ sudo mount /dev/mmcblk0p1 /mnt

마운트 확인

$ df -k
Filesystem     1K-blocks    Used Available Use% Mounted on
udev              178792       0    178792   0% /dev
tmpfs              49432    2440     46992   5% /run
/dev/mmcblk2p1   7304800 1201820   5708872  18% /
tmpfs             247148       0    247148   0% /dev/shm
tmpfs               5120       0      5120   0% /run/lock
tmpfs             247148       0    247148   0% /sys/fs/cgroup
tmpfs             247148       0    247148   0% /tmp
log2ram            51200    1320     49880   3% /var/log
tmpfs              49432       0     49432   0% /run/user/0
tmpfs              49432       0     49432   0% /run/user/1000
/dev/mmcblk0p1  30545420   44992  28925748   1% /mnt

eMMC 백업

$ sudo dd bs=4M if=/dev/mmcblk2 of=/mnt/emmc_backup.img
1864+0 records in
1864+0 records out
7818182656 bytes (7.8 GB, 7.3 GiB) copied, 474.25 s, 16.5 MB/s


BPI-M2 Berry - I2C 이용 PCA9685 제어

OS/Banana Pi 2018.01.01 13:31 Posted by 파란크리스마스

출처 : Maker Projects: Banana Pi I2C Devices
BPI-M2,use wiringPi I2C to read mpu6050 - Banana Pi BPI-M2 / Linux - banana pi single board computer official forum SinoVoip BPI team
node.js - johntreacy/adafruit-pca9685
adafruit/Adafruit_Python_PCA9685: Python code to use the PCA9685 PWM servo/LED controller with a Raspberry Pi or BeagleBone black.

BPI-M2 Berry GPIO Pin define

출처 : BPI-M2 Ultra GPIO Pin define · banana pi BPI-M2 Ultra/Berry allwinner R40/V40 SBC

GPIO Pin Name Default Function Function2:GPIO Function3
CON1-P01 VCC-3V3
CON1-P02 DCIN
CON1-P03 TWI2-SDA PB21 PWM5
CON1-P04 DCIN
CON1-P05 TWI2-SCK PB20 PWM4
CON1-P06 GND
CON1-P07 PB3 PB3 PWM1
CON1-P08 UART2-TX PI18 SPI1_MOSI
CON1-P09 GND
CON1-P10 UART2-RX PI19 SPI1_MISO
CON1-P11 UART7-TX PI20 PWM2
CON1-P12 UART2-CTS PI17 SPI1_CLK
CON1-P13 UART7-RX PI21 PWM3
CON1-P14 GND
CON1-P15 PH25 PH25 CSI1-FIELD
CON1-P16 UART2-RTS PI16 SPI1_CS0
CON1-P17 VCC-3V3
CON1-P18 PH26 PH26 CSI1-HSYNC
CON1-P19 SPI0_MOSI PC0
CON1-P20 GND
CON1-P21 SPI0_MISO PC1
CON1-P22 PH27 PH27 CSI1-VSYNC
CON1-P23 SPI0_CLK PC2
CON1-P24 SPI0_CS PC23
CON1-P25 GND
CON1-P26 PH24 PH24 CSI1-PCLK
CON1-P27 TWI3-SDA PI1
CON1-P28 TWI3-SCK PI0
CON1-P29 PH0 PH0 CSI1-D0
CON1-P30 GND
CON1-P31 PH1 PH1 CSI1-D1
CON1-P32 PD20 PD20 CSI1-MCLK
CON1-P33 PH2 PH2 CSI1-D2
CON1-P34 GND
CON1-P35 PH3 PH3 CSI1-D3
CON1-P36 UART5-RX PH7 CSI1-D7
CON1-P37 UART4-TX PH4 CSI1-D4
CON1-P38 UART5-TX PH6 CSI1-D6
CON1-P39 GND
CON1-P40 UART4-RX PH5 CSI1-D5

I2C 목록 조회 - i2cdetect -l

$ i2cdetect -l
i2c-0   i2c             twi0                                    I2C adapter
i2c-1   i2c             twi1                                    I2C adapter
i2c-2   i2c             twi2                                    I2C adapter
i2c-4   i2c             twi4                                    I2C adapter

I2C 주소 확인 - i2cdetect -y

$ i2cdetect -y 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

gpio readall

 +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |  53 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5v      |     |     |
func:sunxi_get_pin_mode pin:53,  bank:1 index:21 phyaddr:0x1c2082c
read reg val: 0x22222233 offset:20  return: 0
read reg val: 0x22222233 offset:20  return: 2
func:sunxi_digitalRead pin:53,bank:1 index:21 phyaddr:0x1c20834
***** read reg val: 0x0,bank:1,index:21,line:850
 |  52 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |
func:sunxi_get_pin_mode pin:52,  bank:1 index:20 phyaddr:0x1c2082c
read reg val: 0x22222233 offset:16  return: 0
read reg val: 0x22222233 offset:16  return: 2
func:sunxi_digitalRead pin:52,bank:1 index:20 phyaddr:0x1c20834
***** read reg val: 0x0,bank:1,index:20,line:850
| 257 |  30 |   SDA.0  | ALT3 | 0 | 27
func:sunxi_get_pin_mode pin:257,  bank:8 index:1 phyaddr:0x1c20920
read reg val: 0x77703377 offset:4  return: 0
read reg val: 0x77703377 offset:4  return: 7
func:sunxi_digitalRead pin:257,bank:8 index:1 phyaddr:0x1c20930
***** read reg val: 0x0,bank:8,index:1,line:850
                                       || 28 | 0 | ALT3 | SCL.0   | 31  | 256 |
func:sunxi_digitalRead pin:256,bank:8 index:0 phyaddr:0x1c20930
***** read reg val: 0x0,bank:8,index:0,line:850
func:sunxi_get_pin_mode pin:256,  bank:8 index:0 phyaddr:0x1c20920
read reg val: 0x77703377 offset:0  return: 0
read reg val: 0x77703377 offset:0  return: 7

BPI-M2 Berry - I2C 이용 PCA9685 제어 소스 - PCA9685Gpio.java

import java.io.IOException;
/**
 * $ sudo java -cp .:pi4j/* PCA9685Gpio
 */
import java.math.BigDecimal;

import com.pi4j.gpio.extension.pca.PCA9685GpioProvider;
import com.pi4j.gpio.extension.pca.PCA9685Pin;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinPwmOutput;
import com.pi4j.io.gpio.BPIM2BerryGpioProvider;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CFactory;
import com.pi4j.io.i2c.I2CFactory.UnsupportedBusNumberException;

public class PCA9685Gpio {
	
	public static final int SERVO_DURATION_MIN = 600;
	public static final int SERVO_DURATION_NEUTRAL = 1500;
	public static final int SERVO_DURATION_MAX = 2400;
	
	private static PCA9685Gpio instance = null;
	
	private PCA9685GpioProvider gpioProvider = null;
	
	// sudo java -cp .:pi4j-core.jar:pi4j-gpio-extension.jar PCA9685Gpio
	
	private PCA9685Gpio() throws IOException, UnsupportedBusNumberException {		
		
		//GpioFactory.setDefaultProvider(new BPIM2PGpioProvider());
		//GpioFactory.setDefaultProvider(new NanoPiNEOAirGpioProvider());
		GpioFactory.setDefaultProvider(new BPIM2BerryGpioProvider());
		
		System.out.println("<--Pi4J--> PCA9685 PWM Example ... started.");
		// This would theoretically lead into a resolution of 5 microseconds per
		// step:
		// 4096 Steps (12 Bit)
		// T = 4096 * 0.000005s = 0.02048s
		// f = 1 / T = 48.828125
		BigDecimal frequency = new BigDecimal("48.828");
		// Correction factor: actualFreq / targetFreq
		// e.g. measured actual frequency is: 51.69 Hz
		// Calculate correction factor: 51.65 / 48.828 = 1.0578
		// --> To measure actual frequency set frequency without correction
		// factor(or set to 1)
		BigDecimal frequencyCorrectionFactor = new BigDecimal("1.0578");
		// Create custom PCA9685 GPIO provider
		I2CBus bus = I2CFactory.getInstance(I2CBus.BUS_2);
		gpioProvider = new PCA9685GpioProvider(bus, 0x40, frequency, frequencyCorrectionFactor);
		// Define outputs in use for this example
		GpioPinPwmOutput[] myOutputs = provisionPwmOutputs(gpioProvider);
		// Reset outputs
		gpioProvider.reset();
	}
	
	public static PCA9685Gpio getInstance() throws IOException, UnsupportedBusNumberException {
		if (instance==null) instance = new PCA9685Gpio();
		return instance;
	}
	
	public void setPwm(Pin pin, int duration) {
		gpioProvider.setPwm(pin, duration);
	}
	
	public void shutdown() {
		gpioProvider.shutdown();
	}
	
	private static GpioPinPwmOutput[] provisionPwmOutputs(final PCA9685GpioProvider gpioProvider) {
		GpioController gpio = GpioFactory.getInstance();
		GpioPinPwmOutput myOutputs[] = { 
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_00, "Pulse 00"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_01, "Pulse 01"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_02, "Pulse 02"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_03, "Pulse 03"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_04, "Pulse 04"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_05, "Pulse 05"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_06, "Pulse 06"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_07, "Pulse 07"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_08, "Pulse 08"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_09, "Pulse 09"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_10, "Always ON"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_11, "Always OFF"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_12, "Servo pulse MIN"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_13, "Servo pulse NEUTRAL"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_14, "Servo pulse MAX"),
				gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_15, "not used") };
		return myOutputs;
	}

	public static void main(String[] args) throws Exception {
		
		PCA9685Gpio test = PCA9685Gpio.getInstance();
		
		test.setPwm(PCA9685Pin.PWM_01, SERVO_DURATION_NEUTRAL);
		Thread.sleep(200);
		
		for (int i=SERVO_DURATION_MIN; i<=SERVO_DURATION_MAX; i+=30) {
			test.setPwm(PCA9685Pin.PWM_00, i);
			Thread.sleep(200);
		}
		
		for (int i=SERVO_DURATION_MAX; i>=(int)(SERVO_DURATION_MIN+(SERVO_DURATION_MAX-SERVO_DURATION_MIN)/2); i-=30) {
			test.setPwm(PCA9685Pin.PWM_00, i);
			Thread.sleep(200);
		}
				
		for (int i=SERVO_DURATION_MIN; i<=SERVO_DURATION_MAX; i+=30) {
			test.setPwm(PCA9685Pin.PWM_01, i);
			Thread.sleep(200);
		}
		
		for (int i=SERVO_DURATION_MAX-200; i>=(int)(SERVO_DURATION_MIN+(SERVO_DURATION_MAX-SERVO_DURATION_MIN)/2); i-=30) {
			test.setPwm(PCA9685Pin.PWM_01, i);
			Thread.sleep(200);
		}
		
		test.shutdown();

	}
	
}

컴파일

$ javac -cp .:pi4j/* -d . PCA9685Gpio.java

실행

$ sudo java -cp .:pi4j/* PCA9685Gpio

실행 영상




 

티스토리 툴바