控制手套

手套端

#include <Wire.h>

#include <HMC5883L.h>

#include <ADXL345.h>

#include <LiquidCrystal_I2C.h>

#include <SoftwareSerial.h>

#define RX 3 //HC-05 TX接3

#define TX 2 //HC-05 RX接2

SoftwareSerial BT(RX,TX);

#define TrigX 4

#define EchoX 5

#define TrigZ 6

#define EchoZ 7

LiquidCrystal_I2C lcd(0x27,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27

HMC5883L compass;

ADXL345 accelerometer;

float heading0;

float heading1;

float heading2;

float x0,x,x1,x2,z0,z,z1,z2;

int now,old,A,B;

int output;

int Temp=30;

unsigned long t,t1,t2,t3,t4,t5,t6;

double pitch, roll, yaw;

int sw=1;

//無傾斜補償

float noTiltCompensate(Vector mag){

float heading = atan2(mag.YAxis, mag.XAxis);

return heading;

}

// 傾斜補償

float tiltCompensate(Vector mag, Vector normAccel){

roll = asin(normAccel.YAxis);

pitch = asin(-normAccel.XAxis);

if (roll > 0.78 || roll < -0.78 || pitch > 0.78 || pitch < -0.78){return -1000; }

float cosRoll = cos(roll);

float sinRoll = sin(roll);

float cosPitch = cos(pitch);

float sinPitch = sin(pitch);

float Xh = mag.XAxis * cosPitch + mag.ZAxis * sinPitch;

float Yh = mag.XAxis * sinRoll * sinPitch + mag.YAxis * cosRoll - mag.ZAxis * sinRoll * cosPitch;

float heading = atan2(Yh, Xh);

return heading;

}

//角度校正

float correctAngle(float heading){

if (heading < 0) { heading += 2 * PI; }

if (heading > 2 * PI) { heading -= 2 * PI; }

return heading;

}

//得到角度

void getdata(){

// 讀取向量值

Vector mag = compass.readNormalize();

Vector acc = accelerometer.readScaled();

// Calculate headings

heading1 = noTiltCompensate(mag);

heading2 = tiltCompensate(mag, acc);

if (heading2 == -1000){

heading2 = heading1;

}

// Set declination angle on your location and fix heading

// You can find your declination on: http://magnetic-declination.com/

// (+) Positive or (-) for negative

// 台北地區的磁偏角是 4'4 WEST (negative)

// Formula: (deg + (min / 60.0)) / (180 / M_PI);

float declinationAngle = (-4.0 - (4.0 / 60.0)) / (180 / M_PI);

heading1 += declinationAngle;

heading2 += declinationAngle;

// Correct for heading < 0deg and heading > 360deg

heading1 = correctAngle(heading1);

heading2 = correctAngle(heading2);

// Convert to degrees

heading1 = heading1 * 180/M_PI;

heading2 = heading2 * 180/M_PI;

}

void get_dist(){

digitalWrite(TrigX, LOW);

delayMicroseconds(2);

digitalWrite(TrigX, HIGH); delayMicroseconds(10);

digitalWrite(TrigX, LOW);

t = pulseIn(EchoX, HIGH,50000);

x1 = (331+0.6*Temp)*t/20000 ;

if(x1>3&&x1<500){x2=x1;}

digitalWrite(TrigZ, LOW);

delayMicroseconds(2);

digitalWrite(TrigZ, HIGH); delayMicroseconds(10);

digitalWrite(TrigZ, LOW);

t = pulseIn(EchoZ, HIGH,50000);

z1 = (331+0.6*Temp)*t/20000 ;

if(z1>3&&z1<500){z2=z1;}

}

void lcddisp(){

t2 = millis();

if(t2 >t1+100){

lcd.setCursor(0,0);

lcd.print(x1);

lcd.print(" ");

lcd.setCursor(8,0);

lcd.print(z1);

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print(heading0);

lcd.print(" ");

lcd.setCursor(8,1);

lcd.print("op=");

lcd.print(output);

lcd.print(" ");

t1=t2;

}}

void setup(){

Serial.begin(38400);

BT.begin(38400);

lcd.init();

lcd.backlight();

lcd.clear();

pinMode(TrigX, OUTPUT);

pinMode(TrigZ, OUTPUT);

if (!accelerometer.begin()){delay(500);} // 初始化 ADXL345

accelerometer.setRange(ADXL345_RANGE_2G);

while (!compass.begin()) { delay(500);} // 初始化電子羅盤 HMC5883L

compass.setRange(HMC5883L_RANGE_1_3GA); //設定測量範圍

compass.setMeasurementMode(HMC5883L_CONTINOUS); // 設定測量模式

compass.setDataRate(HMC5883L_DATARATE_30HZ); // 設定資料傳輸速率

compass.setSamples(HMC5883L_SAMPLES_8); //設樣本平均數的組數

compass.setOffset(0, 0); //設定檢量線的數值

delay(100);

getdata();

heading0=heading2;

old=90;

get_dist();

x0=x2;

z0=z2;

}

void loop(){

getdata();

if(heading0>=0&&heading0<90){

if(heading2<180&&heading2>=0){

now = 90 + heading2 - heading0 ;

}else if(heading2<360&&heading2>=270){

now = 90 + heading2 - heading0 - 360 ;

}

}

if(heading0>=90&&heading0<180){

if(heading2<270&&heading2>=0){

now = 90 + heading2 - heading0 ;

}}

if(heading0>=180&&heading0<270){

if(heading2<360&&heading2>=90){

now = 90 + heading2 - heading0 ;

}}

if(heading0>=270&&heading0<360){

if(heading2<360&&heading2>=180){

now = 90 + heading2 - heading0 ;

}else if(heading2<90&&heading2>=0){

now = 90 + heading2 - heading0 + 360 ;

}

}

if(analogRead(A0)<100){

sw=sw*(-1);

delay(100);}

now=constrain(now,0,180);

output=4180-now;

t4=millis();

if(t4>t3+50){

BT.println(output);

BT.println(3003+sw);

t3=t4;

}

get_dist();

x=1000 + 500 + x0 - x2;

z=2000 + 500 + z0 - z2;

t6=millis();

if(t6>t5+50){

BT.println(x);

BT.println(z);

t5=t6;

}

lcddisp();

}

第二版

手套端

機械手臂端

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

#include <SoftwareSerial.h>

#include <Adafruit_PWMServoDriver.h>

#define RX 3 //HC-05 TX接3

#define TX 2 //HC-05 RX接2

SoftwareSerial BT(RX,TX);

LiquidCrystal_I2C lcd(0x3F,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

#define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096)

#define SERVOMAX 540 // this is the 'maximum' pulse length count (out of 4096)

String data_A="90";

String data_B="90";

String data_C="90";

String data_D="90";

int A , B ;

int a0,a1,a2,b0,b1,b2,c0,c1,c2,d0,d1,d2;

unsigned long t1,t2,t3,t4;

int p,q,y;

void servoA_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(8, 0, x);

}

void servoB_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(10, 0, x);

}

