micro:bit - 전방향 이동이 가능한 메카넘 휠(Mecanum Wheel)

OS/micro:bit 2019. 11. 21. 23:27 Posted by 파란크리스마스

출처

micro:bit - 전방향 이동이 가능한 메카넘 휠(Mecanum Wheel)

알리에서 주문한 전방향 이동이 가능한 메카넘 휠(Mecanum Wheel)로 RC카를 만들어 보았습니다.
아직 원격 조정은 구현 못했지만 조립한 RC카를 올립니다.

확장보드는 빌딩키트에서 사용한 마이크로비트용 확장보드를 이용했고, Yahboom Omni:bit의 확장 라이브러리을 이용해서 개발시면 됩니다.

전방향 이동이 가능한 메카넘 휠(Mecanum Wheel)

메카넘 휠(Mecanum Wheel) 제어 원리

이미지 출처 : Yahboom programmable Omni:bit smart robot car with Mecanum Wheel – yahboom

레고 마운트 가능한 360도 회전 모터

조립

완성

테스트 영상

댓글을 달아 주세요

micro:bit - 16채널 Servo 모터 제어용 확장보드

OS/micro:bit 2019. 11. 12. 00:24 Posted by 파란크리스마스

출처

micro:bit - 16채널 Servo 모터 제어용 확장보드

16채널 Servo 모터 제어용 확장보드를 이용해서 서브 모터를 제어 해보았습니다. 확장 라이브러리 추가로 간단하게 서브 모터가 제어가 가능합니다.

확장 라이브러리 추가

확장 메뉴 선택

검색창에 https://github.com/waveshare/pxt-Servo 입력하고, Servo를 선택해서 확장 라이브러리 추가 

확장 라이브러리 함수

예제

처음 실행하면 서브모터의 중앙(90도)으로 이동하고, A버튼을 선택하면 0도 이동하고, B버튼을 선택하면 180도 이동하는 예제입니다.

실행

댓글을 달아 주세요

micro:bit - indexOf (문자열에서 원하는 문자열을 검색)

OS/micro:bit 2019. 11. 10. 23:58 Posted by 파란크리스마스

출처

micro:bit - indexOf (문자열에서 원하는 문자열을 검색)

micro:bit 문자열 함수중에는 indexOf 함수가 없어서 구현 해보았습니다.

indexOf 함수

indexOf 함수 사용예제

라디오 통신에서 여러가지 명령을 꼼마 구분자로 문자열을 송신하고, 다른 마이크로비트에서 라디오 통신으로 문자열 수신했을 경우 다시 꼼마단위로 문자열을 분리할때 indexOf 함수를 사용하였습니다.

댓글을 달아 주세요

micro:bit - 함수를 인자로 호출하기

OS/micro:bit 2019. 11. 9. 18:00 Posted by 파란크리스마스

출처

함수를 인자로 호출하기

JavaScript에서 함수를 호출할때 함수를 변수처럼 인자로 전달하는 방법을 문의가 있어서 구현 시도해보았습니다.

결론을 말하자면 완벽하게 micri:bit에서는 함수를 인자로 호출은 되지만 인자나 반환값이 없는 함수는 가능힙니다.

편법으로 전달되는 함수의 인자와 반환값을 전역변수로 선언하고 전역변수를 사용하는 방식으로 구현해보았습니다.

함수를 인자로 전달하는 자료형은 Action 타입을 사용하시면 됩니다.

일반 JavaScript 소스

var fc = function (x) { return Math.sin(x) - Math.cos(x) + (1/2) };

function bisection(f,a,b,etol){
  
  console.log("f(a)= "+f(a)+", f(b)= "+f(b)+", f(a)*f(b)= "+f(a)*f(b));
  var a_n = a;
  var b_n = b;
  var e = 100;
  var n = 0;
  var c_n = (a_n + b_n)/2;
  while (n < 30){
    n++;
    if ((b_n - a_n) > etol){
      if (f(c_n)*f(a_n) < 0){
        a_n = a_n;
        b_n = c_n;
        e = c_n - a_n;
        }
      else if (f(c_n)*f(b_n) < 0){
        a_n = c_n;
        b_n = b_n;
        e = b_n - c_n;
        }
      }
    else if ((b_n - a_n) < etol){
      var arr = [a_n, b_n, c_n, e];
      return arr;
      }
    if (n == 30){
      var arr = [a_n, b_n, c_n, e];
      return arr;
      }
    

    }

}

