开贴扯蛋BLUNO乐高小车搭建过程(视频已更新)
本帖最后由 taelons 于 2014-3-16 16:24 编辑感谢DFROBOT!感谢社区向导!有幸拿到BLUNO试用活动提供的板子!
年底大家都很忙,年终总结、系统测试上线、各路催债的、各种面子工程政绩工程、某监会又不失时机地给俺们增加工作量:Q(真想吐槽这些爷们。。。。。。)
总算能稍微喘口气,开贴记录一下BLUNO乐高小车搭建过程。哥在公司要伺候领导,到家要伺候小祖宗,等小祖宗睡了才能开整,否则逃不出小祖宗的小爪,非把板子废了不可,因此搭建、更新过程慢,请看官和社区向导谅解。。。。。。
秀一下拿到的板子。。。。。。
板子非常小巧,做工精良(只是BLUNO一个排母焊得稍微斜了点)
本帖最后由 taelons 于 2014-2-4 16:05 编辑
由于哥的iphone4蓝牙和wifi坏了,暂时不能调试蓝牙,先搭建小车底盘---
电机驱动板已插在bluno上,再看看反面---
除了两个螺丝螺母,其它都是乐高
继续加固---
晚上继续。。。。。。
自己的装备。。。。。。
电机:额定电压6v,最高9v,便宜得不能再便宜了,3块钱
舵机:最常见的SG90,不到10元。3D打印了一个外壳,可惜有误差,不能扣在乐高上,而且太紧,不小心弄断了。外壳不是必需的,当然如果有最好,但不同的3D打印机打印了好几个,都不理想
双鹿电池及电池扣:9v,这个在调试的时候用,因为手头的锂电池都是JST插头,不能直接接在DFROBOT提供的电机控制板上
锂电池:7.4v JST插头,这个将来成型后用,插头要改造一下
面包板一个、杜邦线一把就不贴出来了
安卓手机程序---
package com.example.myfirstapp;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.os.Bundle;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity
{
private static final String TAG = "THINBTCLIENT";
private static final boolean D = true;
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
Button mButtonF;
Button mButtonB;
Button mButtonL;
Button mButtonR;
Button mButtonS;
private static final UUID MY_UUID = UUID.fromString( "00001101-0000-1000-8000-00805F9B34FB" );
private static String address = "88:33:14:DF:1F:FD";
/** Called when the activity is first created. */
@Override
public void onCreate( Bundle savedInstanceState )
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//前进
mButtonF=(Button)findViewById(R.id.btnF);
mButtonF.setOnTouchListener(new Button.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
String message;
byte[] msgBuffer;
int action = event.getAction();
switch(action)
{
case MotionEvent.ACTION_DOWN:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "w";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
case MotionEvent.ACTION_UP:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "0";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
}
return false;
} // end of onTouch
});
//后退
mButtonB=(Button)findViewById(R.id.btnB);
mButtonB.setOnTouchListener(new Button.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
// TODO Auto-generated method stub
String message;
byte[] msgBuffer;
int action = event.getAction();
switch(action)
{
case MotionEvent.ACTION_DOWN:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "s";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
case MotionEvent.ACTION_UP:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "0";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
}
return false;
} // end of onTouch
}); // end of setOnTouchListener
//左转
mButtonL=(Button)findViewById(R.id.btnL);
mButtonL.setOnTouchListener(new Button.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
// TODO Auto-generated method stub
String message;
byte[] msgBuffer;
int action = event.getAction();
switch(action)
{
case MotionEvent.ACTION_DOWN:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "a";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
case MotionEvent.ACTION_UP:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "0";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
}
return false;
}
});
//右转
mButtonR=(Button)findViewById(R.id.btnR);
mButtonR.setOnTouchListener(new Button.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
// TODO Auto-generated method stub
String message;
byte[] msgBuffer;
int action = event.getAction();
switch(action)
{
case MotionEvent.ACTION_DOWN:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "d";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
case MotionEvent.ACTION_UP:
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
message = "0";
msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
break;
}
return false;
}
});
//停止
mButtonS=(Button)findViewById(R.id.btnS);
mButtonS.setOnTouchListener(new Button.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
// TODO Auto-generated method stub
if (event.getAction()==MotionEvent.ACTION_DOWN)
try
{
outStream = btSocket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
String message = "0";
byte[] msgBuffer = message.getBytes();
try
{
outStream.write(msgBuffer);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
return false;
}
});
if ( D )
Log.e(TAG, "+++ ON CREATE +++");
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null)
{
Toast.makeText(this, "Bluetooth is not available.", Toast.LENGTH_LONG).show();
finish();
return;
}
if (!mBluetoothAdapter.isEnabled())
{
Toast.makeText(this, "Please enable your Bluetooth and re-run this program.", Toast.LENGTH_LONG).show();
finish();
return;
}
if ( D )
Log.e(TAG, "+++ DONE IN ON CREATE, GOT LOCAL BT ADAPTER +++");
} // end of onCreate
@Override
public void onStart()
{
super.onStart();
if (D)
Log.e(TAG, "++ ON START ++");
}
@Override
public void onResume()
{
super.onResume();
if ( D )
{
Log.e(TAG, "+ ON RESUME +");
Log.e(TAG, "+ ABOUT TO ATTEMPT CLIENT CONNECT +");
}
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
try
{
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
}
catch (IOException e)
{
Log.e(TAG, "ON RESUME: Socket creation failed.", e);
}
mBluetoothAdapter.cancelDiscovery();
try
{
btSocket.connect();
Log.e(TAG, "ON RESUME: BT connection established, data transfer link open.");
}
catch (IOException e)
{
try
{
btSocket.close();
}
catch (IOException e2)
{
Log .e(TAG,"ON RESUME: Unable to close socket during connection failure", e2);
}
}
// Create a data stream so we can talk to server.
if ( D )
Log.e(TAG, "+ ABOUT TO SAY SOMETHING TO SERVER +");
/* try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
}
String message = "1";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
*/
}
@Override
public void onPause()
{
super.onPause();
if ( D )
Log.e(TAG, "- ON PAUSE -");
if (outStream != null)
{
try
{
outStream.flush();
}
catch (IOException e)
{
Log.e(TAG, "ON PAUSE: Couldn't flush output stream.", e);
}
}
try
{
btSocket.close();
}
catch (IOException e2)
{
Log.e(TAG, "ON PAUSE: Unable to close socket.", e2);
}
}
@Override
public void onStop()
{
super.onStop();
if ( D )
Log.e(TAG, "-- ON STOP --");
}
@Override
public void onDestroy()
{
super.onDestroy();
if ( D )
Log.e(TAG, "--- ON DESTROY ---");
}
// @Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
// }
//
// @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// // Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.main, menu);
// return true;
// }
}
自己的乐高装备和小车想象图。。。。。。
上图的轮子是前轮,放错了地方,后轮和乐高的转向系统,由于手头缺少一些乐高配件,待以后贴出来
后轮驱动前进后退,前轮负责转向
上图从左到右一次是:前翼、转向系统、舵机、锂电池(留了空间,上图没有电池)BLUNO及电机板、电机、后翼
火钳刘明 同为乐高玩家 托一把 乐高很强大,就是略贵。。。 期待完成的作品。。。 taelons 发表于 2014-1-25 23:01
自己的装备。。。。。。
期待你的小车再度进展啊~~!!这样的帖子我们要顶起来啊~~~ 不打算详细讲乐高怎么搭,重点放在bluno上。昨天总算找到一根micro usb线(老爸三星手机的)给bluno用
现在快递都不发货了,缺的两个乐高配件无法派送,贴个图大家看看,一个简单的转向系统,没有悬挂避震功能
中间的轴一头接舵机
晚上如果有时间,测一下bluno带舵机、电机,再给大家汇报。
demo布局很给力的感觉,期待成品 taelons 发表于 2014-1-27 11:49
不打算详细讲乐高怎么搭,重点放在bluno上。昨天总算找到一根micro usb线(老爸三星手机的)给bluno用
现在 ...
怎么接呢?很好奇 本帖最后由 taelons 于 2014-1-27 23:35 编辑
bluno驱动370电机测试---
bluno插上电机驱动板(L298P Shield 2A),使用vin供电,micro usb接电脑,com4出现。
打开arduino ide,复制电机测试代码,编译、上传bluno成功
接电机前,先用万用表测了5v、gnd,得5.03V,M2+和M2-在1.xV至3.xV之间循环,M1和M2旁各有一个绿色的指示灯亮度渐变
接上电机(我接在M2上、M1空着),M2旁边还有一个红色指示灯亮度渐变
M2上的电机不停正反转。
看来,M1和M2旁的两个指示灯(红灯和绿灯)亮度渐变,说明电机驱动板和电机工作正常。
明天测一下舵机,舵机3根线,明天看看控制线插在哪里
Arduino PWM调速测试代码(摘自DFROBOT的L298P Shield 2A产品资料库,最后少了一个大括号):int E1 = 5;
int M1 = 4;
int E2 = 6;
int M2 = 7;
void setup()
{
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
}
void loop()
{
int value;
for(value = 0 ; value <= 255; value+=5)
{
digitalWrite(M1,HIGH);
digitalWrite(M2, HIGH);
analogWrite(E1, value); //PWM调速
analogWrite(E2, value); //PWM调速
delay(30);
}
}
bluno驱动sg90 9g舵机测试---
舵机接5v和gnd,控制线接D8
#include <Servo.h>
#define ServoPin 8
Servo servo;
int angle = 0;
void calibrateServo(){
servo.write(90);
delay(15);
}
void setup(){
servo.attach(ServoPin);
}
void loop(){
for (angle=0; angle< 160; angle++){
servo.write(angle);
delay(20);
}
for (angle=160; angle > 0; angle--){
servo.write(angle);
delay(20);
}
}
bluno同时驱动电机舵机
#include <Servo.h>
#define ServoPin 8
Servo servo;
int angle = 0;
int E1 = 5;
int M1 = 4;
int E2 = 6;
int M2 = 7;
void calibrateServo(){
servo.write( 90 );
delay( 15 );
}
void setup(){
servo.attach(ServoPin);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
}
void loop()
{
int value;
for ( value = 0 ; value <= 255; value += 5 )
{
digitalWrite( M1,HIGH );
digitalWrite( M2, HIGH );
analogWrite( E1, value ); //PWM调速
analogWrite( E2, value ); //PWM调速
delay( 30 );
}
for ( angle = 0; angle < 160; angle++)
{
servo.write( angle );
delay( 20 );
}
for ( angle = 160; angle > 0; angle -- )
{
servo.write( angle );
delay( 20 );
}
}
今天发现bluno和arduino uno板子的尺寸差不多,于是试了一下我那块arduino乐高积木外壳,bluno插上电机驱动板,放入外壳中,卡得很紧,倒置也不会掉下来,bluno可以摆脱“裸奔”了!但是插上Bluno扩展板 Accessory Shield就放不平了,需要加长一个乐高单位。
虽然外壳接近完美,但不打算用这种方法把板子固定到乐高小车上。
taelons 发表于 2014-2-3 14:47
今天发现bluno和arduino uno板子的尺寸差不多,于是试了一下我那块arduino乐高积木外壳,bluno插上电机驱动 ...
擦,请问楼主这款乐高外壳哪里搞? 初具雏形......
等过两天缺的积木到了再继续
这款至少能放两块电池,一块在舵机后bluno前的预留空间,在的bluno下方再放一块电池没问题
由于dfrobot提供的安卓代码需要安卓4.3的手机,无法装到手头安卓4.04的三星手机里,下载了
google的安卓开发环境,准备自己改写控制代码。。。。。。
无法装到手头安卓4.04的三星手机里,下载了
google的安卓开发环境,准备自己改写控制代码。。。。。。
这个赞,maker精神!
积木部分基本上完成了,需要搭建步骤的,站内短我。。。。。。
安卓代码需要安卓4.3的手机,无法装到手头安卓4.04的三星手机里,下载了
google的安卓开发环境,准备自己改写控制代码。。。。。。
这个真不好搞,蓝牙4.0是4.3系统以后才开始支持的。。 dannygto 发表于 2014-2-10 16:55
安卓代码需要安卓4.3的手机,无法装到手头安卓4.04的三星手机里,下载了
google的安卓开发环境,准备自己改 ...
bluno不支持向下兼容老版本的蓝牙吗?