void servoC_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(9, 0, x);

}

void servoD_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(11, 0, x);

}

void setup(){

Serial.begin(38400);

BT.begin(38400);

pwm.begin();

pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates

yield();

BT.setTimeout(10); // 設定為每10毫秒結束一次讀取(數字愈小愈快)

lcd.init();

lcd.backlight();

lcd.clear();

servoA_write(90);

servoB_write(90);

servoC_write(90);

servoD_write(90);

a0=90,b0=90,c0=90,d0=90;

a2=90,b2=90,c2=90,d2=90;

a1=90,b1=90,c1=90,d1=90;

}

void loop(){

if(BT.available()>0){

y = BT.parseInt();

}

p=y/1000;

q=y%1000;

if(p==1){A=q; }

if(p==2){B=q; }

if(p==3){c2=q; }

if(p==4){d2=q; }

a2= 83 + 3*(A-500);

b2= 132-6*(B-500);

if(a2+b2>=270){

b2=270-a2;

}else if(a2+b2<150){

b2=150-a2;

}

if(a2<0){a2=0;}else if(a2>180){a2=180;}

if(b2>150){b2=150;}else if(b2<0){b2=0;}

//servoD_write(d2);

/*

if(d2>d1){

for(int i=d1;i<d2;i++){

servoD_write(i);

delay(10);

}

d1=d2;

}else if(d2<d1){

for(int i=d1; i>d2 ;i--){

servoD_write(i);

delay(10);

}

d1=d2;

}else if(d2==d1){

servoD_write(d2);

}

*/

t4=millis();

if(t4>t3+10){

int s = 1;

if(a2>a1){a1=a0+s;}else if(a2==a1){a1=a0;}else if(a2<a1){a1=a0-s;}

servoA_write(a1);

a0=a1;

if(b2>b1){b1=b0+s;}else if(b2==b1){b1=b0;}else if(b2<b1){b1=b0-s;}

servoB_write(b1);

b0=b1;

if(c2==4){servoC_write(50);}else if(c2==2){servoC_write(120);}

if(d2>d1){d1=d0+s;}else if(d2==d1){d1=d0;}else if(d2<d1){d1=d0-s;}

servoD_write(d1);

d0=d1;

t3=t4;

}

t2=millis();

if(t2>t1+300){

lcd.setCursor(0,0);

lcd.print(" ");

lcd.setCursor(0,0);

lcd.print("A=");

lcd.print(A-500);

lcd.setCursor(8,0);

lcd.print("B=");

lcd.print(B-500);

lcd.setCursor(0,1);

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("D=");

lcd.print(d2);

lcd.setCursor(8,1);

lcd.print("C=");

lcd.print(c2);

t1=t2;

}

}