bisection(fc, 0, 1, 0.0001)

micro:bit JavaScript 소스

let param1: number; // 첫번째 파라미터용 전역변수
let result: number; // 반환값을 위한 전역변수
 
let fc = function () { result = Math.sin(param1) - Math.cos(param1) + (1 / 2); }; // 함수 변수로 선언
 
function bisection(f: Action, a: number, b: number, etol: number): number[] {
    let a_n = a;
    let b_n = b;
    let e = 100;
    let n = 0;
    let c_n = (a_n + b_n) / 2;
    while (n < 30) {
        n++;
        if ((b_n - a_n) > etol) {
            // -- f(c_n)
            param1 = c_n;
            f();
            let result_c_n = result;
            // -- f(a_n)
            param1 = a_n;
            f();
            let result_a_n = result;
            // -- f(b_n)
            param1 = b_n;
            f();
            let result_b_n = result;
            if (result_c_n * result_a_n < 0) {
                a_n = a_n;
                b_n = c_n;
                e = c_n - a_n;
            }
            else if (result_c_n * result_b_n < 0) {
                a_n = c_n;
                b_n = b_n;
                e = b_n - c_n;
            }
        }
        else if ((b_n - a_n) < etol) {
            let arr = [a_n, b_n, c_n, e];
            return arr;
        }
        if (n == 30) {
            let arr = [a_n, b_n, c_n, e];
            return arr;
        }
    }
    let arr = [0,0,0,0];
    return arr;
}

let resultArray = bisection(fc, 0, 1, 0.0001);
basic.showNumber(resultArray[0]);
//basic.showNumber(resultArray[1]);
//basic.showNumber(resultArray[2]);
//basic.showNumber(resultArray[3]);

댓글을 달아 주세요

micro:bit - PCA9685 (Servo Motor Control)

OS/micro:bit 2019. 10. 24. 00:33 Posted by 파란크리스마스

출처

micro:bit - PCA9685 (Servo Motor Control)

micro:bit에 내장된 PWM 제어는 최대 3개만 지원하고 있어서 3개 이상 서브모터를 제어 하려면 별도의 모듈이 필요합니다.

서브모터용 확장보드가 있지만, PCA9685모듈을 이용해서 서브모터를 제어 해보았습니다.

PCA9685 모듈은 I2C통신방식을 사용하고 있고, 별도의 전원으로 5V을 사용했습니다.

PCA9685 확장모듈 추가

소스

실행

댓글을 달아 주세요

CR123A 리튬 이온 배터리 홀더 for micro: Maqueen

OS/micro:bit 2019. 10. 15. 01:18 Posted by 파란크리스마스

출처

마퀸 전용 충전용 배터리 홀더를 결합해보았습니다.
자체 충전 회로가 있어서 마미크로5핀 케이블로 충전하고, 마퀸을 사용 할 수 있습니다.

배터리 홀더 결합전

리튬이온 건전지

지지대 조립

배터리 홀더 조립

리튬 이온 배터리 장착

충전

댓글을 달아 주세요

micro:Maqueen - Android 원격 제어 (BLE : App Inventor)

OS/micro:bit 2019. 9. 11. 02:02 Posted by 파란크리스마스

출처

micro:Maqueen - BLE RC Car 제어 (App Inventor) pulse-combined.zip

micro:Maqueen을 안드로이드 폰으로 제어하기 위해서 micro:bit는 BLE로 구현하고, 안드로이드개발은 App Inventor를 이용해서 개발했습니다.

micro:bit의 BLE 개발은 이전 게시물의 내용을 참고 하시면 됩니다.

micro:bit - BLE 서버

Maqueen 제어용 상수

#define MOTOR_M1 0
#define MOTOR_M2 1
#define MOTOR_ALL 2

#define MOTOR_CW 0x0
#define MOTOR_CCW 0x1

#define MOTOR_ADDRESSS 0x10 << 1

