xyControl  0.1
Quadrotor Flight Controller on AVR Basis
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups
mag.c
Go to the documentation of this file.
1 /*
2  * mag.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 <mag.h>
36 #include <error.h>
37 #include <config.h>
38 
48 #define MAGREG_CRB 0x01
49 #define MAGREG_MR 0x02
50 #define MAGREG_XH 0x03
52 #define MAG_NORMALIZE 1000
53 
63 Error magWriteRegister(uint8_t reg, uint8_t val) {
65  return TWI_NO_ANSWER;
66  }
67  if (twiWrite(reg)) {
68  return TWI_WRITE_ERROR;
69  }
70  if (twiWrite(val)) {
71  return TWI_WRITE_ERROR;
72  }
73  twiStop();
74  return SUCCESS;
75 }
76 
78  if ((r <= 0) || (r >= 8)) {
79  return ARGUMENT_ERROR;
80  }
81  Error e = magWriteRegister(MAGREG_MR, 0x00); // Continuous Conversion
82  if (e != SUCCESS) {
83  return e;
84  }
85  e = magWriteRegister(MAGREG_CRB, (r << 5)); // Set Range
86  magRange = r;
87  return e;
88 }
89 
91  if (v == NULL) {
92  return ARGUMENT_ERROR;
93  }
95  return TWI_NO_ANSWER;
96  }
97  if (twiWrite(MAGREG_XH)) {
98  return TWI_WRITE_ERROR;
99  }
101  return TWI_NO_ANSWER;
102  }
103  uint8_t xh = twiReadAck();
104  uint8_t xl = twiReadAck();
105  uint8_t zh = twiReadAck();
106  uint8_t zl = twiReadAck();
107  uint8_t yh = twiReadAck();
108  uint8_t yl = twiReadNak();
109 
110  int16_t x = *(int8_t *)(&xh);
111  x *= (1 << 8);
112  x |= xl;
113 
114  int16_t y = *(int8_t *)(&yh);
115  y *= (1 << 8);
116  y |= yl;
117 
118  int16_t z = *(int8_t *)(&zh);
119  z *= (1 << 8);
120  z |= zl;
121 
122  switch (magRange) {
123  case r1g3:
124  v->x = (((double)x) * 1.3 / MAG_NORMALIZE);
125  v->y = (((double)y) * 1.3 / MAG_NORMALIZE);
126  v->z = (((double)z) * 1.3 / MAG_NORMALIZE);
127  break;
128  case r1g9:
129  v->x = (((double)x) * 1.9 / MAG_NORMALIZE);
130  v->y = (((double)y) * 1.9 / MAG_NORMALIZE);
131  v->z = (((double)z) * 1.9 / MAG_NORMALIZE);
132  break;
133  case r2g5:
134  v->x = (((double)x) * 2.5 / MAG_NORMALIZE);
135  v->y = (((double)y) * 2.5 / MAG_NORMALIZE);
136  v->z = (((double)z) * 2.5 / MAG_NORMALIZE);
137  break;
138  case r4g0:
139  v->x = (((double)x) * 4.0 / MAG_NORMALIZE);
140  v->y = (((double)y) * 4.0 / MAG_NORMALIZE);
141  v->z = (((double)z) * 4.0 / MAG_NORMALIZE);
142  break;
143  case r4g7:
144  v->x = (((double)x) * 4.7 / MAG_NORMALIZE);
145  v->y = (((double)y) * 4.7 / MAG_NORMALIZE);
146  v->z = (((double)z) * 4.7 / MAG_NORMALIZE);
147  break;
148  case r5g6:
149  v->x = (((double)x) * 5.6 / MAG_NORMALIZE);
150  v->y = (((double)y) * 5.6 / MAG_NORMALIZE);
151  v->z = (((double)z) * 5.6 / MAG_NORMALIZE);
152  break;
153  case r8g1:
154  v->x = (((double)x) * 8.1 / MAG_NORMALIZE);
155  v->y = (((double)y) * 8.1 / MAG_NORMALIZE);
156  v->z = (((double)z) * 8.1 / MAG_NORMALIZE);
157  break;
158  default:
159  return ARGUMENT_ERROR;
160  }
161 
162  return SUCCESS;
163 }