第二版

手臂端

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

#include <SoftwareSerial.h>

#include <Adafruit_PWMServoDriver.h>

#define RX 3 //HC-05 TX接3

#define TX 2 //HC-05 RX接2

SoftwareSerial BT(RX,TX);

LiquidCrystal_I2C lcd(0x3F,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

#define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096)

#define SERVOMAX 540 // this is the 'maximum' pulse length count (out of 4096)

int A , B ;

int a0,a1,a2,b0,b1,b2,c0,c1,c2,d0,d1,d2;

unsigned long t1,t2,t3,t4;

int p,q,y;

int fb0,fb1,ud0,ud1,z;

void servoA_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(8, 0, x);

}

void servoB_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(10, 0, x);

}

void servoC_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(9, 0, x);

}

void servoD_write(int d){

int x = map(d,0,180,SERVOMIN,SERVOMAX);

pwm.setPWM(11, 0, x);

}

void lcd_display(int time_interval){

t2=millis();

if(t2>t1+time_interval){

lcd.setCursor(0,0);

lcd.print("A=");

lcd.print(p);

lcd.setCursor(8,0);

lcd.print("B=");

lcd.print(q);

lcd.setCursor(0,1);

lcd.print("D=");

lcd.print(d1);

lcd.setCursor(8,1);

lcd.print("C=");

lcd.print(y);

t1=t2;

}}

void setup(){

Serial.begin(38400);

BT.begin(38400);

pwm.begin();

pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates

yield();

BT.setTimeout(10); // 設定為每10毫秒結束一次讀取(數字愈小愈快)

lcd.init();

lcd.backlight();

lcd.clear();

servoA_write(85);

servoB_write(50);

servoC_write(60);

servoD_write(90);

d0=90;

a1=85;

b1=50;

fb0=85;

fb1=85;

}

void loop(){

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//////////////////////////////////////////

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

lcd.setCursor(0,1);

lcd.print(q);

//決定左右

while(p==1){

lcd.setCursor(0,0);

lcd.print("Left / Right 1 ");

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

lcd.setCursor(0,0);

lcd.print("Left / Right 1 ");

p=y/10;

q=y%10;

}

if(p==1&&q==6){ //向右

d1=d0-1;

if(d1<0){d1=0;}

servoD_write(d1);

lcd.setCursor(0,1);

lcd.print("Right...");

lcd.setCursor(13,1);

lcd.print(d1);

lcd.print(" ");

d0=d1;

}else if(p==1&&q==4){ //向左

d1=d0+1;

if(d1>180){d1=180;}

servoD_write(d1);

lcd.setCursor(0,1);

lcd.print("Left... ");

lcd.setCursor(13,1);

lcd.print(d1);

lcd.print(" ");

d0=d1;

}else if(p==1&&q==5){ //不動

servoD_write(d0);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(d0);

lcd.print(" ");

}

delay(5); //這個delay會決定 servo 速度

}