Maqueen 모터 제어 - 100 스피드로 앞으로 전진

char buf[]={0x00,0x0,100};
uBit.i2c.write(MOTOR_ADDRESSS, buf, 3, true);

micro:bit - main.cpp 소스

#include "MicroBit.h"
#include "MicroBitUARTService.h"
 
MicroBit uBit;
MicroBitUARTService *uart;
MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);

#define MOTOR_M1 0
#define MOTOR_M2 1
#define MOTOR_ALL 2

#define MOTOR_CW 0x0
#define MOTOR_CCW 0x1

#define MOTOR_ADDRESSS 0x10 << 1
 
int connected = 0;

void motorRun(int index, char direction, char speed) {
	
  //char buf[]={0x00,0x0,100};
	//uBit.i2c.write(MOTOR_ADDRESSS, buf, 3, true);	
	
	if (index == MOTOR_M1) {
	  char buf[]={0x00,direction,speed};
	  i2c.write(MOTOR_ADDRESSS, buf, 3);
	}
	if (index == MOTOR_M2) {
		char buf[]={0x02,direction,speed};
    i2c.write(MOTOR_ADDRESSS, buf, 3);
	}
	if (index == MOTOR_ALL) {
	  char buf[]={0x00,direction,speed};
	  i2c.write(MOTOR_ADDRESSS, buf, 3);
    buf[0] = 0x02;
    i2c.write(MOTOR_ADDRESSS, buf, 3);
	}
}

void motorStop(int motors) {
  if (motors == MOTOR_M1) {
	  char buf[]={0x00,0x0,0};
	  i2c.write(MOTOR_ADDRESSS, buf, 3);
  }
  if (motors == MOTOR_M2) {
		char buf[]={0x02,0x0,0};
    i2c.write(MOTOR_ADDRESSS, buf, 3);
  }
  if (motors == MOTOR_ALL) {
	  char buf[]={0x00,0x0,0};
	  i2c.write(MOTOR_ADDRESSS, buf, 3);
    buf[0] = 0x02;
    i2c.write(MOTOR_ADDRESSS, buf, 3);
  }
}

// 
void centerMotor(char direction, char speed) {
	motorRun(MOTOR_ALL, direction, speed);
}
 
// 
void rightMotor(char direction, char speed) {
	motorRun(MOTOR_M1, direction, speed);
}
 
// 
void leftMotor(char direction, char speed) {
	motorRun(MOTOR_M2, direction, speed);
}

// BLE 접속 이벤트
void onConnected(MicroBitEvent e) {
  uBit.display.scroll("C");

  connected = 1;

  // my client will send ASCII strings terminated with the colon character
  ManagedString eom(":");

  while (connected == 1) {
    ManagedString msg = uart->readUntil(eom);
    //uBit.display.scroll(msg);
    
    char command = msg.charAt(0);
    //uBit.display.scroll(command);
      
    if (command == 'S') {
	    motorStop(MOTOR_ALL);
	  } else {
		  int speed = 100;
		  ManagedString s = msg.substring(2, msg.length());
		  speed = atoi(s.toCharArray());
		  //uBit.display.scroll(speed);
		  
		  char direction = MOTOR_CW;
		  if (msg.charAt(0) == 'F') {
	      direction = MOTOR_CW;
	    } else if (msg.charAt(0) == 'B') {
	      direction = MOTOR_CCW;
	    }
	 
	    if (msg.charAt(1) == 'C') {
	      centerMotor(direction, speed);
	    } else if (msg.charAt(1) == 'L') {
	      leftMotor(direction, speed);
	    } else if (msg.charAt(1) == 'R') {
	      rightMotor(direction, speed);
	    }
    }
  }
}

// BLE 접속 해지 이벤트
void onDisconnected(MicroBitEvent e) {
    uBit.display.scroll("D");
    connected = 0;
    motorStop(MOTOR_ALL);
}

// 메인 함수
int main() {
    // micro:bit 초기화.
    uBit.init();
 
    // BLE 접속 상태 변경 리스터 등록
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnected);
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnected);
 
    // 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("AVM");
    
    /*
    motorRun(MOTOR_ALL, MOTOR_CW, 100);
    wait(3);
    motorStop(MOTOR_ALL);
    */
    
    // 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();
}

