20181123

Dependencies:   mbed MX28 PID

Files at this revision

API Documentation at this revision

Comitter:
nylon0212
Date:
Fri Nov 23 04:43:52 2018 +0000
Parent:
5:131450b16ce3
Commit message:
20181123

Changed in this revision

LSM9DS1.cpp Show annotated file Show diff for this revision Revisions of this file
PID.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 131450b16ce3 -r f1c0b9476c88 LSM9DS1.cpp
--- a/LSM9DS1.cpp	Fri Aug 31 01:41:04 2018 +0000
+++ b/LSM9DS1.cpp	Fri Nov 23 04:43:52 2018 +0000
@@ -47,18 +47,18 @@
     
     // Gyro initialization stuff:
     initGyro(); // This will "turn on" the gyro. Setting up interrupts, etc.
-    setGyroODR(gODR); // Set the gyro output data rate and bandwidth.
-    setGyroScale(gScale); // Set the gyro range
+//    setGyroODR(gODR); // Set the gyro output data rate and bandwidth.
+//    setGyroScale(gScale); // Set the gyro range
     
     // Accelerometer initialization stuff:
     initAccel(); // "Turn on" all axes of the accel. Set up interrupts, etc.
-    setAccelODR(aODR); // Set the accel data rate.
-    setAccelScale(aScale); // Set the accel range.
+//    setAccelODR(aODR); // Set the accel data rate.
+//    setAccelScale(aScale); // Set the accel range.
     
     // Magnetometer initialization stuff:
     initMag(); // "Turn on" all axes of the mag. Set up interrupts, etc.
-    setMagODR(mODR); // Set the magnetometer output data rate.
-    setMagScale(mScale); // Set the magnetometer's range.
+//    setMagODR(mODR); // Set the magnetometer output data rate.
+//    setMagScale(mScale); // Set the magnetometer's range.
     
     // Once everything is initialized, return the WHO_AM_I registers we read:
     return (xgTest << 8) | mTest;
@@ -114,7 +114,7 @@
     // Write the address we are going to read from and don't end the transaction
     i2c.write(xgAddress, &subAddress, 1, true);
     // Read in all 8 bit registers containing the axes data
-    i2c.read(xgAddress, data, 6);
+    i2c.read(xgAddress, data, 6, false);
 
     // Reassemble the data and convert to g
     ax_raw = data[0] | (data[1] << 8);