//////////////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定前後

while(p==2){

lcd.setCursor(0,0);

lcd.print("Back / Forward 2 ");

if(BT.available()>0){ y = BT.parseInt();}

if(y!=0){

p=y/10;

q=y%10;

lcd.setCursor(0,0);

lcd.print("Back / Forward 2 ");

}

//伸長

if(p==2&&q==6){

fb1=fb0+1;

if(fb1>170){fb1=170;}

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1=fb1-70; }else{ b1=135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Forward...");

lcd.setCursor(13,1);

lcd.print(fb1);

lcd.print(" ");

fb0=fb1;

}

//縮回

if(p==2&&q==4){

fb1=fb0-1;

if(fb1<0){fb1=0;}

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1=fb1-70; }else{ b1=135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Back...");

lcd.setCursor(13,1);

lcd.print(fb1);

lcd.print(" ");

fb0=fb1;

}

//不動

if(p==2&&q==5){

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1 = fb1-70 ; }else{ b1= 135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(fb0);

lcd.print(" ");

fb0=fb1;}

delay(2);

ud0=b1;

ud1=b1;

z=a1+b1;

}

///////////////////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定上下

while(p==3){

lcd.setCursor(0,0);

lcd.print("High / Low 3 ");

if(BT.available()>0){ y = BT.parseInt();}

if(y!=0){ p=y/10 , q=y%10;

lcd.setCursor(0,0);

lcd.print("High / Low 3");

}

//抬高

if(p==3&&q==6){

ud1=ud0+1;

if(ud1>165){ud1=165;}

b1=ud1;

servoB_write(b1);

a1= z-ud1;

servoA_write(a1);

lcd.setCursor(0,1);

lcd.print("UP.....");

lcd.setCursor(13,1);

lcd.print(ud1);

lcd.print(" ");

ud0=ud1;

}

//降低

if(p==3&&q==4){

ud1=ud0-1;

if(z-ud1>170){ud1=z-170;}

b1=ud1;

servoB_write(b1);

a1= z-ud1;

servoA_write(a1);

lcd.setCursor(0,1);

lcd.print("Down...");

lcd.setCursor(13,1);

lcd.print(ud1);

lcd.print(" ");

ud0=ud1;}

//不動

if(p==3&&q==5){

b1=ud1;

a1= z-ud1;

servoA_write(a1);

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(ud0);

lcd.print(" ");

ud0=ud1;}

delay(2);

ud0=b1;

ud1=b1;

z=a1+b1;

}

///////////////////////////////////////////////////////////////////////////

if(BT.available()>0){y = BT.parseInt();}

if(y!=0){

p=y/10;

q=y%10;

}

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

lcd.setCursor(0,1);

lcd.print(q);

//決定左右

while(p==4){

lcd.setCursor(0,0);

lcd.print("Left / Right 4 ");

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

lcd.setCursor(0,0);

lcd.print("Left / Right 4 ");

p=y/10;

q=y%10;

}

if(p==4&&q==6){ //向右

d1=d0-1;

if(d1<0){d1=0;}

servoD_write(d1);

lcd.setCursor(0,1);

lcd.print("Right...");

lcd.setCursor(13,1);

lcd.print(d1);

lcd.print(" ");

d0=d1;

}else if(p==4&&q==4){ //向左

d1=d0+1;

if(d1>180){d1=180;}

servoD_write(d1);

lcd.setCursor(0,1);

lcd.print("Left... ");

lcd.setCursor(13,1);

lcd.print(d1);

lcd.print(" ");

d0=d1;

}else if(p==4&&q==5){ //不動

servoD_write(d0);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(d0);

lcd.print(" ");

}

delay(5); //這個delay會決定 servo 速度

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){y = BT.parseInt();}

if(y!=0){

p=y/10;

q=y%10;

}

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){y = BT.parseInt();}

if(y!=0){

p=y/10;

q=y%10;

}

//決定上下

