Hardware components | ||||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
|
Overview
Movie
Read moreI made BLE controlled train using 100 Yen toy trian by smart phone (Android).
- LiPo Battery and Servo Motor on the first car
- Motor Driver and BLE Nano on the second car
"moterDriveBLEnano00.ino" is created based on the following.
Android CodeI modified Example Code on the following: https://github.com/RedBearLab/Android/tree/master/Examples/Chat
Joy Stick for controller: Reference
Manufacturing process- Mounting of the servo motor
- Implementation of the motor driver
- Implementation of the BLE Nano
#include <Wire.h>
//#include "I2Cdev.h"
#include <BLE_API.h>
#include <Servo.h>
Servo myservo;
const int DRV8830 = 0x64;
int power = 0;
int angle = 0;
int rot = 0;
#define TXRX_BUF_LEN 20
BLE ble;
Timeout timeout;
static uint8_t rx_buf[TXRX_BUF_LEN];
static uint8_t rx_buf_num;
// The Nordic UART Service
static const uint8_t service1_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_tx_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_rx_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};
uint8_t tx_value[TXRX_BUF_LEN] = {0,};
uint8_t rx_value[TXRX_BUF_LEN] = {0,};
int speed1 = 0;
int iniState = 0;
int angleRx_ini = 35;
int angleRx = angleRx_ini;
GattCharacteristic characteristic1(service1_tx_uuid, tx_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE );
GattCharacteristic characteristic2(service1_rx_uuid, rx_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic *uartChars[] = {&characteristic1, &characteristic2};
GattService uartService(service1_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
// I2C motor driver I2C
//Reference
//http://makers-with-myson.blog.so-net.ne.jp/2014-05-15
void writeMotorResister(byte vset, byte data1){
int vdata = vset << 2 | data1;
Wire.beginTransmission(DRV8830);
Wire.write(0x00);
Wire.write(vdata);
Wire.endTransmission(true);
//delay(10);
}
void disconnectionCallBack(Gap::Handle_t handle, Gap::DisconnectionReason_t reason){
Serial.println("Disconnected!");
Serial.println("Restarting the advertising process");
iniState = 0;
ble.startAdvertising();
}
// data Rx
void writtenHandle(const GattWriteCallbackParams *Handler){
uint8_t buf[TXRX_BUF_LEN];
uint16_t bytesRead, index;
//Serial.println("onDataWritten : ");
if (Handler->handle == characteristic1.getValueAttribute().getHandle()) {
ble.readCharacteristicValue(characteristic1.getValueAttribute().getHandle(), buf, &bytesRead);
if (buf[0] == 'c') {
iniState = 1;
power = buf[1];
angle = buf[2];
rot = buf[3];
}
}
speed1 = map(power, 0, 100, 5, 19);
angleRx = map(angle, 0, 180, 0, angleRx_ini * 2);
if (rot == 2){
Serial.print("Forward ");
}
if (rot == 1){
Serial.print("Reverse ");
}
Serial.print("power: ");
Serial.print(power);
Serial.print(" ");
Serial.print("angle: ");
Serial.println(angle);
}
//data Tx
void m_uart_rx_handle(){
rx_buf_num = 1;
rx_buf[0] = 's';
ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), rx_buf, rx_buf_num);
memset(rx_buf, 0x00,1);
delay(500);
Serial.println("Tx: s");
}
void setup() {
Wire.begin(D3, D2, 400000L);
Serial.begin(250000);
writeMotorResister(0x00, 0x00);
//writeMotorResister(0x80, 0x00);
BLEset();
myservo.attach(D4);
myservo.write(angleRx);
}
void loop() {
//delay(300);
if(iniState == 0){
m_uart_rx_handle();
}
if (power >= 0 && power < 45){
angleRx = angleRx_ini;
}
if (power == 0){
writeMotorResister(0x00, 0x00);
}else {
writeMotorResister((byte)speed1, (byte)rot);
}
myservo.write(angleRx);
delay(15);
}
//BLE
void BLEset() {
ble.init();
ble.onDisconnection(disconnectionCallBack);
ble.onDataWritten(writtenHandle);
// setup adv_data and srp_data
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
(const uint8_t *)"motor", sizeof("motor") - 1);
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
(const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev));
// set adv_type
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
// add service
ble.addService(uartService);
// set device name
ble.setDeviceName((const uint8_t *)"Simple Chat");
// set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
ble.setTxPower(4);
// set adv_interval, 100ms in multiples of 0.625ms.
ble.setAdvertisingInterval(160);
// set adv_timeout, in seconds
ble.setAdvertisingTimeout(0);
// start advertising
ble.startAdvertising();
Serial.println("Advertising Start!");
}
package com.redbear.moterDrive_BLEnano02;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.MenuItem;
import android.widget.TextView;
import com.developwear.joystickview.JoystickView;
public class Ctl extends Activity {
private final static String TAG = Ctl.class.getSimpleName();
public static final String EXTRAS_DEVICE = "EXTRAS_DEVICE";
private TextView tv = null;
private JoystickView jsv;
private String mDeviceName;
private String mDeviceAddress;
private RBLService mBluetoothLeService;
private Map<UUID, BluetoothGattCharacteristic> map = new HashMap<UUID, BluetoothGattCharacteristic>();
private int bleState = 0;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName,
IBinder service) {
mBluetoothLeService = ((RBLService.LocalBinder) service)
.getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up
// initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (RBLService.ACTION_GATT_DISCONNECTED.equals(action)) {
tv.setText("Ready..");
bleState = 0;
} else if (RBLService.ACTION_GATT_SERVICES_DISCOVERED
.equals(action)) {
getGattService(mBluetoothLeService.getSupportedGattService());
} else if (RBLService.ACTION_DATA_AVAILABLE.equals(action)) {
//Data Rx
byte[] RxData = intent.getByteArrayExtra(RBLService.EXTRA_DATA);
if(RxData[0] == 's'){
tv.setText("Start!!");
bleState = 1;
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
tv = (TextView) findViewById(R.id.textView);
//Joy Stick
//https://github.com/clkasd/JoystickView
jsv = (JoystickView)findViewById(R.id.joystickview);
jsv.setJoystickChangeListener(new JoystickView.JoystickChangeListener() {
@Override
public void onJoystickChanged(int power, int degree) {
Log.v("power", String.valueOf(String.valueOf(power)));
Log.v("degree", String.valueOf(String.valueOf(degree)));
sendJoyStick(power, degree);
}
});
Intent intent = getIntent();
mDeviceAddress = intent.getStringExtra(Device.EXTRA_DEVICE_ADDRESS);
mDeviceName = intent.getStringExtra(Device.EXTRA_DEVICE_NAME);
getActionBar().setTitle(mDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, RBLService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
System.exit(0);
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(mGattUpdateReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
System.exit(0);
}
private void getGattService(BluetoothGattService gattService) {
if (gattService == null)
return;
BluetoothGattCharacteristic characteristic = gattService
.getCharacteristic(RBLService.UUID_BLE_SHIELD_TX);
map.put(characteristic.getUuid(), characteristic);
BluetoothGattCharacteristic characteristicRx = gattService
.getCharacteristic(RBLService.UUID_BLE_SHIELD_RX);
mBluetoothLeService.setCharacteristicNotification(characteristicRx,
true);
mBluetoothLeService.readCharacteristic(characteristicRx);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(RBLService.ACTION_GATT_CONNECTED);
intentFilter.addAction(RBLService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(RBLService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(RBLService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
//Data Tx
public void sendJoyStick(int pow, int deg){
BluetoothGattCharacteristic characteristic = map
.get(RBLService.UUID_BLE_SHIELD_TX);
byte[] bytes = new byte[4];
bytes[0]='c';
bytes[1]=(byte)pow;
bytes[2]=(byte)(Math.abs(deg)); //
if(deg < 0){
bytes[3] = 1; //
}else{
bytes[3] = 2; //
}
characteristic.setValue(bytes);
if(bleState == 1){
mBluetoothLeService.writeCharacteristic(characteristic);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="1">
<TextView
android:id="@+id/textView"
android:layout_width="256dp"
android:layout_height="50dp"
android:scrollbars="vertical"
android:textSize="30dp"
android:text="Ready..." />
<com.developwear.joystickview.JoystickView
android:id="@+id/joystickview"
android:layout_width="700px"
android:layout_height="700px"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal" />
</LinearLayout>
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.hmg.moterdrive_blenano02"
minSdkVersion 21
targetSdkVersion 21
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.android.support:support-v4:21.0.0'
compile 'com.developwear:joystickviewlib:1.0.1'
}
Comments