Add bmp180 library.

pull/1/head
Luigi Cruz 2021-03-02 02:31:51 -03:00
rodzic 89be513e1b
commit fc390b52a9
12 zmienionych plików z 413 dodań i 0 usunięć

4
.gitignore vendored
Wyświetl plik

@ -50,3 +50,7 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf
build
.cache
pressure.log

9
.gitmodules vendored 100644
Wyświetl plik

@ -0,0 +1,9 @@
[submodule "pico-examples"]
path = pico-examples
url = git@github.com:raspberrypi/pico-examples.git
[submodule "pico-sdk"]
path = pico-sdk
url = git@github.com:raspberrypi/pico-sdk.git
[submodule "pico-extras"]
path = pico-extras
url = git@github.com:raspberrypi/pico-extras.git

9
CMakeLists.txt 100644
Wyświetl plik

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.12)
include(pico_sdk_import.cmake)
project(pico-stuff)
pico_sdk_init()
add_subdirectory(bmp180)

Wyświetl plik

@ -1,2 +1,18 @@
# pico-stuff
I add my Pi Pico (RP2040) stuff here.
## Header-Only Libraries
- BMP180
## Installation
```bash
$ git clone --recursive git@github.com:luigifcruz/pico-stuff.git
$ cd pico-stuff
$ mkdir build
$ cd build
$ PICO_SDK_PATH=../pico-sdk cmake ..
$ make -j$(nproc -n)
```
## Debug
For debug add `#define DEBUG` before the `#include` of a header-only library.

Wyświetl plik

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.12)
project(pico-bmp180)
add_executable(bmp180
test.c
)
target_link_libraries(bmp180
pico_stdlib
pico_stdio
hardware_i2c
)
pico_enable_stdio_usb(bmp180 1)
pico_enable_stdio_uart(bmp180 0)
pico_add_extra_outputs(bmp180)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

255
bmp180/bmp180.h 100644
Wyświetl plik

