34 #if defined(PIOS_INCLUDE_MS5611)
42 #define PIOS_MS5611_OVERSAMPLING oversampling
43 #define MS5611_TASK_PRIORITY PIOS_THREAD_PRIO_HIGHEST
44 #define MS5611_TASK_STACK_BYTES 512
47 #define MS5611_I2C_ADDR_0x76 0x76
48 #define MS5611_I2C_ADDR_0x77 0x77
49 #define MS5611_RESET 0x1E
50 #define MS5611_CALIB_ADDR 0xA2
51 #define MS5611_CALIB_LEN 16
52 #define MS5611_ADC_READ 0x00
53 #define MS5611_PRES_ADDR 0x40
54 #define MS5611_TEMP_ADDR 0x50
55 #define MS5611_ADC_MSB 0xF6
56 #define MS5611_P0 101.3250f
59 uint8_t ms5611_i2c_addr;
62 static int32_t PIOS_MS5611_Read(uint8_t address, uint8_t * buffer, uint8_t len);
63 static int32_t PIOS_MS5611_WriteCommand(uint8_t command);
64 static void PIOS_MS5611_Task(
void *parameters);
70 enum pios_ms5611_dev_magic {
71 PIOS_MS5611_DEV_MAGIC = 0xefba8e1d,
74 enum conversion_type {
82 struct pios_thread *
task;
85 int64_t pressure_unscaled;
86 int64_t temperature_unscaled;
87 uint16_t calibration[6];
88 enum conversion_type current_conversion_type;
89 enum pios_ms5611_dev_magic
magic;
94 static struct ms5611_dev *dev;
99 static struct ms5611_dev * PIOS_MS5611_alloc(
void)
101 struct ms5611_dev *ms5611_dev;
103 ms5611_dev = (
struct ms5611_dev *)
PIOS_malloc(
sizeof(*ms5611_dev));
107 memset(ms5611_dev, 0,
sizeof(*ms5611_dev));
110 if (ms5611_dev->queue == NULL) {
115 ms5611_dev->magic = PIOS_MS5611_DEV_MAGIC;
127 static int32_t PIOS_MS5611_Validate(
struct ms5611_dev *dev)
131 if (dev->magic != PIOS_MS5611_DEV_MAGIC)
133 if (dev->i2c_id == 0)
143 dev = (
struct ms5611_dev *)PIOS_MS5611_alloc();
147 dev->i2c_id = i2c_device;
151 if (dev->cfg->use_0x76_address ==
true)
152 ms5611_i2c_addr = MS5611_I2C_ADDR_0x76;
154 ms5611_i2c_addr = MS5611_I2C_ADDR_0x77;
156 if (PIOS_MS5611_WriteCommand(MS5611_RESET) != 0)
165 PIOS_MS5611_Read(MS5611_CALIB_ADDR +
i * 2, data, 2);
166 dev->calibration[
i] = (data[0] << 8) | data[1];
172 PIOS_MS5611_Task,
"pios_ms5611", MS5611_TASK_STACK_BYTES, NULL, MS5611_TASK_PRIORITY);
183 static int32_t PIOS_MS5611_ClaimDevice(
void)
194 static int32_t PIOS_MS5611_ReleaseDevice(
void)
206 static int32_t PIOS_MS5611_StartADC(
enum conversion_type
type)
208 if (PIOS_MS5611_Validate(dev) != 0)
213 case TEMPERATURE_CONV:
214 while (PIOS_MS5611_WriteCommand(MS5611_TEMP_ADDR + dev->cfg->oversampling) != 0)
218 while (PIOS_MS5611_WriteCommand(MS5611_PRES_ADDR + dev->cfg->oversampling) != 0)
225 dev->current_conversion_type =
type;
233 static int32_t PIOS_MS5611_GetDelay()
235 if (PIOS_MS5611_Validate(dev) != 0)
238 switch(dev->cfg->oversampling) {
259 static int32_t PIOS_MS5611_ReadADC(
void)
261 if (PIOS_MS5611_Validate(dev) != 0)
266 static int64_t delta_temp;
267 static int64_t temperature;
270 if (dev->current_conversion_type == TEMPERATURE_CONV) {
271 uint32_t raw_temperature;
273 if (PIOS_MS5611_Read(MS5611_ADC_READ, data, 3) != 0)
276 raw_temperature = (data[0] << 16) | (data[1] << 8) | data[2];
278 delta_temp = (int32_t)raw_temperature - (dev->calibration[4] << 8);
279 temperature = 2000 + ((delta_temp * dev->calibration[5]) >> 23);
280 dev->temperature_unscaled = temperature;
283 if (temperature < 2000)
284 dev->temperature_unscaled -= (delta_temp * delta_temp) >> 31;
289 uint32_t raw_pressure;
292 if (PIOS_MS5611_Read(MS5611_ADC_READ, data, 3) != 0)
295 raw_pressure = (data[0] << 16) | (data[1] << 8) | (data[2] << 0);
297 offset = ((int64_t)dev->calibration[1] << 16) + (((int64_t)dev->calibration[3] * delta_temp) >> 7);
298 sens = (int64_t)dev->calibration[0] << 15;
299 sens = sens + ((((int64_t) dev->calibration[2]) * delta_temp) >> 8);
302 if (temperature < 2000) {
303 offset -= (5 * (temperature - 2000) * (temperature - 2000)) >> 1;
304 sens -= (5 * (temperature - 2000) * (temperature - 2000)) >> 2;
306 if (dev->temperature_unscaled < -1500) {
307 offset -= 7 * (temperature + 1500) * (temperature + 1500);
308 sens -= (11 * (temperature + 1500) * (temperature + 1500)) >> 1;
312 dev->pressure_unscaled = ((((int64_t)raw_pressure * sens) >> 21) - offset) >> 15;
326 static int32_t PIOS_MS5611_Read(uint8_t address, uint8_t *buffer, uint8_t len)
328 if (PIOS_MS5611_Validate(dev) != 0)
334 .addr = ms5611_i2c_addr,
341 .addr = ms5611_i2c_addr,
359 static int32_t PIOS_MS5611_WriteCommand(uint8_t command)
361 if (PIOS_MS5611_Validate(dev) != 0)
367 .addr = ms5611_i2c_addr,
381 int32_t PIOS_MS5611_Test()
383 if (PIOS_MS5611_Validate(dev) != 0)
386 PIOS_MS5611_ClaimDevice();
387 PIOS_MS5611_StartADC(TEMPERATURE_CONV);
389 PIOS_MS5611_ReadADC();
390 PIOS_MS5611_ReleaseDevice();
392 PIOS_MS5611_ClaimDevice();
393 PIOS_MS5611_StartADC(PRESSURE_CONV);
395 PIOS_MS5611_ReadADC();
396 PIOS_MS5611_ReleaseDevice();
399 if (dev->temperature_unscaled < -4000 ||
400 dev->temperature_unscaled > 8500 ||
401 dev->pressure_unscaled < 1000 ||
402 dev->pressure_unscaled > 120000)
408 static void PIOS_MS5611_Task(
void *parameters)
411 uint32_t temp_press_interleave_count = 1;
412 int32_t read_adc_result = 0;
416 --temp_press_interleave_count;
418 if (temp_press_interleave_count == 0)
421 PIOS_MS5611_ClaimDevice();
422 PIOS_MS5611_StartADC(TEMPERATURE_CONV);
424 PIOS_MS5611_ReadADC();
425 PIOS_MS5611_ReleaseDevice();
427 temp_press_interleave_count = dev->cfg->temperature_interleaving;
428 if (temp_press_interleave_count == 0)
429 temp_press_interleave_count = 1;
433 PIOS_MS5611_ClaimDevice();
434 PIOS_MS5611_StartADC(PRESSURE_CONV);
436 read_adc_result = PIOS_MS5611_ReadADC();
437 PIOS_MS5611_ReleaseDevice();
441 data.
temperature = ((float) dev->temperature_unscaled) / 100.0f;
442 data.pressure = ((float) dev->pressure_unscaled) / 1000.0f;
443 data.altitude = 44330.0f * (1.0f - powf(data.pressure / MS5611_P0, (1.0f / 5.255f)));
445 if (read_adc_result == 0) {
struct pios_queue * PIOS_Queue_Create(size_t queue_length, size_t item_size)
#define PIOS_SEMAPHORE_TIMEOUT_MAX
Main PiOS header to include all the compiled in PiOS options.
void * PIOS_malloc(size_t size)
bool PIOS_Queue_Send(struct pios_queue *queuep, const void *itemp, uint32_t timeout_ms)
uint8_t data[XFER_BYTES_PER_PACKET]
Configuration structure for the MS5611 driver.
static struct flyingpicmd_cfg_fa cfg
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
struct pios_i2c_adapter * pios_i2c_t
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
int32_t PIOS_SENSORS_Register(enum pios_sensor_type type, struct pios_queue *queue)
Register a queue-based sensor with the PIOS_SENSORS interface.
static TaskInfoRunningElem task
Pios sensor structure for generic baro data.
bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
Gives binary semaphore.
int32_t PIOS_I2C_Transfer(pios_i2c_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
void PIOS_free(void *buf)
void PIOS_Thread_Sleep(uint32_t time_ms)
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
static struct pios_queue * queue
int32_t PIOS_MS5611_Init(const struct pios_ms5611_cfg *cfg, pios_i2c_t i2c_device)
#define PIOS_Assert(test)
int32_t PIOS_DELAY_WaitmS(uint32_t mS)