Skip to content

Commit 21ec6a2

Browse files
authored
Merge pull request #1019 from pimoroni/feature/picovector2-and-layers
PicoVector Enhancements & PicoGraphics Layers
2 parents a3811b8 + 8412534 commit 21ec6a2

File tree

137 files changed

+5367
-2321
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+5367
-2321
lines changed

.github/workflows/micropython.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
types: [created]
88

99
env:
10-
MICROPYTHON_VERSION: v1.24.0
10+
MICROPYTHON_VERSION: v1.25.0
1111
MICROPYTHON_FLAVOUR: micropython
1212

1313
jobs:
@@ -36,12 +36,6 @@ jobs:
3636
board: PIMORONI_TUFTY2040
3737
- name: enviro
3838
board: PICO_W_ENVIRO
39-
- name: galactic_unicorn
40-
board: RPI_PICO_W
41-
- name: cosmic_unicorn
42-
board: RPI_PICO_W
43-
- name: stellar_unicorn
44-
board: RPI_PICO_W
4539

4640
env:
4741
# MicroPython version will be contained in github.event.release.tag_name for releases

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@
2525
[submodule "drivers/mlx90640/src"]
2626
path = drivers/mlx90640/src
2727
url = https://github.com/melexis/mlx90640-library
28+
[submodule "drivers/bme69x/src"]
29+
path = drivers/bme69x/src
30+
url = https://github.com/boschsensortec/BME690_SensorAPI

drivers/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ add_subdirectory(st7567)
4444
add_subdirectory(psram_display)
4545
add_subdirectory(shiftregister)
4646
add_subdirectory(inky73)
47-
add_subdirectory(mlx90640)
47+
add_subdirectory(mlx90640)
48+
add_subdirectory(bme69x)

drivers/bme69x/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include(bme69x.cmake)

drivers/bme69x/bme69x.cmake

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(DRIVER_NAME bme69x)
2+
add_library(${DRIVER_NAME} INTERFACE)
3+
4+
target_sources(${DRIVER_NAME} INTERFACE
5+
${CMAKE_CURRENT_LIST_DIR}/src/bme69x.c
6+
${CMAKE_CURRENT_LIST_DIR}/bme69x.cpp
7+
)
8+
9+
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
10+
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src)
11+
12+
13+
# We can't control the uninitialized result variables in the BME68X API
14+
# so demote unitialized to a warning for this target.
15+
target_compile_options(${DRIVER_NAME} INTERFACE -Wno-error=uninitialized)