@ -0,0 +1,255 @@
#ifndef BMP180_H
#define BMP180_H
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdio.h"
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#define BMP_REG_CONTROL 0xF4
#define BMP_REG_RESULT 0xF6
#define BMP_COM_TEMP 0x2E
#define BMP_COM_PRES 0x34
#define BMP_CALIB_COEFF_LEN 0x16
#define BMP_CALIB_COEFF_REG 0xAA
#define BMP_CHIP_ID_REG 0xD0
#define BMP_CHIP_ID_VAL 0x55
#define BMP_MIN_TEMP_THRESHOLD -40
#define BMP_MAX_TEMP_THRESHOLD +85
#define BMP_TEMP_DELAY 5
#define ASSERT_OK(X) { if (X == false) return false; };
typedef struct {
int16_t AC1;
int16_t AC2;
int16_t AC3;
uint16_t AC4;
uint16_t AC5;
uint16_t AC6;
int16_t B1;
int16_t B2;
int16_t MB;
int16_t MC;
int16_t MD;
} bmp_calib_param_t;
typedef struct {
int addr;
int rate;
int scl;
int sda;
i2c_inst_t* inst;
} i2c_t;
typedef struct {
i2c_t i2c;
uint8_t oss;
float temperature;
int32_t pressure;
bmp_calib_param_t calib;
int32_t B5;
} bmp_t;
const uint32_t oss_delay[] = {5, 8, 14, 26};
bool bmp_check_chip_id(bmp_t* bmp) {
uint8_t chip_id_reg = BMP_CHIP_ID_REG;
uint8_t chip_id_val[1];
i2c_write_blocking(bmp->i2c.inst, bmp->i2c.addr, &chip_id_reg, 1, true);
i2c_read_blocking(bmp->i2c.inst, bmp->i2c.addr, chip_id_val, 1, false);
if (chip_id_val[0] != BMP_CHIP_ID_VAL) {
#ifdef DEBUG
printf("Returned Chip ID: 0x%02x\n", chip_id_val[0]);
printf("Check your I2C configuration and connection.\n");
#endif
return false;
}
return true;
}
bool bmp_get_calib_coeffs(bmp_t* bmp) {
uint8_t calib_coeffs_reg = BMP_CALIB_COEFF_REG;
uint8_t calib_coeffs_val[BMP_CALIB_COEFF_LEN];
i2c_write_blocking(bmp->i2c.inst, bmp->i2c.addr, &calib_coeffs_reg, 1, true);
i2c_read_blocking(bmp->i2c.inst, bmp->i2c.addr, calib_coeffs_val, BMP_CALIB_COEFF_LEN, false);
int16_t* data = (int16_t*)&bmp->calib;
for (int i = 0, j = 1; i < BMP_CALIB_COEFF_LEN / 2; i++, j += 2) {
data[i] = (calib_coeffs_val[i * 2] << 8) | calib_coeffs_val[j];
if ((data[i] == 0) | (data[i] == -1)) {
#ifdef DEBUG
printf("Calibation data invalid.\n");
#endif
return false;
}
}
#ifdef DEBUG
printf("==== CALIBRATION COEFFS ====\n");
printf("AC1: %d\n", bmp->calib.AC1);
printf("AC2: %d\n", bmp->calib.AC2);
printf("AC3: %d\n", bmp->calib.AC3);
printf("AC4: %d\n", bmp->calib.AC4);
printf("AC5: %d\n", bmp->calib.AC5);
printf("AC6: %d\n", bmp->calib.AC6);
printf("B1: %d\n", bmp->calib.B1);
printf("B2: %d\n", bmp->calib.B2);
printf("MB: %d\n", bmp->calib.MB);
printf("MC: %d\n", bmp->calib.MC);
printf("MD: %d\n", bmp->calib.MD);
printf("============================\n");
#endif
return true;
}
uint32_t bmp_start_temperature(bmp_t* bmp) {
uint8_t temp_reg[] = {
BMP_REG_CONTROL,
BMP_COM_TEMP
};
i2c_write_blocking(bmp->i2c.inst, bmp->i2c.addr, temp_reg, 2, false);
return BMP_TEMP_DELAY;
}
bool bmp_read_temperature(bmp_t* bmp) {
uint8_t temp_reg = BMP_REG_RESULT;
uint8_t temp_val[2];
i2c_write_blocking(bmp->i2c.inst, bmp->i2c.addr, &temp_reg, 1, true);
if (i2c_read_blocking(bmp->i2c.inst, bmp->i2c.addr, temp_val, 2, false) != 2) {
#ifdef DEBUG
printf("Wrong read length.\n");
#endif
return false;
}
int16_t UT = (temp_val[0] << 8) + temp_val[1];
if (UT == (int16_t)0x8000) {
#ifdef DEBUG
printf("Non-initialized register detected.\n");
#endif
return false;
}
int32_t X1 = (((int32_t)UT - bmp->calib.AC6) * bmp->calib.AC5) >> 15;
int32_t X2 = (bmp->calib.MC << 11) / (X1 + bmp->calib.MD);
bmp->B5 = X1 + X2;
float temp = ((bmp->B5 + 8) >> 4) * 0.1f;
if ((temp <= BMP_MIN_TEMP_THRESHOLD) || (temp >= BMP_MAX_TEMP_THRESHOLD)) {
#ifdef DEBUG
printf("Temperature beyond threshold: %f\n", temp);
#endif
return false;
}
bmp->temperature = temp;
return true;
}
uint32_t bmp_start_pressure(bmp_t* bmp) {
uint8_t pres_reg[] = {
BMP_REG_CONTROL,
BMP_COM_PRES + (bmp->oss << 6)
};
i2c_write_blocking(bmp->i2c.inst, bmp->i2c.addr, pres_reg, 2, false);
return oss_delay[bmp->oss];
}
bool bmp_read_pressure(bmp_t* bmp) {
uint8_t pres_reg = BMP_REG_RESULT;
uint8_t pres_val[3];
i2c_write_blocking(bmp->i2c.inst, bmp->i2c.addr, &pres_reg, 1, true);
if (i2c_read_blocking(bmp->i2c.inst, bmp->i2c.addr, pres_val, 3, false) != 3) {
#ifdef DEBUG
printf("Wrong read length.\n");
#endif
return false;
}
int32_t UP = ((pres_val[0] << 16) + (pres_val[1] << 8) + pres_val[2]) >> (8 - bmp->oss);
int32_t X1, X2, X3, B3, B6, p = 0;
uint32_t B4, B7 = 0;
B6 = bmp->B5 - 4000;
X1 = (bmp->calib.B2 * ((B6 * B6) >> 12)) >> 11;
X2 = (bmp->calib.AC2 * B6) >> 11;
X3 = X1 + X2;
B3 = (((bmp->calib.AC1 * 4 + X3) << bmp->oss) + 2) / 4;
X1 = (bmp->calib.AC3 * B6) >> 13;
X2 = (bmp->calib.B1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = (bmp->calib.AC4 * (uint32_t)(X3 + 32768)) >> 15;
B7 = ((uint32_t)(UP) - B3) * (50000 >> bmp->oss);
if (B7 < 0x80000000) {
p = (B7 * 2) / B4;
} else {
p = (B7 / B4) * 2;
}
X1 = (p >> 8) * (p >> 8);
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
bmp->pressure = p + ((X1 + X2 + 3791) >> 4);
return true;
}
bool bmp_get_temperature(bmp_t* bmp) {
sleep_ms(bmp_start_temperature(bmp));
return bmp_read_temperature(bmp);
}
// User must call bmp_get_temperature() before calling this method.
// Or use the combo bmp_get_pressure_temperature().
bool bmp_get_pressure(bmp_t* bmp) {
sleep_ms(bmp_start_pressure(bmp));
return bmp_read_pressure(bmp);
}
bool bmp_get_pressure_temperature(bmp_t* bmp) {
bool res = true;
res &= bmp_get_temperature(bmp);
res &= bmp_get_pressure(bmp);
return res;
}
bool bmp_init(bmp_t* bmp) {
i2c_init(bmp->i2c.inst, bmp->i2c.rate);
if (bmp->oss < 0 || bmp->oss > 3) {
#ifdef DEBUG
printf("Invalid over-sampling rate (%d). Valid 0 to 3.\n", bmp->oss);
#endif
return false;
}
gpio_set_function(bmp->i2c.scl, GPIO_FUNC_I2C);
gpio_set_function(bmp->i2c.sda, GPIO_FUNC_I2C);
gpio_pull_up(bmp->i2c.scl);
gpio_pull_up(bmp->i2c.sda);
sleep_ms(100);
ASSERT_OK(bmp_check_chip_id(bmp));
ASSERT_OK(bmp_get_calib_coeffs(bmp));
return true;
}
#endif

34
bmp180/test.c 100644
Wyświetl plik

@ -0,0 +1,34 @@
#include <stdio.h>
#define DEBUG
#include "bmp180.h"
int main() {
stdio_init_all();
getchar();
printf("Hello from Pi Pico!\n");
bmp_t bmp;
bmp.oss = 0;
bmp.i2c.addr = 0x77;
bmp.i2c.inst = i2c1;
bmp.i2c.rate = 400000;
bmp.i2c.scl = 27;
bmp.i2c.sda = 26;
if (!bmp_init(&bmp))
return 1;
while (true) {
if (!bmp_get_pressure_temperature(&bmp))
return 1;
printf("BMP180 Temperature (C): %f\n", bmp.temperature);
printf("BMP180 Pressure (hPa): %f\n", (float)bmp.pressure / 100.0);
sleep_ms(250);
}
printf("Bye from pico!\n\n");
return 0;
}

Wyświetl plik

@ -0,0 +1 @@
build/compile_commands.json

1
pico-examples 160000

@ -0,0 +1 @@
Subproject commit 3617ade198cfdfca24c047f02a0d6948c1c8fdbf

1
pico-extras 160000

@ -0,0 +1 @@
Subproject commit 89b8071d2a99e1af25b01c6cb0380ae0216053ca

1
pico-sdk 160000

@ -0,0 +1 @@
Subproject commit 2d5789eca89658a7f0a01e2d6010c0f254605d72

Wyświetl plik

@ -0,0 +1,62 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})