App Inventor 소스 (안드로이드) microbit_ble_rccar.zip

App Inventor 디자인

App Inventor 블럭

실행결과

댓글을 달아 주세요

  1. blueclouds2004 2020.11.18 04:02  댓글주소  수정/삭제  댓글쓰기

    재미있는 내용 잘 배우고 갑니다

마이크로:마퀸 / micro:Maqueen - 모터 테스트

OS/micro:bit 2019. 9. 8. 23:44 Posted by 파란크리스마스

출처

마퀸 확장 라이브러리 추가

[고급] > [확장] 메뉴 선택

[확장 프로그램]창의 검색창에 https://github.com/DFRobot/pxt-maqueen 라고 입력하고 검색후, [maqueen]를 선택

추가된 메뉴 [maqueen]에서 [Motor]함수를 선택 후, 드레그해서 코드창으로 이동

[무한방복 실행]함수에 드레그한 [Motor]함수를 올려 두기

전체 소스

실행 결과

댓글을 달아 주세요

micro:bit 지니어스키트 : 한글출력

OS/micro:bit 2019. 8. 31. 22:15 Posted by 파란크리스마스

출처

micro:bit 지니어스키트 : 한글출력

전체소스 :  source.zip

마이크로비트 지니어스키트의 LCD에 한글을 출력해보았습니다. 

블럭코딩에서 사용가능 하도록 확장라이브러리로 개발을 시도 했었지만, 블럭 코딩에 한글 문자열을 확장라이브러리에 전달 할 수 있는 방법을 알 수 없어서 확장라이브러리 개발은 포기하고, C++로 개발한 소스를 공개합니다. 

중국의 어떤 개발자도 한자 자체를 소리나는 대로 영문으로 전달하면 다시 한자로 변환해서 한자를 출력했는데, 한글을 소리나는 대로 영문으로 전달해서 해볼까 했지만, 굳이 필요로 할지 모르겠고, 개발 기간도 늘어나 구현은 나중으로 미루어 두었습니다.

전체적인 소스는 네이버카페( 블루투스 에서 한글전송하여 OLED에 보여주기.. : 네이버 카페 (아두이노 스토리) )에 공개된 소스를 기본으로 작성되었고, 소스 전체를 공개 했으니 다운 받아서 참고 하시면 됩니다.

main.cpp 소스

#include <MicroBit.h>
#include <mbed/pgmspace.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include "ASCFont.h"
#include "KSFont.h"

#define BLACK       0x0000

void matrixPrint(int XPOS,int YPOS,char *pChar);
byte *getHAN_font(byte HAN1, byte HAN2, byte HAN3);

#define SSD1306_ADDRESS 0x78
MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
Adafruit_SSD1306_I2c *oled;

MicroBit uBit1;
MicroBitThermometer thermometer; 

int XPOS = 0;
int YPOS = 0;

byte HANFontImage[32] = {0, };

int main() {
	/*
  uBit1.init();
  uBit1.display.disable();
  */
  
	if (oled != NULL) delete oled;
	oled = new Adafruit_SSD1306_I2c(i2c, SSD1306_ADDRESS, 64, 128);

	char str[20];
	char mymsg[] = "마이크로비트";
	char mymsg2[] = "온도 : %d";
	
	// 일반 문자열 출력
	oled->printf("%s", "bluexmas.tistory.com");
	
	// 한글 출력
	matrixPrint(XPOS,YPOS+20,mymsg);
	//matrixPrint(XPOS,YPOS+20+16,mymsg2);
	
  oled->display();
  
  while(true) {
  	oled->	fillRect(XPOS,YPOS+20+16, 100, 16, BLACK); // 지우기
  	
  	// 마이크로비트 내장 온도 가져오기
  	int curr_ther = thermometer.getTemperature();
  	sprintf(str, mymsg2, curr_ther);
  	
  	// 온도값 출력
  	matrixPrint(XPOS,YPOS+20+16,str);
  	oled->display();
  	
  	// 1초 대기
  	wait_us(1000); 
  }
}

