xyControl  0.1
Quadrotor Flight Controller on AVR Basis
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups
acc.c
Go to the documentation of this file.
1 /*
2  * acc.c
3  *
4  * Copyright (c) 2013, Thomas Buck <xythobuz@me.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * - Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * - Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include <avr/io.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 
34 #include <twi.h>
35 #include <acc.h>
36 #include <error.h>
37 #include <stdlib.h>
38 #include <config.h>
39 
49 #define ACCREG_CTRL1 0x20
50 #define ACCREG_CTRL4 0x23
51 #define ACCREG_XL 0x28
53 AccRange accRange;
62 Error accWriteRegister(uint8_t reg, uint8_t val) {
64  return TWI_NO_ANSWER;
65  }
66  if (twiWrite(reg)) {
67  return TWI_WRITE_ERROR;
68  }
69  if (twiWrite(val)) {
70  return TWI_WRITE_ERROR;
71  }
72  twiStop();
73  return SUCCESS;
74 }
75 
77  uint8_t v;
78  switch (r) {
79  case r2G:
80  v = 0x00;
81  break;
82  case r4G:
83  v = 0x10;
84  break;
85  case r8G:
86  v = 0x20;
87  break;
88  case r16G:
89  v = 0x30;
90  break;
91  default:
92  return ARGUMENT_ERROR;
93  }
94  accRange = r;
95  Error e = accWriteRegister(ACCREG_CTRL1, 0x57); // Enable all axes, 100Hz
96  if (e != SUCCESS) {
97  return e;
98  }
100  return e;
101 }
102 
104  static double accSumX = 0; /* Buffer for X Low-Pass. */
105  static double accSumY = 0; /* Buffer for Y Low-Pass. */
106  static double accSumZ = 0; /* Buffer for Z Low-Pass. */
107  static double accFilterX = 0; /* Buffer for X Low-Pass. */
108  static double accFilterY = 0; /* Buffer for Y Low-Pass. */
109  static double accFilterZ = 0; /* Buffer for Z Low-Pass. */
110 
111  if (v == NULL) {
112  return ARGUMENT_ERROR;
113  }
114  if (twiStart(ACC_ADDRESS | TWI_WRITE)) {
115  return TWI_NO_ANSWER;
116  }
117  if (twiWrite(ACCREG_XL | (1 << 7))) { // Auto Increment
118  return TWI_WRITE_ERROR;
119  }
121  return TWI_NO_ANSWER;
122  }
123 
124  uint8_t xl = twiReadAck();
125  uint8_t xh = twiReadAck();
126  uint8_t yl = twiReadAck();
127  uint8_t yh = twiReadAck();
128  uint8_t zl = twiReadAck();
129  uint8_t zh = twiReadNak();
130 
131  int16_t x = *(int8_t *)(&xh);
132  x *= (1 << 8);
133  x |= xl;
134 
135  int16_t y = *(int8_t *)(&yh);
136  y *= (1 << 8);
137  y |= yl;
138 
139  int16_t z = *(int8_t *)(&zh);
140  z *= (1 << 8);
141  z |= zl;
142 
143  switch (accRange) {
144  case r2G:
145  v->x = (((double)x) * 2 / 0x8000);
146  v->y = (((double)y) * 2 / 0x8000);
147  v->z = (((double)z) * 2 / 0x8000);
148  break;
149  case r4G:
150  v->x = (((double)x) * 4 / 0x8000);
151  v->y = (((double)y) * 4 / 0x8000);
152  v->z = (((double)z) * 4 / 0x8000);
153  break;
154  case r8G:
155  v->x = (((double)x) * 8 / 0x8000);
156  v->y = (((double)y) * 8 / 0x8000);
157  v->z = (((double)z) * 8 / 0x8000);
158  break;
159  case r16G:
160  v->x = (((double)x) * 16 / 0x8000);
161  v->y = (((double)y) * 16 / 0x8000);
162  v->z = (((double)z) * 16 / 0x8000);
163  break;
164  default:
165  return ARGUMENT_ERROR;
166  }
167 
168  accSumX = accSumX - accFilterX + v->x;
169  accFilterX = accSumX / ACCFILTERFACTOR;
170  v->x = accFilterX;
171 
172  accSumY = accSumY - accFilterY + v->y;
173  accFilterY = accSumY / ACCFILTERFACTOR;
174  v->y = accFilterY;
175 
176  accSumZ = accSumZ - accFilterZ + v->z;
177  accFilterZ = accSumZ / ACCFILTERFACTOR;
178  v->z = accFilterZ;
179 
180  return SUCCESS;
181 }