drivers/bme69x/bme69x.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#include "bme69x.hpp"
2+
#include "pico/stdlib.h"
3+
4+
namespace pimoroni {
5+
bool BME69X::init() {
6+
int8_t result = 0;
7+
8+
if(interrupt != PIN_UNUSED) {
9+
gpio_set_function(interrupt, GPIO_FUNC_SIO);
10+
gpio_set_dir(interrupt, GPIO_IN);
11+
gpio_pull_up(interrupt);
12+
}
13+
14+
i2c_interface.i2c = i2c;
15+
i2c_interface.address = address;
16+
17+
device.intf_ptr = &i2c_interface;
18+
device.intf = bme69x_intf::BME69X_I2C_INTF;
19+
device.read = (bme69x_read_fptr_t)&read_bytes;
20+
device.write = (bme69x_write_fptr_t)&write_bytes;
21+
device.delay_us = (bme69x_delay_us_fptr_t)&delay_us;
22+
device.amb_temp = 20;
23+
24+
result = bme69x_init(&device);
25+
bme69x_check_rslt("bme69x_init", result);
26+
if(result != BME69X_OK) return false;
27+
28+
result = bme69x_get_conf(&conf, &device);
29+
bme69x_check_rslt("bme69x_get_conf", result);
30+
if(result != BME69X_OK) return false;
31+
32+
configure(BME69X_FILTER_OFF, BME69X_ODR_NONE, BME69X_OS_16X, BME69X_OS_1X, BME69X_OS_2X);
33+
34+
return true;
35+
}
36+
37+
bool BME69X::configure(uint8_t filter, uint8_t odr, uint8_t os_humidity, uint8_t os_pressure, uint8_t os_temp) {
38+
int8_t result = 0;
39+
40+
conf.filter = filter;
41+
conf.odr = odr;
42+
conf.os_hum = os_humidity;
43+
conf.os_pres = os_pressure;
44+
conf.os_temp = os_temp;
45+
46+
bme69x_set_conf(&conf, &device);
47+
bme69x_check_rslt("bme69x_set_conf", result);
48+
if(result != BME69X_OK) return false;
49+
50+
return true;
51+
}
52+
53+
bool BME69X::read_forced(bme69x_data *data, uint16_t heater_temp, uint16_t heater_duration) {
54+
int8_t result = 0;
55+
uint8_t n_fields;
56+
uint32_t delay_period;
57+
58+
heatr_conf.enable = BME69X_ENABLE;
59+
heatr_conf.heatr_temp = heater_temp;
60+
heatr_conf.heatr_dur = heater_duration;
61+
result = bme69x_set_heatr_conf(BME69X_FORCED_MODE, &heatr_conf, &device);
62+
bme69x_check_rslt("bme69x_set_heatr_conf", result);
63+
if(result != BME69X_OK) return false;
64+
65+
result = bme69x_set_op_mode(BME69X_FORCED_MODE, &device);
66+
bme69x_check_rslt("bme69x_set_op_mode", result);
67+
if(result != BME69X_OK) return false;
68+
69+
delay_period = bme69x_get_meas_dur(BME69X_FORCED_MODE, &conf, &device) + (heatr_conf.heatr_dur * 1000);
70+
// Could probably just call sleep_us here directly, I guess the API uses this internally
71+
device.delay_us(delay_period, device.intf_ptr);
72+
73+
result = bme69x_get_data(BME69X_FORCED_MODE, data, &n_fields, &device);
74+
bme69x_check_rslt("bme69x_get_data", result);
75+
if(result != BME69X_OK) return false;
76+
77+
return true;
78+
}
79+
80+
/*
81+
Will read profile_length results with the given temperatures and duration multipliers into the results array.
82+
Blocks until it has a valid result for each temp/duration, and returns the entire set in the given order.
83+
*/
84+
bool BME69X::read_parallel(bme69x_data *results, uint16_t *profile_temps, uint16_t *profile_durations, size_t profile_length) {
85+
int8_t result;
86+
bme69x_data data[3]; // Parallel & Sequential mode read 3 simultaneous fields
87+
uint8_t n_fields;
88+
uint32_t delay_period;
89+
90+
heatr_conf.enable = BME69X_ENABLE;
91+
heatr_conf.heatr_temp_prof = profile_temps;
92+
heatr_conf.heatr_dur_prof = profile_durations;
93+
heatr_conf.profile_len = profile_length;
94+
heatr_conf.shared_heatr_dur = 140 - (bme69x_get_meas_dur(BME69X_PARALLEL_MODE, &conf, &device) / 1000);
95+
result = bme69x_set_heatr_conf(BME69X_PARALLEL_MODE, &heatr_conf, &device);
96+
bme69x_check_rslt("bme69x_set_heatr_conf", result);
97+
if(result != BME69X_OK) return false;
98+
99+
result = bme69x_set_op_mode(BME69X_PARALLEL_MODE, &device);
100+
bme69x_check_rslt("bme69x_set_op_mode", result);
101+
if(result != BME69X_OK) return false;
102+
103+
while (1) {
104+
delay_period = bme69x_get_meas_dur(BME69X_PARALLEL_MODE, &conf, &device) + (heatr_conf.shared_heatr_dur * 1000);
105+
device.delay_us(delay_period, device.intf_ptr);
106+
107+
result = bme69x_get_data(BME69X_PARALLEL_MODE, data, &n_fields, &device);
108+
if(result == BME69X_W_NO_NEW_DATA) continue;
109+
bme69x_check_rslt("bme69x_get_data", result);
110+
if(result != BME69X_OK) return false;
111+
112+
for(auto i = 0u; i < n_fields; i++) {
113+
results[data[i].gas_index] = data[i];
114+
115+
if(data[i].gas_index == profile_length - 1) return true;
116+
}
117+
}
118+
119+
return true;
120+
}
121+
}

