meArm專題(二)
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include <LiquidCrystal_I2C.h>
#include <Kalman.h>
#include <SoftwareSerial.h>
#define RX 3 //HC-05 TX接3
#define TX 2 //HC-05 RX接2
#define X_Trig 7
#define X_Echo 6
#define L_Trig 9
#define L_Echo 8
#define H_Trig 11
#define H_Echo 10
SoftwareSerial BT(RX,TX);
LiquidCrystal_I2C lcd(0x3F,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27
Kalman kalmanX , kalmanY, kalmanZ;
MPU6050 accelgyro;
int16_t ax, ay, az, gx, gy, gz;
double accX, accY, accZ, gyroX, gyroY, gyroZ;
uint32_t timer , t1 , t2;
double pitch, roll, yaw, AngleX, AngleY, AngleZ, Xrate, Yrate, Zrate;
int H,L,X,sw,H0,L0,X0,roll_0,pitch_0;
int l,h,a,c;
// 中位值濾波法
#define FILTER_N 3
int filter_buf[FILTER_N];
int i, j;
int filter_temp;
void dist_X(){
for(int i=0; i<3 ; i++){
digitalWrite(X_Trig, LOW);
delayMicroseconds(2);
digitalWrite(X_Trig, HIGH); delayMicroseconds(10);
digitalWrite(X_Trig, LOW);
double t = pulseIn(X_Echo, HIGH,50000);
filter_buf[i] = int(340*t/20000) - X0 ;
}
for(j = 0; j < FILTER_N - 1; j++) {
for(i = 0; i < FILTER_N - 1 - j; i++) {
if(filter_buf[i] > filter_buf[i + 1]) {
filter_temp = filter_buf[i];
filter_buf[i] = filter_buf[i + 1];
filter_buf[i + 1] = filter_temp;
}}}
X=filter_buf[(FILTER_N - 1) / 2];
if(X<0){X=0;}else if(X>60){X=60;}
}
void dist_L(){
for(int i=0; i<3 ; i++){
digitalWrite(L_Trig, LOW);
delayMicroseconds(2);
digitalWrite(L_Trig, HIGH); delayMicroseconds(10);
digitalWrite(L_Trig, LOW);
double t = pulseIn(L_Echo, HIGH,50000);
filter_buf[i] = int(340*t/20000) - L0 ;
}
for(j = 0; j < FILTER_N - 1; j++) {
for(i = 0; i < FILTER_N - 1 - j; i++) {
if(filter_buf[i] > filter_buf[i + 1]) {
filter_temp = filter_buf[i];
filter_buf[i] = filter_buf[i + 1];
filter_buf[i + 1] = filter_temp;
}}}
L=filter_buf[(FILTER_N - 1) / 2];
if(L<0){L=0;}else if(L>45){L=45;}
lcd.setCursor(0,0);
lcd.print("L=");
lcd.print(L);
lcd.print(" ");
}
void dist_H(){
for(int i=0; i<3 ; i++){
digitalWrite(H_Trig, LOW);
delayMicroseconds(2);
digitalWrite(H_Trig, HIGH); delayMicroseconds(10);
digitalWrite(H_Trig, LOW);
double t = pulseIn(H_Echo, HIGH,50000);
filter_buf[i] = int(340*t/20000) - H0 ;
}
for(j = 0; j < FILTER_N - 1; j++) {
for(i = 0; i < FILTER_N - 1 - j; i++) {
if(filter_buf[i] > filter_buf[i + 1]) {
filter_temp = filter_buf[i];
filter_buf[i] = filter_buf[i + 1];
filter_buf[i + 1] = filter_temp;
}}}
H=filter_buf[(FILTER_N - 1) / 2];
if(H<0){H=0;}else if(H>75){H=75;}
lcd.setCursor(7,0);
lcd.print("H=");
lcd.print(H);
lcd.print(" ");
}
void get_angle(){
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
accX = ax;
accY = ay;
accZ = az;
gyroX = gx;
gyroY = gy;
gyroZ = gz;
double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
timer = micros();
pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
roll = atan2(accY,accZ) * RAD_TO_DEG;
yaw = atan2(accX , accY) * RAD_TO_DEG;
Yrate = gyroY / 131.0; // Convert to deg/s
Xrate = gyroX / 131.0;
Zrate = gyroZ / 131.0;
AngleY = kalmanY.getAngle(pitch, Yrate, dt) - roll_0;
AngleX = kalmanX.getAngle(roll, Xrate, dt) - pitch_0;
}
void tx(int cmd_l , int cmd_h , int cmd_a , int cmd_c , int t){
if(cmd_c>0){cmd_c=1;}else if(cmd_c<0){cmd_c=-1;}
if(millis()>t1+t){
long msg = cmd_c * (cmd_a*10000 + cmd_h*100 + cmd_l);
BT.print(msg);
t1=millis();
}}
void setup() {
Wire.begin();
lcd.init();
lcd.backlight();
lcd.clear();
Serial.begin(9600);
BT.begin(38400);
pinMode(X_Trig, OUTPUT);
pinMode(L_Trig, OUTPUT);
pinMode(H_Trig, OUTPUT);
pinMode(13, OUTPUT);
accelgyro.initialize();
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
accX = ax; accY = ay; accZ = az; gyroX = gx; gyroY = gy; gyroZ = gz;
pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
roll = atan2(accY , accZ) * RAD_TO_DEG;
yaw = atan2(accX , accY) * RAD_TO_DEG;
kalmanY.setAngle(pitch);
kalmanX.setAngle(roll);
kalmanZ.setAngle(yaw);
do{
sw = analogRead(A0);
lcd.setCursor(0,0);
lcd.print("Push the Button");
get_angle();
}while(sw>1);
dist_X();
dist_L();
dist_H();
get_angle();
X0 = X;
L0 = L;
H0 = H;
roll_0 = AngleY;
pitch_0 = AngleX;
lcd.clear();
}
void loop() {
get_angle();
if(AngleX<10&&AngleX>-10&&AngleY<10&&AngleY>-10){
sw = analogRead(A0);
if(sw>1){
c=1;
lcd.setCursor(11,1);
lcd.print("open ");
}else{
c=-1;
lcd.setCursor(11,1);
lcd.print("close");
}
digitalWrite(13,1);
dist_L();
dist_H();
dist_X();
if(X<8){
a=1;
lcd.setCursor(15,0);
lcd.print("R");
}else if(X>=8&&X<25){
a=2;
lcd.setCursor(15,0);
lcd.print("S");
}else if(X>=25&&X<50){
a=3;
lcd.setCursor(15,0);
lcd.print("L");
}
tx(L,H,a,c,100),
lcd.setCursor(0,1);
lcd.print(int(AngleX));
lcd.print(" ");
lcd.print(int(AngleY));
lcd.print(" ");
}else{
digitalWrite(13,0);
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Keep horizontal");
lcd.print(" ");
}
}
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27
#include <Adafruit_PWMServoDriver.h>
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)
#include <SoftwareSerial.h>
#define RX 3 //HC-05 TX接3
#define TX 2 //HC-05 RX接2
SoftwareSerial BT(RX,TX);
int R , L , B , a,b,c;
long msg,cmd;
unsigned long t1,t2;
int c1,c2,a0,b0;
int L1,L2,H1,H2;
void servoA_write(int d){
int x = map(d,0,180,SERVOMIN,SERVOMAX);
pwm.setPWM(0, 0, x);
}
void servoB_write(int d){
int x = map(d,0,180,SERVOMIN,SERVOMAX);
pwm.setPWM(1, 0, x);
}
void servoC_write(int d){
int x = map(d,0,180,SERVOMIN,SERVOMAX);
pwm.setPWM(2, 0, x);
}
void servoD_write(int d){
int x = map(d,0,180,SERVOMIN,SERVOMAX);
pwm.setPWM(3, 0, x);
}
void go_zero(){
servoA_write(135);
servoC_write(90);
servoD_write(80);
}
void forward(int arm_length , int arm_height){
arm_length = constrain(arm_length,0,45);
R= 135 + arm_length - arm_height;
L= 80 + arm_length + arm_height;
R=constrain(R,60,180);
L=constrain(L,90,162);
servoA_write(R);
servoD_write(L);
LCD_Display(100,arm_length,arm_height);
}
void LCD_Display(int t , int arm_length , int arm_height){
if(millis()-t1>t){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("L=");
lcd.print(arm_length);
lcd.print(" H=");
lcd.print(arm_height);
t1=millis();
}
}
void setup(){
Serial.begin(9600);
BT.setTimeout(10); // 設定為每10毫秒結束一次讀取(數字愈小愈快)
BT.begin(38400);
lcd.init();
lcd.backlight();
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
yield();
servoA_write(135);
servoD_write(80);
}
void loop(){
if(BT.available()>0){
msg = BT.parseInt();
}
lcd.setCursor(0,1);
lcd.print(msg);
lcd.print(" ");
if(msg!=0){
if(msg>10000||msg<(-10000)){
cmd=msg;
}
if(cmd>0){
lcd.setCursor(11,1);
lcd.print("open ");
servoB_write(150);
}else{
servoB_write(115);
lcd.setCursor(11,1);
lcd.print("close");
}
if(cmd<0){cmd=-1*cmd; }
a=cmd%100;
b=cmd/100%100;
c=cmd/10000;
if(a-a0>15||a-a0<-15){
a=a0;
}
if(b-b0>15||b-b0<-15){
b=b0;
}
if(c==1){
c1=c1+2;
if(c1>90){c1=90;}
}
if(c==2){c1=c1;}
if(c==3){
c1=c1-2;
if(c1<-90){c1=-90;}
}
LCD_Display(100,45-a,b);
servoC_write(90+c1);
forward(45-a,b);
a0=a;
b0=b;
Serial.print(45-a);
Serial.print(",");
Serial.print(b);
Serial.print(",");
Serial.println(c);
}
}