micro:bit - BLE - RC Car -PWM 사용

OS/micro:bit 2018.02.03 00:27 Posted by 파란크리스마스

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

출처 : Motor Driver Board for the BBC micro:bit - V2 | Kitronik
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 - RC Car -PWM 사용

main.cpp

MicroBitRCCAR.apk.zip

pulse-combined.hex

micro:bit 확장 보드중에 모터 드라이버(Motor Driver Board for the BBC micro:bit - V2 | Kitronik)를 이용해서 RC Car를 만들어 보았습니다. 통신방식은 micro:bit에 내장된 BLE를 이용했고, 클라이언트는 Delphi를 이용해서 만들어 보았습니다. 제가 사용한 모터 드라이버는 RWM를 사용해서 속도 제어도 가능했습니다.

 

 

소스 - main.cpp

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

MicroBit uBit;
MicroBitUARTService *uart;

#define MOTER_LOW            0
#define MOTER_HIGH           0.2 // 스피드 - 0 ~ 1 | 최대속도 = 1

PwmOut moter_right_front(P0_18);	//12 - right
PwmOut moter_right_back(P0_20);		//8
PwmOut moter_left_front(P0_3);		//16 - left
PwmOut moter_left_back(P0_16);			//0

//모터A,B 정회전
void bothMotorStart()
{
  moter_right_front = MOTER_HIGH;
  moter_right_back = MOTER_LOW;
  moter_left_front = MOTER_HIGH;
  moter_left_back = MOTER_LOW;
}
 
//모터A,B 역회전
void bothMotorBack()
{
  moter_right_front = MOTER_LOW;
  moter_right_back = MOTER_HIGH;
  moter_left_front = MOTER_LOW;
  moter_left_back = MOTER_HIGH;
}
   
//모터A,B Stop
void stopAllMotor()
{
  moter_right_front = MOTER_LOW;
  moter_right_back = MOTER_LOW;
  moter_left_front = MOTER_LOW;
  moter_left_back = MOTER_LOW;
}
   
//모터A 역회전, 모터B 정회전
void turnLeft()
{
  moter_right_front = MOTER_LOW;
  moter_right_back = MOTER_HIGH;
  moter_left_front = MOTER_HIGH;
  moter_left_back = MOTER_LOW;
}
   
//모터A 정회전, 모터B 역회전
void turnRight()
{
  moter_right_front = MOTER_HIGH;
  moter_right_back = MOTER_LOW;
  moter_left_front = MOTER_LOW;
  moter_left_back = MOTER_HIGH;
}
   
//모터A 정회전, 모터B Stop
void motorA_Rotation()
{
  moter_right_front = MOTER_HIGH;
  moter_right_back = MOTER_LOW;
  moter_left_front = MOTER_LOW;
  moter_left_back = MOTER_LOW;
}
   
//모터A Stop, 모터B 정회전
void motorB_Rotation()
{
  moter_right_front = MOTER_LOW;
  moter_right_back = MOTER_LOW;
  moter_left_front = MOTER_HIGH;
  moter_left_back = MOTER_LOW;
}
   
//모터A 역회전, 모터B Stop
void motorA_Reverse()
{
  moter_right_front = MOTER_LOW;
  moter_right_back = MOTER_HIGH;
  moter_left_front = MOTER_LOW;
  moter_left_back = MOTER_LOW;
}
   
//모터A Stop, 모터B 역회전
void motorB_Reverse()
{
  moter_right_front = MOTER_LOW;
  moter_right_back = MOTER_LOW;
  moter_left_front = MOTER_LOW;
  moter_left_back = MOTER_HIGH;
}

// we use events abd the 'connected' variable to keep track of the status of the Bluetooth connection
void onConnected(MicroBitEvent)
{
    uBit.display.print("C");

    while(1) {
      char command = uart->getc();
      uBit.display.print(command);
      
      if (command == 'F') {
      	bothMotorStart();
      } else if (command == 'B') {
      	bothMotorBack();
      } else if (command == 'L') {
      	turnLeft();
      } else if (command == 'R') {
      	turnRight();
      } else if (command == 'S') {
      	stopAllMotor();
      }
    }
}
 
void onDisconnected(MicroBitEvent)
{
    uBit.display.print("D");
}

int main() { 
  uBit.init();
  uBit.display.scroll("MOTER");
  
  /*  
  while(1) {
    bothMotorStart();
    wait(1);
    stopAllMotor();
    wait(1);
    bothMotorBack();
    wait(1);
    stopAllMotor();
    wait(1);
  }
  */
	
  uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnected);
  uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnected);
	
  uart = new MicroBitUARTService(*uBit.ble, 32, 32); 
  uBit.display.scroll("UART ready");

  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