while(p==5){

lcd.setCursor(0,0);

lcd.print("High / Low 5 ");

if(BT.available()>0){ y = BT.parseInt();}

if(y!=0){ p=y/10 , q=y%10;

lcd.setCursor(0,0);

lcd.print("High / Low 5");

}

//抬高

if(p==5&&q==6){

ud1=ud0+1;

if(ud1>165){ud1=165;}

b1=ud1;

servoB_write(b1);

a1= z-ud1;

servoA_write(a1);

lcd.setCursor(0,1);

lcd.print("UP.....");

lcd.setCursor(13,1);

lcd.print(ud1);

lcd.print(" ");

ud0=ud1;

}

//降低

if(p==5&&q==4){

ud1=ud0-1;

if(z-ud1>170){ud1=z-170;}

b1=ud1;

servoB_write(b1);

a1= z-ud1;

servoA_write(a1);

lcd.setCursor(0,1);

lcd.print("Down...");

lcd.setCursor(13,1);

lcd.print(ud1);

lcd.print(" ");

ud0=ud1;}

//不動

if(p==5&&q==5){

b1=ud1;

a1= z-ud1;

servoA_write(a1);

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(ud0);

lcd.print(" ");

ud0=ud1;}

delay(2);

fb0=a1;

fb1=a1;

}

//////////////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定前後

while(p==6){

lcd.setCursor(0,0);

lcd.print("Back / Forward 6");

if(BT.available()>0){ y = BT.parseInt();}

if(y!=0){

p=y/10;

q=y%10;

lcd.setCursor(0,0);

lcd.print("Back / Forward 6 ");

}

//伸長

if(p==6&&q==6){

fb1=fb0+1;

if(fb1>170){fb1=170;}

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1=fb1-70; }else{ b1=135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Forward...");

lcd.setCursor(13,1);

lcd.print(fb1);

lcd.print(" ");

fb0=fb1;

}

//縮回

if(p==6&&q==4){

fb1=fb0-1;

if(fb1<0){fb1=0;}

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1=fb1-70; }else{ b1=135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Back...");

lcd.setCursor(13,1);

lcd.print(fb1);

lcd.print(" ");

fb0=fb1;

}

//不動

if(p==6&&q==5){

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1 = fb1-70 ; }else{ b1= 135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(fb0);

lcd.print(" ");

fb0=fb1;}

delay(2);

fb0=a1;

fb1=a1;

}

//////////////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定夾夾

while(p==9){

if(q==1){servoC_write(120);

lcd.setCursor(0,0);

lcd.print("Release...");

}

if(q==2){servoC_write(60);

lcd.setCursor(0,0);

lcd.print("Holding...");

}

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

}

//////////////////////////////////////////////////////////////

if(BT.available()>0){

y = BT.parseInt();

}

if(y!=0){

p=y/10;

q=y%10;

}

//決定前後

while(p==7){

lcd.setCursor(0,0);

lcd.print("Back / Forward 7");

if(BT.available()>0){ y = BT.parseInt();}

if(y!=0){

p=y/10;

q=y%10;

lcd.setCursor(0,0);

lcd.print("Back / Forward 7 ");

}

//伸長

if(p==7&&q==6){

fb1=fb0+1;

if(fb1>170){fb1=170;}

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1=fb1-70; }else{ b1=135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Forward...");

lcd.setCursor(13,1);

lcd.print(fb1);

lcd.print(" ");

fb0=fb1;

}

//縮回

if(p==7&&q==4){

fb1=fb0-1;

if(fb1<0){fb1=0;}

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1=fb1-70; }else{ b1=135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Back...");

lcd.setCursor(13,1);

lcd.print(fb1);

lcd.print(" ");

fb0=fb1;

}

//不動

if(p==7&&q==5){

a1=fb1;

servoA_write(a1);

if(fb1>=100){ b1 = fb1-70 ; }else{ b1= 135-fb1; }

servoB_write(b1);

lcd.setCursor(0,1);

lcd.print("Frezze...");

lcd.setCursor(13,1);

lcd.print(fb0);

lcd.print(" ");

fb0=fb1;}

delay(2);

fb0=a1;

fb1=a1;

}

///////////////////////////////////////////////////////////////////////

}

#include <Wire.h>

#include <HMC5883L.h>

#include <ADXL345.h>