void matrixPrint(int XPOS,int YPOS,char *pChar){
  byte rg = 3;   //<b1> red, <b0> green
  byte *pFs;
  byte i, b;
  byte c, c2, c3;

  while(*pChar){ 
    c = *(byte*)pChar++;

    //---------- 한글 ---------
    if(c >= 0x80){
      c2 = *(byte*)pChar++;
      c3 = *(byte*)pChar++;
      //Serial.print(c,DEC);
      //Serial.print(c2,DEC);
      //Serial.print(c3,DEC);      
      pFs = getHAN_font(c, c2, c3);
      oled->drawBitmap(XPOS, YPOS,  pFs, 16, 16, 1);
      XPOS = XPOS+16;
      if(XPOS > 128){
        XPOS = 0;
        YPOS = YPOS+16;
      }
    }
    //---------- ASCII ---------
    else{
      pFs = (byte*)ASCfontSet + ((byte)c - 0x20) * 16;
      oled->drawBitmap(XPOS, YPOS,  pFs, 8, 16, 1);
      XPOS = XPOS+8;
      if(XPOS > 128){
        XPOS = 0;
        YPOS = YPOS+16;
      }   
    }   
  }  
}  


/*=============================================================================
      한글 font 처리부분 
  =============================================================================*/

byte *getHAN_font(byte HAN1, byte HAN2, byte HAN3){

  const byte cho[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 2, 4, 4, 4, 2, 1, 3, 0 };
  const byte cho2[] = { 0, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 6, 6, 7, 7, 7, 6, 6, 7, 5 };
  const byte jong[] = { 0, 0, 2, 0, 2, 1, 2, 1, 2, 3, 0, 2, 1, 3, 3, 1, 2, 1, 3, 3, 1, 1 };

  uint16_t utf16;
  byte first, mid, last;
  byte firstType, midType, lastType;
  byte i;
  byte *pB, *pF;

  /*------------------------------
    UTF-8 을 UTF-16으로 변환한다.

    UTF-8 1110xxxx 10xxxxxx 10xxxxxx
  */------------------------------
  utf16 = (HAN1 & 0x0f) << 12 | (HAN2 & 0x3f) << 6 | HAN3 & 0x3f;

  /*------------------------------
    초,중,종성 코드를 분리해 낸다.

    unicode = {[(초성 * 21) + 중성] * 28}+ 종성 + 0xAC00

          0   1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 
    초성 ㄱ   ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ
    중성 ㅏ   ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ  
    종성 없음 ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅄ ㅅ ㅆ ㅇ ㅈ ㅊ ㅋ ㅌ ㅍ ㅎ
  ------------------------------*/
  utf16 -= 0xac00;
  last = utf16 % 28;
  utf16 /= 28;
  mid = utf16 % 21;
  first = utf16 / 21;

  first++;
  mid++;

  /*------------------------------
    초,중,종성 해당 폰트 타입(벌)을 결정한다.
  ------------------------------*/

  /*
   초성 19자:ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
   중성 21자:ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
   종성 27자:ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅆㅇㅈㅊㅋㅌㅍㅎ

   초성
      초성 1벌 : 받침없는 'ㅏㅐㅑㅒㅓㅔㅕㅖㅣ' 와 결합
      초성 2벌 : 받침없는 'ㅗㅛㅡ'
      초성 3벌 : 받침없는 'ㅜㅠ'
      초성 4벌 : 받침없는 'ㅘㅙㅚㅢ'
      초성 5벌 : 받침없는 'ㅝㅞㅟ'
      초성 6벌 : 받침있는 'ㅏㅐㅑㅒㅓㅔㅕㅖㅣ' 와 결합
      초성 7벌 : 받침있는 'ㅗㅛㅜㅠㅡ'
      초성 8벌 : 받침있는 'ㅘㅙㅚㅢㅝㅞㅟ'

   중성
      중성 1벌 : 받침없는 'ㄱㅋ' 와 결합
      중성 2벌 : 받침없는 'ㄱㅋ' 이외의 자음
      중성 3벌 : 받침있는 'ㄱㅋ' 와 결합
      중성 4벌 : 받침있는 'ㄱㅋ' 이외의 자음

   종성
      종성 1벌 : 중성 'ㅏㅑㅘ' 와 결합
      종성 2벌 : 중성 'ㅓㅕㅚㅝㅟㅢㅣ'
      종성 3벌 : 중성 'ㅐㅒㅔㅖㅙㅞ'
      종성 4벌 : 중성 'ㅗㅛㅜㅠㅡ'

  */
  if(!last){  //받침 없는 경우
    firstType = cho[mid];
    if(first == 1 || first == 24) midType = 0;
    else midType = 1;
  }
  else{       //받침 있는 경우
    firstType = cho2[mid];
    if(first == 1 || first == 24) midType = 2;
    else midType = 3;
    lastType = jong[mid];
  }
  memset(HANFontImage, 0, 32);

  //초성 
  pB = HANFontImage;
  pF = (byte*)KSFont + (firstType*20 + first)*32;
  i = 32;
  while(i--) *pB++ = pgm_read_byte(pF++); 

  //중성
  pB = HANFontImage;
  pF = (byte*)KSFont + (8*20 + midType*22 + mid)*32;
  i = 32;
  while(i--) *pB++ |= pgm_read_byte(pF++); 

  //종성
  if(last){
    pB = HANFontImage;
    pF = (byte*)KSFont + (8*20 + 4*22 + lastType*28 + last)*32;
    i = 32;
    while(i--) *pB++ |= pgm_read_byte(pF++); 
  }

  return HANFontImage;
}

