From dcf04e5db780a735da33d81e4ef37ce041eedbe2 Mon Sep 17 00:00:00 2001 From: "Luigi F. Cruz" Date: Sun, 29 Jan 2023 19:50:05 -0800 Subject: [PATCH] Add altimeter app. --- apps/CMakeLists.txt | 3 +- apps/altimeter/CMakeLists.txt | 14 +++ apps/altimeter/test.c | 173 ++++++++++++++++++++++++++++++++++ apps/altimeter/visualize.py | 36 +++++++ 4 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 apps/altimeter/CMakeLists.txt create mode 100644 apps/altimeter/test.c create mode 100644 apps/altimeter/visualize.py diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 79ee983..478bd0a 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -3,4 +3,5 @@ add_subdirectory(tcp_server) add_subdirectory(adc_dma_chain) add_subdirectory(piccolosdr) add_subdirectory(barometer) -add_subdirectory(filesystem) \ No newline at end of file +add_subdirectory(filesystem) +add_subdirectory(altimeter) \ No newline at end of file diff --git a/apps/altimeter/CMakeLists.txt b/apps/altimeter/CMakeLists.txt new file mode 100644 index 0000000..8586402 --- /dev/null +++ b/apps/altimeter/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.12) + +project(pico-altimeter) + +add_executable(altimeter test.c) + +target_link_libraries(altimeter LINK_PUBLIC littlefs bmp390) + +pico_add_extra_outputs(altimeter) + +pico_enable_stdio_usb(altimeter 1) +pico_enable_stdio_uart(altimeter 0) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) \ No newline at end of file diff --git a/apps/altimeter/test.c b/apps/altimeter/test.c new file mode 100644 index 0000000..5b6f681 --- /dev/null +++ b/apps/altimeter/test.c @@ -0,0 +1,173 @@ +#include +#include + +#include "pico/stdio.h" +#include "pico/stdlib.h" + +#include +#include + +static lfs_t lfs; +static struct lfs_config cfg; + +uint32_t read_boot_count(bool increment) { + uint32_t boot_count = 0; + lfs_file_t boot_count_file; + lfs_file_open(&lfs, &boot_count_file, "boot_count", LFS_O_RDWR | LFS_O_CREAT); + lfs_file_read(&lfs, &boot_count_file, &boot_count, sizeof(boot_count)); + + if (increment) { + boot_count += 1; + lfs_file_rewind(&lfs, &boot_count_file); + lfs_file_write(&lfs, &boot_count_file, &boot_count, sizeof(boot_count)); + } + + lfs_file_close(&lfs, &boot_count_file); + + return boot_count; +} + +void reset_recordings() { + lfs_format(&lfs, &cfg); + lfs_mount(&lfs, &cfg); +} + +void start_altimeter_mode() { + uint32_t boot_count = read_boot_count(true); + printf("Current recoding index: %d\n", boot_count); + + char filename[64] = {0}; + sprintf(filename, "REC_%03d", boot_count); + printf("Creating recording file: %s\n", filename); + lfs_file_t recording_file; + lfs_file_open(&lfs, &recording_file, filename, LFS_O_RDWR | LFS_O_CREAT); + + bmp_t bmp; + bmp.oss = 5; + bmp.i2c.addr = 0x77; + bmp.i2c.inst = i2c1; + bmp.i2c.rate = 400000; + bmp.i2c.scl = 3; + bmp.i2c.sda = 2; + + printf("Starting BMP390...\n"); + if (!bmp_init(&bmp)) { + return; + } + + while(true) { + if (!bmp_get_pressure_temperature(&bmp)) { + continue; + } + + printf("---------------------------------------------\n"); + printf("Temperature (ºC): %f\n", bmp.temperature); + printf("Pressure (hPa): %f\n", bmp.pressure); + printf("Altitude (m): %f\n", bmp.altitude); + + lfs_file_write(&lfs, &recording_file, &bmp.temperature, sizeof(float)); + lfs_file_write(&lfs, &recording_file, &bmp.pressure, sizeof(float)); + lfs_file_sync(&lfs, &recording_file); + + sleep_ms(250); + } + + lfs_file_close(&lfs, &recording_file); +} + +void dump_recording_file(uint32_t index) { + printf("<======"); + + char filename[64] = {0}; + sprintf(filename, "REC_%03d", index); + + lfs_file_t recording_file; + lfs_file_open(&lfs, &recording_file, filename, LFS_O_RDWR); + + int32_t file_size = lfs_file_size(&lfs, &recording_file); + + uint8_t read_buffer[128]; + for (int32_t seek = 0; seek < file_size; seek += sizeof(read_buffer)) { + lfs_file_read(&lfs, &recording_file, read_buffer, sizeof(read_buffer)); + + for (int32_t i = 0; i < sizeof(read_buffer); i++) { + printf("%02X", read_buffer[i]); + } + } + + lfs_file_close(&lfs, &recording_file); + + printf("======>\n"); +} + +int main(void) { + stdio_init_all(); + + sleep_ms(2500); + + printf("Hello from Pi Pico!\n"); + + printf("Checking hardware capabilities...\n"); + lfs_rp2040_init(&cfg); + + printf("Mounting filesystem...\n"); + if (lfs_mount(&lfs, &cfg)) { + lfs_format(&lfs, &cfg); + lfs_mount(&lfs, &cfg); + } + + printf("Filesystem Usage (blocks): %d/%d\n", lfs_fs_size(&lfs), cfg.block_count); + printf("Automatically starting altimeter in 5 seconds...\n"); + printf("Press 'X' to enter in CLI mode.\n"); + + int elapsed = 0; + int iteration_time = 50; + while (getchar_timeout_us(0) != 'X') { + sleep_ms(iteration_time); + elapsed += iteration_time; + + if (elapsed >= 5000) { + start_altimeter_mode(); + } + } + + printf("Available recordings: %d\n", read_boot_count(false)); + printf("Commands:\n"); + printf(" D - Dump recording file.\n"); + printf(" + - Reset recording counter.\n"); + + uint32_t index; + + while(true) { + char cmd = getchar_timeout_us(0); + + switch(cmd) { + case 'D': + printf("Type the recording index.\n"); + scanf("%d", &index); + + if (index >= read_boot_count(false)) { + printf("Index out of range.\n"); + break; + } + + printf("Dumping recording #%d\n", index); + dump_recording_file(index); + break; + + case '+': + printf("Reseting recordings...\n"); + reset_recordings(); + printf("Done! Available recordings: %d\n", read_boot_count(false)); + break; + + default: + sleep_ms(30); + break; + } + } + + lfs_unmount(&lfs); + + return 0; +} diff --git a/apps/altimeter/visualize.py b/apps/altimeter/visualize.py new file mode 100644 index 0000000..f34ce7a --- /dev/null +++ b/apps/altimeter/visualize.py @@ -0,0 +1,36 @@ +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.ticker import FormatStrFormatter + +# Convert HEX file to BIN. +# cat D4.hex | xxd -r -p > D4.bin + +data = np.fromfile('./D5.bin', dtype=np.float32) +temp_x = data[0::2] +pres_x = data[1::2] +alt_x = ((((1013.25 / pres_x) ** (1/5.257)) - 1) * (temp_x + 273.15)) / 0.0065 +y = np.linspace(0, len(temp_x) / 4, len(temp_x)) +max_alt_del = np.max(alt_x) - np.min(alt_x) + +fig = plt.figure() + +ax = fig.add_subplot(111, label="1") +ax2 = fig.add_subplot(111, label="2", frame_on=False) + +ax.set_title(f"Kite Altimeter - 1st Flight | Max Altitude Delta = {max_alt_del:.2f} m") +ax.plot(y, temp_x, color="fuchsia", linewidth=1) +ax.set_ylabel('Temperature (ºC)', color="fuchsia") +ax.yaxis.set_label_position("right") +ax.yaxis.tick_right() +ax.tick_params(axis='y', colors="fuchsia") +ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f')) + +ax2.plot(y, alt_x, color="#50fa7b", linewidth=1) +ax2.set_xlabel("Time (s)") +ax2.set_ylabel("Altitude (m)", color="#50fa7b") +ax2.tick_params(axis='y', colors="#50fa7b") +ax2.yaxis.set_major_formatter(FormatStrFormatter('%.0f')) + +plt.savefig('altitude.png', dpi=300) + +plt.show() \ No newline at end of file