Read GPS data from a Neo6m gps module
Some checks failed
Continuous Integration / Rust Checks (map[args:--all -- --check --color always command:fmt]) (push) Has been cancelled
Continuous Integration / Rust Checks (map[args:--all-targets --all-features --workspace -- -D warnings command:clippy]) (push) Has been cancelled
Continuous Integration / Rust Checks (map[args:--release command:build]) (push) Has been cancelled
Some checks failed
Continuous Integration / Rust Checks (map[args:--all -- --check --color always command:fmt]) (push) Has been cancelled
Continuous Integration / Rust Checks (map[args:--all-targets --all-features --workspace -- -D warnings command:clippy]) (push) Has been cancelled
Continuous Integration / Rust Checks (map[args:--release command:build]) (push) Has been cancelled
This commit is contained in:
parent
4a32d32080
commit
a22efdfca3
@ -19,13 +19,13 @@ opt-level = "z"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
experimental = ["esp-idf-svc/experimental"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] }
|
||||
esp-idf-hal = "0.45.2"
|
||||
aniker-gps = { path = "../aniker-gps" }
|
||||
log = "0.4"
|
||||
|
||||
[build-dependencies]
|
||||
embuild = "0.33"
|
||||
embuild = { version = "0.33", features = ["espidf"] }
|
||||
|
||||
190
src/main.rs
190
src/main.rs
@ -1,92 +1,144 @@
|
||||
use aniker_gps::{parse_gga, GpsError};
|
||||
use esp_idf_hal::peripherals::Peripherals;
|
||||
use esp_idf_hal::prelude::*;
|
||||
use esp_idf_hal::uart::{UartConfig, UartDriver};
|
||||
use esp_idf_svc::hal::delay::FreeRtos;
|
||||
use esp_idf_svc::log::EspLogger;
|
||||
use esp_idf_svc::sys::link_patches;
|
||||
use log::info;
|
||||
|
||||
const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
const GPS_BAUD: u32 = 9600;
|
||||
const INIT_DELAY_MS: u32 = 5000; // 5 second initialization delay
|
||||
const POWER_CHECK_INTERVAL: u32 = 1000; // Check power every second
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize ESP-IDF
|
||||
esp_idf_svc::sys::link_patches();
|
||||
esp_idf_svc::log::EspLogger::initialize_default();
|
||||
link_patches();
|
||||
EspLogger::initialize_default();
|
||||
|
||||
info!("Aniker GPS Test Application v{}", APP_VERSION);
|
||||
info!("----------------------------------------");
|
||||
info!("Aniker GPS Test Application Starting...");
|
||||
info!("GPS Module Connections:");
|
||||
info!("1. GPS TX → ESP32 GPIO16 D16(RX)");
|
||||
info!("2. GPS RX → ESP32 GPIO17 D17(TX)");
|
||||
info!("3. GPS VCC → 3.3V");
|
||||
info!("4. GPS GND → GND");
|
||||
info!("----------------------------------------");
|
||||
info!("Please check if the red LED on the GPS module is lit");
|
||||
info!("This indicates the module is receiving power");
|
||||
info!("----------------------------------------");
|
||||
|
||||
// Example GPS sentences from different locations around the world:
|
||||
// 1. Sydney Opera House, Australia
|
||||
// 2. Mount Everest Base Camp, Nepal
|
||||
// 3. Machu Picchu, Peru
|
||||
// 4. Eiffel Tower, Paris, France
|
||||
// 5. Table Mountain, Cape Town, South Africa
|
||||
let test_sentences = vec![
|
||||
// Sydney Opera House
|
||||
"$GPGGA,023000,3357.3845,S,15112.7983,E,1,08,1.1,5.0,M,39.2,M,,*6D",
|
||||
// Mount Everest Base Camp
|
||||
"$GPGGA,023100,2759.1333,N,08656.9568,E,1,09,1.0,5364.0,M,-95.1,M,,*51",
|
||||
// Machu Picchu
|
||||
"$GPGGA,023200,1308.9511,S,07210.9327,W,1,07,1.2,2430.0,M,-15.3,M,,*62",
|
||||
// Eiffel Tower
|
||||
"$GPGGA,023300,4851.5156,N,00220.2978,E,1,10,0.9,33.0,M,47.0,M,,*68",
|
||||
// Table Mountain
|
||||
"$GPGGA,023400,3357.2828,S,01825.3214,E,1,08,1.0,1085.0,M,-33.0,M,,*6C",
|
||||
];
|
||||
// Initialize peripherals
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
|
||||
// Process each test sentence
|
||||
for (i, sentence) in test_sentences.iter().enumerate() {
|
||||
let mut sentence = sentence.to_string();
|
||||
// Configure UART
|
||||
let config = UartConfig::default().baudrate(Hertz(GPS_BAUD));
|
||||
|
||||
info!("Processing location {}", i + 1);
|
||||
info!("Raw NMEA: {}", sentence);
|
||||
info!("Initializing UART with config: baudrate={}", GPS_BAUD);
|
||||
|
||||
match parse_gga(&mut sentence) {
|
||||
Ok(position) => {
|
||||
info!("Successfully parsed GPS data:");
|
||||
info!(
|
||||
" Latitude: {} {}",
|
||||
position.lat.abs(),
|
||||
if position.lat >= 0.0 { "N" } else { "S" }
|
||||
);
|
||||
info!(
|
||||
" Longitude: {} {}",
|
||||
position.long.abs(),
|
||||
if position.long >= 0.0 { "E" } else { "W" }
|
||||
);
|
||||
info!(" Altitude: {:.1} meters", position.alt);
|
||||
// Create UART driver
|
||||
let mut uart_driver = UartDriver::new(
|
||||
peripherals.uart2,
|
||||
peripherals.pins.gpio17, // TX
|
||||
peripherals.pins.gpio16, // RX
|
||||
Option::<esp_idf_hal::gpio::Gpio0>::None, // RTS (not used)
|
||||
Option::<esp_idf_hal::gpio::Gpio0>::None, // CTS (not used)
|
||||
&config,
|
||||
)?;
|
||||
|
||||
// Add a descriptive location name
|
||||
let location = match i {
|
||||
0 => "Sydney Opera House, Australia",
|
||||
1 => "Mount Everest Base Camp, Nepal",
|
||||
2 => "Machu Picchu, Peru",
|
||||
3 => "Eiffel Tower, Paris, France",
|
||||
4 => "Table Mountain, Cape Town, South Africa",
|
||||
_ => "Unknown Location",
|
||||
};
|
||||
info!(" Location: {}", location);
|
||||
info!("UART initialized at {} baud", GPS_BAUD);
|
||||
info!(
|
||||
"Waiting {}ms for GPS module to initialize...",
|
||||
INIT_DELAY_MS
|
||||
);
|
||||
FreeRtos::delay_ms(INIT_DELAY_MS);
|
||||
|
||||
// Buffer for GPS data
|
||||
let mut buffer = [0u8; 128];
|
||||
let mut timeout_count = 0;
|
||||
let mut last_data_time = 0;
|
||||
let mut start_time = 0;
|
||||
|
||||
loop {
|
||||
let current_time = last_data_time + 1;
|
||||
|
||||
// Read available data from UART with timeout
|
||||
match uart_driver.read(&mut buffer, 1000) {
|
||||
Ok(bytes_read) if bytes_read > 0 => {
|
||||
timeout_count = 0; // Reset timeout counter on successful read
|
||||
last_data_time = current_time;
|
||||
let gps_data = String::from_utf8_lossy(&buffer[..bytes_read]);
|
||||
info!("Raw GPS Data: {}", gps_data);
|
||||
|
||||
// Try to parse each line of GPS data
|
||||
for line in gps_data.lines() {
|
||||
if line.starts_with("$GPGGA") {
|
||||
let mut sentence = line.to_string();
|
||||
match parse_gga(&mut sentence) {
|
||||
Ok(position) => {
|
||||
info!("Successfully parsed GPS data:");
|
||||
info!(
|
||||
" Latitude: {} {}",
|
||||
position.lat.abs(),
|
||||
if position.lat >= 0.0 { "N" } else { "S" }
|
||||
);
|
||||
info!(
|
||||
" Longitude: {} {}",
|
||||
position.long.abs(),
|
||||
if position.long >= 0.0 { "E" } else { "W" }
|
||||
);
|
||||
info!(" Altitude: {:.1} meters", position.alt);
|
||||
}
|
||||
Err(e) => {
|
||||
info!("Error parsing GPS data:");
|
||||
match e {
|
||||
GpsError::InvalidMessageType => {
|
||||
info!(" Invalid message type, expected GGA")
|
||||
}
|
||||
GpsError::InvalidLength => {
|
||||
info!(" Invalid GGA sentence length")
|
||||
}
|
||||
GpsError::ParseError(msg) => info!(" Parse error: {}", msg),
|
||||
GpsError::Other(msg) => info!(" Other error: {}", msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(_) => {
|
||||
timeout_count += 1;
|
||||
if timeout_count % 10 == 0 {
|
||||
// Only log every 10 timeouts to avoid spam
|
||||
info!("No GPS data received (timeout #{})", timeout_count);
|
||||
info!("Please check:");
|
||||
info!("1. GPS module is powered (3.3V) - red LED should be lit");
|
||||
info!("2. GPS TX is connected to ESP32 GPIO16 D16");
|
||||
info!("3. GPS RX is connected to ESP32 GPIO17 D17");
|
||||
info!("4. GPS GND is connected to ESP32 GND");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
info!("Error parsing GPS data:");
|
||||
match e {
|
||||
GpsError::InvalidMessageType => {
|
||||
info!(" Invalid message type, expected GGA")
|
||||
}
|
||||
GpsError::InvalidLength => info!(" Invalid GGA sentence length"),
|
||||
GpsError::ParseError(msg) => info!(" Parse error: {}", msg),
|
||||
GpsError::Other(msg) => info!(" Other error: {}", msg),
|
||||
}
|
||||
info!("UART read error: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we've received any data in the last second
|
||||
if current_time - last_data_time > POWER_CHECK_INTERVAL {
|
||||
info!("GPS Module Status:");
|
||||
info!("1. Power LED should be lit (red)");
|
||||
info!(
|
||||
"2. No data received for {} seconds",
|
||||
(current_time - last_data_time) / 1000
|
||||
);
|
||||
info!(
|
||||
"3. Total runtime: {} seconds",
|
||||
(current_time - start_time) / 1000
|
||||
);
|
||||
}
|
||||
|
||||
info!("----------------------------------------");
|
||||
// Add a small delay between processing sentences
|
||||
FreeRtos::delay_ms(2000);
|
||||
}
|
||||
|
||||
info!("Aniker GPS Test Application Complete");
|
||||
|
||||
// Keep the application running
|
||||
loop {
|
||||
FreeRtos::delay_ms(1000);
|
||||
FreeRtos::delay_ms(3000); // Wait 3 seconds before next reading
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user