static byte c1;  // Last character buffer

byte utf8ascii(byte ascii) {
    if ( ascii<128 )   // Standard ASCII-set 0..0x7F handling  
    {   c1=0;
        return( ascii );
    }

    // get previous input
    byte last = c1;   // get last char
    c1=ascii;         // remember actual character

    switch (last)     // conversion depnding on first UTF8-character
    {   case 0xC2: return  (ascii);  break;
        case 0xC3: return  (ascii | 0xC0);  break;
        case 0x82: if(ascii==0xAC) return(0x80);       // special case Euro-symbol
    }

    return  (0);                                     // otherwise: return zero, if character has to be ignored
}

void utf8ascii(char* s)
{      
        int k=0;
        char c;
        for (int i=0; i<strlen(s); i++)
        {
                c = utf8ascii(s[i]);
                if (c!=0)
                        s[k++]=c;
        }
        s[k]=0;
}
/*=============================================================================

  =============================================================================*/

실행 결과

댓글을 달아 주세요

micro:bit : 스탭모터(28BYJ48 ​+ ULN2003) 제어

OS/micro:bit 2019. 8. 17. 22:49 Posted by 파란크리스마스

출처

micro:bit : 스탭모터(28BYJ48 ​+ ULN2003) 제어

스탭모터(28BYJ48)와 스텝 모터 드라이버(ULN2003)는 저렴하고 많이 사용하고 있어서 많은 예제가 있습니다. 스탭의 반복하면서 반복 하는 시간차와 회수를 계산해서 원하는 각도로 회전하거나, 스탭의 방향에 따라서 정방향, 역방향으로 회전 시킬 수 있습니다.

  • IN1 = micro:bit 디지탈 0번핀
  • IN2 = micro:bit 디지탈 1번핀
  • IN3 = micro:bit 디지탈 2번핀
  • IN4 = micro:bit 디지탈 3번핀​​

소스

/*
############################################
##           sMotor v0.1 Test Program     ##
##          created by Samuel Matildes    ##
############################################
        ---- sam.naeec@gmail.com -----
This library was made for 4-Phase Stepper Motors
I don't take any resposability for the damage caused to your equipment.
 
*/
 
#include "MicroBit.h"
#include "sMotor.h"
 
//MicroBit uBit;
MicroBitSerial gSerial(USBTX, USBRX);
sMotor motor(P0_0, P0_1, P0_2, P0_3); // creates new stepper motor: IN1, IN2, IN3, IN4
//BusOut motor_out(P0_0, P0_1, P0_2, P0_3);  // blue - pink - yellow - orange
 
int step_speed = 1200; // 1200 ; // set default motor speed
int numstep = 512 ; // defines full turn of 360 degree
//you might want to calibrate this value according to your motor
 
int step = 0; 
int dir = 1; // direction
 