#include <LiquidCrystal_I2C.h>

#include <SoftwareSerial.h>

#define RX 3 //HC-05 TX接3

#define TX 2 //HC-05 RX接2

SoftwareSerial BT(RX,TX);

#define TrigX 4

#define EchoX 5

#define TrigZ 6

#define EchoZ 7

LiquidCrystal_I2C lcd(0x27,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27

HMC5883L compass;

ADXL345 accelerometer;

float heading0;

float heading1;

float heading2;

float x0,x,x1,x2,z0,z,z1,z2;

int now,old,A,B;

int output,fb,ud;

int Temp=30;

unsigned long t,t1,t2,t3,t4,t5,t6;

double pitch, roll, yaw;

boolean sw,sw1;

//無傾斜補償

float noTiltCompensate(Vector mag){

float heading = atan2(mag.YAxis, mag.XAxis);

return heading;

}

// 傾斜補償

float tiltCompensate(Vector mag, Vector normAccel){

roll = asin(normAccel.YAxis);

pitch = asin(-normAccel.XAxis);

if (roll > 0.78 || roll < -0.78 || pitch > 0.78 || pitch < -0.78){return -1000; }

float cosRoll = cos(roll);

float sinRoll = sin(roll);

float cosPitch = cos(pitch);

float sinPitch = sin(pitch);

float Xh = mag.XAxis * cosPitch + mag.ZAxis * sinPitch;

float Yh = mag.XAxis * sinRoll * sinPitch + mag.YAxis * cosRoll - mag.ZAxis * sinRoll * cosPitch;

float heading = atan2(Yh, Xh);

return heading;

}

//角度校正

float correctAngle(float heading){

if (heading < 0) { heading += 2 * PI; }

if (heading > 2 * PI) { heading -= 2 * PI; }

return heading;

}

//得到角度

void get_direction(){

// 讀取向量值

Vector mag = compass.readNormalize();

Vector acc = accelerometer.readScaled();

// Calculate headings

heading1 = noTiltCompensate(mag);

heading2 = tiltCompensate(mag, acc);

if (heading2 == -1000){

heading2 = heading1;

}

float declinationAngle = (-4.0 - (4.0 / 60.0)) / (180 / M_PI);

heading1 += declinationAngle;

heading2 += declinationAngle;

heading1 = correctAngle(heading1);

heading2 = correctAngle(heading2);

heading1 = heading1 * 180/M_PI;

heading2 = heading2 * 180/M_PI;

if(heading0>=0&&heading0<90){

if(heading2<180&&heading2>=0){

now = 90 + heading2 - heading0 ;

}else if(heading2<360&&heading2>=270){

now = 90 + heading2 - heading0 - 360 ;

}}

if(heading0>=90&&heading0<180){

if(heading2<270&&heading2>=0){

now = 90 + heading2 - heading0 ;

}}

if(heading0>=180&&heading0<270){

if(heading2<360&&heading2>=90){

now = 90 + heading2 - heading0 ;

}}

if(heading0>=270&&heading0<360){

if(heading2<360&&heading2>=180){

now = 90 + heading2 - heading0 ;

}else if(heading2<90&&heading2>=0){

now = 90 + heading2 - heading0 + 360 ;

}}

now=constrain(now,0,180);

return now,heading2;

}

void get_distX(){

digitalWrite(TrigX, LOW);

delayMicroseconds(2);

digitalWrite(TrigX, HIGH); delayMicroseconds(10);

digitalWrite(TrigX, LOW);

t = pulseIn(EchoX, HIGH,50000);

x1 = (331+0.6*Temp)*t/20000;

if(x1>3&&x1<500){x2=x1;}

}

void get_distZ(){

digitalWrite(TrigZ, LOW);

delayMicroseconds(2);

digitalWrite(TrigZ, HIGH); delayMicroseconds(10);

digitalWrite(TrigZ, LOW);

t = pulseIn(EchoZ, HIGH,50000);

z1 = (331+0.6*Temp)*t/20000 ;

if(z1>3&&z1<500){z2=z1;}

}

void lcddisp(){

t2 = millis();

if(t2 >t1+100){

lcd.setCursor(0,0);

lcd.print(x1);

lcd.print(" ");

lcd.setCursor(8,0);

lcd.print(z1);

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print(now);

lcd.print(" ");

t1=t2;

}}

void button(){

sw=0;

lcd.setCursor(8,1);

lcd.print("sw=");

lcd.setCursor(11,1);

lcd.print(sw);

sw1 = analogRead(A0);

sw1=1-sw1;

if(sw1==1){

delay(20);

sw1 = analogRead(A0);

sw1=1-sw1;

if(sw1==1){

sw=1;

lcd.setCursor(11,1);

lcd.print(sw);

}else{

sw=0;

lcd.setCursor(11,1);

lcd.print(sw);

}}}

void setup(){

Serial.begin(38400);

BT.begin(38400);

lcd.init();

lcd.backlight();

lcd.clear();

pinMode(TrigX, OUTPUT);

pinMode(TrigZ, OUTPUT);

if (!accelerometer.begin()){delay(500);} // 初始化 ADXL345

accelerometer.setRange(ADXL345_RANGE_2G);

while (!compass.begin()) { delay(500);} // 初始化電子羅盤 HMC5883L

compass.setRange(HMC5883L_RANGE_1_3GA); //設定測量範圍

compass.setMeasurementMode(HMC5883L_CONTINOUS); // 設定測量模式

compass.setDataRate(HMC5883L_DATARATE_30HZ); // 設定資料傳輸速率

compass.setSamples(HMC5883L_SAMPLES_8); //設樣本平均數的組數

compass.setOffset(0, 0); //設定檢量線的數值

delay(100);

get_direction();

heading0=heading2;

get_direction();

old=now;

}

void loop(){

delay(100);

BT.println(91); //放開

delay(100);

//////////////////////////////////////////////////////////////////////

//先決定左右

int new_state=4;

int old_state=4;

BT.println(40);

do{

lcd.setCursor(0,0);

lcd.print("Left / Right 1");

get_direction();

if(now-old>10){ //往右

new_state=2;

lcd.setCursor(0,1);

lcd.print(16);

if(old_state != 2 && new_state == 2 ){ BT.println(16); }

old_state = new_state;

}else if(abs(now-old)<=10){ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(15);

if(old_state != 0 && new_state == 0 ){

BT.println(15);

}

old_state = new_state;

}else if(old-now>10){ //往左

new_state=1;

lcd.setCursor(0,1);

lcd.print(14);

if(old_state != 1 && new_state == 1 ){

BT.println(14);

}

old_state = new_state;

}

button();

//lcddisp();

delay(10);

}while(sw==0);

///////////////////////////////////////////////////////////////////

delay(100);

BT.println(91); //放開

delay(100);

///////////////////////////////////////////////////////////////////

//決定前後

new_state=4;

old_state=4;

do{

lcd.setCursor(0,0);

lcd.print("Back / Forward 2");

Vector acc = accelerometer.readScaled();

fb = asin(-acc.XAxis) * 180/M_PI;

if(fb>20){ //往前

new_state=2;

lcd.setCursor(0,1);

lcd.print(26);

if(old_state != 2 && new_state == 2 ){ BT.println(26); }

old_state = new_state;

}else if(fb<-20){ //往後

new_state=1;

lcd.setCursor(0,1);

lcd.print(24);

if(old_state != 1 && new_state == 1 ){ BT.println(24); }

old_state = new_state;

}else{ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(25);

if(old_state != 0 && new_state == 0 ){BT.println(25); }

old_state = new_state;}

button();

delay(10);

}while(sw==0);

///////////////////////////////////////////////////////////////////////

delay(100);

BT.println(92); //夾緊

delay(100);

////////////////////////////////////////////////////////////////////////

//決定高低

new_state=4;

old_state=4;

do{

lcd.setCursor(0,0);

lcd.print("Up / Down 3");

Vector acc = accelerometer.readScaled();

ud = asin(acc.XAxis) * 180/M_PI;

if(ud>20){ //往上

new_state=2;

lcd.setCursor(0,1);

lcd.print(36);

if(old_state != 2 && new_state == 2 ){ BT.println(36); }

old_state = new_state;

}else if(ud<-20){ //往下

new_state=1;

lcd.setCursor(0,1);

lcd.print(34);

if(old_state != 1 && new_state == 1 ){ BT.println(34); }

old_state = new_state;

}else{ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(35);

if(old_state != 0 && new_state == 0 ){BT.println(35); }

old_state = new_state;}

button();

delay(10);

}while(sw==0);

//////////////////////////////////////////////////////////////////////////////

delay(100);

BT.println(92); //夾緊

delay(100);

///////////////////////////////////////////////////////////////////////////////////

//先決定左右

new_state=4;

old_state=4;

BT.println(40);

do{

lcd.setCursor(0,0);

lcd.print("Left or Right 4");

get_direction();

if(now-old>10){ //往右

new_state=2;

lcd.setCursor(0,1);

lcd.print(46);

if(old_state != 2 && new_state == 2 ){ BT.println(46); }

old_state = new_state;

}else if(abs(now-old)<=10){ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(45);

if(old_state != 0 && new_state == 0 ){

BT.println(45);

}

old_state = new_state;

}else if(old-now>10){ //往左

new_state=1;

lcd.setCursor(0,1);

lcd.print(44);

if(old_state != 1 && new_state == 1 ){

BT.println(44);

}

old_state = new_state;

}

button();

//lcddisp();

delay(10);

}while(sw==0);

//////////////////////////////////////////////////////////////////////////////

delay(100);

BT.println(92); //夾緊

delay(100);

///////////////////////////////////////////////////////////////////////////////////

//決定高低

new_state=4;

old_state=4;

do{

lcd.setCursor(0,0);

lcd.print("Up / Down 5");

Vector acc = accelerometer.readScaled();

ud = asin(acc.XAxis) * 180/M_PI;

if(ud>20){ //往上

new_state=2;

lcd.setCursor(0,1);

lcd.print(56);

if(old_state != 2 && new_state == 2 ){ BT.println(56); }

old_state = new_state;

}else if(ud<-20){ //往下

new_state=1;

lcd.setCursor(0,1);

lcd.print(54);

if(old_state != 1 && new_state == 1 ){ BT.println(54); }

old_state = new_state;

}else{ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(55);

if(old_state != 0 && new_state == 0 ){BT.println(55); }

old_state = new_state;}

button();

delay(10);

}while(sw==0);

//////////////////////////////////////////////////////////////////////////////////

delay(100);

BT.println(92); //夾緊

delay(100);

/////////////////////////////////////////////////////////////////////////////////

//決定前後

new_state=4;

old_state=4;

do{

lcd.print("Back / Forward 6");

Vector acc = accelerometer.readScaled();

fb = asin(-acc.XAxis) * 180/M_PI;

if(fb>20){ //往前

new_state=2;

lcd.setCursor(0,1);

lcd.print(66);

if(old_state != 2 && new_state == 2 ){ BT.println(66); }

old_state = new_state;

}else if(fb<-20){ //往後

new_state=1;

lcd.setCursor(0,1);

lcd.print(64);

if(old_state != 1 && new_state == 1 ){ BT.println(64); }

old_state = new_state;

}else{ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(65);

if(old_state != 0 && new_state == 0 ){BT.println(65); }

old_state = new_state;}

button();

delay(10);

}while(sw==0);

///////////////////////////////////////////////////////////////////////

delay(100);

BT.println(91); //放開

delay(100);

//////////////////////////////////////////////////////////////////////

//決定前後

new_state=4;

old_state=4;

do{

lcd.print("Back / Forward 7");

Vector acc = accelerometer.readScaled();

fb = asin(-acc.XAxis) * 180/M_PI;

if(fb>20){ //往前

new_state=2;

lcd.setCursor(0,1);

lcd.print(76);

if(old_state != 2 && new_state == 2 ){ BT.println(76); }

old_state = new_state;

}else if(fb<-20){ //往後

new_state=1;

lcd.setCursor(0,1);

lcd.print(74);

if(old_state != 1 && new_state == 1 ){ BT.println(74); }

old_state = new_state;

}else{ //不動

new_state=0;

lcd.setCursor(0,1);

lcd.print(75);

if(old_state != 0 && new_state == 0 ){BT.println(75); }

old_state = new_state;}

button();

delay(10);

}while(sw==0);

}