个人项目 小跟班——蓝牙控制小车(蓝牙控制篇)
5 藍(lán)牙的配置
到了核心部分了,首先,想要控制手機(jī)藍(lán)牙的打開和關(guān)閉,需要在manifest中添加相應(yīng)的權(quán)限:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" />
布局文件已經(jīng)說完了,接下來看看MainActivity,代碼如下:
package com.zl_sf.tofollow;import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.UUID;import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.Button; import android.widget.ImageButton; import android.widget.ListView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener;public class MainActivity extends Activity implements OnItemClickListener {private BluetoothAdapter mBluetoothAdapter;private BluetoothSocket bluetoothSocket;private OutputStream mOutputStream;private DeviceAdapter mAdapter;private ArrayList<BluetoothDevice> mDevices = new ArrayList<BluetoothDevice>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);ListView lv_item = (ListView) findViewById(R.id.lv_item);mAdapter = new DeviceAdapter(getApplicationContext(), mDevices);lv_item.setAdapter(mAdapter);lv_item.setOnItemClickListener(this);IntentFilter filter = new IntentFilter();filter.addAction(BluetoothDevice.ACTION_FOUND);filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);registerReceiver(mBluetoothReceiver, filter);Button btn_back = (Button) findViewById(R.id.title_back);btn_back.setOnClickListener(new OnClickListener() {public void onClick(View view) {finish();}});Button tostop = (Button) findViewById(R.id.stop);tostop.setOnClickListener(new OnClickListener() {public void onClick(View view) {if (mBluetoothAdapter.isEnabled()) {mBluetoothAdapter.disable();}}});mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// 檢查設(shè)備上是否支持藍(lán)牙if (mBluetoothAdapter == null) {Toast.makeText(this, R.string.error_bluetooth_not_supported,Toast.LENGTH_SHORT).show();finish();return;}// 為了確保設(shè)備上藍(lán)牙能使用, 直接打開藍(lán)牙if (!mBluetoothAdapter.isEnabled()) {if (!mBluetoothAdapter.isEnabled()) {Toast.makeText(this, R.string.error_bluetooth,Toast.LENGTH_SHORT).show();mBluetoothAdapter.enable();}}Button scan = (Button) findViewById(R.id.scan);scan.setOnClickListener(new OnClickListener() {public void onClick(View view) {// 開始搜索mBluetoothAdapter.startDiscovery();}});Button stop = (Button) findViewById(R.id.button_stop);stop.setOnClickListener(new OnClickListener() {public void onClick(View view) {// 停止搜索mBluetoothAdapter.cancelDiscovery();}});Button follow = (Button) findViewById(R.id.follow);follow.setOnClickListener(new OnClickListener() {public void onClick(View view) { try {sendCtrl(0);} catch (Exception e) {Toast.makeText(getApplicationContext(), "未連接設(shè)備",Toast.LENGTH_SHORT).show();}/*float power = (float) ((Math.abs(rssi) - 59) / (10 * 2.0));dis = (int) Math.pow(10, power);distance.setText(dis);*/}});Button maze = (Button) findViewById(R.id.maze);maze.setOnClickListener(new OnClickListener() {public void onClick(View view) {try {sendCtrl(1);} catch (Exception e) {Toast.makeText(getApplicationContext(), "未連接設(shè)備",Toast.LENGTH_SHORT).show();}}});ImageButton up = (ImageButton) findViewById(R.id.up);up.setOnClickListener(new OnClickListener() {public void onClick(View view) {try {sendCtrl(2);} catch (Exception e) {Toast.makeText(getApplicationContext(), "未連接設(shè)備",Toast.LENGTH_SHORT).show();}}});ImageButton down = (ImageButton) findViewById(R.id.down);down.setOnClickListener(new OnClickListener() {public void onClick(View view) {try {sendCtrl(3);} catch (Exception e) {Toast.makeText(getApplicationContext(), "未連接設(shè)備",Toast.LENGTH_SHORT).show();}}});ImageButton left = (ImageButton) findViewById(R.id.left);left.setOnClickListener(new OnClickListener() {public void onClick(View view) {try {sendCtrl(4);} catch (Exception e) {Toast.makeText(getApplicationContext(), "未連接設(shè)備",Toast.LENGTH_SHORT).show();}}});ImageButton right = (ImageButton) findViewById(R.id.right);right.setOnClickListener(new OnClickListener() {public void onClick(View view) {try {sendCtrl(5);} catch (Exception e) {Toast.makeText(getApplicationContext(), "未連接設(shè)備",Toast.LENGTH_SHORT).show();}}});}//發(fā)送控制private void sendCtrl(int i) {try {byte[] bs = new byte[5];bs[0] = (byte)0x00;bs[1] = (byte)0x00;bs[2] = (byte)0x00;//模式一 followif(i== 0) {bs[4]= (byte)0x05;}//模式二 迷宮else if(i==1) {bs[4]= (byte)0x06;}//前進(jìn)else if(i==2) {bs[4]= (byte)0x01;}//后退else if(i==3) {bs[4]= (byte)0x02;}//左轉(zhuǎn)else if(i==4) {bs[4]= (byte)0x03;}//右轉(zhuǎn)else if(i==5) {bs[4]= (byte)0x04;}mOutputStream.write(bs);} catch (IOException e) {e.printStackTrace();Toast.makeText(getApplicationContext(), "發(fā)送失敗",Toast.LENGTH_SHORT).show();}}private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {// 掃描到藍(lán)牙設(shè)備BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);mDevices.add(device);mAdapter.notifyDataSetChanged();} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {Toast.makeText(getApplicationContext(), "開始掃描",Toast.LENGTH_SHORT).show();} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {Toast.makeText(getApplicationContext(), "掃描結(jié)束", Toast.LENGTH_SHORT).show();}}};protected void onDestroy() {super.onDestroy();// 注銷注冊(cè)u(píng)nregisterReceiver(mBluetoothReceiver);}public void onItemClick(AdapterView<?> parent, View view, int position,long id) {BluetoothDevice device = mDevices.get(position);// 連接操作connection(device);}private void connection(final BluetoothDevice device) {// 建立藍(lán)牙連接new Thread() {public void run() {try {// 獲取 BluetoothSocket,UUID要一致,這是大多數(shù)用的bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));// 和藍(lán)牙服務(wù)端建立連接bluetoothSocket.connect();// 獲取輸出流,像藍(lán)牙服務(wù)端寫指令信息mOutputStream = bluetoothSocket.getOutputStream();// 提示用戶runOnUiThread(new Runnable() {public void run() {Toast.makeText(getApplicationContext(), "連接成功",Toast.LENGTH_SHORT).show();}});} catch (IOException e) {e.printStackTrace();}};}.start();} }掃描和連接設(shè)備方法在上面寫的很清楚了,都是API里面給的一些函數(shù),仔細(xì)看看網(wǎng)上的幫助文檔對(duì)應(yīng)用開發(fā)有很大的幫助。
這里還需要一個(gè)DeviceAdapter存放搜索到的藍(lán)牙設(shè)備并顯示在ListView上,代碼如下:
DeviceAdapter:
package com.zl_sf.tofollow;import java.util.ArrayList;import android.bluetooth.BluetoothDevice; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView;public class DeviceAdapter extends BaseAdapter {private ArrayList<BluetoothDevice> mDevices;private Context mContext;public DeviceAdapter(Context context,ArrayList<BluetoothDevice> devices){mDevices = devices;mContext = context;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mDevices.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder holder;if(convertView == null){convertView = View.inflate(mContext, R.layout.item, null);holder = new ViewHolder();holder.item_name = (TextView) convertView.findViewById(R.id.item_name);holder.item_addr = (TextView) convertView.findViewById(R.id.item_addr);convertView.setTag(holder);}else{holder = (ViewHolder) convertView.getTag();}BluetoothDevice device = mDevices.get(position);holder.item_name.setText(device.getName());holder.item_addr.setText(device.getAddress());return convertView;}class ViewHolder {TextView item_name;TextView item_addr;} }這樣,小跟班應(yīng)用基本成型了。
6 設(shè)置發(fā)送指令
設(shè)置發(fā)送指令曾經(jīng)是我很頭疼的一個(gè)問題,網(wǎng)上都是對(duì)于繼電器或者有指令格式的設(shè)備操作,對(duì)于我買的設(shè)備還需要自定義,一開始不知道從何下手,不過,現(xiàn)在看來是非常的容易。首先是對(duì)你小車的程序進(jìn)行設(shè)置,藍(lán)牙是串口通信,只能傳送十六進(jìn)制字節(jié),那么,我們先設(shè)置一些十六進(jìn)制指令代表不同的功能,這樣上位機(jī)就能很容易得對(duì)小車進(jìn)行控制了。就像上面MainActivity里寫的:
byte[] bs = new byte[5];bs[0] = (byte)0x00;bs[1] = (byte)0x00;bs[2] = (byte)0x00;//模式一 followif(i== 0) {bs[4]= (byte)0x05;}//模式二 迷宮else if(i==1) {bs[4]= (byte)0x06;}//前進(jìn)else if(i==2) {bs[4]= (byte)0x01;}//后退else if(i==3) {bs[4]= (byte)0x02;}//左轉(zhuǎn)else if(i==4) {bs[4]= (byte)0x03;}//右轉(zhuǎn)else if(i==5) {bs[4]= (byte)0x04;}mOutputStream.write(bs);這樣看來就很簡潔明了了。
7 對(duì)你的應(yīng)用進(jìn)行包裝
應(yīng)用功能基本實(shí)現(xiàn),現(xiàn)在需要一個(gè)精美的圖標(biāo)來完善它。我從網(wǎng)上找了一個(gè),感覺還行吧,如果能直接PS一個(gè)就更好了。
(1)這個(gè)應(yīng)用的引導(dǎo)界面是每次打開都會(huì)出現(xiàn),然而,真正完善的應(yīng)用是更新之后會(huì)有一個(gè)引導(dǎo)界面,再次打開就只有歡迎界面,這里可以更加完善
(2)這個(gè)應(yīng)用的主界面只有一個(gè),但是放的東西比較多,略顯擁擠,可以將搜索到的設(shè)備放在另一個(gè)界面進(jìn)行連接,再返回來控制。這里也可以更加完善
9 附錄
這個(gè)應(yīng)用配套的小車是通過Arduino UNO 板控制,小車的源碼:
#include <Servo.h>#define to_up 0x01 //前進(jìn) #define to_down 0x02 //后退 #define to_left 0x03 //左轉(zhuǎn) #define to_right 0x04 //右轉(zhuǎn) #define moshi1 0x05 //模式一 #define moshi2 0x06 //模式二int Echo = A1; // Echo回聲腳(P2.0) int Trig = A0; // Trig 觸發(fā)腳(P2.1)const int SensorRight = A2; //右循跡紅外傳感器(P3.2 OUT1) const int SensorLeft = A3; //左循跡紅外傳感器(P3.3 OUT2)const int SensorLeft_2 = A4; //左紅外傳感器(P3.4 OUT3) const int SensorRight_2 = A5; //右紅外傳感器(P3.5 OUT4)int SL; //左循跡紅外傳感器狀態(tài) int SR; //右循跡紅外傳感器狀態(tài) int SL_2; //左紅外傳感器狀態(tài) int SR_2; //右紅外傳感器狀態(tài)int Front_Distance = 0; int Left_Distance = 0; int Right_Distance = 0;int Left_motor_back = 9; //左電機(jī)后退(IN1) int Left_motor_go = 5; //左電機(jī)前進(jìn)(IN2) int Right_motor_go = 6; // 右電機(jī)前進(jìn)(IN3) int Right_motor_back = 10; // 右電機(jī)后退(IN4)int servopin = 2; //設(shè)置舵機(jī)驅(qū)動(dòng)腳到數(shù)字口2 int myangle;//定義角度變量 int pulsewidth;//定義脈寬變量 int val;char inChar;//藍(lán)牙接收的數(shù)據(jù)void setup() {// put your setup code here, to run once:Serial.begin(9600); // 初始化串口//初始化電機(jī)驅(qū)動(dòng)IO為輸出方式pinMode(Left_motor_go, OUTPUT); // PIN 8 (PWM)pinMode(Left_motor_back, OUTPUT); // PIN 9 (PWM)pinMode(Right_motor_go, OUTPUT); // PIN 10 (PWM)pinMode(Right_motor_back, OUTPUT); // PIN 11 (PWM)pinMode(SensorRight, INPUT); //定義右循跡紅外傳感器為輸入pinMode(SensorLeft, INPUT); //定義左循跡紅外傳感器為輸入pinMode(SensorRight_2, INPUT); //定義右紅外傳感器為輸入pinMode(SensorLeft_2, INPUT); //定義左紅外傳感器為輸入pinMode(Echo, INPUT); // 定義超聲波輸入腳pinMode(Trig, OUTPUT); // 定義超聲波輸出腳}void loop() {// put your main code here, to run repeatedly:while (Serial.available() > 0){inChar = Serial.read();if (inChar == to_up){run(1);inChar = 0;}if (inChar == to_down){back(1);inChar = 0;}if (inChar == to_left){left(1);inChar = 0;}if (inChar == to_right){right(1);inChar = 0;}}if (inChar == moshi1){//有信號(hào)為LOW 沒有信號(hào)為HIGHSR_2 = digitalRead(SensorRight_2);SL_2 = digitalRead(SensorLeft_2);if (SL_2 == LOW && SR_2 == LOW)run(); //調(diào)用前進(jìn)函數(shù)else if (SL_2 == HIGH & SR_2 == LOW)// 右邊探測(cè)到有障礙物,有信號(hào)返回,向右轉(zhuǎn)right();else if (SR_2 == HIGH & SL_2 == LOW) //左邊探測(cè)到有障礙物,有信號(hào)返回,向左轉(zhuǎn)left();else // 沒有障礙物,停brake();inChar = 0;}if (inChar == moshi2){front_detection();//測(cè)量前方距離if (Front_Distance < 32) //當(dāng)遇到障礙物時(shí){back(2);//后退減速brake(2);//停下來做測(cè)距l(xiāng)eft_detection();//測(cè)量左邊距障礙物距離right_detection();//測(cè)量右邊距障礙物距離if ((Left_Distance < 35 ) && ( Right_Distance < 35 )) //當(dāng)左右兩側(cè)均有障礙物靠得比較近spin_left(0.7);//旋轉(zhuǎn)掉頭else if (Left_Distance > Right_Distance) //左邊比右邊空曠{left(3);//左轉(zhuǎn)brake(1);//剎車,穩(wěn)定方向}else//右邊比左邊空曠{right(3);//右轉(zhuǎn)brake(1);//剎車,穩(wěn)定方向}}else{run(); //無障礙物,直行}inChar = 0;}}void run() // 前進(jìn) {digitalWrite(Right_motor_go, HIGH); // 右電機(jī)前進(jìn)digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 165); //PWM比例0~255調(diào)速,左右輪差異略增減analogWrite(Right_motor_back, 0);digitalWrite(Left_motor_go, HIGH); // 左電機(jī)前進(jìn)digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 160); //PWM比例0~255調(diào)速,左右輪差異略增減analogWrite(Left_motor_back, 0); }void run(int time) // 前進(jìn) {digitalWrite(Right_motor_go, HIGH); // 右電機(jī)前進(jìn)digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 165); //PWM比例0~255調(diào)速,左右輪差異略增減analogWrite(Right_motor_back, 0);digitalWrite(Left_motor_go, HIGH); // 左電機(jī)前進(jìn)digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 160); //PWM比例0~255調(diào)速,左右輪差異略增減analogWrite(Left_motor_back, 0);delay(time * 100);//執(zhí)行時(shí)間,可以調(diào)整 }void brake() //剎車,停車 {digitalWrite(Right_motor_go, LOW);digitalWrite(Right_motor_back, LOW);digitalWrite(Left_motor_go, LOW);digitalWrite(Left_motor_back, LOW); }void brake(int time) //剎車,停車 {digitalWrite(Right_motor_go, LOW);digitalWrite(Right_motor_back, LOW);digitalWrite(Left_motor_go, LOW);digitalWrite(Left_motor_back, LOW);delay(time * 100);//執(zhí)行時(shí)間,可以調(diào)整 }void left(int time) //左轉(zhuǎn)(左輪不動(dòng),右輪前進(jìn)) {digitalWrite(Right_motor_go, HIGH); // 右電機(jī)前進(jìn)digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 200);analogWrite(Right_motor_back, 0); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, LOW); //左輪后退digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 0);analogWrite(Left_motor_back, 0); //PWM比例0~255調(diào)速delay(time * 100); //執(zhí)行時(shí)間,可以調(diào)整 }void left() //左轉(zhuǎn)(左輪不動(dòng),右輪前進(jìn)) {digitalWrite(Right_motor_go, HIGH); // 右電機(jī)前進(jìn)digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 200);analogWrite(Right_motor_back, 0); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, LOW); //左輪后退digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 0);analogWrite(Left_motor_back, 0); //PWM比例0~255調(diào)速 }void right(int time) //右轉(zhuǎn)(右輪不動(dòng),左輪前進(jìn)) {digitalWrite(Right_motor_go, LOW); //右電機(jī)后退digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 0);analogWrite(Right_motor_back, 0); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, HIGH); //左電機(jī)前進(jìn)digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 200);analogWrite(Left_motor_back, 0); //PWM比例0~255調(diào)速delay(time * 100); //執(zhí)行時(shí)間,可以調(diào)整 }void right() //右轉(zhuǎn)(右輪不動(dòng),左輪前進(jìn)) {digitalWrite(Right_motor_go, LOW); //右電機(jī)后退digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 0);analogWrite(Right_motor_back, 0); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, HIGH); //左電機(jī)前進(jìn)digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 200);analogWrite(Left_motor_back, 0); //PWM比例0~255調(diào)速 }void spin_left(int time) //左轉(zhuǎn)(左輪后退,右輪前進(jìn)) {digitalWrite(Right_motor_go, HIGH); // 右電機(jī)前進(jìn)digitalWrite(Right_motor_back, LOW);analogWrite(Right_motor_go, 150);analogWrite(Right_motor_back, 0); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, LOW); //左輪后退digitalWrite(Left_motor_back, HIGH);analogWrite(Left_motor_go, 0);analogWrite(Left_motor_back, 150); //PWM比例0~255調(diào)速delay(time * 100); //執(zhí)行時(shí)間,可以調(diào)整 }void spin_right(int time) //右轉(zhuǎn)(右輪后退,左輪前進(jìn)) {digitalWrite(Right_motor_go, LOW); //右電機(jī)后退digitalWrite(Right_motor_back, HIGH);analogWrite(Right_motor_go, 0);analogWrite(Right_motor_back, 150); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, HIGH); //左電機(jī)前進(jìn)digitalWrite(Left_motor_back, LOW);analogWrite(Left_motor_go, 150);analogWrite(Left_motor_back, 0); //PWM比例0~255調(diào)速delay(time * 100); //執(zhí)行時(shí)間,可以調(diào)整 }void back(int time) //后退 {digitalWrite(Right_motor_go, LOW); //右輪后退digitalWrite(Right_motor_back, HIGH);analogWrite(Right_motor_go, 0);analogWrite(Right_motor_back, 200); //PWM比例0~255調(diào)速digitalWrite(Left_motor_go, LOW); //左輪后退digitalWrite(Left_motor_back, HIGH);analogWrite(Left_motor_go, 0);analogWrite(Left_motor_back, 200); //PWM比例0~255調(diào)速delay(time * 100); //執(zhí)行時(shí)間,可以調(diào)整 }float Distance_test() // 量出前方距離 {digitalWrite(Trig, LOW); // 給觸發(fā)腳低電平2μsdelayMicroseconds(2);digitalWrite(Trig, HIGH); // 給觸發(fā)腳高電平10μs,這里至少是10μsdelayMicroseconds(10);digitalWrite(Trig, LOW); // 持續(xù)給觸發(fā)腳低電float Fdistance = pulseIn(Echo, HIGH); // 讀取高電平時(shí)間(單位:微秒)Fdistance = Fdistance / 58; //Y米=(X秒*344)/2return Fdistance; }void servopulse(int servopin, int myangle) //定義一個(gè)脈沖函數(shù),用來模擬方式產(chǎn)生PWM值 {pulsewidth = (myangle * 11) + 500; //將角度轉(zhuǎn)化為500-2480 的脈寬值digitalWrite(servopin, HIGH); //將舵機(jī)接口電平置高delayMicroseconds(pulsewidth);//延時(shí)脈寬值的微秒數(shù)digitalWrite(servopin, LOW); //將舵機(jī)接口電平置低delay(20 - pulsewidth / 1000); //延時(shí)周期內(nèi)剩余時(shí)間 }void front_detection() {//此處循環(huán)次數(shù)減少,為了增加小車遇到障礙物的反應(yīng)速度for (int i = 0; i <= 5; i++) //產(chǎn)生PWM個(gè)數(shù),等效延時(shí)以保證能轉(zhuǎn)到響應(yīng)角度{servopulse(servopin, 90); //模擬產(chǎn)生PWM}Front_Distance = Distance_test(); }void left_detection() {for (int i = 0; i <= 15; i++) //產(chǎn)生PWM個(gè)數(shù),等效延時(shí)以保證能轉(zhuǎn)到響應(yīng)角度{servopulse(servopin, 175); //模擬產(chǎn)生PWM}Left_Distance = Distance_test(); }void right_detection() {for (int i = 0; i <= 15; i++) //產(chǎn)生PWM個(gè)數(shù),等效延時(shí)以保證能轉(zhuǎn)到響應(yīng)角度{servopulse(servopin, 5); //模擬產(chǎn)生PWM}Right_Distance = Distance_test(); }
有學(xué)習(xí)Arduino的朋友們可以分享分享~另外,我這個(gè)也不是很穩(wěn)定,可能程序還是有BUG,目前就先這樣告一段落,期待后期的改進(jìn)和更新。
PS:小車源碼下載地址:http://download.csdn.net/detail/zl_1205/9725864
總結(jié)
以上是生活随笔為你收集整理的个人项目 小跟班——蓝牙控制小车(蓝牙控制篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Day01-Oracle的连接与账户
- 下一篇: torchtorchvision对应版本