@@ -365,7 +365,7 @@
     switch (aScale)
     {
         case A_SCALE_2G:
-            aRes = 2.0 / 32768.0;
+            aRes = 0.061e-3;
             break;
         case A_SCALE_4G:
             aRes = 4.0 / 32768.0;
diff -r 131450b16ce3 -r f1c0b9476c88 PID.lib
--- a/PID.lib	Fri Aug 31 01:41:04 2018 +0000
+++ b/PID.lib	Fri Nov 23 04:43:52 2018 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/teams/LDSC_Robotics_TAs/code/PID/#4df4895863cd
+https://os.mbed.com/users/nylon0212/code/PID/#d2c5f7d65d0d
diff -r 131450b16ce3 -r f1c0b9476c88 main.cpp
--- a/main.cpp	Fri Aug 31 01:41:04 2018 +0000
+++ b/main.cpp	Fri Nov 23 04:43:52 2018 +0000
@@ -1,7 +1,8 @@
-#include "mbed.h"
+#include "mbed.h"       //不用gyro的data,只要輸出兩個imu的acce的xyz資料即可
 #include "encoder.h"
 #include "Mx28.h"
 #include "PID.h"
+#include "LSM9DS1.h"
 
 //********************* Dynamxiel ******************************
 #define SERVO_ID 0x01               // ID of which we will set Dynamixel too 
@@ -12,32 +13,6 @@
 #define CW_LIMIT_ANGLE 1        // lowest clockwise angle is 1, as when set to 0 it set servo to wheel mode
 #define CCW_LIMIT_ANGLE 4095       // Highest anit-clockwise angle is 0XFFF, as when set to 0 it set servo to wheel mode
 #define PI 3.14159265f
-//***************************************************************
-
-Serial uart(USBTX, USBRX);
-//Serial uart(D10,D2);            // TX : D10     RX : D2           // blueteeth
-DigitalOut LED(A4);            // check if the code is running
-DigitalOut led2(A5);            // check if the code is running interrupt
-uint8_t led2f;
-
-// Timer
-Ticker timer1;
-float ITR_time1 = 4000.0;  // unit:us
-float Ts = ITR_time1/1000000;
-uint8_t flag;
-
-// uart_tx
-union splitter {
-    short j;
-    char C[2];
-    // C[0] is lowbyte of j, C[1] is highbyte of j
-};
-char T[16] = {255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-int i = 0;
-
-// PID
-PID motor_pid(1500, 0, 40, Ts);// 6.4 0.13   7.2 0.13     8.4       6.5, 0, 0.19
-float PIDout = 0.0f;
 
 // Dynamixel
 DynamixelClass dynamixelClass(SERVO_SET_Baudrate,SERVO_ControlPin,TxPin,RxPin);
@@ -53,7 +28,7 @@
 float torque_measured = 0.0;
 float ks = 2.6393*2;  //spring constant
 //int angle_dif = 0;
-float torque_ref = 0.0;
+float torque_ref = 0.0; //可不令為0,而是以范僑芯的學習結果為input。令為0可使馬達扭力輸出為0,抵抗減速機摩擦力,使穿戴者感到跟沒有戴一樣。
 //float friction = 0.0f;
 float friction = 0.18f;
 float rate = 0.5;
@@ -61,17 +36,61 @@
 //float check = 0.0f;
 float Angle_Dif;
 short rotation_;
+//***************************************************************
+
+Serial uart(USBTX, USBRX);
+//Serial uart(D10,D2);            // TX : D10     RX : D2           // bluetooth
+AnalogIn EMG(PC_4);            //
+DigitalOut LED(A4);            // check if the code is running
+DigitalOut led2(A5);            // check if the code is running interrupt
+uint8_t led2f;
+/*IMU*******************************************************************/
+LSM9DS1 imu(D14, D15);    //SDA SCL
+LSM9DS1 imu2(PC_9,PA_8);   //SDA SCL
+void init_IMU();
+int16_t Gyro_axis_data[6] = {0};     // X, Y, Z axis
+int16_t Acce_axis_data[6] = {0};     // X, Y, Z axis
+float Acce_axis_data_f[6] = {0};     //_f代表經過低通濾波的資料
+float Acce_axis_data_f_old[6] = {0};
+float Gyro_axis_data_f[6] = {0};
+float Gyro_axis_data_f_old[6] = {0};
+
+// Timer
+Ticker timer1;
+float ITR_time1 = 4000.0;  //timer interrupt unit:us  多少us計時一次 4毫秒
+float Ts = ITR_time1/1000000;    //控馬達的某個時間參數 不用理他
+
+// PID
+PID motor_pid(1500, 0, 40, Ts);// 6.4 0.13   7.2 0.13     8.4       6.5, 0, 0.19
+float PIDout = 0.0f;
+
+// EMG
+float lpf(float input, float output_old, float frequency);  //low pass filter
+float emg_value;
+float emg_value_f;
+float emg_value_f_old;
+float Tf = ITR_time1/1000000;     // 低通濾波的採樣週期
+
+// uart_tx
+union splitter {   //將data切割為兩個byte
+    short j;
+    char C[2];
+    // C[0] is lowbyte of j, C[1] is highbyte of j
+};
+uint8_t T[40] = {255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+// T[16]中的16是2+14,2為start btye 255 255,14為要傳7個參數到電腦,拆成high byte和low byte,所以是7*2=14
+// 若要更改傳到電腦的參數個數,則改x*2=y,x為要傳的參數個數,y為char T[]裡面要有多少個0
+int i = 0;
 
 // function
 void init_UART();
+void uart_tx(); // 傳data到電腦
 void init_TIMER();
 void timer1_ITR();
-void uart_tx();
-
 void init_DYNAMIXEL();
 void D_angle_measure();
 void find_torque();
-
+/**************************************************************************/
 int main()
 {
     LED = 1; // darken
@@ -79,27 +98,73 @@
     // initial sensor
     init_SPI_encoder();
     init_encoder();
+    init_UART();
     init_DYNAMIXEL();
-    // initial uart
-    init_UART();
-
-    wait_ms(500);
-
-    led2 = 1;
-//    led2f = 0;
-    LED = 0; // lighten
-
+    init_IMU();
     init_TIMER();
 
     while(1) {
+        // EMG
+        //emg_value = EMG.read();
+//    emg_value_f = lpf(emg_value,emg_value_f_old,15);
+//    emg_value_f_old = emg_value_f;
 
+        // IMU
+      imu.readAccel();
+      imu.readGyro();
+      imu2.readAccel();
+      imu2.readGyro();
+
+        Acce_axis_data[0] = imu.ax*Acce_gain_x;
+        Acce_axis_data[1] = imu.ay*Acce_gain_y;
+        Acce_axis_data[2] = imu.az*Acce_gain_z;
+        Acce_axis_data[3] = -imu2.ax*Acce_gain_x_2;
+        Acce_axis_data[4] = imu2.az*Acce_gain_y_2;
+        Acce_axis_data[5] = imu2.ay*Acce_gain_z_2;
+
+        Gyro_axis_data[0] = imu.gx*Gyro_gain_x;
+        Gyro_axis_data[1] = imu.gy*Gyro_gain_y;
+        Gyro_axis_data[2] = imu.gz*Gyro_gain_z;
+        Gyro_axis_data[3] = -imu2.gx*Gyro_gain_x_2;
+        Gyro_axis_data[4] = imu2.gz*Gyro_gain_y_2;
+        Gyro_axis_data[5] = imu2.gy*Gyro_gain_z_2;
+
+    for(i=0; i<6; i++) {
+        Acce_axis_data_f[i] = lpf(Acce_axis_data[i],Acce_axis_data_f_old[i],15);
+        Acce_axis_data_f_old[i] = Acce_axis_data_f[i];
+        Gyro_axis_data_f[i] = lpf(Gyro_axis_data[i],Gyro_axis_data_f_old[i],15);
+        Gyro_axis_data_f_old[i] = Gyro_axis_data_f[i];
     }
+//        int16_t shit2 = imu.ax_raw;
+//        uart.printf("%d\n\r", shit2);
+//    uart.printf("x: %.4f, y: %.4f, z: %.4f\n\r", imu.ax, imu.ay, imu.az);
+    uart_tx();
+    init_TIMER();
+    while(1) {}
+
+//        wait_ms(500);
+    }
+}
+
+void init_IMU()
+{
+    uint16_t shit;
+    shit = imu.begin(imu.G_SCALE_245DPS,imu.A_SCALE_2G,imu.M_SCALE_4GS,imu.G_ODR_238_BW_14,imu.A_ODR_119,imu.M_ODR_0625); //imu.G_SCALE_245DPS,imu.A_SCALE_2G,imu.M_SCALE_4GS,imu.G_ODR_238_BW_14,imu.A_ODR_119,imu.M_ODR_0625
+//    imu2.begin(imu.G_SCALE_500DPS,imu.A_SCALE_2G,imu.M_SCALE_4GS,imu.G_ODR_476_BW_21,imu.A_ODR_476,imu.M_ODR_0625);
+    if(shit != 0x683D) {
+        while(1) {
+            uart.printf("IMU error\n\r");
+        }
+    }
+    uart.printf("IMU init success\n\r");
+
+//    uart.printf("%d\n\r", shit);
 }
 
 void init_DYNAMIXEL()
 {
 //    dynamixelClass.torqueMode(SERVO_ID, 1);
-    dynamixelClass.setMode(SERVO_ID, WHEEL, 0, 0);
+    dynamixelClass.setMode(SERVO_ID, WHEEL, 0, 0);  //Wheel:= continuously rotating; others: torque, position
     wait_ms(1);
 }
 
@@ -113,7 +178,7 @@
     timer1.attach_us(&timer1_ITR, ITR_time1);
 }
 
-void timer1_ITR()
+void timer1_ITR()    //開始讀取資料
 {
     led2 = !led2;
     angle_measure();
@@ -121,28 +186,7 @@
     find_torque();
     motor_pid.Compute(torque_ref, torque_measured);
     PIDout = motor_pid.output;
-//    servo_cmd = -PIDout*121.8f;   // 1023/8.4Nm = 121.7857
-    servo_cmd = -PIDout;   // 1023/8.4Nm = 121.7857
-/*
-    // 電流控制
-    if (servo_cmd > 0) {
-        //                servo_cmd = servo_cmd + ((-torque_ref)*rate+friction)*121.8f;
-        servo_cmd = servo_cmd;
-        if (servo_cmd >= 1023)
-            servo_cmd = 1023;
-    } else {
-        //                servo_cmd = -servo_cmd + 1024 + ((torque_ref)*rate+friction)*121.8f;
-        servo_cmd = -servo_cmd + 1024;
-        if (servo_cmd >= 2047)
-            servo_cmd = 2047;
-    }
-
-    if (servo_cmd >= 1023) {
-        row_cmd = -(servo_cmd-1023);
-    } else {
-        row_cmd = servo_cmd;
-    }
-*/
+    servo_cmd = -PIDout;   // 1023/8.4Nm = 121.7857 可視情況調整負號
     // 速度控制
         if (servo_cmd > 0) {
             row_cmd = servo_cmd;
@@ -165,12 +209,12 @@
         }
     
 //    dynamixelClass.torque(SERVO_ID, servo_cmd);
-    dynamixelClass.wheel(SERVO_ID, rotation_, servo_cmd);  //0~1023   (rotation)
+    dynamixelClass.wheel(SERVO_ID, rotation_, servo_cmd);  //0~1023   (rotation) 12V之下的最高轉速為45rpm,切割為等分
 //    dynamixelClass.wheel(SERVO_ID, 0, 150);  //0~1023      (rotation)
     uart_tx();
 }
 
-void uart_tx()
+void uart_tx()    //分割資料
 {
     splitter s1;
     splitter s2;
@@ -179,17 +223,38 @@
     splitter s5;
     splitter s6;
     splitter s7;
+    splitter s8;
+    splitter s9;
+    splitter s10;
+    splitter s11;
+    splitter s12;
+    splitter s13;
+    splitter s14;
+    splitter s15;
+    splitter s16;
+    splitter s17;
+    splitter s18;
+    splitter s19;
 
-    s1.j = torque_ref*1000;
-    s2.j = torque_measured*1000;
-    s3.j = Angle_Dif/4096*3600;
-//    s3.j = servo_cmd;
-//    s4.j = 1;
-//    s5.j = 3;
-    s4.j = D_Angle;
-    s5.j = Angle*3;
-    s6.j = row_cmd;
-    s7.j = 1;
+    s1.j = Acce_axis_data_f[0];  //  0x6161;//
+    s2.j = Acce_axis_data_f[1];
+    s3.j = Acce_axis_data_f[2];
+    s4.j = Acce_axis_data_f[3];
+    s5.j = Acce_axis_data_f[4];
+    s6.j = Acce_axis_data_f[5];
+    s7.j = Gyro_axis_data_f[0];
+    s8.j = Gyro_axis_data_f[1];
+    s9.j = Gyro_axis_data_f[2];
+    s10.j = Gyro_axis_data_f[3];
+    s11.j = Gyro_axis_data_f[4];
+    s12.j = Gyro_axis_data_f[5];
+    s13.j = emg_value_f;
+    s14.j = torque_ref*1000; //即reference input指令
+    s15.j = torque_measured*1000; //由angle_difference*ks而來
+    s16.j = Angle_Dif/4096*3600;
+    s17.j = D_Angle;
+    s18.j = Angle*3; //經過減速比
+    s19.j = row_cmd;
 
     T[2] = s1.C[0];
     T[3] = s1.C[1];
@@ -205,19 +270,46 @@
     T[13] = s6.C[1];
     T[14] = s7.C[0];
     T[15] = s7.C[1];
+    T[16] = s8.C[0];
+    T[17] = s8.C[1];
+    T[18] = s9.C[0];
+    T[19] = s9.C[1];
+    T[20] = s10.C[0];
+    T[21] = s10.C[1];
+    T[22] = s11.C[0];
+    T[23] = s11.C[1];
+    T[24] = s12.C[0];
+    T[25] = s12.C[1];
+    T[26] = s13.C[0];
+    T[27] = s13.C[1];
+    T[28] = s14.C[0];
+    T[29] = s14.C[1];
+    T[30] = s15.C[0];
+    T[31] = s15.C[1];
+    T[32] = s16.C[0];
+    T[33] = s16.C[1];
+    T[34] = s17.C[0];
+    T[35] = s17.C[1];
+    T[36] = s18.C[0];
+    T[37] = s18.C[1];
+    T[38] = s19.C[0];
+    T[39] = s19.C[1];
 
-    while(1) {
-        if (uart.writeable() == 1) {
-            uart.putc(T[i]);
-            i++;
-        }
-        if (i >= sizeof(T)) {
-            i = 0;
-            break;
-        }
+    for(int k=0;k<40;k++)
+    {
+        uart.putc(T[k]);
     }
 }
 
+float lpf(float input, float output_old, float frequency)
+{
+    float output = 0;
+
+    output = (output_old + frequency*Tf*input) / (1 + frequency*Tf);
+
+    return output;
+}
+
 void D_angle_measure()
 {
     D_angle = dynamixelClass.readPosition(SERVO_ID);
@@ -251,3 +343,4 @@
 
     torque_measured = angle_difference*ks;
 }
+