add missing sd_log.[ch] files
[protos/imu.git] / imu.c
1 #include <stdio.h>
2 #include <string.h>
3
4 #include <aversive/irq_lock.h>
5 #include <aversive/wait.h>
6 #include <aversive/pgmspace.h>
7 #include <uart.h>
8
9
10 #include <i2c.h>
11 //#include "i2cm_sw.h"
12
13
14 #include "math.h"
15
16 #include "i2c_helper.h"
17 //#include "bma150.h"
18 //#include "itg3200.h"
19 //#include "ak8500.h"
20
21 #include "main.h"
22 #include "mpu6050.h"
23
24 #include "vector.h"
25 #include "matrix.h"
26
27 #include "MadgwickAHRS.h"
28
29
30
31 #include <string.h>
32 #include <avr/pgmspace.h>
33 #include <avr/sleep.h>
34 #include "fat.h"
35 #include "fat_config.h"
36 #include "partition.h"
37 #include "sd_raw.h"
38 #include "sd_raw_config.h"
39 #include "sd_log.h"
40
41 #include <uart.h>
42 #include <stdio.h>
43 #include <aversive/error.h>
44 #include "cmdline.h"
45
46
47 //#define LED_PRIO           170
48 #define GYRO_PRIO           100
49
50 int internal_mag_x;
51 int internal_mag_y;
52 int internal_mag_z;
53
54 int mag_x;
55 int mag_y;
56 int mag_z;
57
58
59 #if 0
60 static void main_timer_interrupt(void)
61 {
62         static uint8_t cpt = 0;
63         cpt++;
64         sei();
65         if ((cpt & 0x3) == 0)
66                 scheduler_interrupt();
67 }
68 #endif
69
70 #define LED1_TOGGLE()   PORTB ^= 0x20;
71
72
73 uint16_t counter;
74
75 void do_led_blink(void *dummy)
76 {
77         (void)dummy;
78
79 #if 1 /* simple blink */
80         LED1_TOGGLE();
81 #endif
82         //counter ++;
83         printf("\r\n%"PRId16"\r\n", counter);
84         counter = 0;
85
86 }
87
88
89 /* for i2c */
90 //uint8_t command_buf[I2C_SEND_BUFFER_SIZE];
91
92
93 double Accel_Vector[3]= {0,0,0}; //Store the acceleration in a vector
94 double Gyro_Vector[3]= {0,0,0};//Store the gyros rutn rate in a vector
95 double Magnet_Vector[3]= {0,0,0}; //Store the acceleration in a vector
96
97 double Omega_Vector[3]= {0,0,0}; //Corrected Gyro_Vector data
98 double Omega_P[3]= {0,0,0};//Omega Proportional correction
99 double Omega_I[3]= {0,0,0};//Omega Integrator
100 double Omega[3]= {0,0,0};
101
102 double Update_Matrix[3][3]={{0,1,2},{3,4,5},{6,7,8}}; //Gyros here
103
104 double DCM_Matrix[3][3]= {
105   {
106     1,0,0  }
107   ,{
108     0,1,0  }
109   ,{
110     0,0,1  }
111 };
112
113 double Temporary_Matrix[3][3]={
114   {
115     0,0,0  }
116   ,{
117     0,0,0  }
118   ,{
119     0,0,0  }
120 };
121
122 double errorRollPitch[3]= {0,0,0};
123 double errorYaw[3]= {0,0,0};
124 double errorCourse=180;
125 double COGX=0; //Course overground X axis
126 double COGY=1; //Course overground Y axis
127
128
129
130 #define OUTPUTMODE 2
131
132 #define ToRad(x) (x*0.01745329252)  // *pi/180
133 #define ToDeg(x) (x*57.2957795131)  // *180/pi
134
135 /*
136 #define Gyro_Gain_X 0.92 //X axis Gyro gain
137 #define Gyro_Gain_Y 0.92 //Y axis Gyro gain
138 #define Gyro_Gain_Z 0.94 //Z axis Gyro gain
139 */
140 #define Gyro_Gain_X (1.) //X axis Gyro gain
141 #define Gyro_Gain_Y (1.) //Y axis Gyro gain
142 #define Gyro_Gain_Z (1.) //Z axis Gyro gain
143
144 #define Gyro_Scaled_X(x) ((x)*ToRad(Gyro_Gain_X)) //Return the scaled ADC raw data of the gyro in radians for second
145 #define Gyro_Scaled_Y(x) ((x)*ToRad(Gyro_Gain_Y)) //Return the scaled ADC raw data of the gyro in radians for second
146 #define Gyro_Scaled_Z(x) ((x)*ToRad(Gyro_Gain_Z)) //Return the scaled ADC raw data of the gyro in radians for second
147
148 double G_Dt=0.02;    // Integration time (DCM algorithm)
149
150 #define GRAVITY 1.01 //this equivalent to 1G in the raw data coming from the accelerometer
151 #define Accel_Scale(x) x*(GRAVITY/9.81)//Scaling the raw data of the accel to actual acceleration in meters for seconds square
152
153
154 #define Kp_ROLLPITCH (1.515/GRAVITY)
155 #define Ki_ROLLPITCH (0.00101/GRAVITY)
156
157 #define Kp_YAW 1.2
158 //#define Kp_YAW 2.5      //High yaw drift correction gain - use with caution!
159 #define Ki_YAW 0.00005
160
161 #define MAGNETIC_DECLINATION 4.0
162
163 #define constrain(v, a, b) (((v)<(a))?(a):((v)>(b)?(b):(v)))
164
165
166 int mag_offset[3];
167 double Heading;
168 double Heading_X;
169 double Heading_Y;
170
171
172 // Euler angles
173 double roll;
174 double pitch;
175 double yaw;
176
177 int SENSOR_SIGN[]= {
178         1,1,1,   // GYROX, GYROY, GYROZ,
179         1,1,1,   // ACCELX, ACCELY, ACCELZ,
180         1,1,1    // MAGX, MAGY, MAGZ,
181 };
182
183 #if 0
184
185 double read_adc(uint8_t index)
186 {
187         int16_t value;
188
189         switch(index) {
190                 case 0:
191                         itg3200_read_axe(0, &value);
192                         return (double) (SENSOR_SIGN[index] * value);
193                 case 1:
194                         itg3200_read_axe(1, &value);
195                         return (double) (SENSOR_SIGN[index] * value);
196                 case 2:
197                         itg3200_read_axe(2, &value);
198                         return (double) (SENSOR_SIGN[index] * value);
199                 case 3:
200                         bma150_read_axe(0, &value);
201                         return (double) (SENSOR_SIGN[index] * bma15_axe2g(value));
202                 case 4:
203                         bma150_read_axe(1, &value);
204                         return (double) (SENSOR_SIGN[index] * bma15_axe2g(value));
205                 case 5:
206                         bma150_read_axe(2, &value);
207                         return (double) (SENSOR_SIGN[index] * bma15_axe2g(value));
208         }
209         return 0.0;
210 }
211
212
213 uint8_t measure_time = 0;
214 void read_sensors(void)
215 {
216         uint8_t flags;
217         uint8_t err;
218         uint16_t axes[3];
219
220         /* read mag */
221         measure_time ++;//= (measure_time +1)%3;
222         if (measure_time%2 == 0) {
223                 err = ak8500_start_measure();
224                 if (err) {
225                         printf("mag start err %X\r\n", err);
226                         measure_time = 0;
227                 }
228         }
229         else if (measure_time%2 == 1) {
230                 err = ak8500_read_all_axes(&axes);
231                 if (err == 0) {
232                         /*
233                         Magnet_Vector[0] = (double)SENSOR_SIGN[6] * (double)axes[0];
234                         Magnet_Vector[1] = (double)SENSOR_SIGN[7] * (double)axes[1];
235                         Magnet_Vector[2] = (double)SENSOR_SIGN[8] * (double)axes[2];
236                         */
237                         /*
238                         */
239                         mag_x = SENSOR_SIGN[6] * axes[0];
240                         mag_y = SENSOR_SIGN[7] * axes[1];
241                         mag_z = SENSOR_SIGN[8] * axes[2];
242                         Magnet_Vector[0] = mag_x;
243                         Magnet_Vector[1] = mag_y;
244                         Magnet_Vector[2] = mag_z;
245
246                 }
247                 else {
248                         printf("mag read err %X\r\n", err);
249                 }
250         }
251         /*
252         printf("%d %d %d\r\n",
253                mag_x,
254                mag_y,
255                mag_z
256                );
257         */
258         /*
259         printf("%f %f %f\r\n",
260                Magnet_Vector[0],
261                Magnet_Vector[1],
262                Magnet_Vector[2]);
263         */
264         /*
265         Gyro_Vector[0]=Gyro_Scaled_X(read_adc(0)); //gyro x roll
266         Gyro_Vector[1]=Gyro_Scaled_Y(read_adc(1)); //gyro y pitch
267         Gyro_Vector[2]=Gyro_Scaled_Z(read_adc(2)); //gyro Z yaw
268         */
269         Gyro_Vector[0]=ToRad(read_adc(0)); //gyro x roll
270         Gyro_Vector[1]=ToRad(read_adc(1)); //gyro y pitch
271         Gyro_Vector[2]=ToRad(read_adc(2)); //gyro Z yaw
272
273         Accel_Vector[0]=9.81 * read_adc(3); // acc x
274         Accel_Vector[1]=9.81 * read_adc(4); // acc y
275         Accel_Vector[2]=9.81 * read_adc(5); // acc z
276
277 }
278
279 #endif
280
281
282 void quaternion2euler(void)
283 {
284         /*
285         roll = atan2f(2. * (q0*q1 + q2*q3), 1. - 2. * (q1*q1 + q2*q2));
286         pitch = asinf(2 * (q0*q2 - q3*q1));
287         yaw =  atan2f(2. * (q0*q3 + q1*q2), 1. - 2. * (q2*q2 + q3*q3));
288         */
289         roll = atan2f(2.0f * (q0 * q1 + q2 * q3), q0*q0 - q1*q1 - q2*q2 + q3*q3);
290         pitch = -asinf(2.0f * (q1 * q3 - q0 * q2));
291         yaw = atan2f(2.0f * (q1 * q2 + q0 * q3), q0*q0 + q1*q1 - q2*q2 - q3*q3);
292 }
293
294 #define swap_u16(a) (((a>>8)&0xff) | (((a&0xFF)<<8)))
295
296 void imu_init(void)
297 {
298         /*
299         bma150_init();
300         itg3200_init();
301         ak8975_read_sensitivity();
302         */
303         /*
304         scheduler_add_periodical_event_priority(update_gyro, NULL,
305                                                 1000000L / SCHEDULER_UNIT,
306                                                 GYRO_PRIO);
307         */
308         mpu6050_init();
309 }
310
311 int imu_loop(void)
312 {
313         struct fat_file_struct *fd = NULL;
314         int16_t mpu6050_axes[10];
315         char buf[128];
316         int16_t len;
317         uint32_t ms;
318         uint8_t flags;
319
320         while (1) {
321
322                 counter ++;
323                 mpu6050_read_all_axes(mpu6050_axes);
324                 /*
325                 for (i=0;i<7; i++){
326                         printf("%"PRId16" ", mpu6050_axes[i]);
327                 }
328                 printf("\r\n");
329                 */
330                 /*
331                 printf("%3.3f %3.3f %3.3f\r\n",
332                        mpu6050_gx,
333                        mpu6050_gy,
334                        mpu6050_gz);
335                 continue;
336                 */
337
338                 /*
339                 MadgwickAHRSupdateIMU(mpu6050_gx,
340                                       mpu6050_gy,
341                                       mpu6050_gz,
342                                       mpu6050_ax,
343                                       mpu6050_ay,
344                                       mpu6050_az);
345                 */
346
347                 MadgwickAHRSupdate(mpu6050_gx,
348                                    mpu6050_gy,
349                                    mpu6050_gz,
350                                    mpu6050_ax,
351                                    mpu6050_ay,
352                                    mpu6050_az,
353                                    mpu6050_mx,
354                                    mpu6050_my,
355                                    mpu6050_mz
356                                    );
357
358                 quaternion2euler();
359
360                 /*
361                 mpu6050_axes[7] = swap_u16(mpu6050_axes[7]);
362                 mpu6050_axes[8] = swap_u16(mpu6050_axes[8]);
363                 mpu6050_axes[9] = swap_u16(mpu6050_axes[9]);
364                 */
365                 //printf("%+3.3f\t%+3.3f\t%+3.3f\r\n", roll, pitch, yaw);
366
367                 IRQ_LOCK(flags);
368                 ms = global_ms;
369                 IRQ_UNLOCK(flags);
370
371                 if (fd != NULL) {
372                         len = snprintf(buf, sizeof(buf),
373                                 "%"PRIu32"\t"
374                                 "gyro %+3.3f\t%+3.3f\t%+3.3f\t\t"
375                                 "accel %+3.3f\t%+3.3f\t%+3.3f\t\t"
376                                 "magnet %+3.3f\t%+3.3f\t%+3.3f\r\n",
377                                 ms,
378                                 mpu6050_gx, mpu6050_gy, mpu6050_gz,
379                                 mpu6050_ax, mpu6050_ay, mpu6050_az,
380                                 mpu6050_mx, mpu6050_my, mpu6050_mz);
381                         if (fat_write_file(fd, (unsigned char *)buf, len) != len) {
382                                 printf_P(PSTR("error writing to file\n"));
383                                 return -1;
384                         }
385                 }
386
387                 printf("%"PRIu32"\t", ms);
388                 printf("gyro %+3.3f\t%+3.3f\t%+3.3f\t\t",
389                         mpu6050_gx, mpu6050_gy, mpu6050_gz);
390                 printf("accel %+3.3f\t%+3.3f\t%+3.3f\t\t",
391                         mpu6050_ax, mpu6050_ay, mpu6050_az);
392                 printf("magnet %+3.3f\t%+3.3f\t%+3.3f\r\n",
393                         mpu6050_mx, mpu6050_my, mpu6050_mz);
394
395                 //printf("%+.4d %+.4d %+.4d\r\n", mpu6050_axes[7], mpu6050_axes[8], mpu6050_axes[9]);
396                 //printf("%+3.3f\r\n", mpu6050_temp);//, mpu6050_axes[9]);
397                 //printf("%+3.3f\t%+3.3f\t%+3.3f\r\n", mpu6050_mx, mpu6050_my, mpu6050_mz );
398
399         }
400
401         return 0;
402 }