728x90

출처

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도 회전 모터

조립

완성

테스트 영상

728x90
728x90

출처

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

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

확장 라이브러리 추가

확장 메뉴 선택

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

확장 라이브러리 함수

예제

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

실행

728x90
728x90

출처

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

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

indexOf 함수

indexOf 함수 사용예제

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

728x90
728x90

출처

함수를 인자로 호출하기

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]);
728x90
728x90

출처

micro:bit - PCA9685 (Servo Motor Control)

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

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

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

PCA9685 확장모듈 추가

소스

실행

728x90
728x90

출처

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

배터리 홀더 결합전

리튬이온 건전지

지지대 조립

배터리 홀더 조립

리튬 이온 배터리 장착

충전

728x90
728x90

출처

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 블럭

실행결과

728x90
728x90

출처

마퀸 확장 라이브러리 추가

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

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

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

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

전체 소스

실행 결과

728x90

+ Recent posts