int main() {
	
	 //uBit.init();
	 //uBit.display.disable();
 
    //Credits
    printf("4 Phase Stepper Motor v0.1 - Test Program\r\n");
    printf("developed by Samuel Matildes\r\n");
    printf("\n\r");
 
    // Screen Menu
    printf("Default Speed: %d\n\r",step_speed);
    printf("1- 360 degree clockwise step\n\r");
    printf("2- 360 degree anticlockwise step\n\r");
    printf("3- 180 degree clockwise step\n\r");
    printf("4- 180 degree anticlockwise step\n\r");
    printf("5- Change Speed\n\r");
    
    while (1) {
 
        if (gSerial.readable()) { // checks for serial
 
            if (gSerial.getc()=='1') 
                motor.step(numstep,0,step_speed); // number of steps, direction, speed
 
            if (gSerial.getc()=='2')
                motor.step(numstep,1,step_speed);
 
            if (gSerial.getc()=='3')
                motor.step(numstep/2,0,step_speed);
 
            if (gSerial.getc()=='4')
                motor.step(numstep/2,1,step_speed);
 
            if (gSerial.getc()=='5') {
                printf("Current Speed: %d\n\r", step_speed);
                printf("New speed: \n\r");
                //gSerial.scanf("%d",&step_speed); // sets new speed
            }
        }
    }
    
    /*
		while(1)
    { 
        switch(step)
        { 
            case 0: motor_out = 0x1; break;  // 0001
            case 1: motor_out = 0x3; break;  // 0011
            case 2: motor_out = 0x2; break;  // 0010   
            case 3: motor_out = 0x6; break;  // 0110
            case 4: motor_out = 0x4; break;  // 0100
            case 5: motor_out = 0xC; break;  // 1100
            case 6: motor_out = 0x8; break;  // 1000
            case 7: motor_out = 0x9; break;  // 1001
            
            default: motor_out = 0x0; break; // 0000
        }
  
        if(dir) step++; else step--; 
        if(step>7)step=0; 
        if(step<0)step=7; 
        //wait(0.015);  // speed
        wait_us(step_speed);
    }
    */
}

실행 영상

댓글을 달아 주세요

micro:bit : BLE 통신 - App Inventor 2 과 BLE 통신

OS/micro:bit 2019. 8. 14. 13:42 Posted by 파란크리스마스

출처

micro:bit : BLE 통신 - App Inventor 2 과 BLE 통신

micro:bit를 이용해서 BLE 서버를 만들고 App Inventor를 이용해서 안드로이드 용 BLE 클라이언트를 만들어 보았습니다.

BLE 서버는 BLE 이름과 UUID(고유주소)를 송출하고, 이 정보로 BLE 클라이언트가 접속하면, BLE 기기는 다른 BLE 클라이언트가 접속하지 않도록, BLE 이름을 더 이상 송출하지않고, 서비스목록과 해당 서비스의 특성 정보를 송출합니다. BLE 클라이언트는 필요한 서비스와 특성을 찾아서 용도에 따라 다르겠지만 여기 예제에서는 간단하게 문자열을 주고 받도록 했습니다.

micro:bit BLE 서버 만들기  pulse-combined.hex

서비스 UUID, 특성 UUID는 고정 되어 수정 할 수 없고, 정해지 UUID를 사용해야 됩니다.

micro:bit BLEUART Service 구성 UUID

  • Service UUID : 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
  • TX Characteristic : 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
  • RX Characteristic : 6E400003-B5A3-F393-E0A9-E50E24DCCA9E

micro:bit 소스 - main.cpp

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

MicroBit uBit;
MicroBitUARTService *uart;

int connected = 0;

void onConnected(MicroBitEvent e) {
    uBit.display.scroll("C");

    connected = 1;

    // my client will send ASCII strings terminated with the colon character
    ManagedString eom(":");

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

void onDisconnected(MicroBitEvent e) {
    uBit.display.scroll("D");
    connected = 0;
}

void onButtonA(MicroBitEvent e) {
    if (connected == 0) {
        uBit.display.scroll("NC");
        return;
    }
    uart->send("YES");
    uBit.display.scroll("YES");
}

void onButtonB(MicroBitEvent e) {
    if (connected == 0) {
        uBit.display.scroll("NC");
        return;
    }
    uart->send("NO");
    uBit.display.scroll("NO");
}

void onButtonAB(MicroBitEvent e) {
    if (connected == 0) {
        uBit.display.scroll("NC");
        return;
    }
    uart->send("GOT IT!!");
    uBit.display.scroll("GOT IT!!");
}

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

    // listen for Bluetooth connection state changes
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnected);
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnected);

    // 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);

    // 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("AVM");

    // 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();
}

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"
    }
}

