UAVX Multicopter Flight Controller.

Dependencies:   mbed

Committer:
gke
Date:
Tue Apr 26 12:12:29 2011 +0000
Revision:
2:90292f8bd179
Parent:
1:1e3318a30ddd
Not flightworthy. Posted for others to make use of the I2C SW code.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gke 0:62a1c91a859a 1 // ===============================================================================================
gke 0:62a1c91a859a 2 // = UAVXArm Quadrocopter Controller =
gke 0:62a1c91a859a 3 // = Copyright (c) 2008 by Prof. Greg Egan =
gke 0:62a1c91a859a 4 // = Original V3.15 Copyright (c) 2007 Ing. Wolfgang Mahringer =
gke 2:90292f8bd179 5 // = http://code.google.com/p/uavp-mods/ =
gke 0:62a1c91a859a 6 // ===============================================================================================
gke 0:62a1c91a859a 7
gke 0:62a1c91a859a 8 // This is part of UAVXArm.
gke 0:62a1c91a859a 9
gke 0:62a1c91a859a 10 // UAVXArm is free software: you can redistribute it and/or modify it under the terms of the GNU
gke 0:62a1c91a859a 11 // General Public License as published by the Free Software Foundation, either version 3 of the
gke 0:62a1c91a859a 12 // License, or (at your option) any later version.
gke 0:62a1c91a859a 13
gke 0:62a1c91a859a 14 // UAVXArm is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without
gke 0:62a1c91a859a 15 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gke 0:62a1c91a859a 16 // See the GNU General Public License for more details.
gke 0:62a1c91a859a 17
gke 0:62a1c91a859a 18 // You should have received a copy of the GNU General Public License along with this program.
gke 0:62a1c91a859a 19 // If not, see http://www.gnu.org/licenses/
gke 0:62a1c91a859a 20
gke 0:62a1c91a859a 21 #include "UAVXArm.h"
gke 0:62a1c91a859a 22
gke 0:62a1c91a859a 23 // Barometers Freescale TI ADC and Bosch BMP085 3.8MHz, Bosch SMD500 400KHz
gke 0:62a1c91a859a 24
gke 0:62a1c91a859a 25 #define BARO_MIN_CLIMB 150.0 // M minimum available barometer climb from origin
gke 0:62a1c91a859a 26 #define BARO_MIN_DESCENT -50.0 //M minimum available barometer descent from origin
gke 0:62a1c91a859a 27
gke 0:62a1c91a859a 28 void GetBaroAltitude(void);
gke 0:62a1c91a859a 29 void InitBarometer(void);
gke 0:62a1c91a859a 30
gke 0:62a1c91a859a 31 void ShowBaroType(void);
gke 0:62a1c91a859a 32 void BaroTest(void);
gke 0:62a1c91a859a 33
gke 0:62a1c91a859a 34 #define BaroROCFilter HardFilter
gke 0:62a1c91a859a 35
gke 0:62a1c91a859a 36 uint16 BaroPressure, BaroTemperature;
gke 0:62a1c91a859a 37 boolean AcquiringPressure;
gke 0:62a1c91a859a 38 int16 BaroOffsetDAC;
gke 0:62a1c91a859a 39
gke 0:62a1c91a859a 40 #define BARO_BUFF_SIZE 4
gke 0:62a1c91a859a 41
gke 0:62a1c91a859a 42 struct {
gke 0:62a1c91a859a 43 uint8 Head, Tail;
gke 0:62a1c91a859a 44 int24 B[BARO_BUFF_SIZE];
gke 0:62a1c91a859a 45 } BaroQ;
gke 0:62a1c91a859a 46
gke 0:62a1c91a859a 47 int32 OriginBaroPressure, CompBaroPressure;
gke 0:62a1c91a859a 48 real32 BaroRelAltitude, BaroRelAltitudeP;
gke 0:62a1c91a859a 49 i16u BaroVal;
gke 0:62a1c91a859a 50 int8 BaroType;
gke 0:62a1c91a859a 51 int16 BaroClimbAvailable, BaroDescentAvailable;
gke 0:62a1c91a859a 52 int16 AltitudeUpdateRate;
gke 0:62a1c91a859a 53 int8 BaroRetries;
gke 0:62a1c91a859a 54
gke 0:62a1c91a859a 55 real32 FakeBaroRelAltitude;
gke 0:62a1c91a859a 56 int8 SimulateCycles = 0;
gke 0:62a1c91a859a 57
gke 0:62a1c91a859a 58 void ShowBaroType(void) {
gke 0:62a1c91a859a 59 switch ( BaroType ) {
gke 0:62a1c91a859a 60 case BaroMPX4115:
gke 0:62a1c91a859a 61 TxString("MPX4115\r\n");
gke 0:62a1c91a859a 62 break;
gke 0:62a1c91a859a 63 case BaroSMD500:
gke 0:62a1c91a859a 64 TxString("SMD500\r\n");
gke 0:62a1c91a859a 65 break;
gke 0:62a1c91a859a 66 case BaroBMP085:
gke 0:62a1c91a859a 67 TxString("BMP085\r\n");
gke 0:62a1c91a859a 68 break;
gke 0:62a1c91a859a 69 case BaroUnknown:
gke 0:62a1c91a859a 70 TxString("None\r\n");
gke 0:62a1c91a859a 71 break;
gke 0:62a1c91a859a 72 default:
gke 0:62a1c91a859a 73 break;
gke 0:62a1c91a859a 74 }
gke 0:62a1c91a859a 75 } // ShowBaro
gke 0:62a1c91a859a 76
gke 0:62a1c91a859a 77 void BaroTest(void) {
gke 2:90292f8bd179 78
gke 0:62a1c91a859a 79 TxString("\r\nAltitude test\r\n");
gke 0:62a1c91a859a 80 TxString("Initialising\r\n");
gke 0:62a1c91a859a 81
gke 0:62a1c91a859a 82 InitBarometer();
gke 0:62a1c91a859a 83
gke 0:62a1c91a859a 84 while ( F.BaroAltitudeValid && ! F.NewBaroValue )
gke 0:62a1c91a859a 85 GetBaroAltitude();
gke 0:62a1c91a859a 86
gke 0:62a1c91a859a 87 TxString("\r\nType:\t");
gke 0:62a1c91a859a 88 ShowBaroType();
gke 0:62a1c91a859a 89
gke 2:90292f8bd179 90 TxString("BaroScale:\t");
gke 2:90292f8bd179 91 TxVal32(P[BaroScale],0,0);
gke 2:90292f8bd179 92 TxString("\r\nInit Retries:\t");
gke 0:62a1c91a859a 93 TxVal32((int32)BaroRetries - 2, 0, ' '); // always minimum of 2
gke 0:62a1c91a859a 94 if ( BaroRetries >= BARO_INIT_RETRIES )
gke 0:62a1c91a859a 95 TxString(" FAILED Init.\r\n");
gke 0:62a1c91a859a 96 else
gke 0:62a1c91a859a 97 TxNextLine();
gke 0:62a1c91a859a 98
gke 0:62a1c91a859a 99 if ( BaroType == BaroMPX4115 ) {
gke 2:90292f8bd179 100 TxString("\r\nAddress :\t0x");
gke 2:90292f8bd179 101 TxValH(MCP4725_ID_Actual);
gke 2:90292f8bd179 102 TxString("\r\nRange :\t");
gke 0:62a1c91a859a 103 TxVal32((int32) BaroDescentAvailable * 10.0, 1, ' ');
gke 0:62a1c91a859a 104 TxString("-> ");
gke 0:62a1c91a859a 105 TxVal32((int32) BaroClimbAvailable * 10.0, 1, 'M');
gke 0:62a1c91a859a 106 TxString(" {Offset ");
gke 0:62a1c91a859a 107 TxVal32((int32)BaroOffsetDAC, 0,'}');
gke 0:62a1c91a859a 108 if (( BaroClimbAvailable < BARO_MIN_CLIMB ) || (BaroDescentAvailable > BARO_MIN_DESCENT))
gke 0:62a1c91a859a 109 TxString(" Bad climb or descent range - offset adjustment?");
gke 0:62a1c91a859a 110 TxNextLine();
gke 0:62a1c91a859a 111 }
gke 0:62a1c91a859a 112
gke 2:90292f8bd179 113 if ( F.BaroAltitudeValid ) {
gke 2:90292f8bd179 114
gke 2:90292f8bd179 115 while ( !F.NewBaroValue )
gke 2:90292f8bd179 116 GetBaroAltitude();
gke 2:90292f8bd179 117
gke 2:90292f8bd179 118 F.NewBaroValue = false;
gke 0:62a1c91a859a 119
gke 2:90292f8bd179 120 TxString("Alt.: \t");
gke 2:90292f8bd179 121 TxVal32(BaroRelAltitude * 10.0, 1, ' ');
gke 2:90292f8bd179 122 TxString("M\r\n");
gke 0:62a1c91a859a 123
gke 2:90292f8bd179 124 } else
gke 2:90292f8bd179 125 TxString("Barometer FAILED\r\n");
gke 0:62a1c91a859a 126
gke 0:62a1c91a859a 127 TxString("\r\nR.Finder: \t");
gke 0:62a1c91a859a 128 if ( F.RangefinderAltitudeValid ) {
gke 0:62a1c91a859a 129 GetRangefinderAltitude();
gke 0:62a1c91a859a 130 TxVal32(RangefinderAltitude * 100.0, 2, ' ');
gke 0:62a1c91a859a 131 TxString("M\r\n");
gke 0:62a1c91a859a 132 } else
gke 0:62a1c91a859a 133 TxString("no rangefinder\r\n");
gke 0:62a1c91a859a 134
gke 1:1e3318a30ddd 135 TxString("\r\nUAVXArm Shield:\t");
gke 0:62a1c91a859a 136 TxVal32((int32)AmbientTemperature.i16, 1, ' ');
gke 0:62a1c91a859a 137 TxString("C\r\n");
gke 0:62a1c91a859a 138
gke 0:62a1c91a859a 139 } // BaroTest
gke 0:62a1c91a859a 140
gke 0:62a1c91a859a 141 void GetBaroAltitude(void) {
gke 0:62a1c91a859a 142 static real32 Temp, AltChange;
gke 0:62a1c91a859a 143
gke 0:62a1c91a859a 144 if ( BaroType == BaroMPX4115 )
gke 0:62a1c91a859a 145 GetFreescaleBaroAltitude();
gke 0:62a1c91a859a 146 else
gke 0:62a1c91a859a 147 GetBoschBaroAltitude();
gke 0:62a1c91a859a 148
gke 0:62a1c91a859a 149 if ( F.NewBaroValue ) {
gke 0:62a1c91a859a 150 #ifdef SIMULATE
gke 0:62a1c91a859a 151 if ( State == InFlight ) {
gke 0:62a1c91a859a 152 if ( ++SimulateCycles >= AltitudeUpdateRate ) {
gke 0:62a1c91a859a 153 FakeBaroRelAltitude += ( DesiredThrottle - CruiseThrottle ) + Comp[Alt];
gke 0:62a1c91a859a 154 if ( FakeBaroRelAltitude < -5.0 )
gke 0:62a1c91a859a 155 FakeBaroRelAltitude = 0.0;
gke 0:62a1c91a859a 156
gke 0:62a1c91a859a 157 SimulateCycles = 0;
gke 0:62a1c91a859a 158
gke 0:62a1c91a859a 159 ROC = FakeBaroRelAltitude - BaroRelAltitudeP;
gke 0:62a1c91a859a 160 BaroRelAltitudeP = FakeBaroRelAltitude;
gke 0:62a1c91a859a 161 }
gke 0:62a1c91a859a 162 BaroRelAltitude = FakeBaroRelAltitude;
gke 0:62a1c91a859a 163 }
gke 0:62a1c91a859a 164 #else
gke 0:62a1c91a859a 165
gke 0:62a1c91a859a 166 AltChange = BaroRelAltitude - BaroRelAltitudeP;
gke 0:62a1c91a859a 167 Temp = AltChange * AltitudeUpdateRate;
gke 0:62a1c91a859a 168
gke 0:62a1c91a859a 169 if ( fabs( Temp ) > BARO_SANITY_CHECK_MPS ) {
gke 0:62a1c91a859a 170 BaroRelAltitude = BaroRelAltitudeP; // use previous value
gke 0:62a1c91a859a 171 Temp = 0;
gke 0:62a1c91a859a 172 Stats[BaroFailS]++;
gke 0:62a1c91a859a 173 }
gke 0:62a1c91a859a 174
gke 2:90292f8bd179 175 Temp = Limit1(Temp, BARO_SANITY_CHECK_MPS);
gke 0:62a1c91a859a 176 ROC = ROC * 0.9 + Temp * 0.1;
gke 0:62a1c91a859a 177 BaroRelAltitudeP = BaroRelAltitude;
gke 0:62a1c91a859a 178
gke 0:62a1c91a859a 179 #endif // SIMULATE
gke 0:62a1c91a859a 180
gke 0:62a1c91a859a 181 if ( State == InFlight ) {
gke 0:62a1c91a859a 182 if ( ROC > Stats[MaxROCS] )
gke 0:62a1c91a859a 183 Stats[MaxROCS] = ROC;
gke 0:62a1c91a859a 184 else
gke 0:62a1c91a859a 185 if ( ROC < Stats[MinROCS] )
gke 0:62a1c91a859a 186 Stats[MinROCS] = ROC;
gke 0:62a1c91a859a 187
gke 0:62a1c91a859a 188 if ( BaroRelAltitude > Stats[BaroRelAltitudeS] )
gke 0:62a1c91a859a 189 Stats[BaroRelAltitudeS] = BaroRelAltitude;
gke 0:62a1c91a859a 190 }
gke 0:62a1c91a859a 191 }
gke 0:62a1c91a859a 192
gke 0:62a1c91a859a 193 } // GetBaroAltitude
gke 0:62a1c91a859a 194
gke 0:62a1c91a859a 195 void InitBarometer(void) {
gke 0:62a1c91a859a 196 BaroRelAltitude = BaroRelAltitudeP = CompBaroPressure = OriginBaroPressure = 0;
gke 0:62a1c91a859a 197 BaroType = BaroUnknown;
gke 0:62a1c91a859a 198
gke 2:90292f8bd179 199 AltComp = AltDiffSum = AltDSum = 0;
gke 0:62a1c91a859a 200 F.BaroAltitudeValid= true; // optimistic
gke 2:90292f8bd179 201
gke 0:62a1c91a859a 202 if ( IsFreescaleBaroActive() )
gke 0:62a1c91a859a 203 InitFreescaleBarometer();
gke 0:62a1c91a859a 204 else
gke 0:62a1c91a859a 205 if ( IsBoschBaroActive() )
gke 0:62a1c91a859a 206 InitBoschBarometer();
gke 2:90292f8bd179 207 else
gke 0:62a1c91a859a 208 F.BaroAltitudeValid = F.HoldingAlt = false;
gke 2:90292f8bd179 209
gke 0:62a1c91a859a 210 } // InitBarometer
gke 0:62a1c91a859a 211
gke 0:62a1c91a859a 212 // -----------------------------------------------------------
gke 0:62a1c91a859a 213
gke 0:62a1c91a859a 214 // Freescale ex Motorola MPX4115 Barometer with ADS7823 12bit ADC
gke 0:62a1c91a859a 215
gke 0:62a1c91a859a 216 void SetFreescaleMCP4725(int16);
gke 1:1e3318a30ddd 217 boolean IdentifyMCP4725(void);
gke 0:62a1c91a859a 218 void SetFreescaleOffset(void);
gke 0:62a1c91a859a 219 void ReadFreescaleBaro(void);
gke 0:62a1c91a859a 220 real32 FreescaleToDM(int24);
gke 0:62a1c91a859a 221 void GetFreescaleBaroAltitude(void);
gke 0:62a1c91a859a 222 boolean IsFreescaleBaroActive(void);
gke 0:62a1c91a859a 223 void InitFreescaleBarometer(void);
gke 0:62a1c91a859a 224
gke 1:1e3318a30ddd 225 uint8 MCP4725_ID_Actual;
gke 1:1e3318a30ddd 226
gke 0:62a1c91a859a 227 void SetFreescaleMCP4725(int16 d) {
gke 0:62a1c91a859a 228 static i16u dd;
gke 0:62a1c91a859a 229
gke 0:62a1c91a859a 230 dd.u16 = d << 4; // left align
gke 0:62a1c91a859a 231
gke 0:62a1c91a859a 232 I2CBARO.start();
gke 2:90292f8bd179 233 if ( I2CBARO.write(MCP4725_ID_Actual) != I2C_ACK ) goto MCP4725Error;
gke 2:90292f8bd179 234 if ( I2CBARO.write(MCP4725_CMD) != I2C_ACK ) goto MCP4725Error;
gke 2:90292f8bd179 235 if ( I2CBARO.write(dd.b1) != I2C_ACK ) goto MCP4725Error;
gke 2:90292f8bd179 236 if ( I2CBARO.write(dd.b0) != I2C_ACK ) goto MCP4725Error;
gke 0:62a1c91a859a 237 I2CBARO.stop();
gke 0:62a1c91a859a 238
gke 2:90292f8bd179 239 return;
gke 2:90292f8bd179 240
gke 2:90292f8bd179 241 MCP4725Error:
gke 2:90292f8bd179 242 I2CBARO.stop();
gke 2:90292f8bd179 243 I2CError[MCP4725_ID_Actual]++;
gke 2:90292f8bd179 244
gke 0:62a1c91a859a 245 } // SetFreescaleMCP4725
gke 0:62a1c91a859a 246
gke 1:1e3318a30ddd 247 boolean IdentifyMCP4725(void) {
gke 1:1e3318a30ddd 248
gke 1:1e3318a30ddd 249 static boolean r;
gke 2:90292f8bd179 250
gke 1:1e3318a30ddd 251 r = true;
gke 2:90292f8bd179 252 MCP4725_ID_Actual = MCP4725_ID_0xCC;
gke 2:90292f8bd179 253 if ( I2CBAROAddressResponds( MCP4725_ID_0xCC ) )
gke 2:90292f8bd179 254 MCP4725_ID_Actual = MCP4725_ID_0xCC;
gke 2:90292f8bd179 255 else
gke 2:90292f8bd179 256 if ( I2CBAROAddressResponds( MCP4725_ID_0xC8 ) )
gke 2:90292f8bd179 257 MCP4725_ID_Actual = MCP4725_ID_0xC8;
gke 1:1e3318a30ddd 258 else
gke 1:1e3318a30ddd 259 r = false;
gke 2:90292f8bd179 260
gke 2:90292f8bd179 261 return(r);
gke 2:90292f8bd179 262
gke 2:90292f8bd179 263 // MCP4725_ID_Actual = FORCE_BARO_ID;
gke 2:90292f8bd179 264 // return(true);
gke 2:90292f8bd179 265
gke 1:1e3318a30ddd 266 } // IdentifyMCP4725
gke 1:1e3318a30ddd 267
gke 0:62a1c91a859a 268 void SetFreescaleOffset(void) {
gke 0:62a1c91a859a 269 // Steve Westerfeld
gke 0:62a1c91a859a 270 // 470 Ohm, 1uF RC 0.47mS use 2mS for settling?
gke 0:62a1c91a859a 271
gke 0:62a1c91a859a 272 TxString("\r\nOffset \tPressure\r\n");
gke 0:62a1c91a859a 273
gke 0:62a1c91a859a 274 BaroOffsetDAC = MCP4725_MAX;
gke 0:62a1c91a859a 275
gke 0:62a1c91a859a 276 SetFreescaleMCP4725(BaroOffsetDAC);
gke 0:62a1c91a859a 277
gke 0:62a1c91a859a 278 Delay1mS(20); // initial settling
gke 0:62a1c91a859a 279 ReadFreescaleBaro();
gke 0:62a1c91a859a 280
gke 0:62a1c91a859a 281 while ( (BaroVal.u16 < (uint16)(((uint24)ADS7823_MAX*4L*7L)/10L) )
gke 0:62a1c91a859a 282 && (BaroOffsetDAC > 20) ) { // first loop gets close
gke 0:62a1c91a859a 283 BaroOffsetDAC -= 20; // approach at 20 steps out of 4095
gke 0:62a1c91a859a 284 SetFreescaleMCP4725(BaroOffsetDAC);
gke 0:62a1c91a859a 285 Delay1mS(20);
gke 0:62a1c91a859a 286 ReadFreescaleBaro();
gke 0:62a1c91a859a 287 TxVal32(BaroOffsetDAC,0,HT);
gke 0:62a1c91a859a 288 TxVal32(BaroVal.u16,0,' ');
gke 0:62a1c91a859a 289 TxNextLine();
gke 0:62a1c91a859a 290 LEDYellow_TOG;
gke 0:62a1c91a859a 291 }
gke 0:62a1c91a859a 292
gke 0:62a1c91a859a 293 BaroOffsetDAC += 20; // move back up to come at it a little slower
gke 0:62a1c91a859a 294 SetFreescaleMCP4725(BaroOffsetDAC);
gke 0:62a1c91a859a 295 Delay1mS(100);
gke 0:62a1c91a859a 296 ReadFreescaleBaro();
gke 0:62a1c91a859a 297
gke 2:90292f8bd179 298 while ( (BaroVal.u16 < (uint16)(((uint24)ADS7823_MAX*4L*3L)/4L) ) && (BaroOffsetDAC > 1) ) {
gke 2:90292f8bd179 299 BaroOffsetDAC -= 1;
gke 0:62a1c91a859a 300 SetFreescaleMCP4725(BaroOffsetDAC);
gke 2:90292f8bd179 301 Delay1mS(10); // 10
gke 0:62a1c91a859a 302 ReadFreescaleBaro();
gke 0:62a1c91a859a 303 TxVal32(BaroOffsetDAC,0,HT);
gke 2:90292f8bd179 304 TxVal32(BaroVal.u16,0,HT);
gke 2:90292f8bd179 305 TxVal32((int32)FreescaleToDM(BaroVal.u16), 1, 0);
gke 0:62a1c91a859a 306 TxNextLine();
gke 0:62a1c91a859a 307 LEDYellow_TOG;
gke 0:62a1c91a859a 308 }
gke 0:62a1c91a859a 309
gke 0:62a1c91a859a 310 Delay1mS(200); // wait for caps to settle
gke 0:62a1c91a859a 311 F.BaroAltitudeValid = BaroOffsetDAC > 0;
gke 0:62a1c91a859a 312
gke 0:62a1c91a859a 313 } // SetFreescaleOffset
gke 0:62a1c91a859a 314
gke 0:62a1c91a859a 315 void ReadFreescaleBaro(void) {
gke 0:62a1c91a859a 316 static char B[8];
gke 0:62a1c91a859a 317 static i16u B0, B1, B2, B3;
gke 0:62a1c91a859a 318
gke 0:62a1c91a859a 319 mS[BaroUpdate] = mSClock() + ADS7823_TIME_MS;
gke 0:62a1c91a859a 320
gke 0:62a1c91a859a 321 I2CBARO.start(); // start conversion
gke 2:90292f8bd179 322 if ( I2CBARO.write(ADS7823_WR) != I2C_ACK ) goto ADS7823Error;
gke 2:90292f8bd179 323 if ( I2CBARO.write(ADS7823_CMD) != I2C_ACK ) goto ADS7823Error;
gke 2:90292f8bd179 324 I2CBARO.stop();
gke 0:62a1c91a859a 325
gke 2:90292f8bd179 326 if ( I2CBARO.blockread(ADS7823_RD, B, 8) ) goto ADS7823Error;
gke 0:62a1c91a859a 327
gke 2:90292f8bd179 328 // read block of 4 baro samples
gke 0:62a1c91a859a 329
gke 0:62a1c91a859a 330 B0.b0 = B[1];
gke 0:62a1c91a859a 331 B0.b1 = B[0];
gke 0:62a1c91a859a 332 B1.b0 = B[3];
gke 0:62a1c91a859a 333 B1.b1 = B[2];
gke 0:62a1c91a859a 334 B2.b0 = B[5];
gke 0:62a1c91a859a 335 B2.b1 = B[4];
gke 0:62a1c91a859a 336 B3.b0 = B[7];
gke 0:62a1c91a859a 337 B3.b1 = B[6];
gke 0:62a1c91a859a 338
gke 0:62a1c91a859a 339 BaroVal.u16 = (uint16)16380 - ( B0.u16 + B1.u16 + B2.u16 + B3.u16 );
gke 0:62a1c91a859a 340
gke 0:62a1c91a859a 341 F.BaroAltitudeValid = true;
gke 0:62a1c91a859a 342
gke 0:62a1c91a859a 343 return;
gke 0:62a1c91a859a 344
gke 2:90292f8bd179 345 ADS7823Error:
gke 0:62a1c91a859a 346 I2CBARO.stop();
gke 0:62a1c91a859a 347
gke 2:90292f8bd179 348 I2CError[ADS7823_ID]++;
gke 2:90292f8bd179 349
gke 2:90292f8bd179 350 // F.BaroAltitudeValid = F.HoldingAlt = false;
gke 0:62a1c91a859a 351 if ( State == InFlight ) {
gke 0:62a1c91a859a 352 Stats[BaroFailS]++;
gke 0:62a1c91a859a 353 F.BaroFailure = true;
gke 0:62a1c91a859a 354 }
gke 2:90292f8bd179 355
gke 0:62a1c91a859a 356 } // ReadFreescaleBaro
gke 0:62a1c91a859a 357
gke 0:62a1c91a859a 358 real32 FreescaleToDM(int24 p) { // decreasing pressure is increase in altitude negate and rescale to metre altitude
gke 0:62a1c91a859a 359 return( -( (real32)p * 0.8 ) / (real32)P[BaroScale] );
gke 0:62a1c91a859a 360 } // FreescaleToDM
gke 0:62a1c91a859a 361
gke 0:62a1c91a859a 362 void GetFreescaleBaroAltitude(void) {
gke 0:62a1c91a859a 363 static int24 BaroPressure;
gke 0:62a1c91a859a 364
gke 0:62a1c91a859a 365 if ( mSClock() >= mS[BaroUpdate] ) {
gke 0:62a1c91a859a 366 ReadFreescaleBaro();
gke 0:62a1c91a859a 367 if ( F.BaroAltitudeValid ) {
gke 0:62a1c91a859a 368 BaroPressure = (int24)BaroVal.u16; // sum of 4 samples
gke 0:62a1c91a859a 369 BaroRelAltitude = FreescaleToDM(BaroPressure - OriginBaroPressure);
gke 0:62a1c91a859a 370 F.NewBaroValue = F.BaroAltitudeValid;
gke 0:62a1c91a859a 371 }
gke 0:62a1c91a859a 372 }
gke 0:62a1c91a859a 373
gke 0:62a1c91a859a 374 } // GetFreescaleBaroAltitude
gke 0:62a1c91a859a 375
gke 0:62a1c91a859a 376 boolean IsFreescaleBaroActive(void) { // check for Freescale Barometer
gke 0:62a1c91a859a 377
gke 1:1e3318a30ddd 378 static boolean r;
gke 0:62a1c91a859a 379
gke 1:1e3318a30ddd 380 r = I2CBAROAddressResponds( ADS7823_ID );
gke 1:1e3318a30ddd 381 if ( r ) {
gke 1:1e3318a30ddd 382 BaroType = BaroMPX4115;
gke 1:1e3318a30ddd 383 r = IdentifyMCP4725();
gke 1:1e3318a30ddd 384 TrackMinI2CRate(400000);
gke 1:1e3318a30ddd 385 }
gke 1:1e3318a30ddd 386 return (r);
gke 0:62a1c91a859a 387
gke 0:62a1c91a859a 388 } // IsFreescaleBaroActive
gke 0:62a1c91a859a 389
gke 0:62a1c91a859a 390 void InitFreescaleBarometer(void) {
gke 0:62a1c91a859a 391 static int16 BaroOriginAltitude, MinAltitude;
gke 0:62a1c91a859a 392 static int24 BaroPressureP;
gke 0:62a1c91a859a 393
gke 0:62a1c91a859a 394 AltitudeUpdateRate = 1000L/ADS7823_TIME_MS;
gke 0:62a1c91a859a 395
gke 0:62a1c91a859a 396 BaroTemperature = 0;
gke 2:90292f8bd179 397 if ( P[BaroScale] <= 0 )
gke 2:90292f8bd179 398 P[BaroScale] = 56; // failsafe setting
gke 2:90292f8bd179 399
gke 0:62a1c91a859a 400 BaroPressure = 0;
gke 0:62a1c91a859a 401 BaroRetries = 0;
gke 0:62a1c91a859a 402 do {
gke 0:62a1c91a859a 403 BaroPressureP = BaroPressure;
gke 0:62a1c91a859a 404
gke 0:62a1c91a859a 405 SetFreescaleOffset();
gke 0:62a1c91a859a 406
gke 0:62a1c91a859a 407 while ( mSClock() < mS[BaroUpdate] ) {};
gke 0:62a1c91a859a 408 ReadFreescaleBaro();
gke 0:62a1c91a859a 409 BaroPressure = (int24)BaroVal.u16;
gke 0:62a1c91a859a 410 } while ( ( ++BaroRetries < BARO_INIT_RETRIES )
gke 2:90292f8bd179 411 && ( fabs( FreescaleToDM(BaroPressure - BaroPressureP) ) > 5 ) );
gke 0:62a1c91a859a 412
gke 0:62a1c91a859a 413 F.BaroAltitudeValid = BaroRetries < BARO_INIT_RETRIES;
gke 0:62a1c91a859a 414
gke 0:62a1c91a859a 415 OriginBaroPressure = BaroPressure;
gke 0:62a1c91a859a 416
gke 0:62a1c91a859a 417 BaroRelAltitudeP = BaroRelAltitude = 0.0;
gke 0:62a1c91a859a 418
gke 0:62a1c91a859a 419 MinAltitude = FreescaleToDM((int24)ADS7823_MAX*4);
gke 0:62a1c91a859a 420 BaroOriginAltitude = FreescaleToDM(OriginBaroPressure);
gke 0:62a1c91a859a 421 BaroDescentAvailable = MinAltitude - BaroOriginAltitude;
gke 0:62a1c91a859a 422 BaroClimbAvailable = -BaroOriginAltitude;
gke 0:62a1c91a859a 423
gke 0:62a1c91a859a 424 //F.BaroAltitudeValid &= (( BaroClimbAvailable >= BARO_MIN_CLIMB )
gke 0:62a1c91a859a 425 // && (BaroDescentAvailable <= BARO_MIN_DESCENT));
gke 0:62a1c91a859a 426
gke 0:62a1c91a859a 427 #ifdef SIMULATE
gke 0:62a1c91a859a 428 FakeBaroRelAltitude = 0;
gke 0:62a1c91a859a 429 #endif // SIMULATE
gke 0:62a1c91a859a 430
gke 0:62a1c91a859a 431 } // InitFreescaleBarometer
gke 0:62a1c91a859a 432
gke 0:62a1c91a859a 433 // -----------------------------------------------------------
gke 0:62a1c91a859a 434
gke 0:62a1c91a859a 435 // Bosch SMD500 and BMP085 Barometers
gke 0:62a1c91a859a 436
gke 0:62a1c91a859a 437 void StartBoschBaroADC(boolean);
gke 0:62a1c91a859a 438 int24 CompensatedBoschPressure(uint16, uint16);
gke 0:62a1c91a859a 439
gke 0:62a1c91a859a 440 void GetBoschBaroAltitude(void);
gke 0:62a1c91a859a 441 boolean IsBoschBaroActive(void);
gke 0:62a1c91a859a 442 void InitBoschBarometer(void);
gke 0:62a1c91a859a 443
gke 0:62a1c91a859a 444 // SMD500 9.5mS (T) 34mS (P)
gke 0:62a1c91a859a 445 // BMP085 4.5mS (T) 25.5mS (P) OSRS=3
gke 0:62a1c91a859a 446 #define BOSCH_TEMP_TIME_MS 11 // 10 increase to make P+T acq time ~50mS
gke 0:62a1c91a859a 447 //#define BMP085_PRESS_TIME_MS 26
gke 0:62a1c91a859a 448 //#define SMD500_PRESS_TIME_MS 34
gke 0:62a1c91a859a 449 #define BOSCH_PRESS_TIME_MS 38
gke 0:62a1c91a859a 450 #define BOSCH_PRESS_TEMP_TIME_MS 50 // pressure and temp time + overheads
gke 0:62a1c91a859a 451
gke 0:62a1c91a859a 452 void StartBoschBaroADC(boolean ReadPressure) {
gke 0:62a1c91a859a 453 static uint8 TempOrPress;
gke 0:62a1c91a859a 454
gke 0:62a1c91a859a 455 if ( ReadPressure ) {
gke 0:62a1c91a859a 456 TempOrPress = BOSCH_PRESS;
gke 0:62a1c91a859a 457 mS[BaroUpdate] = mSClock() + BOSCH_PRESS_TIME_MS;
gke 0:62a1c91a859a 458 } else {
gke 0:62a1c91a859a 459 mS[BaroUpdate] = mSClock() + BOSCH_TEMP_TIME_MS;
gke 0:62a1c91a859a 460 if ( BaroType == BaroBMP085 )
gke 0:62a1c91a859a 461 TempOrPress = BOSCH_TEMP_BMP085;
gke 0:62a1c91a859a 462 else
gke 0:62a1c91a859a 463 TempOrPress = BOSCH_TEMP_SMD500;
gke 0:62a1c91a859a 464 }
gke 0:62a1c91a859a 465
gke 0:62a1c91a859a 466 I2CBARO.start();
gke 2:90292f8bd179 467 if ( I2CBARO.write(BOSCH_ID) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 468 // access control register, start measurement
gke 2:90292f8bd179 469 if ( I2CBARO.write(BOSCH_CTL) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 470 // select 32kHz input, measure temperature
gke 2:90292f8bd179 471 if ( I2CBARO.write(TempOrPress) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 472 I2CBARO.stop();
gke 0:62a1c91a859a 473
gke 0:62a1c91a859a 474 F.BaroAltitudeValid = true;
gke 0:62a1c91a859a 475 return;
gke 0:62a1c91a859a 476
gke 2:90292f8bd179 477 BoschError:
gke 0:62a1c91a859a 478 I2CBARO.stop();
gke 2:90292f8bd179 479
gke 2:90292f8bd179 480 I2CError[BOSCH_ID]++;
gke 2:90292f8bd179 481 F.BaroAltitudeValid = false;
gke 2:90292f8bd179 482
gke 0:62a1c91a859a 483 } // StartBoschBaroADC
gke 0:62a1c91a859a 484
gke 0:62a1c91a859a 485 void ReadBoschBaro(void) {
gke 2:90292f8bd179 486
gke 0:62a1c91a859a 487 // Possible I2C protocol error - split read of ADC
gke 0:62a1c91a859a 488 I2CBARO.start();
gke 2:90292f8bd179 489 if ( I2CBARO.write(BOSCH_WR) != I2C_ACK ) goto BoschError;
gke 2:90292f8bd179 490 if ( I2CBARO.write(BOSCH_ADC_MSB) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 491 I2CBARO.start(); // restart
gke 2:90292f8bd179 492 if ( I2CBARO.write(BOSCH_RD) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 493 BaroVal.b1 = I2CBARO.read(I2C_NACK);
gke 0:62a1c91a859a 494 I2CBARO.stop();
gke 0:62a1c91a859a 495
gke 0:62a1c91a859a 496 I2CBARO.start();
gke 2:90292f8bd179 497 if ( I2CBARO.write(BOSCH_WR) != I2C_ACK ) goto BoschError;
gke 2:90292f8bd179 498 if ( I2CBARO.write(BOSCH_ADC_LSB) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 499 I2CBARO.start(); // restart
gke 2:90292f8bd179 500 if ( I2CBARO.write(BOSCH_RD) != I2C_ACK ) goto BoschError;
gke 0:62a1c91a859a 501 BaroVal.b0 = I2CBARO.read(I2C_NACK);
gke 0:62a1c91a859a 502 I2CBARO.stop();
gke 0:62a1c91a859a 503
gke 0:62a1c91a859a 504 F.BaroAltitudeValid = true;
gke 0:62a1c91a859a 505 return;
gke 0:62a1c91a859a 506
gke 2:90292f8bd179 507 BoschError:
gke 0:62a1c91a859a 508 I2CBARO.stop();
gke 0:62a1c91a859a 509
gke 2:90292f8bd179 510 I2CError[BOSCH_ID]++;
gke 2:90292f8bd179 511
gke 0:62a1c91a859a 512 F.BaroAltitudeValid = F.HoldingAlt = false;
gke 0:62a1c91a859a 513 if ( State == InFlight ) {
gke 0:62a1c91a859a 514 Stats[BaroFailS]++;
gke 0:62a1c91a859a 515 F.BaroFailure = true;
gke 0:62a1c91a859a 516 }
gke 2:90292f8bd179 517
gke 0:62a1c91a859a 518 } // ReadBoschBaro
gke 0:62a1c91a859a 519
gke 0:62a1c91a859a 520 #define BOSCH_BMP085_TEMP_COEFF 62L
gke 0:62a1c91a859a 521 #define BOSCH_SMD500_TEMP_COEFF 50L
gke 0:62a1c91a859a 522
gke 0:62a1c91a859a 523 int24 CompensatedBoschPressure(uint16 BaroPress, uint16 BaroTemp) {
gke 0:62a1c91a859a 524 static int24 BaroTempComp;
gke 0:62a1c91a859a 525
gke 0:62a1c91a859a 526 if ( BaroType == BaroBMP085 )
gke 0:62a1c91a859a 527 BaroTempComp = (BaroTemp * BOSCH_BMP085_TEMP_COEFF + 64L) >> 7;
gke 0:62a1c91a859a 528 else
gke 0:62a1c91a859a 529 BaroTempComp = (BaroTemp * BOSCH_SMD500_TEMP_COEFF + 8L) >> 4;
gke 0:62a1c91a859a 530
gke 0:62a1c91a859a 531 return ((int24)BaroPress + BaroTempComp - OriginBaroPressure);
gke 0:62a1c91a859a 532
gke 0:62a1c91a859a 533 } // CompensatedBoschPressure
gke 0:62a1c91a859a 534
gke 0:62a1c91a859a 535 void GetBoschBaroAltitude(void) {
gke 0:62a1c91a859a 536 static int24 Temp;
gke 0:62a1c91a859a 537
gke 0:62a1c91a859a 538 if ( mSClock() >= mS[BaroUpdate] ) {
gke 0:62a1c91a859a 539 ReadBoschBaro();
gke 0:62a1c91a859a 540 if ( F.BaroAltitudeValid )
gke 0:62a1c91a859a 541 if ( AcquiringPressure ) {
gke 0:62a1c91a859a 542 BaroPressure = (int24)BaroVal.u16;
gke 0:62a1c91a859a 543 AcquiringPressure = false;
gke 0:62a1c91a859a 544 } else {
gke 0:62a1c91a859a 545 BaroTemperature = (int24)BaroVal.u16;
gke 0:62a1c91a859a 546 AcquiringPressure = true;
gke 0:62a1c91a859a 547
gke 0:62a1c91a859a 548 Temp = CompensatedBoschPressure(BaroPressure, BaroTemperature);
gke 0:62a1c91a859a 549 CompBaroPressure -= BaroQ.B[BaroQ.Head];
gke 0:62a1c91a859a 550 BaroQ.B[BaroQ.Head] = Temp;
gke 0:62a1c91a859a 551 CompBaroPressure += Temp;
gke 0:62a1c91a859a 552 BaroQ.Head = (BaroQ.Head + 1) & (BARO_BUFF_SIZE -1);
gke 0:62a1c91a859a 553
gke 0:62a1c91a859a 554 // Pressure queue has 4 entries corresponding to an average delay at 20Hz of 0.1Sec
gke 0:62a1c91a859a 555 // decreasing pressure is increase in altitude negate and rescale to decimetre altitude
gke 0:62a1c91a859a 556
gke 0:62a1c91a859a 557 BaroRelAltitude = - ( (real32)CompBaroPressure * (real32)P[BaroScale] ) / 1280.0;
gke 0:62a1c91a859a 558
gke 0:62a1c91a859a 559 F.NewBaroValue = F.BaroAltitudeValid;
gke 0:62a1c91a859a 560 }
gke 2:90292f8bd179 561 else
gke 0:62a1c91a859a 562 AcquiringPressure = true;
gke 0:62a1c91a859a 563
gke 0:62a1c91a859a 564 StartBoschBaroADC(AcquiringPressure);
gke 0:62a1c91a859a 565 }
gke 0:62a1c91a859a 566 } // GetBoschBaroAltitude
gke 0:62a1c91a859a 567
gke 0:62a1c91a859a 568 boolean IsBoschBaroActive(void) { // check for Bosch Barometers
gke 0:62a1c91a859a 569 static uint8 r;
gke 0:62a1c91a859a 570
gke 0:62a1c91a859a 571 I2CBARO.start();
gke 1:1e3318a30ddd 572 if ( I2CBARO.write(BOSCH_WR) != I2C_ACK ) goto BoschInactive;
gke 0:62a1c91a859a 573 if ( I2CBARO.write(BOSCH_TYPE) != I2C_ACK ) goto BoschInactive;
gke 0:62a1c91a859a 574 I2CBARO.start(); // restart
gke 1:1e3318a30ddd 575 if ( I2CBARO.write(BOSCH_RD) != I2C_ACK ) goto BoschInactive;
gke 0:62a1c91a859a 576 r = I2CBARO.read(I2C_NACK);
gke 0:62a1c91a859a 577 I2CBARO.stop();
gke 0:62a1c91a859a 578
gke 0:62a1c91a859a 579 if (r == BOSCH_ID_BMP085 )
gke 0:62a1c91a859a 580 BaroType = BaroBMP085;
gke 0:62a1c91a859a 581 else
gke 0:62a1c91a859a 582 BaroType = BaroSMD500;
gke 1:1e3318a30ddd 583
gke 0:62a1c91a859a 584 TrackMinI2CRate(400000);
gke 0:62a1c91a859a 585
gke 0:62a1c91a859a 586 return(true);
gke 0:62a1c91a859a 587
gke 0:62a1c91a859a 588 BoschInactive:
gke 2:90292f8bd179 589
gke 0:62a1c91a859a 590 return(false);
gke 0:62a1c91a859a 591
gke 0:62a1c91a859a 592 } // IsBoschBaroActive
gke 0:62a1c91a859a 593
gke 0:62a1c91a859a 594 void InitBoschBarometer(void) {
gke 0:62a1c91a859a 595 int8 s;
gke 0:62a1c91a859a 596 int24 Temp, CompBaroPressureP;
gke 0:62a1c91a859a 597
gke 0:62a1c91a859a 598 AltitudeUpdateRate = 1000L / BOSCH_PRESS_TEMP_TIME_MS;
gke 0:62a1c91a859a 599
gke 0:62a1c91a859a 600 F.NewBaroValue = false;
gke 0:62a1c91a859a 601 CompBaroPressure = 0;
gke 0:62a1c91a859a 602
gke 0:62a1c91a859a 603 TxString("Temp. \tPressure\r\n");
gke 0:62a1c91a859a 604
gke 0:62a1c91a859a 605 BaroRetries = 0;
gke 0:62a1c91a859a 606 do { // occasional I2C misread of Temperature so keep doing it until the Origin is stable!!
gke 0:62a1c91a859a 607 CompBaroPressureP = CompBaroPressure;
gke 0:62a1c91a859a 608 CompBaroPressure = BaroQ.Head = 0;
gke 0:62a1c91a859a 609
gke 0:62a1c91a859a 610 AcquiringPressure = true;
gke 0:62a1c91a859a 611 StartBoschBaroADC(AcquiringPressure); // Pressure
gke 0:62a1c91a859a 612
gke 0:62a1c91a859a 613 for ( s = 0; s < 4; s++ ) {
gke 0:62a1c91a859a 614 while ( mSClock() < mS[BaroUpdate] );
gke 0:62a1c91a859a 615 ReadBoschBaro(); // Pressure
gke 0:62a1c91a859a 616 BaroPressure = BaroVal.u16;
gke 0:62a1c91a859a 617
gke 0:62a1c91a859a 618 AcquiringPressure = !AcquiringPressure;
gke 0:62a1c91a859a 619 StartBoschBaroADC(AcquiringPressure); // Temperature
gke 0:62a1c91a859a 620 while ( mSClock() < mS[BaroUpdate] );
gke 0:62a1c91a859a 621 ReadBoschBaro();
gke 0:62a1c91a859a 622 BaroTemperature = BaroVal.u16;
gke 0:62a1c91a859a 623
gke 0:62a1c91a859a 624 TxVal32(BaroTemperature,0,HT);
gke 0:62a1c91a859a 625 TxVal32(BaroPressure,0,0);
gke 0:62a1c91a859a 626 TxNextLine();
gke 0:62a1c91a859a 627
gke 0:62a1c91a859a 628 Temp = CompensatedBoschPressure(BaroPressure, BaroTemperature);
gke 0:62a1c91a859a 629 BaroQ.B[s] = Temp;
gke 0:62a1c91a859a 630 CompBaroPressure += Temp;
gke 0:62a1c91a859a 631
gke 0:62a1c91a859a 632 AcquiringPressure = !AcquiringPressure;
gke 0:62a1c91a859a 633 StartBoschBaroADC(AcquiringPressure);
gke 0:62a1c91a859a 634 }
gke 0:62a1c91a859a 635
gke 0:62a1c91a859a 636 } while ( ( ++BaroRetries < BARO_INIT_RETRIES ) && ( abs(CompBaroPressure - CompBaroPressureP) > 12 ) ); // stable within ~0.5M
gke 0:62a1c91a859a 637
gke 0:62a1c91a859a 638 OriginBaroPressure = SRS32(CompBaroPressure, 2);
gke 0:62a1c91a859a 639
gke 0:62a1c91a859a 640 F.BaroAltitudeValid = BaroRetries < BARO_INIT_RETRIES;
gke 0:62a1c91a859a 641 BaroRelAltitudeP = BaroRelAltitude = 0.0;
gke 0:62a1c91a859a 642
gke 0:62a1c91a859a 643 #ifdef SIMULATE
gke 0:62a1c91a859a 644 FakeBaroRelAltitude = 0.0;
gke 0:62a1c91a859a 645 #endif // SIMULATE
gke 0:62a1c91a859a 646
gke 0:62a1c91a859a 647 } // InitBoschBarometer