Blueinno2(RFduinoBLE) - Raspberry PI 3 / BLE 연동

OS/Raspberry Pi 2016.12.14 01:11 Posted by 파란크리스마스

출처 : Raspberry Pi: Control WS2812B (NeoPixels) With Bluetooth LE
Eclipse Kura™ Documentation
The Pi4J Project

Bluetooth 모듈이 내장된 블루이노2로 BLE 송신하고, 라즈베리파이3의 Bluetooth 모듈로 수신 받아 데이터처리 해보았습니다.

블루이노2 코드

#include <RFduinoBLE.h>

int Potent=2;
boolean is_connect;

void setup() {
  // put your setup code here, to run once:
  RFduinoBLE.deviceName = "bluexmas";

  // this is the data we want to appear in the advertisement
  //RFduinoBLE.advertisementData = "My BLE LED";
  
  //RFduinoBLE.advertisementInterval = MILLISECONDS(300);
  //RFduinoBLE.txPowerLevel = -20;  // (-20dbM to +4 dBm)
    
  Serial.begin(9600);  
  Serial.println("Start Test");      // With more than 15 characters thie Start Test keeps happening

  // start the BLE stack
  RFduinoBLE.begin();  
}

void loop() {
  char BPM_lcd[10];
  
  RFduino_ULPDelay(100);  
  // Switch to lower power mode
  //RFduino_ULPDelay(INFINITE);
  //RFduino_ULPDelay( SECONDS(1) ); //sample once per second

  if (is_connect) {
    int sensorValue = analogRead(Potent);
    Serial.println(sensorValue);             // debug value

    //sprintf(BPM_lcd, "%10d", sensorValue);
    //lcd.println(BPM_lcd);     
    
    RFduinoBLE.sendInt(sensorValue);  //sends the char array
  }
}

void RFduinoBLE_onConnect() {
  // Debug message printed to Serial interface
  Serial.println("RFduino connected");
  is_connect = true;
}

void RFduinoBLE_onDisconnect() { 
  // Debug message printed to Serial interface
  Serial.println("RFduino disconnected");
  is_connect = false;
}

void RFduinoBLE_onReceive(char *data, int len) {
  // Debug message printed to Serial interface
  Serial.println("Data received: ");
  for(int i=0;i<len;i++)
    Serial.print(data[i]);
    Serial.println();
    Serial.println(data);
}

Blueinno.java

BLE 관련 코드만 보기 편하게 하기 위해서 모터 제어 관련 코드는 빼고 블루이노2와 통신하는 부분만 공개

package ble.blueinno2;

import java.util.List;
import java.util.Scanner;