drivers/bme69x/bme69x.hpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#pragma once
2+
3+
#include "hardware/i2c.h"
4+
#include "hardware/gpio.h"
5+
#include "bme69x.h"
6+
#include "bme69x_defs.h"
7+
#include "common/pimoroni_i2c.hpp"
8+
#include "stdio.h"
9+
10+
namespace pimoroni {
11+
class BME69X {
12+
public:
13+
static const uint8_t DEFAULT_I2C_ADDRESS = 0x76;
14+
static const uint8_t ALTERNATE_I2C_ADDRESS = 0x77;
15+
16+
struct i2c_intf_ptr {
17+
I2C *i2c;
18+
int8_t address;
19+
};
20+
21+
i2c_intf_ptr i2c_interface;
22+
23+
bool debug = true;
24+
25+
bool init();
26+
bool configure(uint8_t filter, uint8_t odr, uint8_t os_humidity, uint8_t os_pressure, uint8_t os_temp);
27+
bool read_forced(bme69x_data *data, uint16_t heater_temp=300, uint16_t heater_duration=100);
28+
bool read_parallel(bme69x_data *results, uint16_t *profile_temps, uint16_t *profile_durations, size_t profile_length);
29+
30+
BME69X() : BME69X(new I2C()) {}
31+
BME69X(uint8_t address, uint interrupt = PIN_UNUSED) : BME69X(new I2C(), address, interrupt) {}
32+
BME69X(I2C *i2c, uint8_t address = DEFAULT_I2C_ADDRESS, uint interrupt = PIN_UNUSED) : i2c(i2c), address(address), interrupt(interrupt) {}
33+
34+
I2C *get_i2c() {return i2c;}
35+
uint get_int() {return PIN_UNUSED;}
36+
37+
// Bindings for bme69x_dev
38+
static int write_bytes(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) {
39+
BME69X::i2c_intf_ptr* i2c = (BME69X::i2c_intf_ptr *)intf_ptr;
40+
41+
uint8_t buffer[length + 1];
42+
buffer[0] = reg_addr;
43+
for(auto x = 0u; x < length; x++) {
44+
buffer[x + 1] = reg_data[x];
45+
}
46+
47+
int result = i2c->i2c->write_blocking(i2c->address, buffer, length + 1, false);
48+
49+
return result == PICO_ERROR_GENERIC ? 1 : 0;
50+
};
51+
52+
static int read_bytes(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) {
53+
BME69X::i2c_intf_ptr* i2c = (BME69X::i2c_intf_ptr *)intf_ptr;
54+
55+
int result = i2c->i2c->write_blocking(i2c->address, &reg_addr, 1, true);
56+
result = i2c->i2c->read_blocking(i2c->address, reg_data, length, false);
57+
58+
return result == PICO_ERROR_GENERIC ? 1 : 0;
59+
};
60+
61+
static void delay_us(uint32_t period, void *intf_ptr) {
62+
sleep_us(period);
63+
}
64+
65+
/* From BME69X API examples/common/common.c */
66+
void bme69x_check_rslt(const char api_name[], int8_t rslt)
67+
{
68+
if(!debug) return;
69+
switch (rslt)
70+
{
71+
case BME69X_OK:
72+
/* Do nothing */
73+
break;
74+
case BME69X_E_NULL_PTR:
75+
printf("%s: Error [%d] : Null pointer\r\n", api_name, rslt);
76+
break;
77+
case BME69X_E_COM_FAIL:
78+
printf("%s: Error [%d] : Communication failure\r\n", api_name, rslt);
79+
break;
80+
case BME69X_E_INVALID_LENGTH:
81+
printf("%s: Error [%d] : Incorrect length parameter\r\n", api_name, rslt);
82+
break;
83+
case BME69X_E_DEV_NOT_FOUND:
84+
printf("%s: Error [%d] : Device not found\r\n", api_name, rslt);
85+
break;
86+
case BME69X_E_SELF_TEST:
87+
printf("%s: Error [%d] : Self test error\r\n", api_name, rslt);
88+
break;
89+
case BME69X_W_NO_NEW_DATA:
90+
printf("%s: Warning [%d] : No new data found\r\n", api_name, rslt);
91+
break;
92+
default:
93+
printf("%s: Error [%d] : Unknown error code\r\n", api_name, rslt);
94+
break;
95+
}
96+
}
97+
98+
private:
99+
bme69x_dev device;
100+
bme69x_conf conf;
101+
bme69x_heatr_conf heatr_conf;
102+
103+
I2C *i2c;
104+
105+
int8_t address = DEFAULT_I2C_ADDRESS;
106+
uint interrupt = I2C_DEFAULT_INT;
107+
};
108+
}

drivers/bme69x/src

Submodule src added at 4381e37

0 commit comments

Comments
 (0)