module.json

{
  "name": "pulse",
  "version": "0.0.0",
  "keywords": [],
  "author": "",
  "license": "Apache-2.0",
  "repository": {
    "url": "https://github.com/ARMmbed/mbed-os.git",
    "type": "git"
  },
  "dependencies": {
  	"mbed-classic": "lancaster-university/mbed-classic#microbit_hfclk+mb6",
    "microbit": "lancaster-university/microbit"
  },
  "extraIncludes": [
  	"source/Device",
  	"source/ChaN",
  	"source/ea3a618e0818",
  	"source/ESP8266",
  	"source/ESP8266/ATParser",
  	"source/ESP8266/ATParser/BufferedSerial",
  	"source/ESP8266/ATParser/BufferedSerial/Buffer"
  ],
  "bin": "./source"
}

App Inventor 2 : BLE 클라이언트 만들기 (http://ai2.appinventor.mit.edu/ microbit_ble.apk

App Inventor는 MIT에서 만든 블럭 형태의 코딩으로 안드로이드 어플을 쉽게 만들 수 있어서 IOT 개발시 많이 사용됩니다. 기본적으로 BT 통신만 지원했고, BLE 통신은 지원하지 않았지만, 최근에 확장 라이브러리를 통해서 지원하고 있습니다. BLE 확장 라이브러리를 다운 받아서 Import 하시면 BLE 통신을 구현 할 수 있습니다.

예제는 BLE 목록을 조회하고, 조회된 목록에서 micro:bit를 선택하여 BLE 서버에 접속하고, 미리 정해둔 서비스와 특성을 등록하고, micro:bit에서 A나 B버튼을 선택시 전달 받은 문자열을 텍스트박스에 출력하고, 안드로이드 어플에서도 문자열을 micro:bit에 전송 합니다.

App Inventor BLE 확장 라이브러리 다운로드

http://appinventor.mit.edu/extensions 에 접속하셔서 BluetoothLE.aix 파일을 다운 받습니다.

App Inventor BLE 확장 라이브러리 Import

팔레트 -> Extension -> import extension 에서 파일 선택버튼을 누른 후 위에서 다운받은 bluetoothLE.aix 를 선택해줍니다.

App Inventor 화면 구성

전역 변수 선언 (서비스, 특성 UUID 정의)

BLE 문자열 전달 함수 생성

[버튼1]을 선택해서 BLE 목록 조회

BLE 목록이 조회되면 목록를 리스트 박스(목록_선택1)에 담기

BLE 목록에서 접속하려고 하는 BLE 기기 선택했을 경우 BLE 주소 UUID(리스트의 문자열 1에서 17의 문자열)를 가지고 와서 해당 BLE에 접속 시도

BLE 기기에 접속하면 BLE로 문자열 수신 이벤트를 받기 위해서 서비스와 특성 등록

BLE 기기에서 문자열을 수신 했을 경우 텍스트 박스(텍스트_상자1)에 수신한 문자열 출력

[버튼3]을 선택해서 텍스트 박스(텍스트_상자2)의 문자열을 BLE기기에 전송

[버튼2]을 선택해서 BLE 연결끊기

App Inventor 전체 소스

실행 영상

댓글을 달아 주세요

micro:bit : 지니어스 키트 레고 마운트

OS/micro:bit 2019. 7. 1. 02:03 Posted by 파란크리스마스

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

 

지니어스 키트의 경우 레고 마운트가 가능합니다.

 

마이크로비트 지니어스키트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
아이씨뱅큐 공식 카페 : http://cafe.naver.com/icbanq
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq
마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
나도메이커 유튜브 채널 : https://www.youtube.com/user/ICbanQ

댓글을 달아 주세요