import org.eclipse.kura.KuraException;
import org.eclipse.kura.bluetooth.BluetoothDevice;
import org.eclipse.kura.bluetooth.BluetoothGatt;
import org.eclipse.kura.bluetooth.BluetoothGattService;
import org.eclipse.kura.bluetooth.BluetoothLeNotificationListener;
import org.eclipse.kura.bluetooth.BluetoothLeScanListener;
import org.eclipse.kura.linux.bluetooth.util.BluetoothProcess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Blueinno implements BluetoothLeNotificationListener, BluetoothLeScanListener {
	
	private static final Logger logger = LoggerFactory.getLogger(BluetoothProcess.class);

	private BluetoothGatt m_bluetoothGatt;
	private BluetoothDevice m_device;
	private boolean m_connected;

	public Blueinno(BluetoothDevice bluetoothDevice) {
		// m_device = bluetoothDevice;
		m_connected = false;
	}

	public BluetoothDevice getBluetoothDevice() {
		return m_device;
	}

	public void setBluetoothDevice(BluetoothDevice device) {
		m_device = device;
	}

	public boolean isConnected() {
		return m_connected;
	}

	public boolean connect(BluetoothLeNotificationListener listener) throws KuraException {
		m_bluetoothGatt = m_device.getBluetoothGatt();
		logger.info("접속시도");
		boolean connected = m_bluetoothGatt.connect();
		if (connected) {
			m_bluetoothGatt.setBluetoothLeNotificationListener(listener);
			logger.info("리스너등록");
			m_connected = true;
			return true;
		} else {
			// If connect command is not executed, close gatttool
			m_bluetoothGatt.disconnect();
			m_connected = false;
			return false;
		}
	}

	public void disconnect() {
		if (m_bluetoothGatt != null) {
			m_bluetoothGatt.disconnect();
			m_connected = false;
		}
	}

	/*
	 * Discover services
	 */
	public List<BluetoothGattService> discoverServices() {
		return m_bluetoothGatt.getServices();
	}

	@Override
	public void onScanFailed(int errorCode) {
		// TODO Auto-generated method stub
		System.out.println("error = " + errorCode);
	}

	@Override
	public void onScanResults(List<BluetoothDevice> devices) {
		logger.info("onScanResults = " + devices.size());

		for (BluetoothDevice device : devices) {
			logger.info("Found Bluetooth Device " + device.getName() + " [" + device.getAdress() + "]");
		}
		
		System.out.print("ble address > ");
		Scanner scanner = new Scanner(System.in);
		String blc_address = scanner.next();
		
		BluetoothDevice nurum_device = null;
		for (BluetoothDevice device : devices) {
			if (device.getAdress().equals(blc_address)) {
				nurum_device = device;
			}
		}
		
		if (nurum_device != null) {
			//ble_nurum = new Blueinno(nurum_device);
			this.setBluetoothDevice(nurum_device);
			try {
				if (this.connect(this)) {
					System.out.println("ble connect");
					
					Runnable aa = new Runnable() {
						
						@Override
						public void run() {
							while (true) {
								try {
									String sensorValue = m_bluetoothGatt.readCharacteristicValue("0x000e");
									System.out.println(sensorValue);
									
									// 모터제어
									// 생략
								} catch (KuraException e1) {
									e1.printStackTrace();
								}
								try {
									Thread.sleep(100);
								} catch (Exception e) {
									
								}
							}
						}
					};
					
					Thread bb = new Thread(aa);
					bb.start();
				}
			} catch (KuraException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	@Override
	public void onDataReceived(String handle, String value) {
		System.out.println("handle: " + handle + " value: " + value);
	}
}

BlueinnoMain.java

package ble.blueinno2;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.kura.linux.bluetooth.le.BluetoothLeScanner;

public class BlueinnoMain {
	
	Logger logger = Logger.getLogger(this.getClass());

	private Blueinno blueinno = null;
	
	public static void main(String[] args) throws Exception {
		BlueinnoMain bletest = new BlueinnoMain();
		bletest.init();
		bletest.startScan();
	}
	
	public void init() {
		Logger.getRootLogger().setLevel(Level.DEBUG);
		logger.info("초기화");
		blueinno = new Blueinno();
	}

	public void startScan() throws InterruptedException {
		BluetoothLeScanner m_bls = new BluetoothLeScanner();
		m_bls.startScan("hci0", blueinno);
		Thread.sleep(10000);
		m_bls.killScan();
	}
}

실행


Raspberry Pi & Bluetooth LE(nurum) / LED Control

OS/Raspberry Pi 2016.11.20 02:11 Posted by 파란크리스마스

출처 : Eclipse Kura™ Documentation
The Pi4J Project

라즈베리파이2에 BLE 동글이와 BLE 스마트 버튼인 nurum으로 클릭 이벤트를 받아서
GPIO를 이용해서 LED를 컨트롤 해보았습니다.

BleNurum class

package bletest;

import java.util.List;

import org.eclipse.kura.KuraException;
import org.eclipse.kura.bluetooth.BluetoothDevice;
import org.eclipse.kura.bluetooth.BluetoothGatt;
import org.eclipse.kura.bluetooth.BluetoothGattService;
import org.eclipse.kura.bluetooth.BluetoothLeNotificationListener;

public class BleNurum {

	private BluetoothGatt m_bluetoothGatt;
	private BluetoothDevice m_device;
	private boolean m_connected;

	public BleNurum(BluetoothDevice bluetoothDevice) {
		m_device = bluetoothDevice;
		m_connected = false;
	}

	public BluetoothDevice getBluetoothDevice() {
		return m_device;
	}

	public void setBluetoothDevice(BluetoothDevice device) {
		m_device = device;
	}

	public boolean isConnected() {
		return m_connected;
	}

	public boolean connect(BluetoothLeNotificationListener listener) throws KuraException {
		m_bluetoothGatt = m_device.getBluetoothGatt();
		boolean connected = m_bluetoothGatt.connect();
		if (connected) {
			m_bluetoothGatt.setBluetoothLeNotificationListener(listener);
			m_connected = true;
			return true;
		} else {
			// If connect command is not executed, close gatttool
			m_bluetoothGatt.disconnect();
			m_connected = false;
			return false;
		}
	}

	public void disconnect() {
		if (m_bluetoothGatt != null) {
			m_bluetoothGatt.disconnect();
			m_connected = false;
		}
	}

	/*
	 * Discover services
	 */
	public List<BluetoothGattService> discoverServices() {
		return m_bluetoothGatt.getServices();
	}
}

BleTestMain class

package bletest;

import java.nio.ByteBuffer;
import java.util.List;
import java.util.Scanner;

import org.eclipse.kura.KuraException;
import org.eclipse.kura.bluetooth.BluetoothDevice;
import org.eclipse.kura.bluetooth.BluetoothLeNotificationListener;
import org.eclipse.kura.bluetooth.BluetoothLeScanListener;
import org.eclipse.kura.linux.bluetooth.le.BluetoothLeScanner;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class BleTestMain implements BluetoothLeScanListener, BluetoothLeNotificationListener {
	
	private BleNurum ble_nurum = null;
	private GpioController gpio = null;
	private GpioPinDigitalOutput led_01 = null;
	private GpioPinDigitalOutput led_02 = null;
	
	public static void main(String[] args) throws Exception {
		BleTestMain bletest = new BleTestMain();
		bletest.init();
		bletest.startScan();
	}
	
	public void init() {
		// create gpio controller
		gpio = GpioFactory.getInstance();
		led_01 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08, "Red LED", PinState.HIGH);
		led_02 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_09, "Blue LED", PinState.HIGH);
		// set shutdown state for this pin
		led_01.setShutdownOptions(true, PinState.LOW);
		led_02.setShutdownOptions(true, PinState.LOW);
		led_01.low();
		led_02.low();
	}

	public void startScan() throws InterruptedException {
		BluetoothLeScanner m_bls = new BluetoothLeScanner();
		m_bls.startScan("hci0", this);

		Thread.sleep(3000);

		m_bls.killScan();
	}

	@Override
	public void onScanFailed(int errorCode) {
		// TODO Auto-generated method stub
		System.out.println("error = " + errorCode);
	}

	@Override
	public void onScanResults(List<BluetoothDevice> devices) {
		System.out.println("onScanResults = " + devices.size());

		for (BluetoothDevice device : devices) {
			System.out.println("Found Bluetooth Device " + device.getName() + " [" + device.getAdress() + "]");
		}
		
		System.out.print("ble address > ");
		Scanner scanner = new Scanner(System.in);
		String blc_address = scanner.next();
		
		BluetoothDevice nurum_device = null;
		for (BluetoothDevice device : devices) {
			if (device.getAdress().equals(blc_address)) {
				nurum_device = device;
			}
		}
		
		if (nurum_device != null) {
			ble_nurum = new BleNurum(nurum_device);
			try {
				if (ble_nurum.connect(this)) {
					System.out.println("ble connect");
				}
			} catch (KuraException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static byte[] decode(String hex) {

		String[] list = hex.split("(?<=\\G.{2})");
		ByteBuffer buffer = ByteBuffer.allocate(list.length);
		System.out.println(list.length);
		for (String str : list)
			buffer.put(Byte.parseByte(str, 16));

		return buffer.array();

	}

	@Override
	public void onDataReceived(String handle, String value) {
		String val = new String( decode(value.replaceAll("\\p{Z}", "")) );
		
		System.out.println("handle: " + handle + " value: " + value + " / " + val);
		
		if (val.equals("!1")) {
			led_01.toggle();
		}
		
		if (val.equals("!2")) {
			led_02.toggle();
		}
		
		if (val.equals("!3")) {
			led_01.low();
			led_02.low();
		}		
		
		if (val.equals("!H")) {
			ble_nurum.disconnect();
			gpio.shutdown();
			System.exit(1);
		}
	}
}

실행

$ sudo java -cp .:pi4j-core.jar:org.apache.commons.io_2.4.0.jar:org.eclipse.equinox.io_1.0.400.v20120522-2049.jar:org.eclipse.osgi_3.8.1.v20120830-144521.jar:org.eclipse.osgi.services_3.3.100.v20120522-1822.jar:org.eclipse.osgi.util_3.2.300.v20120522-1822.jar:org.eclipse.soda.dk.comm_1.2.1.jar:slf4j.api_1.6.4.jar:slf4j.jdk14_1.6.4.jar:slf4j.log4j12_1.6.0.jar:usb4java-javax_1.0.0.jar bletest.BleTestMain



 

티스토리 툴바