介紹使用HMC5883L三軸數位羅盤,詳細內容如下列影片所示。
有關4-line serial TFT libarary請參閱:
成果影片
程式碼:
- CMakeLists.txt
# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work == if(WIN32) set(USERHOME $ENV{USERPROFILE}) else() set(USERHOME $ENV{HOME}) endif() set(sdkVersion 2.1.1) set(toolchainVersion 14_2_Rel1) set(picotoolVersion 2.1.1) set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake) if (EXISTS ${picoVscode}) include(${picoVscode}) endif() # ==================================================================================== # Generated Cmake Pico project file cmake_minimum_required(VERSION 3.13) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) # Initialise pico_sdk from installed location # (note this can come from environment, CMake cache etc) set(PICO_SDK_PATH "/home/duser/pico/pico-sdk") set(PICO_BOARD pico CACHE STRING "Board type") # Pull in Raspberry Pi Pico SDK (must be before project) include(pico_sdk_import.cmake) if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0") message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") endif() project(compass C CXX ASM) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() # Add executable. Default name is the project name, version 0.1 add_executable(compass compass.c ) pico_set_program_name(compass "compass") pico_set_program_version(compass "0.1") pico_enable_stdio_uart(compass 0) pico_enable_stdio_usb(compass 1) # Add the standard library to the build target_link_libraries(compass pico_stdlib) # Add the standard include files to the build target_include_directories(compass PRIVATE ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required ) # Add any user requested libraries target_link_libraries(compass hardware_i2c hardware_dma ) add_subdirectory(pico_tft) target_link_libraries( compass pico_tft ) pico_add_extra_outputs(compass)
- compass.c
#include <stdio.h> #include "stdlib.h" #include "pico/stdlib.h" #include "hardware/i2c.h" #include "hardware/dma.h" #include "hardware/pio.h" #include "pico_tft.h" #include "tft_string.h" #include "fonts/font_fixedsys_mono_16.h" #include "compass_img.h" #include "string.h" #include "registers.h" #include "math.h" #define I2C_PORT i2c0 #define I2C_SDA 16 #define I2C_SCL 17 #define DEVICE_ADDR 0x1E typedef struct _rotate_obj_t { uint8_t *srcimg; uint8_t *destimg; uint16_t width; uint16_t height; uint16_t angle; } rotate_obj_t; int16_t x_offset=-64; int16_t z_offset= 76; int main() { uint8_t cmd_buf[4]; uint8_t read_data[7]; stdio_init_all(); rotate_obj_t *rotate_img = (rotate_obj_t*) calloc(1, sizeof(rotate_obj_t)); uint8_t *read_buff = (uint8_t*) calloc(TFT_WIDTH*TFT_HEIGHT*2, sizeof(uint8_t)); //frame buffer if (!read_buff) { printf("alloc memory error\n"); return 0; } uint8_t *write_buff = (uint8_t*) calloc(TFT_WIDTH*TFT_HEIGHT*2, sizeof(uint8_t)); //frame buffer if (!write_buff) { printf("alloc memory error\n"); return 0; } tft_init(); tft_fill_rect(0,0, TFT_WIDTH, TFT_HEIGHT, 0xffff); // I2C Initialisation. Using it at 400Khz. i2c_init(I2C_PORT, 400*1000); gpio_set_function(I2C_SDA, GPIO_FUNC_I2C); gpio_set_function(I2C_SCL, GPIO_FUNC_I2C); gpio_pull_up(I2C_SDA); gpio_pull_up(I2C_SCL); // init 8-average, 15 Hz default, normal measurement cmd_buf[0] = 0x00; cmd_buf[1] = 0x70; i2c_write_blocking(i2c0, DEVICE_ADDR,cmd_buf, 2,true); cmd_buf[0] = 0x01; cmd_buf[1] = 0xa0; //0xa0 i2c_write_blocking(i2c0, DEVICE_ADDR,cmd_buf, 2,true); int16_t x,y,z; double heading; memcpy(read_buff, image_data_compass, TFT_WIDTH*TFT_WIDTH*2); tft_rotate_image((uint16_t*)read_buff, (uint16_t*)write_buff, TFT_WIDTH, TFT_WIDTH, 90); tft_set_address_window (0, 0, TFT_WIDTH, TFT_WIDTH); tft_cmd(TFT_MEMORYWRITE, TFT_WIDTH*TFT_WIDTH*2, (uint8_t*)write_buff); char buf_heading[10]; while(1) { //Single-Measurement Mode (Default). cmd_buf[0] = 0x02; cmd_buf[1] = 0x01; //0x00 i2c_write_blocking(i2c0, DEVICE_ADDR,cmd_buf, 2,false); sleep_ms(10); cmd_buf[0] = 0x03; i2c_write_blocking(i2c0, DEVICE_ADDR,cmd_buf, 1,false); i2c_read_blocking(i2c0, DEVICE_ADDR, read_data, 6, false); x = ((uint16_t)read_data[0]) << 8 | read_data[1]; z = ((uint16_t)read_data[2]) << 8 | read_data[3]; y = ((uint16_t)read_data[4]) << 8 | read_data[5]; printf("%d, %d, %d \n", x,y,z ); // print out for calibration heading = atan2(x-x_offset,z-z_offset)*57.3; //180/PI if(heading < 0) heading+=360; //heading=360-heading; // N=0/360, E=90, S=180, W=270 tft_rotate_image((uint16_t*)read_buff, (uint16_t*)write_buff, TFT_WIDTH, TFT_WIDTH, 360-heading); tft_set_address_window (0, 0, TFT_WIDTH, TFT_WIDTH); tft_cmd(TFT_MEMORYWRITE, TFT_WIDTH*TFT_WIDTH*2, (uint8_t*)write_buff); sprintf(buf_heading, "%03.02f ", heading); tft_draw_string_withbg(10, TFT_WIDTH+4, buf_heading, 0xf800, 0xffff, &font_fixedsys_mono_16); } return 0; }
- compass_img.h:
使用lcd-image-converter軟體產生。
沒有留言:
張貼留言