Uploaded by Oikiydkn11 Chan

การเขียนโปรแกรมQuadAuto32bitV1 26 4 59

advertisement
โครงการอบรมเสริมสร้างทักษะวิชาชีพด้านวิศวกรรมเมคคาทรอนิกส์
คณะวิศวกรรมศาสตร์
------------------------------เรื่องการสร้างเครื่องบินสี่ใบพัดและควบคุมตาแหน่งเบื้องต้นด้วยระบบจีพีเอส
สาขาวิชาวิศวกรรมเมคคาทรอนิกส์ มหาวิทยาลัยเทคโนโลยีราชมงคลอีสานวิทยาเขตขอนแก่น
..................................
วันที่ 7-8 พฤษภาคม 2559
สาขาวิชาวิศวกรรมเมคคาทรอนิกส์ คณะวิศวกรรมศาสตร์
มหาวิทยาลัยเทคโนโลยีราชมงคลอีสานวิทยาเขตขอนแก่น
โดย
วิทยากร
นายทินกร เขียวรี
อาจารย์วิศวกรรมเครื่องกล คณะวิศวกรรมศาสตร์และสถาปัตยกรรมศาสตร์
มหาวิทยาลัยเทคโนโลยีราชมงคลสุวรรณภูมิ ศูนย์นนทบุรี
http://quad3d-tin.lnwshop.com tinnakon_za@hotmail.com
https://www.facebook.com/tinnakonza โทร 086-054-0582
……………อัพเดทวันที่ 26 เม.ย 59……………
2
สารบัญ
หน้า
รายละเอียดอุปกรณ์ที่ใช้
ขั้นตอนการประกอบ
หัวข้อที่ต้องรู้ในการเขียนโปรแกรม
ตัวอย่างโปรแกรมที่เขียน (Quadrotor Autopilot / Flight Controller)
1. ไฟล์ Due32bit_GY521MPU_5_V1.ino
2. ไฟล์ Aconfigsam3x8e.h
3. ไฟล์ AnalogSource_Arduino.h
4. ไฟล์ Control_PPIDsam3x8e.h
5. ไฟล์ Kalman_ObserverTin.h
6. ไฟล์ Ultrasonic04.h
7. ไฟล์ ahrs_tinsam3x8e.h
8. ไฟล์ motorX4sam3x8e.h
9. ไฟล์ mpu6050sam3x8e.h
10. ไฟล์ multi_rx_sam3x8e.h
11. ไฟล์ GPSNEO6N_multi.h
12. ไฟล์ AP_Baro_MS5611.cpp
13. ไฟล์ AP_Baro_MS5611.h
14. ไฟล์ SPI_sam.cpp
15. ไฟล์ SPI_sam.h
16. ไฟล์ Wire_due32.cpp
17. ไฟล์ Wire_due32.h
3
8
19
21
21
28
31
32
37
38
40
43
47
53
55
58
-
เอกสารอ้างอิง
ประวัติผู้จัดทา
59
60
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
3
รายการชิ้นส่วนที่ใช้
ที่
รายการ
๑ GPS ublox NEO 7n with compass
๒ Arduino Due 32bit
๓ GY-521 IMU MPU6050
๔ MS5611 SPI Communication
๕ Logic Level Converter 3.3 v
๖ Afro ESC 30Amp
๗ มอเตอร์ UFO 4010-850KV
๘ ใบพัด 10x4.5 นิ้ว
๙ เฟรม quad Frame_Auto450_V2
๑๐ Hobbywing UBEC 5V/6V 3A
๑๑ สายไฟ ขั้วแบท แผ่นปริ้น รัดแบต
๑๒ รีโมท STORM i6S 2.4GHz
๑๓ แบต 2200 mah 3s 30c
๑๔ เครื่องชาจ์ท i6AC- 80W
๑๕ Programmable and Documents
๑๖ เสาตั้ง GPS สีดา
๑๗ Module RGB LED
๑๘ อัลตราโซนิก HC-SR04
จานวน
1
1
1
1
1
4
4
4
1
1
1
1
1
1
1
1
1
1
หน่วย
ชิ้น
ชิ้น
ชิ้น
ชิ้น
ชิ้น
ชิ้น
ตัว
ใบ
ชุด
ชิ้น
อัน
ชิ้น
ชิ้น
ชุด
ชุด
ชิ้น
ชิ้น
ชิ้น
รายละเอียดอุปกรณ์ที่ใช้
1. GPS ublox NEO 7n with compass
Receiver type 56 Channels
Cold Start 29 s 30 s
Warm Start 28 s 28 s
Hot Start 1 s 1 s
Horizontal position accuracy Autonomous 2.5 m
SBAS 2.0 m
Max navigation update rate 10 Hz
Velocity accuracy 0.1 m/s
Heading accuracy 0.5 degrees
Dynamics ≤ 4 g
Altitude 50,000 m
Velocity 500 m/s
2. Arduino Due 32bit
Microcontroller
AT91SAM3X8E
Operating Voltage 3.3V
Flash Memory
512 KB
SRAM
96 KB (two banks: 64KB and 32KB)
Clock Speed
84 MHz
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
4
3. GY-521 IMU MPU6050
Use the chip: MPU-6050
Power supply: 3V-5v.
Communication modes: standard IIC communication protocol.
Chip built-in 16 bit AD converter, 16 bits of data output
Gyroscope range: + 250 500 1000 2000 ° / s
Acceleration range: ± 2 ± 4 ± 8 ± 16 g
4. MS5611 GY-63 SPI Communication
Name: MS5611 module (atmospheric pressure module)
Built-in 24bit AD converter chip
High quality Immersion Gold PCB
Using the chip: MS5611
Power supply: 3V-5V (internal low dropout regulator)
Communication: Standard IIC / SPI communications protocol
5. Logic Level Converter 3.3 v
Can be used with normal serial,
I2C, SPI, and any other digital signal
6. Afro ESC 30Amp
high efficiency,
all N-channel MOSFET design
multi-rotor specific SimonK software
Current Draw: 30A Continuous
Voltage Range: 2-4s Lipoly
BEC: 0.5A Linear
Input Freq: 1KHz
Firmware: afro_nfet.hex
7.มอเตอร์ UFO 4010-850KV
UFO 4010 850KV Motor
Lipo 3-4 S
prop 10-13 in
FlightPower 3S 40C 5200mA batt
1255 T-Type Carbon fober prop
Frame 1020 g + batt 440 g = 1460 g
Flight time : 20 mins
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
5
8. ใบพัด 10x4.5 นิ้ว
Propeller 10x4.5 Black (CW/CCW) (4pcs)
Prop Hole Size: 4.75mm
Prop-Adaptor Hole Size 3.0mm, 3.17mm, 4.0mm
Weight of 1 prop: 8g approximately
1 x ABS Plastic Prop CW (clockwise)
1 x ABS Plastic Prop CCW (counter - clockwise)
2 x Prop Adaptor Rings
9 เฟรม quad Frame_Auto450_V2
10 Hobbywing UBEC 5V/6V 3A
Item Name: 3A-UBEC
Output Voltage: 5V@3A or 6V@3A (Selectable by using a jumper connector)
Continuous output current: 3 Amps
Input: 5.5V-26V (2-6S Lipo or 5-18 cells NiMH /NiCd)
Size: 43x 17 x 7mm
Weight: 11g
11 สายไฟ ขั้วแบท แผ่นปริ้น รัดแบต
Silicone Wire 16AWG 14 AWG
Battery Strap สายรัดแบตเตอร์รี่
สายรัดแยต กว้าง 20 ยาว 200 มิลลิเมตร
Nylon XT60 Connectors Male/Female
XT = heXTronik.
60 = 60A constant.
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
6
12 รีโมท STORM i6S 2.4GHz
Frequency: 2.4GHz
Modulation: DSMX
No. of Channels: 6
Model Memory: 10
Stick Mode: Mode 2 (left stick throttle)
13 แบต 2200 mah 3s 30c
Fullymax 2200 mah/3s/30c XT60 plug
14 เครื่องชาจ์ท i6AC- 80W
Dual input: DC 11-18V, AC 100-240V
AC to DC adapter(DC 11-18V/6A)
Charge current/power: 0.1-8A/80W
Discharge current/power: 0.1-2A/10W
Current drain for balancing Lipo: 300mAh/cell
Cell count: 1-6s Lixx; 1-15s Nixx; 2-10s Pb
Dimensions: 135*145*43mm
Approx Weight: 590 g
15 Programmable and Documents
The open-source Arduino Software (IDE)
Arduino ide 1.5.8
Due32bit_GY521MPU_1-6_V1
16 เสาตั้ง GPS สีดา
GPS Holder Mount Bracket Stand
For 7N 6M M8N Neo-7N GPS
Module Black Color
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
7
17 Module RGB LED
Wrobot Full Color RGB LED Module adopt one pcs 5050 anode luminotron.
Common termination port connect with +5V, it is effective when control prot is low level.
This module can achieve effect of different color change through PWM program code.
Wrobot Full Color RGB LED Module pin definitions : (1) Vcc (2) R (3) B (4) G.
18 อัลตราโซนิก HC-SR04
PIN ที่ 1 -- 5V Supply
PIN ที่ 2 -- Trigger Pulse Input
PIN ที่ 3 -- Echo Pulse Output
PIN ที่ 4 -- GND
Working voltage: DC 5 V
Static current: 3 mA
Induction Angle: Less than 15
Detection range:2 cm to 4 m
Detecting precision: 0.3 cm + 1%
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
8
ขั้นตอนการประกอบเริ่มต้น
1.ทาการประกอบเฟรมเครื่องบิน 4 ใบพัด
เตรียมอุปกรณ์
ประกอบแผ่นเฟรมหลัก แขนยึดมอเตอร์
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
9
ประกอบขาตั้ง
ไขควงขันน็อตให้แน่นทุกตัว
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
10
2. ทาการประกอบมอเตอร์
3. ทาการประกอบสปีดคอนโทรลเลอร์ (ESC)
แสดงทิศทางการหมุน กับการเสียบสายไฟมอเตอร์ บรัชเรด Motor Brushless
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
11
4. ทาการประกอบขาตั้ง GPS จะต้องมีสว่านมือ เจาะรู 3 mm
ประกอบมอเตอร์ สปีด เฟรม ขาตั้ง GPS ดังรูปที่แสดง
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
12
5. ตรวจสอบทิศทางหมุนของมอเตอร์ โดยใช้ Servo Tester
แสดงทิศทางหมุนมอเตอร์แบบต่าง ๆ ที่มา
http://wiki.dji.com/en/index.php/A2_Mixer_Type_Supported
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
13
6. ติดตั้งเซนเซอร์และไมโครคอนโทรลเลอร์
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
14
ไดอะแกรมการต่อสายไฟ
ตัว Logic Level Converter 3.3 v ใช้เพื่อแก้ปัญหา ไมโครค้างเนื่องจาก i2c เข็มทิศ hmc5883l
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
15
7. ติดตั้งรีซีปรีโมท ต่อสายไฟเข้าขา A8 ของ Arduino
แสดงกราฟสัญญาณ PPM และ PWM
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
16
8. ทาการอับโหลดโปรแกรม Due32bit_GY521MPU_1_V1 โดยการเสียบสาย usb เข้า
Programming Port
กด Upload รอสักพักหนึ่ง
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
17
9. เปิด Serial Monitor เพื่อดูค่าสถานะเซนเซอร์ต่างๆ
ขึ้นอยู่กับที่เราเปิด code ว่าจะปริ้นค่าอะไรมาดูบ้าง
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
18
แสดงการเปิดคาสั่งปริ้นค่า Serial Monitor
10.ตรวจสอบทิศทางเซนเซอร์ ค่าความเร่งและความเร็วเชิงมุม
accelRaw[XAXIS]; accelRaw[YAXIS]; accelRaw[ZAXIS];
GyroXf*RAD_TO_DEG; GyroYf*RAD_TO_DEG; GyroZf*RAD_TO_DEG;
แสดงทิศทางการหมุนแกนเครื่องบิน ที่มา https://www.grc.nasa.gov
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
19
หัวข้อที่ต้องรู้ในการเขียนโปรแกรม
บอร์ด Arduino Due 32 bit ,กับ เซนเซอร์ MPU6050 - i2c , MS5611 - spi
อธิบาย Code Due32bit_GY521MPU_1-6_V1.ino
1. การกาหนดความเร็วลูป
1000 Hz, 200 Hz, 100 Hz, 50 Hz, 20 Hz, 10 Hz, 5 Hz, 2 Hz, 1 Hz
1000 Hz ทา อ่านเซนเซอร์ gyro,acc,
200 Hz ทา ลูปคานวณ ค่ามุม , ควบคุม PID , Filter ,สั่งมอเตอร์
100 Hz ทา อ่านเซนเซอร์ baro ความดัน
50 Hz ทา อ่านค่ารีโมท PPM หรือ PWM
20 Hz อ่านค่า Ultrasonic , อ่านค่าเข็มทิศ, ควบคุม Position Hold
10 Hz ทา Automatic Takeoff และ Landing
และ Chack_Command, By Remote idle-up settings 0,1,2,3
5 Hz คานวณค่า GPS , คานวณความสูงจาก baro
2 Hz ทาไฟกระพริบจานวนดาวเทียมจาก GPS
1 Hz แสดงสถานะหลอดไฟ LED ทา Accelerometers trim โดยใช้ รีโมท
2. การสร้างตัวแปรเพื่อเก็บค่า int 16 bit, long 32 bit ,uint8_t, unsigned long ,
float 32bit,
3. การอ่านค่าเซนเซอร์ gyroscope , accelerometer, magnetometer
4. การอ่านค่าบาโรเพื่อมาคานวณค่าความสูงจากเซนเซอร์ MS5611
5. การทาตัวสังเกตเพื่อประมาณค่าความสูง ,State estimation with Kalman Filter
6. การอ่านค่าเซนเซอร์ Ultrasonic , Trigger, Echo
7. การอ่านค่าเซนเซอร์ GPS ใช้ NMEA_BINARY settings ของ MultiWii หรือ APM
8. การอ่านค่ารีโมท PWM 1-1.9 ms แบบ PPM (Pulse Position Modulation)
สายเส้นเดียว ได้ 6 CH
9. การกาหนดค่าเริ่มต้นใน setup()
- ค่าเริ่มต้นการอ่านรีโมท
- ค่าเริ่มต้นสั่งมอเตอร์
- ค่าเริ่มต้น GPS
- ค่าเริ่มต้น I2C เปลี่ยน I2C clock rate to 400kHz
- ค่าเริ่มต้นเซนเซอร์ mpu6050, HMC5883, MS5611
- ค่าเริ่มต้นอัลตร้าโซนิค
- การอ่านเซนเซอร์เริ่มต้น
- การทาคาริเบทเซนเซอร์ Gyro ให้เป็นศูนย์
- ตั้งค่าเริ่มต้นการหามุม AHRS (An attitude and heading reference
system , AHRS)
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
20
- กาหนดเวลาเริ่มต้น
10. การทา sensor Calibration และการแปลงหน่วย rad/s , deg/s , m/s^2
11. การลดสัญญานรบกวน sensor , Moving average filter , Low pass filter
12. วิธีการหาค่ามุม AHRS, Quaternion , direction cosine matrix , Euler angles,
Rotation matrix, Body Fixed Frame, Earth-Fixed frame
13. การอ่านค่า GPS latitude and longitude , ความเร็วการเคลื่อนที่
Earth-Fixed frame
14. การควบคุมพีไอดี , P-PID , Roll, Pitch, Yaw
- คานวณหาค่ามุมรีโมท
- การดิฟหาความเร็วจากมุมรีโมท
- การคานวณค่า error
- การคานวณกฏการควบคุมมุมและ Rate Gyro
- การป้องกันค่าเกิน Saturation
15. การควบคุมความสูง Altitude ใช้ State feedback control หรือ PIDA
16. เทคนิคการจูนค่า Gain ที่ใช้ควบคุม
17. เงื่อนไขการทา Automatic Takeoff และ Landing
18. การควบคุมต่าแหน่ง GPS ใช้ PID control
19. การทา Motor mixing theory, Quad +,x
20. การสั่ง PWM 1-1.9 ms, 400 Hz ให้มอเตอร์หมุน
21. การทา Electronic Speed Controllers Calibration 1000 - 1850 us
22. การทา Accelerometers trim โดยใช้ รีโมท
23. การทา Calibration sensor Accelerometer หาค่า Max , Min
24. การทา Calibration sensor Magnetometer หาค่า Max , Min
25. การกาหนดค่าเข้าโหมดบิน ต่าง ๆ Stabilizer, Altitude Hold, Position Hold, RTH,
Automatic
26. การทา ARM and DISARM มอเตอร์หมุนและไม่หมุน
27. อื่น ๆ .....
- การตั้งค่ารีโมทวิทยุ 2.4 GHz
- การชาร์จแบตเตอรี่ลิโพ 4.2 โวลต์ Lithium Polymer
-----------------------------------------------------
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
21
ตัวอย่างโปรแกรมที่เขียน
(Quadrotor Autopilot / Flight Controllers)
ดาวโหลด Code ได้ที่ https://github.com/QuadTinnakon/Due32bit_GY521MPU_5_V1
1. ไฟล์ Due32bit_GY521MPU_5_V1.ino
/*
Test By tinnakon kheowree
project
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
27/03/2559
write Due32bit_GY521MPU_5_V1
support : Arduino 1.5.8
Arduino Due 32 bit
, MPU6050
MS5611
• Atmel SAM3X8E ARM Cortex-M3 CPU 32-bit a 84 MHz clock, ARM core microcontroller
• MPU6050 Gyro Accelerometer //I2C 400kHz nois gyro +-0.05 deg/s , acc +-0.04 m/s^2
• MS5611 Barometer//SPI
• HMC5883L Magnetometer //I2C_BYPASS ,I2C 400kHz
• GPS NEO-7N //
Quad-X
pin 9 FRONTL
M1CW
M2CCW
\
FRONTR pin 8
/
\ --- /
|
|
/ --- \
/
pin 6 motor_BackL
\
M4 CCW
M3 CW
motor_BackR
pin 7
----------rx----------A8 = PPM 8 CH
*/
#include <Arduino.h>
#include "Wire_due32.h"
#include "SPI_sam.h"
#include "AP_Baro_MS5611.h"
#include "Aconfigsam3x8e.h"
#include "multi_rx_sam3x8e.h"
#include "mpu6050sam3x8e.h"
#include "ahrs_tinsam3x8e.h"
#include "GPSNEO6N_multi.h"
#include "Control_PPIDsam3x8e.h"
#include "motorX4sam3x8e.h"
#include "Ultrasonic04.h"
#include "Kalman_ObserverTin.h"
#include "AnalogSource_Arduino.h"
////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(57600);//115200
//Serial1.begin(57600);
Serial.print("Due32bit_GY521MPU_5_V1");Serial.println("\n");
GPS_multiInt();
pinMode(13, OUTPUT);//pinMode (30, OUTPUT);pinMode (31, OUTPUT);//pinMode (30, OUTPUT);pinMode (31,
OUTPUT);//(13=A=M),(31=B=STABLEPIN),(30=C,GPS FIG LEDPIN)
pinMode(12, OUTPUT);
digitalWrite(12, HIGH);
pinMode(Pin_Laser, OUTPUT);
pinMode(Pin_LED_B, OUTPUT);
pinMode(Pin_LED_G, OUTPUT);
pinMode(Pin_LED_R, OUTPUT);
digitalWrite(13, HIGH);
digitalWrite(Pin_Laser, HIGH);
digitalWrite(Pin_LED_B, LOW);
digitalWrite(Pin_LED_G, LOW);
digitalWrite(Pin_LED_R, LOW);
configureReceiver();
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
22
motor_initialize();
ESC_calibration();
delay(10);
Wire.begin();
Wire.setClock(400000);
delay(10);
Wire1.begin();
Wire1.setClock(400000);//400000
delay(10);
mpu6050_initialize();
delay(30); //GYROSCOPE START-UP TIME 30 ms
MagHMC5883Int();
Serial.print("HMC5883_initialize");Serial.print("\n");
delay(10);
SPI.begin();
//SPI.setClockDivider(SPI_CLOCK_DIV32);
// 500khz for debugging, increase later
delay(10);
//baro.init(MS561101BA_ADDR_CSB_LOW);
baro.init();
//baro.calibrate();
//Serial.print("MS5611_initialize");Serial.print("\n");
delay(10);
UltrasonicInt();
delay(10);
Serial.print("Read Sensor");Serial.println("\t");
for(int i=0; i<100; i++)
{
mpu6050_readGyroSum();
mpu6050_readAccelSum();
Mag5883Read();
//temperaturetr = baro.getTemperature(MS561101BA_OSR_4096);
//presser = baro.getPressure(MS561101BA_OSR_4096);
baro._update(micros());
baro.read();
presser = baro.get_pressure();
temperaturetr = baro.get_temperature();
pushAvg(presser, temperaturetr);
delay(10);
}
presserf = getAvg(movavg_buff, MOVAVG_SIZE);
temperaturetrf = getAvg(movavg_buffT, MOVAVG_SIZE);
sea_press = presserf - 0.12;// + 0.09 presser 1007.25
1003.52
Serial.print("presser ");Serial.print(sea_press);
Serial.print(" Temperature ");Serial.println(temperaturetrf);
digitalWrite(Pin_LED_B, HIGH);
digitalWrite(Pin_LED_G, HIGH);
digitalWrite(Pin_LED_R, HIGH);
mpu6050_Get_accel();
mpu6050_Get_gyro();
delay(10);
sensor_Calibrate();//sensor.h
ahrs_initialize();//ahrs.h
RC_Calibrate();//"multi_rxPPM2560.h"
setupFourthOrder();//ahrs
delay(100);
digitalWrite(13, LOW);
for(uint8_t i=0;i<=10;i++){
//GPS_NewData();
while(Serial2.available())
{
char byteGPS1=Serial2.read();
GPS_UBLOX_newFrame(byteGPS1);
}
GPS_LAT1 = GPS_coord[LAT]/10000000.0;// 1e-7 degrees / position as degrees (*10E7)
GPS_LON1 = GPS_coord[LON]/10000000.0;
GPS_LAT_HOME = GPS_LAT1;
GPS_LON_HOME = GPS_LON1;
digitalWrite(Pin_LED_B, LOW);
delay(20);
digitalWrite(Pin_LED_B, HIGH);
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
23
delay(80);
}
digitalWrite(Pin_Laser, LOW);
digitalWrite(Pin_LED_B, LOW);
digitalWrite(Pin_LED_G, LOW);
digitalWrite(Pin_LED_R, LOW);
sensorPreviousTime = micros();
previousTime = micros();
}
void loop() {
while(1){
while(Serial2.available()){ /////GPS///////////////////////////////
char byteGPS1=Serial2.read();
GPS_UBLOX_newFrame(byteGPS1);
}//end gps
///////////////////////////////////////
Dt_sensor = micros() - sensorPreviousTime;///////////Roop sensor 1 kHz/////////
if(Dt_sensor <= 0){Dt_sensor = 1001;}
if(Dt_sensor >= 1000 && gyroSamples < 4)////Collect 2 samples = 1000 us
{
sensorPreviousTime = micros();
mpu6050_readGyroSum();
mpu6050_readAccelSum();
}
Dt_roop = micros() - previousTime;// 200 Hz task loop (5 ms)
, 2500 us = 400 Hz
if(Dt_roop <= 0){Dt_roop = 5001;}
if (Dt_roop >= 5000)
{
previousTime = micros();
G_Dt = Dt_roop*0.000001;
frameCounter++;
/////get sensor////////////////////////////////////////////////////////////
mpu6050_Get_accel();
mpu6050_Get_gyro();
baro._update(previousTime);
//digitalWrite(12, HIGH);
//digitalWrite(12, LOW);
//////////////////////////////////////////////////////////
if (frameCounter % TASK_100HZ == 0)// 100 Hz tak
{
/*
///////////////////Filter FourthOrder ///////////////////////////////////////
Accel[XAXIS] = AccX;
Accel[YAXIS] = AccY;
Accel[ZAXIS] = AccZ;
for (int axis = XAXIS; axis <= ZAXIS; axis++) {
filteredAccel[axis] = computeFourthOrder(Accel[axis], &fourthOrder[axis]);//"ahrs_tin.h"
}
AccXf = filteredAccel[XAXIS];
AccYf = filteredAccel[YAXIS];
AccZf = filteredAccel[ZAXIS];
*/
//presser = baro.getPressure(MS561101BA_OSR_4096);
baro.read();
presser = baro.get_pressure();
temperaturetr = baro.get_temperature();
pushAvg(presser, temperaturetr);
}
////////////////Moving Average Filters///////////////////////////
GyroXf = (GyroX + GyroX2)/2.0;
GyroYf = (GyroY + GyroY2)/2.0;
GyroZf = (GyroZ + GyroZ2)/2.0;
//AccXf = (AccX + AccX2)/2.0;
//AccYf = (AccY + AccY2)/2.0;
//AccZf = (AccZ + AccZ2)/2.0;
//AccX2 = AccX;AccY2 = AccY;AccZ2 = AccZ;//acc Old1
GyroX2 = GyroX;GyroY2 = GyroY;GyroZ2 = GyroZ;//gyro Old1
////////////////Low pass filter/////////////////////////////////
AccXf = AccXf + (AccX - AccXf)*0.12101;//0.240121 ,0.121
//Low pass filter ,smoothing factor
α := dt / (RC + dt)
AccYf = AccYf + (AccY - AccYf)*0.12101;//0.240121 ,0.121
AccZf = AccZf + (AccZ - AccZf)*0.12101;//0.240121 ,0.121
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
24
//////////////////////////////////////////////////////////
ahrs_updateMARG(GyroXf, GyroYf, GyroZf, AccXf, AccYf, AccZf, c_magnetom_x, c_magnetom_y, c_magnetom_z,
G_Dt);//quaternion ,direction cosine matrix ,Euler angles
//Observer kalman filter//////////////////////////////////
Observer_kalman_filter();
//Sliding modeControl/////////////////////////////////////
Control_PPIDRate();//"Control_Slid.h"
//////Out motor///////////
//armed = 1;
motor_Mix();//"motor.h"
/////////////////////////
motor_command();
////////end Out motor//////
if (frameCounter % TASK_50HZ == 0)// 50 Hz tak (20 ms)
{
//mpu6050_Get_accel();
computeRC();//multi_rx.h
if (CH_THR < MINCHECK)
//////ARM and DISARM your Quadrotor///////////////
{
if (CH_RUD > MAXCHECK && armed == 0 && abs(ahrs_p) < 10 && abs(ahrs_r) < 10)//+- 10 deg, ARM
{
armed = 1;
digitalWrite(Pin_LED_R, HIGH);
Altitude_Ground = Altitude_baro;
setHeading = ahrs_y;// 0 degree ,ahrs_tin.h
}
if (CH_RUD < MINCHECK && armed == 1) //DISARM
{
armed = 0;
digitalWrite(Pin_LED_R, LOW);
Altitude_Ground = Altitude_baro;
setHeading = ahrs_y;// 0 degree ,ahrs_tin.h
}
if (CH_RUD < MINCHECK && armed == 0 && CH_ELE > MAXCHECK) //Mag_Calibrate
{
Mag_Calibrate();//#include "mpu6050.h"
}
}//end
ARM and DISARM your helicopter///////////////
}
if (frameCounter % TASK_20HZ == 0)// 20 Hz task (50 ms)
{
Mag5883Read();
UltrasonicRead();//"Ultrasonic04.h"
//updateOF();//AP_OPTICALFLOW_ADNS3080
//Get_pixy();
//update_positionA3080(GyroXfMO ,GyroYfMO ,1.0 ,0.0 ,z1_hat);//(float Gyroroll, float Gyropitch, float
cos_yaw_x, float sin_yaw_y, float altitude)
Control_PositionHold();//#include "Control_SlidingPIDsam3x8e.h"
}
if (frameCounter % TASK_10HZ == 0)//roop TASK_10HZ
{
Chack_Command();
Automatictakeland();
}
if (frameCounter % TASK_5HZ == 0)//GPS_calc TASK_5HZ
{
presserf = getAvg(movavg_buff, MOVAVG_SIZE);
temperaturetrf = getAvg(movavg_buffT, MOVAVG_SIZE);
presserfF = presserfF + (presserf - presserfF)*0.3852101;//0.9852101 0.785 0.685 0.545 0.345 Low Pass
Filter
Altitude_baro = getAltitude(presserfF,temperaturetrf);//Altitude_Ground
Altitude_barof = Altitude_baro - Altitude_Ground + Altitude_II;
baro_vz = (z1_hat - baro_vz_old)/0.2;//G_Dt Diff Baro 5HZ=0.2 s
,,20 Hz=0.05
baro_vz_old = z1_hat;
if(GPS_FIX
== 1){
//baro_vz = _vel_down/100.0;
}
else{
//baro_vz = baro_vz;
}
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
25
GPS_LAT1 = GPS_coord[LAT]/10000000.0;// 1e-7 degrees / position as degrees (*10E7)
GPS_LON1 = GPS_coord[LON]/10000000.0;
Cal_GPS();//#include "Control_PPIDsam3x8e.h"
//Control_PositionHold();
//GPS_distance_m_bearing(GPS_LAT1, GPS_LON1, GPS_LAT_HOME, GPS_LON_HOME, Altitude_hat);
}
if (frameCounter % TASK_2HZ == 0)//LED GPS
{
if(Status_LED_GPS == LOW && GPS_FIX
== 1)
{
Status_LED_GPS = HIGH;
Counter_LED_GPS++;
if(Counter_LED_GPS >= GPS_numSat){
Counter_LED_GPS = 0;
digitalWrite(Pin_LED_G, HIGH);
}
else
{
digitalWrite(Pin_LED_G, LOW);
}
}
else
{
Status_LED_GPS = LOW;
}
digitalWrite(Pin_LED_B, Status_LED_GPS);
}//end if LED GPS
if (frameCounter % TASK_NoHZ == 0)//roop print
,TASK_NoHZ TASK_5HZ
TASK_10HZ
,TASK_NoHZ TASK_5HZ
TASK_10HZ
{
Voltage = analogRead(A5);
Ampere = analogRead(A6);
}
if (frameCounter % TASK_NoHZ == 0)//roop print
{
Serial.print(CH_THRf);Serial.print("\t");
Serial.print(CH_AILf);Serial.print("\t");
Serial.print(CH_ELEf);Serial.print("\t");
Serial.print(CH_RUDf);Serial.print("\t");
Serial.print(AUX_1);Serial.print("\t");
//Serial.print(AUX_2);Serial.print("\t");
//Serial.print(AUX_3);Serial.print("\t");
//Serial.print(AUX_4);Serial.print("\t");
//Serial.print(failsafeCnt);Serial.print("\t");
//Serial.print(setpoint_rate_roll);Serial.print("\t");
//Serial.print(setpoint_rate_pitch);Serial.print("\t");
//Serial.print(MagX1);Serial.print("\t");
Serial.print(MagXf);Serial.print("\t");
//Serial.print(MagY1);Serial.print("\t");
Serial.print(MagYf);Serial.print("\t");
//Serial.print(MagZ1);Serial.print("\t");
Serial.print(MagZf);Serial.print("\t");
//Serial.print(c_magnetom_x);Serial.print("\t");
//Serial.print(c_magnetom_y);Serial.print("\t");
//Serial.print(c_magnetom_z);Serial.print("\t");
//Serial.print(GPS_FIX1);Serial.print("\t");
//Serial.print(GPS_LAT1,9);Serial.print("\t");
//Serial.print(GPS_LAT1f,9);Serial.print("\t");
//Serial.print(GPS_LON1,9);Serial.print("\t");
//Serial.print(GPS_LON1f,9);Serial.print("\t");
//Serial.print(GPS_LON1f2,9);Serial.print("\t");
//Serial.print(error_LAT);Serial.print("\t");
//Serial.print(error_LON);Serial.print("\t");
//Serial.print(GPS_speed);Serial.print("\t");//cm/s
//Serial.print(GPS_ground_course);Serial.print("\t");//deg
//Serial.print(_velocity_north);Serial.print("\t");
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
26
//Serial.print(actual_speedX);Serial.print("\t");
//Serial.print(actual_speedXf);Serial.print("\t");
//Serial.print(vx_hat);Serial.print("\t");
//Serial.print(_velocity_east);Serial.print("\t");
//Serial.print(_vel_down);Serial.print("\t");
//Serial.print(actual_speedY);Serial.print("\t");
//Serial.print(actual_speedYf);Serial.print("\t");
//Serial.print(vy_hat);Serial.print("\t");
//Serial3.print(GPS_Distance);Serial3.print("\t");
//Serial3.print(GPS_ground_course);Serial3.print("\t");
//Serial3.print(Control_XEf);Serial3.print("\t");
//Serial3.print(Control_YEf);Serial3.print("\t");
//Serial3.print(Control_XBf);Serial3.print("\t");
//Serial3.print(Control_YBf);Serial3.print("\t");
//Serial.print(Control_XEf);Serial.print("\t");
//Serial.print(Control_YEf);Serial.print("\t");
//Serial.print(Control_XBf);Serial.print("\t");
//Serial.print(Control_YBf);Serial.print("\t");
//Serial.print(panError);Serial.print("\t");
//Serial.print(tiltError);Serial.print("\t");
//Serial.print(LError);Serial.print("\t");
//Serial.print(posistion_X);Serial.print("\t");
//Serial.print(posistion_Y);Serial.print("\t");
//Serial.print(surface_quality);Serial.print("\t");
//Serial.print(Distance_L);Serial.print("\t");
//Serial.print(Distance_R);Serial.print("\t");
//Serial.print(Distance_F);Serial.print("\t");
//Serial.print(Distance_B);Serial.print("\t");
//Serial.print(Distance_X);Serial.print("\t");
//Serial.print(Distance_Y);Serial.print("\t");
//Serial.print(Voltage);Serial.print("\t");
//Serial.print(Ampere);Serial.print("\t");
//Serial.print(TempMPU);Serial.print("\t");
//Serial.print(temperaturetr);Serial.print("\t");
//Serial.print(presser,3);Serial.print("\t");
//Serial.print(presserf,3);Serial.print("\t");
//Serial.print(presserfF,3);Serial.print("\t");
//Serial.print(Altitude_baro);Serial.print("\t");
//Serial.print(Altitude_Baro_ult);Serial.print("\t");
Serial.print(Altitude_barof);Serial.print("\t");
Serial.print(Altitude_sonaf);Serial.print("\t");
Serial.print(z1_hat);Serial.print("\t");
//Serial.print(Vz_Baro_ult);Serial.print("\t");
//Serial.print(baro_vz);Serial.print("\t");
//Serial.print(vz_sonaf);Serial.print("\t");
//Serial.print(z2_hat);Serial.print("\t");
//Serial.print(Altitude_sona);Serial.print("\t");
//Serial.print(Altitude_hat);Serial.print("\t");
//Serial.print(vz_sona*10);Serial.print("\t");
//Serial.print(vz_hat*10);Serial.print("\t");
//Serial.print(h_counter);Serial.print("\t");
//Serial.print(GPS_hz);Serial.print("\t");
//Serial.print(vz_hat);Serial.print("\t");
//Serial.print(DCM10);Serial.print("\t");
//Serial.print(DCM11);Serial.print("\t");
//Serial.print(DCM12);Serial.print("\t");
//Serial.print(AccX);Serial.print("\t");
//Serial.print(AccXf);Serial.print("\t");
//Serial.print(AccXf2);Serial.print("\t");
//Serial.print(AccY);Serial.print("\t");
//Serial.print(AccYf);Serial.print("\t");
//Serial.print(AccZ);Serial.print("\t");
//Serial.print(AccZf2,3);Serial.print("\t");
//Serial.print(AccZf3,3);Serial.print("\t");
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
27
//Serial.print(AccZf);Serial.print("\t");
//Serial.print(accrX_Earth);Serial.print("\t");
//Serial.print(accrY_Earth);Serial.print("\t");
//Serial.print(accrZ_Earthf);Serial.print("\t");
//Serial.print(accrZ_Earth);Serial.print("\t");
Serial.print(accelRaw[XAXIS]);Serial.print("\t");
Serial.print(accelRaw[YAXIS]);Serial.print("\t");
Serial.print(accelRaw[ZAXIS]);Serial.print("\t");
//Serial.print(-GyroX*RAD_TO_DEG);Serial.print("\t");
//Serial.print(GyroXf*RAD_TO_DEG);Serial.print("\t");
//Serial.print(roll_D_rate);Serial.print("\t");
//Serial.print(_accel9250X);Serial.print("\t");
//Serial.print(_accel9250Y);Serial.print("\t");
//Serial.print(_accel9250Z);Serial.print("\t");
Serial.print(ahrs_r);Serial.print("\t");
Serial.print(ahrs_p);Serial.print("\t");
Serial.print(ahrs_y);Serial.print("\t");
//Serial3.print(ahrs_y*RAD_TO_DEG);Serial3.print("\t");
//Serial.print(cos_rollcos_pitch);Serial.print("\t");
//Serial.print(x_angle);Serial.print("\t");
//Serial.print(u_roll);Serial.print("\t");
//Serial.print(u_pitch);Serial.print("\t");
//Serial.print(u_yaw);Serial.print("\t");
//Serial.print(motor_FrontL);Serial.print("\t");
//Serial.print(motor_FrontLf);Serial.print("\t");
//Serial.print(motor_FrontR);Serial.print("\t");
//Serial.print(motor_FrontRf);Serial.print("\t");
//Serial.print(motor_BackL);Serial.print("\t");
//Serial.print(motor_BackLf);Serial.print("\t");
//Serial.print(motor_BackR);Serial.print("\t");
//Serial.print(motor_BackRf);Serial.print("\t");
//Serial.print(motor_Left);Serial.print("\t");
//Serial.print(motor_Right);Serial.print("\t");
//Serial.print(GPS_numSat);Serial.print("\t");
Serial.print(Mode);Serial.print("\t");
//Serial.print(gyroSamples2);Serial.print("\t");
//Serial.print(1/G_Dt);Serial.print("\t");
//Serial.print("Hz");
//Serial.print(millis()/1000.0);//millis() micros()
Serial.print("\n");
}//end roop 5 Hz
if (frameCounter >= TASK_1HZ) { // Reset frameCounter back to 0 after reaching 100 (1s)
frameCounter = 0;
time_auto++;
//temperaturetr = baro.getTemperature(MS561101BA_OSR_4096);
//mpu6050_Temp_Values();
Remote_TrimACC();//motor.h
if(Status_LED == LOW)
{
Status_LED = HIGH;
//digitalWrite(Pin_LED_G, LOW);
}
else
{
Status_LED = LOW;
//digitalWrite(Pin_LED_G, HIGH);
}
digitalWrite(13, Status_LED);//A
}//end roop 1 Hz
}//end roop 400 Hz
}//end while roop
}
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
28
2. ไฟล์ Aconfigsam3x8e.h
/*
project_Quad 32 bit Arduino Due
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
*/
//The type of multicopter
//#define HEX_X
#define Quad_X
//#define Quad_P
#define CPPM
///////////////Mode///////////////////////////
#define AltHold 1259
#define RTH 1890
#define PositionHold 1443
//Loiter mode
#define Auto 1659
#define FailSafe 980
////////////////////////////////////////
#define MINTHROTTLE 1200 //1064 1090
#define MAXTHROTTLE 1950 //1850
#define MINCOMMAND 1000
#define MAXCOMMAND 1950
#define MIDRC 1500
#define MINCHECK 1100
#define MAXCHECK 1900
int Mode = 0;
//Mode 0 = Stabilize
//Mode 1 = Altitude Hold
//Mode 2 = Position Hold ,Loiter
//Mode 3 = Automatic
Takeoff ,Landing
/////////////////////////////////////////////
// Automatic take-off and landing
float h_control = 3.5;
//2.7 0.6 0.9 meter
//Parameter system Quadrotor
#define m_quad 1.22
#define L_quad 0.16
//kg
//m quad+=0.25
I = (1/3)mL2 = 0.02291
/////////////////////////////////////////////////////////////////////
//P-PID-------------Rate
float Kp_rateRoll = 2.12;//2.42 2.78 1.18 5.28
float Ki_rateRoll = 1.12;//1.12 2.75
float Kd_rateRoll = 0.075;//0.095 0.15 0.085 0.025 - 0.045
float Kp_ratePitch = 2.12;//2.42 1.18 5.28
float Ki_ratePitch = 1.12;//1.12 2.75 0.5 - 2.8
float Kd_ratePitch = 0.075;//0.095 0.15 0.078 0.025 - 0.045
float Kp_rateYaw = 2.75;//2.75 3.75 5.75 1.75 - 3.450
float Ki_rateYaw = 1.85;//1.85 3.65
350.0
2.95
float Kd_rateYaw = 0.042;//0.095 0.035 0.065
//PID--------------Stable
float Kp_levelRoll= 4.75;//4.95 4.2 6.2 7.8 9.2
//float Ki_levelRoll= 0.00;//0.0
//float Kd_levelRoll= 0.00;//0.0
float Kp_levelPitch= 4.75;//4.95 4.2 6.2 9.2
//float Ki_levelPitch= 0.00;
//float Kd_levelPitch= 0.00;
float Kp_levelyaw= 5.25;//5.15 4.2 4.5
//stat feedback--------------Altitude
float Kp_altitude = 145.2;//155.2 225.2 265.2
175.0
165.0
float Ki_altitude = 1.15;//2.1 12.25 52.13 2.13 0.018 2.5,0.0
float Kd_altitude = 175.2;//185.2 195.2 185.2 250 280.5 315.5 120
float Kd2_altitude = 35.25;//35.25 18.25 22.25 42.5 12.2 1.25
float Ka_altitude = 11.5;//12.5 8.5 18.5 26 32.5 38.5 41.5 35 25 - 45
//////////////////RC//////////////////////////////////
//#define tarremote 0.025 // fast
//#define tarremote 0.062
//0.092 slow 0.12 0.02 0.08 remote
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
29
#define tar 0.011 //0.012 0.015
float tarremote = 0.095;//0.065
//////////////////////////////////////////////////
//PID GPS////////////////////////////////////////////
float Kp_gps = 0.245;//0.15 0.101 2.101 5.101
float Ki_gps = 0.122;//0.68 2.68 0.25 0.085 0.15
float Kd_gps = 1.85;//2.85 3.35 4.35 1.05 1.9 4.3 0.35 1.35 3.35
float Kp_speed = 0.43;//0.37 0.27 0.15 0.35 0.095 min 0.15
#define Pin_Laser 2
#define Pin_LED_B 4
#define Pin_LED_G 5
#define Pin_LED_R 3
//GPS //
สตาร์ท//////////////////////////////////////
float GPS_LAT_HOME = 13.868180;
float GPS_LON_HOME = 100.496297;
//
ลงจอด
float waypoint1_LAT = 13.868544;
float waypoint1_LON = 100.496433;
//
//float waypoint2_LAT = 13.8670005791;
//float waypoint2_LON = 100.483291625;//13.866970, 100.483240
//
//float waypoint3_LAT = 13.8670005791;
//float waypoint3_LON = 100.483291625;
//
//float waypoint4_LAT = 13.8670005791;
//float waypoint4_LON = 100.483291625;
////////////////////////////////////////////////////////////////////
//Accelerometer calibration constants; use the Calibrate example from print(accelRaw[XAXIS]);
int A_X_MIN = -4100;
//
int A_X_MAX = 4110;
//
int A_Y_MIN = -3980;
//
int A_Y_MAX = 4230;
//
int A_Z_MIN = -4270;
//
int A_Z_MAX = 3970;
//4007
////////////////////////////////////////////////////////////////////
//magnetometer calibration constants; use the Calibrate example from print(MagXf);
// the Pololu library to find the right values for your board
int M_X_MIN = -325;
//-490 -654
-693
-688
int M_X_MAX = 426;
//310 185
209
170
int M_Y_MIN = -380;
//-369 -319
-311
-310
int M_Y_MAX = 380;
//397 513
563
546
int M_Z_MIN = -370;
//-392 -363
-374
-377
int M_Z_MAX = 350;
//346 386
429
502
////////////////////////////////////////////////////////////////////
//Observer hz
float Altitude_Hold = 0.0;
//float Altitude_hat=0.0;//Observer hx
float vx_hat=0.0;
float vx_hat2=0.0;
float vy_hat=0.0;
float vy_hat2=0.0;
//float vz_hat=0.0;
//float vz_hat2=0.0;
//float h=0.0;
float seth=0.0;//set control
float uthrottle=0.0;
float uAltitude = 1000.0;
float accrX_Earth = 0.0;
float accrY_Earth = 0.0;
float accrZ_Earth = 0.0;
float accrX_Earthf = 0.0;
float accrY_Earthf = 0.0;
float accrZ_Earthf = 0.0;
//float vz = 0.0;
//kalman
float z1_hat = 0.0;
float z2_hat = 0.0;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
30
float z1_hat2 = 0.0;
float z2_hat2 = 0.0;
float u_z = 0.0;
float baro_vz = 0.0;
float baro_vz_old = 0.0;
float baro_vz_old2 = 0.0;
//GPS
float GPS_LAT1 = 0.0;
float GPS_LON1 = 0.0;
float GPS_LAT1f = 0.0;
float GPS_LON1f = 0.0;
float GPS_LAT1Lf = 0.0;
float GPS_LON1Lf = 0.0;
float GPS_LAT1lead = 0.0;
float GPS_LON1lead = 0.0;
float GPS_speed = 0.0;
float actual_speedX = 0.0;
float actual_speedY = 0.0;
float actual_speedXf = 0.0;
float actual_speedYf = 0.0;
float actual_speedXold = 0.0;
float actual_speedYold = 0.0;
float _last_velocityX = 0.0;
float _last_velocityY = 0.0;
float GPS_LAT1_old = GPS_LAT_HOME;
float GPS_LON1_old = GPS_LON_HOME;
float Control_XEf = 0.0;
float Control_YEf = 0.0;
float Control_XBf = 0.0;
float Control_YBf = 0.0;
float target_LAT = 0.0;
float target_LON = 0.0;
byte currentCommand[23];
byte Read_command = 0;
float GPS_hz = 0.0;
float GPS_vz = 0.0;
float GPS_ground_course2 = 0.0;
float GPS_Distance = 0.0;
float error_LAT = 0.0;
float error_LON = 0.0;
float GPSI_LAT = 0.0;
float GPSI_LON = 0.0;
uint8_t GPS_filter_index = 0;
float GPS_SUM_LAT[5];
float GPS_SUM_LON[5];
bool Status_LED_GPS = LOW;
uint8_t Status_waypoint = 0;
uint8_t Counter_LED_GPS = 0;
int Voltage = 0;
int Ampere = 0;
////////time roop////////////////////////////////////////////
#define TASK_100HZ 2
#define TASK_50HZ 4
#define TASK_20HZ 10
#define TASK_10HZ 20
#define TASK_5HZ 40
#define TASK_2HZ 100
#define TASK_1HZ 200
#define TASK_NoHZ 410
//#define RAD_TO_DEG 57.295779513082320876798154814105
//#define DEG_TO_RAD 0.017453292519943295769236907684886
//direction cosine matrix (DCM)
Rotated Frame to Stationary Frame ZYX
float DCM00 = 1.0;
float DCM01 = 0.0;
float DCM02 = 0.0;
float DCM10 = 0.0;
float DCM11 = 1.0;
float DCM12 = 0.0;
float DCM20 = 0.0;
float DCM21 = 0.0;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
31
float DCM22 = 1.0;
//float DCM23 = 1.0;
float cos_rollcos_pitch = 1.0;
// Main loop variables
unsigned long currentTime = 0;
unsigned long previousTime = 0;
unsigned long sensorPreviousTime = 0;
uint16_t frameCounter = 0;
uint8_t timeLanding = 0;
uint8_t timeOff = 0;
byte armed = 0;
float G_Dt = 0.01;
long Dt_sensor = 1000;
long Dt_roop = 10000;
bool Status_LED = LOW;
int ESC_calibra = 0;
int Counter_LED_Auto = 0;
//Baro
//MS561101BA32bit baro = MS561101BA32bit();
AP_Baro_MS5611 baro;
#define
MOVAVG_SIZE 10 //100 80 20
float movavg_buff[MOVAVG_SIZE];
float movavg_buffT[MOVAVG_SIZE];
int movavg_i=0;
float sea_press=1013.25;
float temperaturetr = 32.5;
float temperaturetrf = 32.5;
float presser=1013.25;
float presserf=1013.25;
float presserfF=1013.25;
float Altitude_baro = 0.0;
float Altitude_barof=0.0;
float Altitude_Ground = 0.0;
3. ไฟล์ AnalogSource_Arduino.h
//project_Quad
32 bit Arduino
Due
//1. stabilized quadrotor
//by: tinnakon kheowree
//0860540582
//tinnakon_za@hotmail.com
//tinnakonza@gmail.com
//https://www.facebook.com/tinnakonza
int AD0_V = 0;
int AD1_L = 0;
int AD2_R = 0;
int AD3_F = 0;
int AD4_B = 0;
int AD0_SUM = 0;
int AD1_SUM = 0;
int AD2_SUM = 0;
int AD3_SUM = 0;
int AD4_SUM = 0;
int Distance_L = 0;
int Distance_R = 0;
int Distance_F = 0;
int Distance_B = 0;
float V_Bat = 0;
int Distance_X = 0;
int Distance_Y = 0;
uint8_t ADCSamples;
// increase this if we need more than 5 analog sources
//#define MAX_PIN_SOURCES 5
void Distance_Measuring_Sensor(){
AD0_V = analogRead(A0);
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
32
AD1_L = analogRead(A1);
AD2_R = analogRead(A2);
AD3_F = analogRead(A3);
AD4_B = analogRead(A4);
}
void analogReadSUM(){
Distance_Measuring_Sensor();
AD0_SUM += AD0_V;
AD1_SUM += AD1_L;
AD2_SUM += AD2_R;
AD3_SUM += AD3_F;
AD4_SUM += AD4_B;
ADCSamples++;
}
void Distance_Measuring_Get()
{
// Calculate average
V_Bat = (AD0_SUM / ADCSamples)*0.01409;//867 = 0.01409 ,889 = 0.01374;
Distance_L = (AD1_SUM / ADCSamples);
Distance_R = (AD2_SUM / ADCSamples);
Distance_F = (AD3_SUM / ADCSamples);
Distance_B = (AD4_SUM / ADCSamples);
applyDeadband(Distance_L, 160);//190 = 1 m
applyDeadband(Distance_R, 160);
applyDeadband(Distance_F, 160);
applyDeadband(Distance_B, 160);
Distance_X = Distance_L - Distance_R;
Distance_Y = Distance_B - Distance_F;
// Reset SUM variables
AD0_SUM = 0;
AD1_SUM = 0;
AD2_SUM = 0;
AD3_SUM = 0;
AD4_SUM = 0;
ADCSamples = 0;
}
4. ไฟล์ Control_PPIDsam3x8e.h
/*
project_Quad 32 bit Arduino Due
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
*/
float u_roll = 0;
float u_pitch = 0;
float u_yaw = 0;
float roll_I_rate = 0.0;
float roll_D_rate = 0.0;
float setpoint_rollold = 0.0;
float setpoint_rate_roll = 0.0;
float error_rollold = 0.0;
float error_rate_rollold = 0.0;
float pitch_I_rate = 0.0;
float pitch_D_rate = 0.0;
float setpoint_pitchold = 0.0;
float setpoint_rate_pitch = 0.0;
float error_pitchold = 0.0;
float error_rate_pitchold = 0.0;
float yaw_I_rate = 0.0;
float yaw_D_rate = 0.0;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
33
float error_rate_yawold = 0.0;
//Automatic take-off and landing
float err_hz = 0.0;
int time_auto = 0;
float h_counter = 0.1;//0.08
float h_counter_old = 0.1;
float Vz_Hold = 0.0;
float hz_I = 0.0;
float hz_D_rate = 0.0;
float error_Vz_old = 0.0;
uint8_t takeoff = 0;
uint8_t endAuto = 0;
void Control_PPIDRate(){
// ROLL CONTROL P-PID
control
By tinnakon///////////
float setpoint_roll = ((CH_AILf-CH_AIL_Cal)*0.085) + Control_YBf;//0.12 max +-45 deg
////+-18
+ Control_YBf
applyDeadband(setpoint_roll, 2.5);//1.2
setpoint_rate_roll = (0.065*setpoint_rate_roll/(0.065+G_Dt)) + ((setpoint_rollsetpoint_rollold)/(0.065+G_Dt));//Diff remote
setpoint_rollold = setpoint_roll;
setpoint_rate_roll = constrain(setpoint_rate_roll, -80, 80);//+-80 deg/s
float error_roll = setpoint_roll - ahrs_r;//ahrs_r*ToDeg
float error_rate_roll = setpoint_rate_roll + error_roll*Kp_levelRoll
- GyroXf*RAD_TO_DEG;
roll_I_rate += error_rate_roll*Ki_rateRoll*G_Dt;
roll_I_rate = constrain(roll_I_rate, -5, 5);//+-150
roll_D_rate = (tar*roll_D_rate/(tar+G_Dt)) + ((error_rate_roll-error_rate_rollold)/(tar+G_Dt));
error_rate_rollold = error_rate_roll;
u_roll = Kp_rateRoll*error_rate_roll + roll_I_rate + Kd_rateRoll*roll_D_rate;
u_roll = constrain(u_roll, -280, 280);//+-250 +-300 120
// PITCH CONTROL P-PID
control
By tinnakon///////////
float setpoint_pitch = ((CH_ELEf-CH_ELE_Cal)*-0.085) + Control_XBf;//max +-45 deg
////+-18 - Control_XBf
applyDeadband(setpoint_pitch, 2.5);//1.2
setpoint_rate_pitch = (0.065*setpoint_rate_pitch/(0.065+G_Dt)) + ((setpoint_pitchsetpoint_pitchold)/(0.065+G_Dt));//Diff remote
setpoint_pitchold = setpoint_pitch;
setpoint_rate_pitch = constrain(setpoint_rate_pitch, -80, 80);//+-80
float error_pitch = setpoint_pitch - ahrs_p;//ahrs_p*RAD_TO_DEG
float error_rate_pitch = setpoint_rate_pitch + error_pitch*Kp_levelPitch - GyroYf*RAD_TO_DEG;
pitch_I_rate += error_rate_pitch*Ki_ratePitch*G_Dt;
pitch_I_rate = constrain(pitch_I_rate, -5, 5);//+-150
pitch_D_rate = (tar*pitch_D_rate/(tar+G_Dt)) + ((error_rate_pitch-error_rate_pitchold)/(tar+G_Dt));
error_rate_pitchold = error_rate_pitch;
u_pitch = Kp_ratePitch*error_rate_pitch + pitch_I_rate + Kd_ratePitch*pitch_D_rate;
u_pitch = constrain(u_pitch, -280, 280);//+-250 +-300 120
// YAW
CONTROL P-PID
control
By tinnakon///////////
float setpoint_rate_yaw = (CH_RUDf-CH_RUD_Cal)*0.55;//0.4 0.35
applyDeadband(setpoint_rate_yaw, 8.5);//6.5
if(abs(setpoint_rate_yaw) > 0.1){
setHeading = ahrs_y;// 0 degree ,ahrs_tin.h
}
float error_yaw = 0.0 - Heading;
float error_rate_yaw = setpoint_rate_yaw + error_yaw*Kp_levelyaw - GyroZf*RAD_TO_DEG;
yaw_I_rate += error_rate_yaw*Ki_rateYaw*G_Dt;
yaw_I_rate = constrain(yaw_I_rate, -50, 50);//+-100
yaw_D_rate = (tar*yaw_D_rate/(tar+G_Dt)) + ((error_rate_yaw-error_rate_yawold)/(tar+G_Dt));
error_rate_yawold = error_rate_yaw;
u_yaw = Kp_rateYaw*error_rate_yaw + yaw_I_rate + Kd_rateYaw*yaw_D_rate;
u_yaw = constrain(u_yaw, -170, 170);//+-170 +-150
////Altitude//////////////////////////////////////////////////////////////////////////////////////////////////////
if(Mode == 1 || Mode == 2)//Altitude Hold,
{
err_hz = Altitude_Hold - z1_hat;
err_hz = constrain(err_hz, -1.0, 1.0);//+-2 m
//applyDeadband(err_hz, 0.11);//nois 0.2 m
float error_Vz = 0.0 - z2_hat;
hz_D_rate = (tar*hz_D_rate/(tar+G_Dt)) + ((error_Vz - error_Vz_old)/(tar+G_Dt));// D Controller
error_Vz_old = error_Vz;
float error_hII = err_hz*1.25 + error_Vz;//0.55
hz_I = hz_I + (Ki_altitude*error_hII*G_Dt);//1.9 - 2.9
18.5
22.5
hz_I = constrain(hz_I, -20, 20);//+-200
float uthrottle2 = (err_hz*Kp_altitude) + hz_I + (error_Vz*Kd_altitude) + (hz_D_rate*Kd2_altitude) -
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
34
(accrZ_Earth*Ka_altitude);//state feedback
//uthrottle = uthrottle2*m_quad/(cos_roll*cos_pitch);// = u*m*d/b*(cosr*cosp)
,m*d/b = 122.33
(cos_roll*cos_pitch)
uthrottle = uthrottle2*m_quad;//
/cos_rollcos_pitch
}
else if(Mode == 3)//Automatic
Takeoff, Landing
{
err_hz = h_counter - z1_hat;
err_hz = constrain(err_hz, -1.0, 1.0);//+-2 m
float error_Vz = Vz_Hold - z2_hat;//Vz_Hold
hz_D_rate = (tar*hz_D_rate/(tar+G_Dt)) + ((error_Vz - error_Vz_old)/(tar+G_Dt));// D Controller
error_Vz_old = error_Vz;
float error_hII = err_hz*1.25 + error_Vz;//0.55
hz_I = hz_I + (Ki_altitude*error_hII*G_Dt);//1.9 - 2.9
18.5
22.5
hz_I = constrain(hz_I, -100, 100);//+-200
float uthrottle2 = (err_hz*Kp_altitude) + hz_I + (error_Vz*Kd_altitude) + (hz_D_rate*Kd2_altitude) (accrZ_Earth*Ka_altitude);//state feedback
//uthrottle = uthrottle2*m_quad/(cos_roll*cos_pitch);// = u*m*d/b*(cosr*cosp)
(cos_roll*cos_pitch)
uthrottle = uthrottle2*m_quad;//
,m*d/b = 122.33
/cos_rollcos_pitch
}
else
{
hz_I = 0.0;
uthrottle = 0.0;
Altitude_Hold = z1_hat;
}//end Altitude Hold
uthrottle = constrain(uthrottle, -200, 200);//+-120 +-150
uAltitude = CH_THRf + uthrottle;//m*g = 10.8 N =
uAltitude = constrain(uAltitude, MINCOMMAND, MAXTHROTTLE);
}
/////////////////////////////
void LED_Auto(){
Counter_LED_Auto++;
if(Counter_LED_Auto > 5){
digitalWrite(Pin_LED_R, HIGH);
}
if(Counter_LED_Auto > 7){
digitalWrite(Pin_LED_R, LOW);
Counter_LED_Auto = 0;
}
}
///////////////////////
void Chack_Command(){
if(AUX_1 <= (AltHold-10))//Stabilize
{
Mode = 0;
}
if(AUX_1 > (AltHold-10) && AUX_1 <= (AltHold+10))//Altitude Hold,
{
Mode = 1;
}
if(AUX_1 > (PositionHold-10) && AUX_1 <= (PositionHold+10))//Position Hold
{
Mode = 2;
}
if(AUX_1 > (Auto-10))//Automatic
Takeoff
{
Mode = 3;
LED_Auto();
}
if(AUX_1 > (RTH-10) && AUX_1 <= (RTH+10))//RTH
{
Mode = 2;
target_LAT = GPS_LAT_HOME;//GPS_LAT_Hold
target_LON = GPS_LON_HOME;//GPS_LON_Hold
}
//////////////////
if(AUX_2 <= 1300)//Set Home
{
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
35
GPS_LAT_HOME = GPS_LAT1f;
GPS_LON_HOME = GPS_LON1f;
digitalWrite(Pin_LED_G, HIGH);
digitalWrite(Pin_LED_R, LOW);
}
if(AUX_2 >= 1700)//Set waypoint1
{
waypoint1_LAT = GPS_LAT1f;
waypoint1_LON = GPS_LON1f;
digitalWrite(Pin_LED_R, HIGH);
digitalWrite(Pin_LED_G, LOW);
}
}//end Chack_Command()
///////////////////////////////////////////////////////////////////////////////////
void Automatictakeland(){
//Altitude control and 1 waypoint navigation
if(Mode == 3 && CH_THRf > MINCHECK && armed == 1)
{
if(time_auto < 2){//Check time < 5
takeoff = 1;
}
if(z1_hat >= h_control && endAuto == 1)//waypoint1
{
target_LAT = waypoint1_LAT;
target_LON = waypoint1_LON;
Status_waypoint = 1;
}
if(time_auto > 8 && abs(error_LAT) <= 70 && abs(error_LON) <= 70 && endAuto == 1 && Status_waypoint == 1)//50 10
Landing and position hold mode
{
timeLanding++;
if(timeLanding >= 30)//relay 3 s Landing
{
takeoff = 0;
}
}
}
else//(Mode == 3 && CH_THR > MINCHECK && armed == 1)
{
takeoff = 0;
timeLanding = 0;
timeOff = 0;
time_auto = 0;
h_counter = 0.1;//0.0
h_counter_old = 0.1;
Vz_Hold = 0.0;
Status_waypoint = 0;
}
//////////////////////////////////////////////////////////////////
if(h_counter < h_control && takeoff == 1)//take-off
{
endAuto = 1;
h_counter = h_counter + 0.042;//0.023 0.01- 0.03
0.1 = 10 s
//ramp input hz take-off
Vz_Hold = (h_counter - h_counter_old)/0.1;//(m/s) roop 10 Hz
h_counter_old = h_counter;
}
if(takeoff == 0 && endAuto == 1)//landing
{
h_counter = h_counter - 0.029;//0.023 ramp input hz
landing
Vz_Hold = (h_counter - h_counter_old)/0.1;//(m/s) roop 10 Hz
h_counter_old = h_counter;
if(z1_hat <= 0.18)
{
endAuto = 0;
}
}
////////////////////////////////////
if(time_auto > 25 && endAuto == 0) //15 s End waypoint quadrotor
{
timeOff++;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
36
if(timeOff > 60)//relay 6 s time-Off
{
armed = 0;
}
}
///////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////
void Control_PositionHold(){
if(Mode == 2 || Mode == 3 && GPS_FIX
== 1){
error_LAT = (target_LAT - GPS_LAT1f)*6371000.0; // X Error cm
error_LON = (target_LON - GPS_LON1f)*6371000.0;// Y Error
cm
error_LAT = constrain(error_LAT,-500,500);//200 = +-2 m
error_LON = constrain(error_LON,-500,500);
float target_speedLAT = error_LAT*Kp_speed;//P Control Velocity GPS
float target_speedLON = error_LON*Kp_speed;//P Control Velocity GPS
target_speedLAT = constrain(target_speedLAT,-200,200);//+-100 cm/s = 1m/s
target_speedLON = constrain(target_speedLON,-200,200);
float error_rate_LAT = target_speedLAT - vx_hat;
float error_rate_LON = target_speedLON - vy_hat;
error_rate_LAT = constrain(error_rate_LAT,-300,300);//+-200 cm/s
error_rate_LON = constrain(error_rate_LON,-300,300);
GPSI_LAT = GPSI_LAT + (error_rate_LAT*Ki_gps*0.05);//5Hz=0.2 ,, 20 Hz = 0.05
GPSI_LON = GPSI_LON + (error_rate_LON*Ki_gps*0.05);
GPSI_LAT = constrain(GPSI_LAT,-200,200);//win speed +-200 cm/s
GPSI_LON = constrain(GPSI_LON,-200,200);//250
//Control_XEf = error_rate_LAT*Kd_gps;//P Control speed
//Control_YEf = error_rate_LON*Kd_gps;
Control_XEf = error_LAT*Kp_gps + error_rate_LAT*Kd_gps + GPSI_LAT;//PID Control speed
Control_YEf = error_LON*Kp_gps + error_rate_LON*Kd_gps + GPSI_LON;
Control_XEf = constrain(Control_XEf,-800,800);//PWM 1000 - 1900
Control_YEf = constrain(Control_YEf,-800,800);
//The desired roll and pitch angles by tinnakon
float urolldesir = (Control_YEf*m_quad)/uAltitude;//uAltitude/2 = 1000 - 1900
float upitchdesir = (Control_XEf*m_quad*-1.0)/uAltitude;//*-1
urolldesir = constrain(urolldesir,-0.7,0.7);//+-0.7 = +-44.427
upitchdesir = constrain(upitchdesir,-0.7,0.7);
float temp_YBf = asin(urolldesir)*RAD_TO_DEG;//Control Earth Frame
float temp_XBf = asin(upitchdesir)*RAD_TO_DEG;//Control Earth Frame
Control_XBf = (DCM00*temp_XBf) + (DCM01*temp_YBf);//Control Body Frame use Rotation matrix
Control_YBf = (DCM10*temp_XBf) + (DCM11*temp_YBf);//Control Body Frame use Rotation matrix
Control_XBf = constrain(Control_XBf, -20, 20);//+-20 deg
Control_YBf = constrain(Control_YBf, -20, 20);//+-20 deg
//The desired roll and pitch angles by paper Modeling and Backstepping-based Nonlinear Control
//Ashfaq Ahman Mian 2008 (eq.25 and eq.26)
//float urolldesir = ((Control_XEf*m_quad*sin(ahrs_y))/uAltitude) ((Control_YEf*m_quad*cos_yaw)/uAltitude);
//float upitchdesir = ((Control_XEf*m_quad)/(uAltitude*cos_roll*cos_yaw)) ((sin(ahrs_r)*sin(ahrs_y))/(cos_roll*cos_yaw));
//urolldesir = constrain(urolldesir,-0.7,0.7);//+-0.7 = +-44.427
//upitchdesir = constrain(upitchdesir,-0.7,0.7);
//Control_YBf = asin(urolldesir)*RAD_TO_DEG;//Control roll eq.25
//Control_XBf = asin(upitchdesir)*RAD_TO_DEG*-1.0;//Control roll eq.26
//Control_XBf = constrain(Control_XBf, -20, 20);//+-20 +- 44
//Control_YBf = constrain(Control_YBf, -20, 20);
}
else{
Control_XBf = 0.0;
Control_YBf = 0.0;
GPSI_LAT = 0.0;
GPSI_LON = 0.0;
target_LAT = GPS_LAT1f;//GPS_LAT_Hold
target_LON = GPS_LON1f;//GPS_LON_Hold
}
}//end
Control_PositionHold()
/////////////////////////////////////////////////////////////////////////
void Cal_GPS(){
if(GPS_FIX
== 1){
//Apply moving average filter to GPS data
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
37
GPS_filter_index = (GPS_filter_index+1) % 4;// 4 moving average
GPS_SUM_LAT[GPS_filter_index] = GPS_LAT1;
GPS_SUM_LON[GPS_filter_index] = GPS_LON1;
float sum1=0.0;
float sum2=0.0;
for(int i=0;i<4;i++)
{
sum1 += GPS_SUM_LAT[i];
sum2 += GPS_SUM_LON[i];
}
GPS_LAT1f = sum1/4.0;
GPS_LON1f = sum2/4.0;
}
/* ///////////////////////////////////////
//Diff speed
actual_speedX = (GPS_LAT1f - GPS_LAT1_old)*6371000.0/0.3;//5 Hz = 0.2 ,cm/s
10000000.0 ,R = 6371000.0
actual_speedY = (GPS_LON1f - GPS_LON1_old)*637100.0/0.3;//cm/s
//actual_speedX = constrain(actual_speedX, -400, 400);//+-400 cm/s
//actual_speedY = constrain(actual_speedY, -400, 400);//+-400 cm/s
GPS_LAT1_old = GPS_LAT1f;
GPS_LON1_old = GPS_LON1f;
actual_speedXf = (actual_speedX + actual_speedXold)/2.0;//Moving Average Filters/
actual_speedYf = (actual_speedY + actual_speedYold)/2.0;//Moving Average Filters/
actual_speedXold = actual_speedX;
actual_speedYold = actual_speedY;
/////////////LeadFilter GPS/////////////////////////////////
float lag_in_seconds = 0.85;//1.0 0.5
float accel_contribution = (actual_speedXf - _last_velocityX) * lag_in_seconds * lag_in_seconds;
float vel_contribution = actual_speedXf * lag_in_seconds;
_last_velocityX = actual_speedXf;
GPS_LAT1lead = GPS_LAT1f
// store velocity for next iteration
+ vel_contribution + accel_contribution;
float accel_contributio = (actual_speedYf - _last_velocityY) * lag_in_seconds * lag_in_seconds;
float vel_contributio = actual_speedYf * lag_in_seconds;
_last_velocityY = actual_speedYf;
GPS_LON1lead = GPS_LON1f
// store velocity for next iteration
+ vel_contributio + accel_contributio;
*/
}
5. ไฟล์ Kalman_ObserverTin.h
/*
project_Quad 32 bit Arduino Due
//GPS
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
//A=[1 0.01;0 1]; //B=[0;0.01];
//C = [1 0];
//Plant = ss(A,[B B],C,0,-1,'inputname',{'u' 'w'},'outputname','y');
//Q = 0.1; % A number greater than zero
//R = 0.135; % A number greater than zero
//[kalmf,L,P,M,Z] = kalman(Plant,Q,R); //%kalmf = kalmf(1,:); //M,
% innovation gain
*/
void Observer_kalman_filter()
{
///Complimentary Filter, Observer velocity vx vy vz kalman//accelerometer and
GPS/////////////////////////////////////////////////////
//GPS Speed Low Pass Filter
//GPS_LAT1Lf = GPS_LAT1Lf + (GPS_LAT1lead - GPS_LAT1Lf)*8.2521*G_Dt;//12.5412
//GPS_LON1Lf = GPS_LON1Lf + (GPS_LON1lead - GPS_LON1Lf)*8.2521*G_Dt;
//actual_speedXf = actual_speedXf + (actual_speedX - actual_speedXf)*10.2*G_Dt;//5.2 10.4
//cm/s
+-400 cm/s
//actual_speedYf = actual_speedYf + (actual_speedY - actual_speedYf)*10.2*G_Dt;//5.2 10.17
float temp_vx = accrX_Earth*100.1 + (_velocity_north - vx_hat2)*9.2;//2.15
1.5 6.5
vx_hat = vx_hat +
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
38
temp_vx*G_Dt;
vx_hat2 = vx_hat2 + temp_vx*G_Dt;
vx_hat = constrain(vx_hat2, -400, 400);//+-400 cm/s
applyDeadband(vx_hat, 4.5);//4.5 10.5
float temp_vy = accrY_Earth*100.1 + (_velocity_east - vy_hat2)*9.2;//2.15
1.5 6.5
vy_hat2 = vy_hat2 + temp_vy*G_Dt;
vy_hat = constrain(vy_hat2, -400, 400);
applyDeadband(vy_hat, 4.5);//4.5 10.5
//Predicted (a priori) state estimate
Altitude
//u_z = (motor_FrontLf + motor_FrontRf + motor_BackLf + motor_BackRf);//uz - g ,,unit N *0.001691) - 9.81
u_z = accrZ_Earth;//applyDeadband = 0.1 m/s^2
= ,,(u - c*z2_hat)/m = Accz
z2_hat2 = z2_hat + u_z*G_Dt;//z2_hat = velocity ,, m/s
z1_hat2 = z1_hat + z2_hat2*G_Dt;//z1_hat = Altitude ,, m
//z1_hat = constrain(z1_hat, 0, 100);//0 - 100 m
///////////////////////////////////////////////////////////////////
//Updated (a posteriori) state estimate
//Update estimate with measurement zk
z2_hat = z2_hat2 + 0.012502*(Altitude_Baro_ult - z1_hat2) + 0.01641023*(Vz_Baro_ult - z2_hat2);//K2 = 0.0002141023,
0.0001641, 0.00145, 0.00045,,,k2 0.097502,
0.065502, 0.009
z1_hat = z1_hat2 + 0.015102*(Altitude_Baro_ult - z1_hat2) + 0.01741023*(Vz_Baro_ult - z2_hat2);//K1 =0.035102,
0.015102 0.065 0.2887
0.09187 0.01187 0.0140
}
6. ไฟล์ Ultrasonic04.h
/*
project_Quad 32 bit Arduino Due
//GPS
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
#include "Ultrasonic.h"
Ultrasonic LV-EZ4
AnalogRead
every 50mS, (20-Hz rate)
from 6-inches out to 254-inches
from 0.15-m out to 6.45 m
5V yields ~9.8mV/in. , 1 in = 0.0254 m =~9.8mV/0.0254 m = 0.38582 v/m
Ultrasonic_HC-SR04
from 0.02 -m out to 1.4 m
//Just connect VCC to (+) on D9, trig to D9, echo to D10, Gnd to (-)
*/
#define HCSR04_TriggerPin 27 // should be modified to 9
#define HCSR04_EchoPin 26
12 in next version
// should be modified to 10
11 in next version
float hz_Ultra = 0.0;
float Altitude_sona = 0.0;
float Altitude_sona2 = 0.0;
float Altitude_sonaf = 0.0;
float Altitude_sonaold = 0.0;
float vz_sona = 0.0;
float vz_sona2 = 0.0;
float vz_sonaf = 0.0;
float Altitude_II = 0.0;
float Altitude_Baro_ult = 0.0;
float Vz_Baro_ult = 0.0;
unsigned long HCSR04_startTime = 0;
unsigned long HCSR04_echoTime = 0;
int
tempSonarAlt=0;
// EchoPin will change to high signalize beginning
// and back to low after 58*cm us
// First interrupt is needed to start measurement, second interrupt to calculate the distance
void UltaHandler() {
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
39
// Here is a routine missing, to check, if the interrupt was raised for echo pin - not needed at the moment, because
we don't have any interrupts
// for this interrupt group, but maybe later
uint8_t sensorVal = digitalRead(HCSR04_EchoPin);
if (sensorVal == 1) { //indicates if the EchoPin is at a high state
HCSR04_startTime = micros();
}
else {
HCSR04_echoTime = micros() - HCSR04_startTime;
if (HCSR04_echoTime <= 25000)
// maximum = 4,31 meter - 30000 us means out of range
tempSonarAlt = HCSR04_echoTime / 5.8;//to mm
else
tempSonarAlt = 9999;
}
}
void UltrasonicInt()
{
Serial.print("Altitude_sona");Serial.print("\n");
pinMode(HCSR04_EchoPin,INPUT);
pinMode(HCSR04_TriggerPin,OUTPUT);
attachInterrupt(HCSR04_EchoPin, UltaHandler, CHANGE); //RISING
FALLING CHANGE
//PCICR |= (1<<PCIE0);// enable PCINT0 // PCINT 0-7 belong to PCIE0 //HCSR04_EchoPin_PCICR
//PCMSK0 = (1<<PCINT4);//PB4 ( OC2A/PCINT4 )= Digital pin 10 (PWM)
// Mask Pin PCINT5 - all other PIns PCINT0-7 are not allowed to create interrupts!
}
void UltrasonicRead()
{
//Ultrasonic LV-EZ4
//int sensorValue = analogRead(A0);
//hz_Ultra = (sensorValue*5/1024.0)/0.38528;//5V yields ~9.8mV/in. , 1 in = 0.0254 m =~9.8mV/0.0254 m = 0.38582 v/m
//hz_Ultra = constrain(hz_Ultra, 0, 6.45);//m
//Ultrasonic_HC-SR04 // create a trigger pulse for 10 us
//digitalWrite(HCSR04_TriggerPin, LOW);
//delayMicroseconds(2);
digitalWrite(HCSR04_TriggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(HCSR04_TriggerPin, LOW);
Altitude_sona = tempSonarAlt/1000.0;//m
//Altitude_sonaf = (Altitude_sona + Altitude_sona2)/2.0;//filter
Altitude_sonaf = Altitude_sonaf + (((Altitude_sona + Altitude_sona2)/2.0) - Altitude_sonaf)*0.622012;//*0.687 filter
42 Hz
Altitude_sona2 = Altitude_sona;
vz_sona = (Altitude_sonaf - Altitude_sonaold)/0.05;//diff 20 Hz = 0.05 s
Altitude_sonaold = Altitude_sonaf;
//vz_sonaf = (vz_sona + vz_sona2)/2.0;//filter
//vz_sonaf = vz_sonaf + (((vz_sona + vz_sona2)/2.0) - vz_sonaf)*0.62;//filter 42 Hz
//vz_sona2 = vz_sona;
vz_sonaf = constrain(vz_sona, -3, 3);
//Altitude_sonano = constrain(Altitude_sonano, 0, 3.0);//m
//Ultrasonic max 0.7 m change to Baro//////////////////////////////
if(z1_hat > 0.8){//Altitude_sonaf
Altitude_Baro_ult = Altitude_barof;
Vz_Baro_ult = baro_vz;
}
else{
float error_Altitude = Altitude_sonaf - Altitude_barof;
Altitude_II = Altitude_II + (error_Altitude*0.019501);//0.0185 0.005 ,,20 Hz = 0.05
Altitude_II = constrain(Altitude_II, -100, 100);
Altitude_Baro_ult = Altitude_sonaf;
Vz_Baro_ult = vz_sonaf;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
float getAltitude(float pressure2, float temperature2)
{
//return (1.0f - pow(pressure2/sea_press, 0.190295f)) * 44330.0f;
//return log(sea_press/pressure2) * (temperature2+273.15f) * 29.271267f; // in meter
1007.23 1008.83
return ((pow((sea_press/pressure2),1/5.257)-1.0)*(temperature2+273.15))/0.0065;
}
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
40
void pushAvg(float val, float val2)
{
movavg_buff[movavg_i] = val;
movavg_buffT[movavg_i] = val2;
movavg_i = (movavg_i + 1) % MOVAVG_SIZE;
}
float getAvg(float * buff, int size)
{
float sum=0.0;
for(int i=0;i<size;i++)
{
sum += buff[i];
}
return sum/size;
}
7. ไฟล์ ahrs_tinsam3x8e.h
/*
//An attitude and heading reference system (AHRS)
By tinnakon 26_05_2557(2014)
project_Quad 32 bit Arduino Due
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
*/
#define Kp 0.35 //0.22 0.15
//0.2 1.62
// proportional gain governs rate of convergence to
accelerometer/magnetometer
#define Ki 0.0005011 //0.122 0.072 0.096 0.05
// integral gain governs rate of convergence of gyroscope
biases
#define Kp_mag 0.25
//0.22
#define Ki_mag 0.0005101 //0.142
float exInt , eyInt , ezInt ;
// scaled integral error
float q0, q1 , q2 , q3 ;
// quaternion elements representing the estimated orientation
float ahrs_p,ahrs_r,ahrs_y;
float Heading = 0.0;
float setHeading = 0.0;
float previousEx = 0.0;
float previousEy = 0.0;
float previousEz = 0.0;
void ahrs_initialize()
{
exInt=0.0;
eyInt=0.0;
ezInt=0.0;
q0=1.0;
q1=0.0;
q2=0.0;
q3=0.0;
}
boolean isSwitched(float previousError, float currentError) {
if ((previousError > 0.0 &&
currentError < 0.0) || (previousError < 0.0 &&
currentError > 0.0)) {
return true;
}
return false;
}
void ahrs_updateMARG(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz, float
G_Dt){
float norm1,halfT;
float hx, hy, hz, bx, bz;
float vx, vy, vz, wx, wy, wz;
float ex, ey, ez, ezMag;
halfT=G_Dt/2.0;
norm1 = sqrt(ax*ax + ay*ay + az*az); // normalise the measurements
ax = ax / norm1;
ay = ay / norm1;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
41
az = az / norm1;
norm1 = sqrt(mx*mx + my*my + mz*mz);
mx = mx / norm1;
my = my / norm1;
mz = mz / norm1;
hx = mx*DCM00 + my*DCM01 + mz*DCM02;
// compute reference direction of flux, Earth Frame
hy = mx*DCM10 + my*DCM11 + mz*DCM12;
hz = mx*DCM20 + my*DCM21 + mz*DCM22;
bx = sqrt((hx*hx) + (hy*hy));
bz = hz;
vx = DCM20;//2*(q1q3 - q0q2)
// estimated direction of gravity and flux (v and w)
vy = DCM21;//2*(q0q1 + q2q3)
vz = DCM22;//q0q0 - q1q1 - q2q2 + q3q3
wx = bx*DCM00 + bz*DCM20;
wy = bx*DCM01 + bz*DCM21;
wz = bx*DCM02 + bz*DCM22;
ex = (ay*vz - az*vy);
// error is sum of cross product between reference direction of fields and direction measured
by sensors
ey = (az*vx - ax*vz);
ez = (ax*vy - ay*vx);
//ez = (ax*vy - ay*vx);// + (mx*wy - my*wx)
ezMag = (mx*wy - my*wx);
// integral error scaled integral gain
//exInt += ex*Ki*G_Dt;
//eyInt += ey*Ki*G_Dt;
//ezInt += (ez*Ki + ezMag*Ki_mag)*G_Dt;
//*
exInt += ex*Ki;
if (isSwitched(previousEx,ex)) {
exInt = 0.0;
}
previousEx = ex;
eyInt += ey*Ki;
if (isSwitched(previousEy,ey)) {
eyInt = 0.0;
}
previousEy = ey;
float ezi = (ez*Ki + ezMag*Ki_mag);
ezInt += ezi;
if (isSwitched(previousEz,ezi)) {
ezInt = 0.0;
}
previousEz = ezi;
gx += (Kp*ex + exInt);
// adjusted gyroscope measurements
gy += (Kp*ey + eyInt);
gz += (Kp*ez + ezMag*Kp_mag + ezInt);
q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
// integrate quaternion rate and normalise
q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;
norm1 = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
// normalise quaternion
q0 = q0 / norm1;
q1 = q1 / norm1;
q2 = q2 / norm1;
q3 = q3 / norm1;
//float q0q0 = q0*q0;
float q0q1 = q0*q1;// auxiliary variables to reduce number of repeated operations
float q0q2 = q0*q2;
float q0q3 = q0*q3;
float q1q1 = q1*q1;
float q1q2 = q1*q2;
float q1q3 = q1*q3;
float q2q2 = q2*q2;
float q2q3 = q2*q3;
float q3q3 = q3*q3;
//direction cosine matrix (DCM), Rotation matrix , Rotated Frame to Stationary Frame XYZ
,,
Quaternions_and_spatial_rotation
DCM00 = 2*(0.5 - q2q2 - q3q3);//2*(0.5 - q2q2 - q3q3);//=q0q0 + q1q1 - q2q2 - q3q3
DCM01 = 2*(q1q2 - q0q3);//2*(q0q1 + q2q3)
DCM02 = 2*(q1q3 + q0q2);//2*(q1q3 - q0q2); 2*(q0q2 - q1q3)
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
42
DCM10 = 2*(q1q2 + q0q3);
DCM11 = 2*(0.5 - q1q1 - q3q3);//2*(0.5 - q1q1 - q3q3);//q0q0 - q1q1 + q2q2 - q3q3
DCM12 = 2*(q2q3 - q0q1);
DCM20 = 2*(q1q3 - q0q2);//-sin pitch
DCM21 = 2*(q2q3 + q0q1);
DCM22 = 2*(0.5 - q1q1 - q2q2);//2*(0.5 - q1q1 - q2q2);//=q0q0 - q1q1 - q2q2 + q3q3
//DCM23 = q0*q0 - q1*q1 + q2*q2 - q3*q3;
//ahrs_toEuler();
ahrs_y=degrees(atan2(DCM10, DCM00));//2*q0*q0+2*q1*q1-1)
ahrs_p=degrees(-asin(DCM20)); // theta
//ahrs_p=acos(22);//http://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions
ahrs_r=degrees(atan2(DCM21, DCM22)); // phi
cos_rollcos_pitch = DCM22;
if(cos_rollcos_pitch <= 0.866025403)//30 deg = 0.866025403
{
cos_rollcos_pitch = 0.866025403;
}
////transition between 0 and 360 or -180 and 180 ,By aeroquad//////////
Heading = ahrs_y - setHeading;
if (ahrs_y <= (setHeading - 180)) {
Heading += 360;
}
if (ahrs_y >= (setHeading + 180)) {
Heading -= 360;
}
//////Earth Frame///////////////
//accrX_Earth = hx;
//accrY_Earth = hy;
//accrZ_Earth = hz;
accrX_Earthf = (AccXf*DCM00 + AccYf*DCM01 + AccZf*DCM02)*-1.0;
accrY_Earthf = (AccXf*DCM10 + AccYf*DCM11 + AccZf*DCM12)*-1.0;
accrZ_Earthf = (AccXf*DCM20 + AccYf*DCM21 + AccZf*DCM22) - acc_offsetZ2;//acc_offsetZ2
accrX_Earth = accrX_Earth + (accrX_Earthf - accrX_Earth)*G_Dt*32.51245;
accrY_Earth = accrY_Earth + (accrY_Earthf - accrY_Earth)*G_Dt*32.51245;
accrZ_Earth = accrZ_Earth + (accrZ_Earthf - accrZ_Earth)*G_Dt*32.51245;//22.51245 42.5 18.5 Low pass filter ,smoothing
factor
α := dt / (RC + dt)
applyDeadband(accrX_Earthf, 0.02);//+-0.03 m/s^2
applyDeadband(accrY_Earthf, 0.02);//+-0.03 m/s^2
applyDeadband(accrZ_Earthf, 0.02);//+-0.03 m/s^2
}
///////////////////Filter FourthOrder ///////////////////////////////////////
struct fourthOrderData
{
float
inputTm1,
inputTm2,
inputTm3,
inputTm4;
float outputTm1, outputTm2, outputTm3, outputTm4;
} fourthOrder[4];
float computeFourthOrder(float currentInput, struct fourthOrderData *filterParameters)
{
// cheby2(4,60,12.5/50)
#define _b0
0.001893594048567
#define _b1 -0.002220262954039
#define _b2
0.003389066536478
#define _b3 -0.002220262954039
#define _b4
0.001893594048567
#define _a1 -3.362256889209355
#define _a2
4.282608240117919
#define _a3 -2.444765517272841
#define _a4
0.527149895089809
float output;
output = _b0 * currentInput
+
_b1 * filterParameters->inputTm1
+
_b2 * filterParameters->inputTm2
+
_b3 * filterParameters->inputTm3
+
_b4 * filterParameters->inputTm4
-
_a1 * filterParameters->outputTm1 _a2 * filterParameters->outputTm2 _a3 * filterParameters->outputTm3 _a4 * filterParameters->outputTm4;
filterParameters->inputTm4 = filterParameters->inputTm3;
filterParameters->inputTm3 = filterParameters->inputTm2;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
43
filterParameters->inputTm2 = filterParameters->inputTm1;
filterParameters->inputTm1 = currentInput;
filterParameters->outputTm4 = filterParameters->outputTm3;
filterParameters->outputTm3 = filterParameters->outputTm2;
filterParameters->outputTm2 = filterParameters->outputTm1;
filterParameters->outputTm1 = output;
return output;
}
void setupFourthOrder()
{
fourthOrder[XAXIS].inputTm1 = 0.0;
fourthOrder[XAXIS].inputTm2 = 0.0;
fourthOrder[XAXIS].inputTm3 = 0.0;
fourthOrder[XAXIS].inputTm4 = 0.0;
fourthOrder[XAXIS].outputTm1 = 0.0;
fourthOrder[XAXIS].outputTm2 = 0.0;
fourthOrder[XAXIS].outputTm3 = 0.0;
fourthOrder[XAXIS].outputTm4 = 0.0;
fourthOrder[YAXIS].inputTm1 = 0.0;
fourthOrder[YAXIS].inputTm2 = 0.0;
fourthOrder[YAXIS].inputTm3 = 0.0;
fourthOrder[YAXIS].inputTm4 = 0.0;
fourthOrder[YAXIS].outputTm1 = 0.0;
fourthOrder[YAXIS].outputTm2 = 0.0;
fourthOrder[YAXIS].outputTm3 = 0.0;
fourthOrder[YAXIS].outputTm4 = 0.0;
fourthOrder[ZAXIS].inputTm1 = acc_offsetZ;
fourthOrder[ZAXIS].inputTm2 = acc_offsetZ;
fourthOrder[ZAXIS].inputTm3 = acc_offsetZ;
fourthOrder[ZAXIS].inputTm4 = acc_offsetZ;
fourthOrder[ZAXIS].outputTm1 = acc_offsetZ;
fourthOrder[ZAXIS].outputTm2 = acc_offsetZ;
fourthOrder[ZAXIS].outputTm3 = acc_offsetZ;
fourthOrder[ZAXIS].outputTm4 = acc_offsetZ;
}
8. ไฟล์ motorX4sam3x8e.h
/*
project_Quad 32 bit Arduino Due
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
*/
int MOTOR_FrontL_PIN = 4;//PWML7 = pin 6
int MOTOR_FrontR_PIN = 5;//PWML6 = pin 7
int MOTOR_BackL_PIN = 7;// PWML5 = pin 8
int MOTOR_BackR_PIN = 6;// PWML4 = pin 9
#define PWM_DUE_FREQUENCY 400
#define PWM_DUE_PERIOD 2500
//400 in Hz
// in us
//#define PWM_PRESCALER 8
//#define PWM_COUNTER_PERIOD (F_CPU/PWM_PRESCALER/PWM_FREQUENCY)
float motor_FrontL = 1000;
float motor_FrontR = 1000;
float motor_BackL = 1000;
float motor_BackR = 1000;
//lag filter motor/
float motor_FrontLf = 1000;
float motor_FrontLold = 1000;
float motor_FrontLold2 = 1000;
float motor_FrontRf = 1000;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
44
float motor_FrontRold = 1000;
float motor_FrontRold2 = 1000;
float motor_BackLf = 1000;
float motor_BackLold = 1000;
float motor_BackLold2 = 1000;
float motor_BackRf = 1000;
float motor_BackRold = 1000;
float motor_BackRold2 = 1000;
///////////////////////////////////////////////////////////////////////////////
static void setPWMpin(uint32_t pin) {
PIO_Configure(g_APinDescription[pin].pPort,
PIO_PERIPH_B, //hack Arduino does not allow high PWM by default
g_APinDescription[pin].ulPin,
g_APinDescription[pin].ulPinConfiguration);
}
static void configOneMotor(uint8_t ch, uint32_t period) {
PWMC_ConfigureChannel(PWM, ch, PWM_CMR_CPRE_CLKA, 0, 0);
PWMC_SetPeriod(PWM, ch, period);
PWMC_SetDutyCycle(PWM, ch, MINCOMMAND);
PWMC_EnableChannel(PWM, ch);
}
void motor_command_all()
{
for (int j = 0 ; j <= 50 ; j++)
{
motor_FrontL = 1000;
motor_FrontR = 1000;
motor_BackL = 1000;
motor_BackR = 1000;
PWMC_SetDutyCycle(PWM, 4, 1000);
PWMC_SetDutyCycle(PWM, 5, 1000);
PWMC_SetDutyCycle(PWM, 6, 1000);
PWMC_SetDutyCycle(PWM, 7, 1000);
delay(20);
}
}
void motor_initialize()
{
Serial.print("motor_initialize");Serial.print("\n");
pinMode(MOTOR_FrontL_PIN,OUTPUT);
pinMode(MOTOR_FrontR_PIN,OUTPUT);
pinMode(MOTOR_BackL_PIN,OUTPUT);
pinMode(MOTOR_BackR_PIN,OUTPUT);
digitalWrite(MOTOR_FrontL_PIN, LOW);
digitalWrite(MOTOR_FrontR_PIN, LOW);
digitalWrite(MOTOR_BackL_PIN, LOW);
digitalWrite(MOTOR_BackR_PIN, LOW);
delay(1000);
setPWMpin(6);
PWMC_DisableChannel(PWM, 4);
setPWMpin(7);
PWMC_DisableChannel(PWM, 5);
setPWMpin(8);
PWMC_DisableChannel(PWM, 6);
setPWMpin(9);
PWMC_DisableChannel(PWM, 7);
pmc_enable_periph_clk(ID_PWM);
PWMC_ConfigureClocks(1000000,0,VARIANT_MCK);
// set PWM clock A to 1MHz
configOneMotor(4, PWM_DUE_PERIOD);
configOneMotor(5, PWM_DUE_PERIOD);
configOneMotor(6, PWM_DUE_PERIOD);
configOneMotor(7, PWM_DUE_PERIOD);
motor_command_all();
}
void motor_command()
{
PWMC_SetDutyCycle(PWM, MOTOR_FrontL_PIN, motor_FrontLf);//6 = PWML7
PWMC_SetDutyCycle(PWM, MOTOR_BackR_PIN, motor_BackRf);//7 = PWML6
PWMC_SetDutyCycle(PWM, MOTOR_FrontR_PIN, motor_FrontRf);//8 = PWML5
PWMC_SetDutyCycle(PWM, MOTOR_BackL_PIN, motor_BackLf);//9 = PWML4
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
45
}
/********************************************************************/
/****
ESCs calibration
By tinnakon
****/
/********************************************************************/
void ESC_calibration() {
Serial.print("ESC_calibration");Serial.print("\n");
for (int i = 0; i < 5; i++)
{
computeRC();
if(CH_THR > MAXCHECK)
{
ESC_calibra = 1;
}
else
{
ESC_calibra = 0;
}
delay(20);
}
int jprint = 0;
while(ESC_calibra == 1){
computeRC();
motor_FrontL = (CH_THR - 500)*1.5;
motor_FrontR = (CH_THR - 500)*1.5;
motor_BackL = (CH_THR - 500)*1.5;
motor_BackR = (CH_THR - 500)*1.5;
motor_FrontL = constrain(motor_FrontL, MINCOMMAND, MAXCOMMAND);
motor_FrontR = constrain(motor_FrontR, MINCOMMAND, MAXCOMMAND);
motor_BackL = constrain(motor_BackL, MINCOMMAND, MAXCOMMAND);
motor_BackR = constrain(motor_BackR, MINCOMMAND, MAXCOMMAND);
PWMC_SetDutyCycle(PWM, 7, motor_FrontL);
PWMC_SetDutyCycle(PWM, 6, motor_BackR);
PWMC_SetDutyCycle(PWM, 5, motor_FrontR);
PWMC_SetDutyCycle(PWM, 4, motor_BackL);
jprint++;
if(jprint > 10)
{
jprint = 0;
Serial.print(motor_FrontL);Serial.print("\t");
Serial.print(motor_FrontR);Serial.print("\t");
Serial.print(motor_BackL);Serial.print("\t");
Serial.print(motor_BackR);Serial.println("\t");
//Serial1.println(motor_Back);
if(Status_LED == LOW)
Status_LED = HIGH;
else
Status_LED = LOW;
digitalWrite(13, Status_LED);
digitalWrite(Pin_LED_R, Status_LED);
digitalWrite(Pin_LED_G, Status_LED);
digitalWrite(Pin_LED_B, Status_LED);
}
delay(20);
}
}
/*
void motor_Lag(){
////////lag lead compensator filter motor////////////////////////////////////
float k_Lag = 2.45;//2.65 3.95 5.85 1.85 0.45 1.078 1.0 1.25
float k_Lead = 25.5;//35.25
float diff_motor_FrontL = (motor_FrontL - motor_FrontLold2)/0.02;
float temp_motor_FrontL = diff_motor_FrontL + (motor_FrontL - motor_FrontLf)*k_Lead;//35.5
motor_FrontLf = motor_FrontLf + (temp_motor_FrontL*G_Dt*k_Lag);
float diff_motor_FrontR = (motor_FrontR - motor_FrontRold2)/0.02;
float temp_motor_FrontR = diff_motor_FrontR + (motor_FrontR - motor_FrontRf)*k_Lead;//35.5
motor_FrontRf = motor_FrontRf + (temp_motor_FrontR*G_Dt*k_Lag);
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
46
float diff_motor_BackL = (motor_BackL - motor_BackLold2)/0.02;
float temp_motor_BackL = diff_motor_BackL + (motor_BackL - motor_BackLf)*k_Lead;//35.5
motor_BackLf = motor_BackLf + (temp_motor_BackL*G_Dt*k_Lag);
float diff_motor_BackR = (motor_BackR - motor_BackRold2)/0.02;
float temp_motor_BackR = diff_motor_BackR + (motor_BackR - motor_BackRf)*k_Lead;//35.5
motor_BackRf = motor_BackRf + (temp_motor_BackR*G_Dt*k_Lag);
motor_FrontLold2 = motor_FrontLold;
motor_FrontLold = motor_FrontL;//store PWM for next diff
motor_FrontRold2 = motor_FrontRold;
motor_FrontRold = motor_FrontR;
motor_BackLold2 = motor_BackLold;
motor_BackLold = motor_BackL;
motor_BackRold2 = motor_BackRold;
motor_BackRold = motor_BackR;
}
*/
void motor_Mix(){
motor_FrontL = uAltitude + u_pitch*0.7071 + u_roll*0.7071 - u_yaw;//Front L , cos45 = 0.7071
motor_FrontR = uAltitude + u_pitch*0.7071 - u_roll*0.7071 + u_yaw;//Front R
motor_BackL = uAltitude - u_pitch*0.7071 + u_roll*0.7071 + u_yaw;//Back L
motor_BackR = uAltitude - u_pitch*0.7071 - u_roll*0.7071 - u_yaw;////Back R
/*
#ifdef Quad_P
motor_Front = uAltitude + u_pitch - u_yaw;
motor_Right = uAltitude - u_roll + u_yaw;
motor_Left = uAltitude + u_roll + u_yaw;
motor_Back = uAltitude - u_pitch - u_yaw;
#endif
motor_FrontL = constrain(motor_FrontL, MINCOMMAND, MAXCOMMAND);
motor_FrontR = constrain(motor_FrontR, MINCOMMAND, MAXCOMMAND);
motor_BackL = constrain(motor_BackL, MINCOMMAND, MAXCOMMAND);
motor_BackR = constrain(motor_BackR, MINCOMMAND, MAXCOMMAND);
*/
if (CH_THR < MINTHROTTLE)
{
roll_I_rate = 0;
pitch_I_rate = 0;
yaw_I_rate = 0;
motor_FrontL = 1000;
motor_FrontR = 1000;
motor_BackL = 1000;
motor_BackR = 1000;
}
if(armed == 1)
{
//motor_Lag();
motor_FrontLf = constrain(motor_FrontL, MINTHROTTLE, MAXCOMMAND);//set PWM data (1000 - 2000)*2 to (2000 4000)
motor_FrontRf = constrain(motor_FrontR, MINTHROTTLE, MAXCOMMAND);
motor_BackLf = constrain(motor_BackL, MINTHROTTLE, MAXCOMMAND);
motor_BackRf = constrain(motor_BackR, MINTHROTTLE, MAXCOMMAND);
}
else
{
motor_FrontLf = 1000;//set PWM data (1000 - 2000)*2 to (2000 - 4000)
motor_FrontRf = 1000;
motor_BackLf = 1000;
motor_BackRf = 1000;
}
}
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
47
9. ไฟล์ mpu6050sam3x8e.h
/*
project_Quad 32 bit Arduino Due
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
//#include "mpu6050.h" MPU 6050 I2C Gyroscope and Accelerometer MPU6050 HMC5883L Magnetometer
*/
#define XAXIS 0
#define YAXIS 1
#define ZAXIS 2
float gyro[3];
float accel[3];
float gyroScaleFactor = radians(2000.0/32768.0);//32768.0 32730 , +-32756
32768.0
float accelScaleFactor = 9.80665;//9.80665/4100.62 9.81/8192.09 9.81 / 8205
uint8_t gyroSamples = 0;
uint8_t gyroSamples2 = 0;
uint8_t accSamples = 0;
int16_t gyroRaw[3];
float gyroSum[3];
int16_t accelRaw[3];
float accelSum[3];
float AccXm,AccYm,AccZm;
float AccX,AccY,AccZ;
float AccXf,AccYf,AccZf;
float AccX2,AccY2,AccZ2;
float GyroXf,GyroYf,GyroZf;
float gyro_offsetX,gyro_offsetY,gyro_offsetZ,acc_offsetX,acc_offsetY,acc_offsetZ;
float acc_offsetZ2 = 9.81;
float GyroX,GyroY,GyroZ,GyroTemp;
float GyroX2,GyroY2,GyroZ2;
float Accel[3] = {0.0,0.0,0.0};
float filteredAccel[3] = {0.0,0.0,0.0};
#define HMC5883_Address 0x1E // I2C adress: 0x3C (8bit)
0x1E (7bit)
int16_t MagX1,MagY1,MagZ1;
float MagXf,MagYf,MagZf;
float c_magnetom_x;
float c_magnetom_y;
float c_magnetom_z;
//sensor MPU6050 ------------------------------------// MPU 6050 Registers
#define MPU6050_ADDRESS
//#define MPUREG_WHOAMI
0x68
0x75
#define MPUREG_SMPLRT_DIV
0x19
#define MPUREG_CONFIG
0x1A
#define MPUREG_GYRO_CONFIG
0x1B
#define MPUREG_ACCEL_CONFIG
0x1C
//#define MPUREG_FIFO_EN
#define MPUREG_INT_PIN_CFG
//#define MPUREG_INT_ENABLE
//#define MPUREG_INT_STATUS
#define MPUREG_ACCEL_XOUT_H
0x23
0x37
0x38
0x3A
0x3B
//#define MPUREG_ACCEL_XOUT_L
0x3C
//#define MPUREG_ACCEL_YOUT_H
0x3D
//#define MPUREG_ACCEL_YOUT_L
0x3E
//#define MPUREG_ACCEL_ZOUT_H
0x3F
//#define MPUREG_ACCEL_ZOUT_L
0x40
//#define MPUREG_TEMP_OUT_H
0x41
//#define MPUREG_TEMP_OUT_L
#define MPUREG_GYRO_XOUT_H
0x42
0x43
//#define MPUREG_GYRO_XOUT_L
0x44
//#define MPUREG_GYRO_YOUT_H
0x45
//#define MPUREG_GYRO_YOUT_L
0x46
//#define MPUREG_GYRO_ZOUT_H
0x47
//#define MPUREG_GYRO_ZOUT_L
0x48
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
48
//#define MPUREG_USER_CTRL
0x6A
#define MPUREG_PWR_MGMT_1
0x6B
//#define MPUREG_PWR_MGMT_2
0x6C
//#define MPUREG_FIFO_COUNTH
0x72
//#define MPUREG_FIFO_COUNTL
0x73
//#define MPUREG_FIFO_R_W
0x74
// Configuration bits
//#define BIT_SLEEP
0x40
#define BIT_H_RESET
0x80
//#define BITS_CLKSEL
0x07
//#define MPU_CLK_SEL_PLLGYROX
0x01
#define MPU_CLK_SEL_PLLGYROZ
0x03
//#define MPU_EXT_SYNC_GYROX
0x02
//#define BITS_FS_250DPS
0x00
//#define BITS_FS_500DPS
0x08
//#define BITS_FS_1000DPS
0x10
#define BITS_FS_2000DPS
0x18
//#define BITS_FS_MASK
//#define BITS_DLPF_CFG_256HZ
0x18
0x00// //Default settings LPF 256Hz/8000Hz sample
//#define BITS_DLPF_CFG_188HZ
0x01
//#define BITS_DLPF_CFG_98HZ
0x02
#define BITS_DLPF_CFG_42HZ
0x03
//#define BITS_DLPF_CFG_20HZ
0x04
//#define BITS_DLPF_CFG_10HZ
0x05
//#define BITS_DLPF_CFG_5HZ
0x06
//#define BITS_DLPF_CFG_2100HZ_NOLPF
0x07
//#define BITS_DLPF_CFG_MASK
0x07
//#define BIT_INT_ANYRD_2CLEAR
0x10
//#define BIT_RAW_RDY_EN
0x01
//#define BIT_I2C_IF_DIS
0x10
//#define BIT_INT_STATUS_DATA
0x01
//sensor --------------------#define applyDeadband(value, deadband)
if(fabs(value) < deadband) {
value = 0.0;
\
\
\
} else if(value > 0.0){
\
value -= deadband;
\
} else if(value < 0.0){
\
value += deadband;
\
}
void mpu6050_initialize()
{
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_PWR_MGMT_1);
// Chip reset DEVICE_RESET 1
Wire.write(BIT_H_RESET);//DEVICE_RESET
Wire.endTransmission();
delay(30);// Startup delay
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_PWR_MGMT_1);
Wire.write(MPU_CLK_SEL_PLLGYROZ);//CLKSEL 3 (PLL with Z Gyro reference)
Wire.endTransmission();
delay(5);
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_SMPLRT_DIV);// SAMPLE RATE
Wire.write(0x00);//// Sample rate = 1kHz
Wire.endTransmission();
delay(5);
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_CONFIG);
Wire.write(BITS_DLPF_CFG_42HZ);//98 BITS_DLPF_CFG_188HZ, BITS_DLPF_CFG_42HZ, default DLPF_CFG = 0 => ACC bandwidth
= 260Hz
GYRO bandwidth = 256Hz)
Wire.endTransmission();
delay(5);
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_GYRO_CONFIG);
Wire.write(BITS_FS_2000DPS);//BITS_FS_1000DPS FS_SEL = 3: Full scale set to 2000 deg/sec,
BITS_FS_2000DPS
Wire.endTransmission();
delay(5);
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_ACCEL_CONFIG);
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
49
Wire.write(0x10);//0x10 = 1G=4096, AFS_SEL=2 (0x00 = +/-2G)
1G = 16,384 //0x10 = 1G = 4096 ,//0x08 = +-4g
Wire.endTransmission();
delay(5);
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_INT_PIN_CFG);// enable I2C bypass for AUX I2C
Wire.write(0x00);//0x00=off ,, 0x02 , I2C_BYPASS_EN=1
Wire.endTransmission();
}
void mpu6050_Gyro_Values()
{
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_GYRO_XOUT_H);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDRESS, 6);
int i = 0;
byte result[6];
while(Wire.available())
{
result[i] = Wire.read();
i++;
}
Wire.endTransmission();
gyroRaw[XAXIS] = ((result[0] << 8) | result[1]);//-12
-3
gyroRaw[YAXIS] = ((result[2] << 8) | result[3])*-1;//37
gyroRaw[ZAXIS] = ((result[4] << 8) | result[5])*-1;//11
15
5
}
void mpu6050_Accel_Values()
{
Wire.beginTransmission(MPU6050_ADDRESS);
Wire.write(MPUREG_ACCEL_XOUT_H);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDRESS, 6);
int i = 0;
byte result[6];
while(Wire.available())
{
result[i] = Wire.read();
i++;
}
Wire.endTransmission();
accelRaw[XAXIS] = ((result[0] << 8) | result[1])*-1 + 61;//+ 105 + 100
max=4054.46, min=-4149.48
accelRaw[YAXIS] = ((result[2] << 8) | result[3]) + 167;// - 45 - 35
max=4129.57, min=-4070.64
accelRaw[ZAXIS] = ((result[4] << 8) | result[5]);// + 150 + 170
// adjust for
max=4014.73 , min=-4165.13
acc axis offsets/sensitivity differences by scaling to +/-1 g range
AccXm = ((float)(accelRaw[XAXIS] - A_X_MIN) / (A_X_MAX - A_X_MIN))*2.0 - 1.0;
AccYm = ((float)(accelRaw[YAXIS] - A_Y_MIN) / (A_Y_MAX - A_Y_MIN))*2.0 - 1.0;
AccZm = ((float)(accelRaw[ZAXIS] - A_Z_MIN) / (A_Z_MAX - A_Z_MIN))*2.0 - 1.0;
}
void MagHMC5883Int()
{
Wire1.beginTransmission(HMC5883_Address); //open communication with HMC5883
Wire1.write(0x00); //Configuration Register A
Wire1.write(0x70); //num samples: 8 ; output rate: 15Hz ; normal measurement mode
Wire1.endTransmission();
delay(10);
Wire1.beginTransmission(HMC5883_Address); //open communication with HMC5883
Wire1.write(0x01); //Configuration Register B
Wire1.write(0x20); //configuration gain 1.3Ga
Wire1.endTransmission();
delay(10);
//Put the HMC5883 IC into the correct operating mode
Wire1.beginTransmission(HMC5883_Address); //open communication with HMC5883
Wire1.write(0x02); //select mode register
Wire1.write(0x00); //continuous measurement mode
Wire1.endTransmission();
delay(10);
}
void Mag5883Read()
{
Wire1.beginTransmission(HMC5883_Address);
//Tell the HMC5883 where to begin reading data
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
50
Wire1.write(0x03); //select register 3, X MSB register
Wire1.endTransmission();//Read data from each axis, 2 registers per axis
Wire1.requestFrom(HMC5883_Address, 6);
int i = 0;
byte result[6];
while(Wire1.available())
{
result[i] = Wire1.read();
i++;
}
Wire1.endTransmission();
MagY1 = ((result[0] << 8) | result[1]);//offset + 1.05
MagZ1 = ((result[2] << 8) | result[3]);// + 0.05
MagX1 = ((result[4] << 8) | result[5])*-1;// - 0.55
MagXf = MagXf + (MagX1 - MagXf)*0.45;//0.45
MagYf = MagYf + (MagY1 - MagYf)*0.45;
MagZf = MagZf + (MagZ1 - MagZf)*0.45;
// adjust for
compass axis offsets/sensitivity differences by scaling to +/-5 range
c_magnetom_x = ((float)(MagXf - M_X_MIN) / (M_X_MAX - M_X_MIN))*10.0 - 5.0;
c_magnetom_y = ((float)(MagYf - M_Y_MIN) / (M_Y_MAX - M_Y_MIN))*10.0 - 5.0;
c_magnetom_z = ((float)(MagZf - M_Z_MIN) / (M_Z_MAX - M_Z_MIN))*10.0 - 5.0;
}
void Mag_Calibrate()//Calibration_sensor Magnetometer
{
// Output MIN/MAX values
M_X_MIN = 0;
M_Y_MIN = 0;
M_Z_MIN = 0;
M_X_MAX = 0;
M_Y_MAX = 0;
M_Z_MAX = 0;
Serial.print("magn x,y,z (min/max) = ");
for (int i = 0; i < 600; i++) {//Calibration 30 s
digitalWrite(13, HIGH);//30
Mag5883Read();
if (MagX1 < M_X_MIN) M_X_MIN = MagX1;
if (MagX1 > M_X_MAX) M_X_MAX = MagX1;
if (MagY1 < M_Y_MIN) M_Y_MIN = MagY1;
if (MagY1 > M_Y_MAX) M_Y_MAX = MagY1;
if (MagZ1 < M_Z_MIN) M_Z_MIN = MagZ1;
if (MagZ1 > M_Z_MAX) M_Z_MAX = MagZ1;
delay(25);
digitalWrite(13, LOW);//30
delay(25);
}
Serial.print(M_X_MIN);Serial.print("/");
Serial.print(M_X_MAX);Serial.print("\t");
Serial.print(M_Y_MIN);Serial.print("/");
Serial.print(M_Y_MAX);Serial.print("\t");
Serial.print(M_Z_MIN);Serial.print("/");
Serial.print(M_Z_MAX);
Serial.print("\n");
}
void mpu6050_readGyroSum() {
mpu6050_Gyro_Values();
gyroSum[XAXIS] += gyroRaw[XAXIS];
gyroSum[YAXIS] += gyroRaw[YAXIS];
gyroSum[ZAXIS] += gyroRaw[ZAXIS];
gyroSamples++;
}
void mpu6050_Get_gyro()
{
if(gyroSamples == 0){
gyroSamples = 1;
}
GyroX = (gyroSum[XAXIS] / gyroSamples)*gyroScaleFactor - gyro_offsetX;// Calculate average
GyroY = (gyroSum[YAXIS] / gyroSamples)*gyroScaleFactor - gyro_offsetY;
GyroZ = (gyroSum[ZAXIS] / gyroSamples)*gyroScaleFactor - gyro_offsetZ;
gyroSum[XAXIS] = 0.0;// Reset SUM variables
gyroSum[YAXIS] = 0.0;
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
51
gyroSum[ZAXIS] = 0.0;
gyroSamples2 = gyroSamples;
gyroSamples = 0;
}
void mpu6050_readAccelSum() {
mpu6050_Accel_Values();
accelSum[XAXIS] += AccXm;
accelSum[YAXIS] += AccYm;
accelSum[ZAXIS] += AccZm;
accSamples++;
}
void mpu6050_Get_accel()
{
if(accSamples == 0){
accSamples = 1;
}
AccX = (accelSum[XAXIS] / accSamples)*accelScaleFactor - acc_offsetX;// Calculate average
AccY = (accelSum[YAXIS] / accSamples)*accelScaleFactor - acc_offsetY;
AccZ = (accelSum[ZAXIS] / accSamples)*accelScaleFactor;// Apply correct scaling (at this point accel reprensents
+- 1g = 9.81 m/s^2)
accelSum[XAXIS] = 0.0;
// Reset SUM variables
accelSum[YAXIS] = 0.0;
accelSum[ZAXIS] = 0.0;
accSamples = 0;
}
void sensor_Calibrate()
{
Serial.print("Sensor_Calibrate");Serial.println("\t");
gyroSum[XAXIS] = 0.0;// Reset SUM variables
gyroSum[YAXIS] = 0.0;
gyroSum[ZAXIS] = 0.0;
gyroSamples = 0;
accelSum[XAXIS] = 0.0;
// Reset SUM variables
accelSum[YAXIS] = 0.0;
accelSum[ZAXIS] = 0.0;
for (uint8_t i=0; i<45; i++) //Collect 60, 100 samples
{
Serial.print("- ");
mpu6050_readGyroSum();
mpu6050_readAccelSum();
Mag5883Read();
digitalWrite(13, HIGH);
digitalWrite(Pin_LED_R, HIGH);
delay(20);
digitalWrite(13, LOW);
digitalWrite(Pin_LED_R, LOW);
delay(20);
}
Serial.println("- ");
gyro_offsetX = (gyroSum[XAXIS]/gyroSamples)*gyroScaleFactor;
gyro_offsetY = (gyroSum[YAXIS]/gyroSamples)*gyroScaleFactor;
gyro_offsetZ = (gyroSum[ZAXIS]/gyroSamples)*gyroScaleFactor;
acc_offsetX = (accelSum[XAXIS]/gyroSamples)*accelScaleFactor;
acc_offsetY = (accelSum[YAXIS]/gyroSamples)*accelScaleFactor;
acc_offsetZ = (accelSum[ZAXIS]/gyroSamples)*accelScaleFactor;
acc_offsetZ2 = sqrt(acc_offsetX*acc_offsetX + acc_offsetY*acc_offsetY + acc_offsetZ*acc_offsetZ);
AccZf = acc_offsetZ;//15.4
MagXf = MagX1;
MagYf = MagY1;
MagZf = MagZ1;
gyroSamples = 0;
accSamples = 0;
Serial.print("GYRO_Calibrate");Serial.print("\t");
Serial.print(gyro_offsetX);Serial.print("\t");//-0.13
Serial.print(gyro_offsetY);Serial.print("\t");//-0.10
Serial.print(gyro_offsetZ);Serial.println("\t");//0.03
Serial.print("ACC_Calibrate");Serial.print("\t");
Serial.print(acc_offsetX);Serial.print("\t");
Serial.print(acc_offsetY);Serial.print("\t");
Serial.print(acc_offsetZ);Serial.print("\t");
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
52
Serial.print(acc_offsetZ2);Serial.println("\t");
acc_offsetX = 0.18;//-0.18 0.11 -0.36
Trim PITCH CONTROL
acc_offsetY = 0.12;//0.16 -0.14 0.18 Trim ROLL CONTROL
-10.07
-10.55
10.39 9.74
11
-9.82
//acc_offsetZ = 0.0;//0.245 0.235 10.2
}
/* ******************************************************************
***
Accelerometers trim
Remote Trim By tinnakon
***
//With the help of your roll and pitch stick you could now trim the ACC mode.
//You must first put the throttle stick in maximal position. (obviously with motors disarmed)
//full PITCH forward/backward and full ROLL left/right (2 axis possibilities) will trim the level
//mode according to the neutral angle you want to change.
//The status LED will blink to confirm each ticks.
*/
void Remote_TrimACC() {
if(CH_THR > MAXCHECK && armed == 0)
{
////Trim ROLL CONTROL/////////////
if(CH_AIL > MAXCHECK)
{
acc_offsetY = acc_offsetY + 0.04;
for (int i = 0; i < 5; i++)
{
digitalWrite(13, HIGH);
delay(20);
digitalWrite(13, LOW);
delay(20);
}
Serial.println(acc_offsetY);
}
if(CH_AIL < MINCHECK)
{
acc_offsetY = acc_offsetY - 0.04;
for (int i = 0; i < 5; i++)
{
digitalWrite(13, HIGH);
delay(20);
digitalWrite(13, LOW);
delay(20);
}
Serial.println(acc_offsetY);
}
///////Trim PITCH CONTROL//////////////////////
if(CH_ELE > MAXCHECK)
{
acc_offsetX = acc_offsetX + 0.04;
for(int i = 0; i < 5; i++)
{
digitalWrite(13, HIGH);
delay(20);
digitalWrite(13, LOW);
delay(20);
}
Serial.println(acc_offsetX);
}
if(CH_ELE < MINCHECK)
{
acc_offsetX = acc_offsetX - 0.04;
for(int i = 0; i < 5; i++)
{
digitalWrite(13, HIGH);
delay(20);
digitalWrite(13, LOW);
delay(20);
}
Serial.println(acc_offsetX);
}
}//end CH_THR > MAXCHECK && armed == 0
}///////////////////////////////////////////////////////
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
53
10. ไฟล์ multi_rx_sam3x8e.h
/*
project_Quad 32 bit Arduino Due
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
//clock timer7
(1000 - 2000 us) = (2625 - 5250) = 2625
*/
float CH_THR = 1000.0;
float CH_AIL = 1500.0;
float CH_ELE = 1500.0;
float CH_RUD = 1500.0;
float AUX_1 = 1000.0;
float AUX_2 = 1000.0;
float AUX_3 = 1000.0;
float AUX_4 = 1000.0;
float CH_THRf = 1000.0;
float CH_AILf = 1500.0;
float CH_ELEf = 1500.0;
float CH_RUDf = 1500.0;
int CH_AIL_Cal = 1500;
int CH_ELE_Cal = 1500;
int CH_RUD_Cal = 1500;
//RX PIN assignment inside the port
//SET YOUR PINS! TO MATCH RECIEVER CHANNELS
#define CHAN1PIN 62 // RECIEVER 1 PPM ,pin A8
//#define CHAN2PIN 63 // RECIEVER 2
//#define CHAN3PIN 64 // RECIEVER 3
//#define CHAN4PIN 65 // RECIEVER 4
//#define CHAN5PIN 61 // RECIEVER 5
//#define CHAN6PIN 67 //not used at the moment
//#define CHAN7PIN 50 //not used at the moment
//#define CHAN8PIN 51 //not used at the moment
#define ROLL
0
#define PITCH
1
#define YAW
3
#define THROTTLE
2
#define AUX1
4
#define AUX2
5
#define CAMPITCH
6
#define CAMROLL
7
//volatile unsigned long pwmLast[8];
volatile unsigned long last = 0;
uint8_t chan1 = 0;
volatile uint32_t rcValue[8] = {3937, 3937, 3937, 3937, 3937, 3937, 3937, 3937}; // interval [1000;2000]
void pwmHandler(int ch, int pin) {
///PPM/////////////////// Arduino Due RX PPM
uint32_t now, diff;
//now = micros();
diff = TC_ReadCV(TC2, 1);// Read TC2 = timer 7
TC_Stop(TC2, 1);
TC_Start(TC2, 1);
//last = now;
if (diff > 7875) chan1 = 0;//3000 us
else {
if (2363 < diff && diff < 5775 && chan1 < 8) { //900 - 2200 us
rcValue[chan1] = diff;
}
chan1++;
}
}
void ch1Handler() {
pwmHandler(0, CHAN1PIN);
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
54
}
//void ch2Handler() { pwmHandler(1, CHAN2PIN); }
//void ch3Handler() { pwmHandler(2, CHAN3PIN); }
//void ch4Handler() { pwmHandler(3, CHAN4PIN); }
//void ch5Handler() { pwmHandler(4, CHAN5PIN); }
void configureReceiver() {
Serial.print("Configure Receiver CPPM");Serial.print("\n");
for (uint8_t chan = 0; chan < 8; chan++) {
for (uint8_t a = 0; a < 4; a++) {
rcValue[a] = 3937;//1500 = 3937.5
}
}
rcValue[THROTTLE] = 2625;//2625 = 1000 us
rcValue[AUX1] = 2625;
rcValue[AUX2] = 2625;
rcValue[CAMPITCH] = 2625;
rcValue[CAMROLL] = 2625;
attachInterrupt(CHAN1PIN, ch1Handler, RISING); //RISING
FALLING CHANGE
//attachInterrupt(CHAN2PIN,ch2Handler,CHANGE);
//attachInterrupt(CHAN3PIN,ch3Handler,CHANGE);
//attachInterrupt(CHAN4PIN,ch4Handler,CHANGE);
//attachInterrupt(CHAN5PIN,ch5Handler,CHANGE);
/* turn on the timer clock in the power management controller */
pmc_set_writeprotect(false);
// disable write protection for pmc registers
pmc_enable_periph_clk(ID_TC7); // enable peripheral clock TC7
//TC_CMR_TCCLKS_TIMER_CLOCK1 84Mhz/2 = 42.000 MHz
//TC_CMR_TCCLKS_TIMER_CLOCK2 84Mhz/8 = 10.500 MHz
//TC_CMR_TCCLKS_TIMER_CLOCK3 84Mhz/32 = 2.625 MHz
//TC_CMR_TCCLKS_TIMER_CLOCK4
84Mhz/128 = 656.250 KHz
/* we want wavesel 01 with RC (timer 7 = TC2,1) (timer 8 = TC2,2)*/
TC_Configure(/* clock */TC2,/* channel */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC |
TC_CMR_TCCLKS_TIMER_CLOCK3);//TC_CMR_TCCLKS_TIMER_CLOCK3
//TC_SetRC(TC2, 1, 131200);
TC_Start(TC2, 1);
}
void computeRC() {
CH_THR = rcValue[THROTTLE]*0.3809523;// 84MHz/32 * 1500 us = 3937.5
CH_AIL = rcValue[ROLL]*0.3809523;
CH_ELE = rcValue[PITCH]*0.3809523;
CH_RUD = rcValue[YAW]*0.3809523;
AUX_1 = rcValue[AUX1]*0.3809523;
AUX_2 = rcValue[AUX2]*0.3809523;
AUX_3 = rcValue[CAMPITCH]*0.3809523;
AUX_4 = rcValue[CAMROLL]*0.3809523;
CH_THRf = CH_THRf + (CH_THR - CH_THRf) * 0.02 / tarremote; //Low pass filter
CH_AILf = CH_AILf + (CH_AIL - CH_AILf) * 0.02 / tarremote; //Low pass filter
CH_ELEf = CH_ELEf + (CH_ELE - CH_ELEf) * 0.02 / tarremote;
CH_RUDf = CH_RUDf + (CH_RUD - CH_RUDf) * 0.02 / tarremote;
}
void RC_Calibrate() {
Serial.print("RC_Calibrate"); Serial.println("\t");
//By tinnakon
for (int i = 0; i < 10; i++) {
computeRC();
delay(20);
}
CH_AIL_Cal = CH_AIL;
CH_ELE_Cal = CH_ELE;
CH_RUD_Cal = CH_RUD;
Serial.print(CH_AIL_Cal); Serial.print("\t"); //1505
Serial.print(CH_ELE_Cal); Serial.print("\t"); //1498
Serial.print(CH_RUD_Cal); Serial.println("\t"); //1502
}
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
55
11. ไฟล์ GPSNEO6N_multi.h
/*
project_Quad 32 bit Arduino Due
//GPS I2C_GPS_NAV_v2_2
1. stabilized quadrotor
by: tinnakon kheowree
0860540582
tinnakon_za@hotmail.com
tinnakonza@gmail.com
http://quad3d-tin.lnwshop.com/
https://www.facebook.com/tinnakonza
UBLOX
tree
- U-Blox binary protocol, use the ublox config file (u-blox-config.ublox.txt) from the source
*/
int32_t GPS_coord[2];// 1e-7 degrees / position as degrees (*10E7)
float GPS_ground_course = 0.0;
// velocities in cm/s if available from the GPS
int32_t _velocity_north;
int32_t _velocity_east;
int32_t _vel_down;
int LAT=0;
int LON=1;
uint8_t GPS_FIX=0;
int GPS_numSat=0;
int GPS_altitude=0;
int GPS_Present=0;
float Alt_Home = 2;//m
float yaw = 0.0;
float pitch = 0.0;
float Distance = 0.0;
#define ToRad 0.01745329252
// *pi/180
#define ToDeg 57.2957795131
// *180/pi
//prog_char
prog_char UBLOX_INIT[] PROGMEM = { // PROGMEM array must be outside any function !!!
0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x05,0x00,0xFF,0x19,
//disable all default NMEA messages
0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x03,0x00,0xFD,0x15, //0x06 Configuration Input Messages: Set Dynamic Model,
Set DOP Mask, Set Baud Rate, etc.
0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x01,0x00,0xFB,0x11,
0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x00,0x00,0xFA,0x0F,
0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x02,0x00,0xFC,0x13,
0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x04,0x00,0xFE,0x17,
0xB5,0x62,0x06,0x01,0x03,0x00,0x01,0x02,0x01,0x0E,0x47,
//set POSLLH MSG rate
0xB5,0x62,0x06,0x01,0x03,0x00,0x01,0x03,0x01,0x0F,0x49,
//set STATUS MSG rate
0xB5,0x62,0x06,0x01,0x03,0x00,0x01,0x06,0x01,0x12,0x4F,
//set SOL MSG rate
0xB5,0x62,0x06,0x01,0x03,0x00,0x01,0x12,0x01,0x1E,0x67,
//set VELNED MSG rate
0xB5,0x62,0x06,0x16,0x08,0x00,0x03,0x07,0x03,0x00,0x51,0x08,0x00,0x00,0x8A,0x41,
0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A
//set WAAS to EGNOS
// set rate to 5Hz
};
//http://www.multiwii.com/forum/viewtopic.php?f=6&t=4964
//0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xC8, 0x00, 0x01, 0x00, 0x01, 0x00, 0xDE, 0x6A //set rate to 5Hz
//#define UBLOX_1HZ
0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39
// set rate to
0xB5,0x62,0x06,0x08,0x06,0x00,0xF4,0x01,0x01,0x00,0x01,0x00,0x0B,0x77
// set rate
0xB5,0x62,0x06,0x08,0x06,0x00,0x4D,0x01,0x01,0x00,0x01,0x00,0x64,0x8D
// set rate to
0xB5,0x62,0x06,0x08,0x06,0x00,0xFA,0x00,0x01,0x00,0x01,0x00,0x10,0x96
// set rate
0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A
// set rate to
1Hz
// #define UBLOX_2HZ
to 2Hz
//#define UBLOX_3HZ
3Hz
// #define UBLOX_4HZ
to 4Hz
//#define UBLOX_5HZ
5Hz
#define UBLOX_SET_BINARY "$PUBX,41,1,0003,0001,38400,0*26\n\265\142\006\001\003\000\001\006\001\022\117"
void GPS_multiInt()
{
Serial.print("GPS_multiInt 9600 to 38400");Serial.print("\n");
Serial2.begin(9600);//GPS2 38400
//GPS UBLOX switch UART speed for sending SET BAUDRATE command (NMEA mode)
// (which depends on the NMEA or MTK_BINARYxx settings)
delay(200);
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
56
Serial2.print("$PUBX,41,1,0003,0001,38400,0*26\r\n");
//Serial2.print("$PUBX,41,1,0003,0001,115200,0*1E\r\n");
//delay(10);
//Serial1.print("$PUBX,41,1,0003,0001,38400,0*26\r\n");
//Serial2.print("$PUBX,41,1,0003,0001,115200,0*1E\r\n");
delay(200);
Serial2.begin(38400);
delay(20);
for(uint8_t i=0; i<sizeof(UBLOX_INIT); i++) {
// send configuration data in UBX protocol
Serial2.write(pgm_read_byte(UBLOX_INIT+i));
delay(5); //simulating a 38400baud pace (or less), otherwise commands are not accepted by the device.
}
Serial.print("End");Serial.print("\n");
}
struct ubx_header {
uint8_t preamble1;
uint8_t preamble2;
uint8_t msg_class;
uint8_t msg_id;
uint16_t length;
};
struct ubx_nav_posllh {
uint32_t time;
// GPS msToW
int32_t longitude;
int32_t latitude;
int32_t altitude_ellipsoid;
int32_t altitude_msl;
uint32_t horizontal_accuracy;
uint32_t vertical_accuracy;
};
struct ubx_nav_solution {
uint32_t time;
int32_t time_nsec;
int16_t week;
uint8_t fix_type;
uint8_t fix_status;
int32_t ecef_x;
int32_t ecef_y;
int32_t ecef_z;
uint32_t position_accuracy_3d;
int32_t ecef_x_velocity;
int32_t ecef_y_velocity;
int32_t ecef_z_velocity;
uint32_t speed_accuracy;
uint16_t position_DOP;
uint8_t res;
uint8_t satellites;
uint32_t res2;
};
struct ubx_nav_velned {
uint32_t time;
// GPS msToW
int32_t ned_north;
int32_t ned_east;
int32_t ned_down;
uint32_t speed_3d;
uint32_t speed_2d;
int32_t heading_2d;
uint32_t speed_accuracy;
uint32_t heading_accuracy;
};
enum ubs_protocol_bytes {
PREAMBLE1 = 0xb5,
PREAMBLE2 = 0x62,
CLASS_NAV = 0x01,
CLASS_ACK = 0x05,
CLASS_CFG = 0x06,
MSG_ACK_NACK = 0x00,
MSG_ACK_ACK = 0x01,
MSG_POSLLH = 0x2,
MSG_STATUS = 0x3,
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
57
MSG_SOL = 0x6,
MSG_VELNED = 0x12,
MSG_CFG_PRT = 0x00,
MSG_CFG_RATE = 0x08,
MSG_CFG_SET_RATE = 0x01,
MSG_CFG_NAV_SETTINGS = 0x24
};
enum ubs_nav_fix_type {
FIX_NONE = 0,
FIX_DEAD_RECKONING = 1,
FIX_2D = 2,
FIX_3D = 3,
FIX_GPS_DEAD_RECKONING = 4,
FIX_TIME = 5
};
enum ubx_nav_status_bits {
NAV_STATUS_FIX_VALID = 1
};
// Packet checksum accumulators
static uint8_t _ck_a;
static uint8_t _ck_b;
// State machine state
static uint8_t _step;
static uint8_t _msg_id;
static uint16_t _payload_length;
static uint16_t _payload_counter;
//
static bool next_fix;
static uint8_t _class;
static uint8_t _fix_ok;
// Receive buffer
static union {
ubx_nav_posllh posllh;
//
ubx_nav_status status;
ubx_nav_solution solution;
ubx_nav_velned velned;
uint8_t bytes[];
} _buffer;
bool UBLOX_parse_gps(void) {
GPS_Present = 1;
switch (_msg_id) {
case MSG_POSLLH:
//i2c_dataset.time
= _buffer.posllh.time;
if(_fix_ok) {
GPS_coord[LON] = _buffer.posllh.longitude;
GPS_coord[LAT] = _buffer.posllh.latitude;
GPS_altitude
= _buffer.posllh.altitude_msl / 1000;
//alt in m
}
GPS_FIX = _fix_ok;
return true;
// POSLLH message received, allow blink GUI icon and LED
break;
case MSG_SOL:
_fix_ok = 0;
if((_buffer.solution.fix_status & NAV_STATUS_FIX_VALID) && (_buffer.solution.fix_type == FIX_3D ||
_buffer.solution.fix_type == FIX_2D)) _fix_ok = 1;
GPS_numSat = _buffer.solution.satellites;
break;
case MSG_VELNED:
GPS_speed
= _buffer.velned.speed_2d;
// cm/s
GPS_ground_course = (_buffer.velned.heading_2d / 100000.0); // (uint16_t) Heading 2D deg * 100000 rescaled to
deg * 10
_velocity_north
= _buffer.velned.ned_north;
_velocity_east
= _buffer.velned.ned_east;
_vel_down
= _buffer.velned.ned_down * -1;
break;
default:
break;
}
return false;
}
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
58
bool GPS_UBLOX_newFrame(uint8_t data){
bool parsed = false;
GPS_Present = 0;
switch(_step) {
case 1:
if (PREAMBLE2 == data) {
_step++;
break;
}
_step = 0;
case 0:
if(PREAMBLE1 == data) _step++;
break;
case 2:
_step++;
_class = data;
_ck_b = _ck_a = data;
// reset the checksum accumulators
break;
case 3:
_step++;
_ck_b += (_ck_a += data);
// checksum byte
_msg_id = data;
break;
case 4:
_step++;
_ck_b += (_ck_a += data);
_payload_length = data;
// checksum byte
// payload length low byte
break;
case 5:
_step++;
_ck_b += (_ck_a += data);
// checksum byte
_payload_length += (uint16_t)(data<<8);
if (_payload_length > 512) {
_payload_length = 0;
_step = 0;
}
_payload_counter = 0;
// prepare to receive payload
break;
case 6:
_ck_b += (_ck_a += data);
// checksum byte
if (_payload_counter < sizeof(_buffer)) {
_buffer.bytes[_payload_counter] = data;
}
if (++_payload_counter == _payload_length)
_step++;
break;
case 7:
_step++;
if (_ck_a != data) _step = 0;
// bad checksum
break;
case 8:
_step = 0;
if (_ck_b != data)
break;
// bad checksum
GPS_Present = 1;
if (UBLOX_parse_gps()) { parsed = true;}
} //end switch
return parsed;
}
12. ไฟล์ AP_Baro_MS5611.cpp
13. ไฟล์ AP_Baro_MS5611.h
14. ไฟล์ SPI_sam.cpp
15. ไฟล์ SPI_sam.h
16. ไฟล์ Wire_due32.cpp
17. ไฟล์ Wire_due32.h
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
59
เอกสารอ้างอิง
1. น.ต.วัชรพงษ์ เข็มเพ็ชร Optical flow-based
http://www.dae.mi.th/aeroblog/?p=2796
2. น.ต.ดร. กฤษฎา แสงเพ็ชร์ส่อง Kalman Filter แนวคิดพื้นฐานและหลักการทางานของ Kalman
Filter Algorithm http://library.rtna.ac.th/web/RTNA_Journal/y.4c.4/05.pdf
3. DIY mini Quad Copter Chiang Mai Maker Club
http://www.cmmakerclub.com/2014/11/667
4. Quadcopter Parts List | What You Need to Build a DIY Quadcopter
http://quadcoptergarage.com/quadcopter-parts-list-what-you-need-to-build-adiy-quadcopter/
5. MultiWii http://www.multiwii.com/ http://witespyquad.gostorego.com/
6. AeroQuad http://aeroquad.com/content.php
7. MegaPirateNG https://github.com/MegaPirateNG/ardupilot-mpng
8. APM Open source autopilot http://planner.ardupilot.com/
http://ardupilot.com/
9. OpenPilot CC3D http://www.openpilot.org/
10. UAVX-ARM32 Full Sensors http://www.quadroufo.com/
11. AutoQuad is an Open Source firmware project http://autoquad.org/
12. ศึกษาการเขียนโปรแกรมควบคุม quadrotor http://www.rcthai.net/
13. ทินกร เขียวรี การเขียนโปรแกรม Quadrotor พื้นฐาน http://quad3d-tin.lnwshop.com
https://github.com/QuadTinnakon/QuadX_2560GY86_PIDAuto_V5
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
60
ประวัติผู้จัดทา
ชื่อ
สาขาวิชา
: นายทินกร เขียวรี
: วิศวกรรมเครื่องกล
สถานที่อยู่ที่ติดต่อได้สะดวก สาขาวิชาวิศวกรรมเครื่องกล คณะวิศวกรรมศาสตร์และสถาปัตยกรรมศาสตร์มหาวิทยาลัยเทคโนโลยีราชมงคล
สุวรรณภูมิ ศูนย์นนทบุรี เลขที่ 7/1 ถ.นนทบุรี ต.สวนใหญ่ อ.เมือง จ.นนทบุรี 11000 โทรศัพท์ 086-0540582
e-mail
tinnakon_za@hotmail.com หรือ tinnakonza@gmail.com , เว็บไซต์ http://quad3d-tin.lnwshop.com/ ,
https://www.facebook.com/tinnakonza อัพเดทล่าสุด 8 มกราคม 2558
ประวัติ
ประวัติส่วนตัว เกิดเมื่อวันที่ 3 มกราคม 2530 บ้านเลขที่ 28/5 หมู่ 6 ตาบล พักทัน อาเภอ
บางระจัน จังหวัดสิงห์บุรี 16130
ประวัติการศึกษา สาเร็จการศึกษามัธยมศึกษาตอนต้นและตอนปลายจาก โรงเรียนศรีศักดิ์สุวรรณ
วิทยา จังหวัดสิงห์บุรี ปีการศึกษา 2544 - 2547 สาเร็จการศึกษาระดับประกาศนียบัตรวิชาชีพชั้นสูง
สาขาช่างยนต์ จากมหาวิทยาลัยเทคโนโลยีราชมงคลสุวรรณภูมิ ศูนย์หันตรา
จังหวัด
พระนครศรีอยุธยา ปีการศึกษา 25 49 และสาเร็จการศึกษาระดับวิศวกรรมศาสตรบัณฑิต สาขาวิชา
วิศวกรรมเครื่องกล คณะวิศวกรรมศาสตร์และสถาปัตยกรรมศาสตร์ ณ มหาวิทยาลัยเทคโนโลยีราช
มงคลสุวรรณภูมิ ศูนย์นนทบุรี ปีการศึกษา 25 53 และสาเร็จการศึกษาระดับวิศวกรรมศาสตร
มหาบัณฑิต สาขา วิชาวิศวกรรมเครื่องกล คณะวิศวกรรมศาสตร์ มหาวิทยาลัยเทคโนโลยีพระจอม
เกล้าพระนครเหนือ ปีการศึกษา 2555
ประวัติการทางาน ปี พ.ศ. 2552 - 2553 เป็นวิศวกรด้านการจัดการพลังงาน และวิทยากรงาน
สัมมนาโครงการอนุรักษ์พลังงานแบบมีส่วนร่วม ปี พ.ศ. 2554 – 2555 ทางานเป็นผู้ช่วยวิจัย
มหาวิทยาลัยเทคโนโลยีพระจอมเกล้าพระนครเหนือ ปี พ.ศ. 2556 – ปัจจุบันทางานตาแหน่งอาจารย์
สอนวิชาการควบคุมอัตโนมัติ สาขาวิศวกรรมเครื่องกล คณะวิศวกรรมศาสตร์ และสถาปัตยกรรม
ศาสตร์ มหาวิทยาลัยเทคโนโลยีราชมงคลสุวรรณภูมิ ศูนย์นนทบุรี
ประวัติงานวิจัย การควบคุมแบบชดเชยแรงเสียดทานสาหรับฐานเคลื่อนไหวที่ขับเคลื่อนด้วย
ระบบไฮดรอลิกส์. การประชุมวิชาการเครือข่ายวิศวกรรมเครื่องกลแห่งประเทศไทย ครั้งที่ 25 จังหวัด
กระบี่ วันที่ 19 - 21 ตุลาคม 2554 การค้นคว้าและศึกษาตัวสังเกตแบบไม่เชิงเส้นของระบบพลวัต
เชิงกล โดยประมาณค่าแรงเสียดทานที่เกิดขึ้นในกระบอกสูบไฮดรอลิกส์ นาไปใช้ชดเชยการควบคุมไม่
เชิงเส้นโดยใช้วิธีการควบคุมแบบขั้นถอยหลัง (Backstepping Control) และการควบคุมแบบปรับตัว
เองได้ (Adaptive Control) และ ปี 2557 ได้รับทุนงบประมาณเงินกองทุนส่งเสริมงานวิจัยเรื่องการ
ควบคุมความสูงระดับเพดานบินโดยใช้ตัวควบคุมแบบปรับตัวเองได้ร่วมกับตัวสังเกตคาลมานสาหรับ
เครื่องบิน 4 ใบพัดขนาดเล็ก
โดยนายทินกร เขียวรี http://quad3d-tin.lnwshop.com/ tinnakonza@gmail.com T.086-054-0582
Download