Created some very verbose, inefficient and messy code that sends data down an I2C bus for a SSD1306 display to pickup.

This commit is contained in:
Luke Else 2023-07-14 14:01:46 +01:00
parent 1f8fe3020f
commit 46ca82f379
3 changed files with 74 additions and 9 deletions

View File

@ -34,6 +34,8 @@ esp-idf-hal = { version = "0.41", optional = true, default-features = false }
esp-idf-svc = { version = "0.46", optional = true, default-features = false } esp-idf-svc = { version = "0.46", optional = true, default-features = false }
embedded-svc = { version = "0.25", optional = true, default-features = false } embedded-svc = { version = "0.25", optional = true, default-features = false }
nmea-parser = "0.10.0" nmea-parser = "0.10.0"
embedded-graphics = "0.8.0"
ssd1306 = "0.8.0"
[build-dependencies] [build-dependencies]
embuild = "0.31.2" embuild = "0.31.2"

View File

@ -1,15 +1,26 @@
use esp_idf_sys::{self as _, EspError}; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use esp_idf_sys::{self as _, EspError}; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use esp_idf_hal::{ use esp_idf_hal::{
prelude::Peripherals, prelude::Peripherals,
uart,
units::Hertz,
gpio::{AnyInputPin, AnyOutputPin}, gpio::{AnyInputPin, AnyOutputPin},
delay::BLOCK delay::BLOCK,
units::Hertz,
uart,
i2c::{I2cConfig, I2cDriver}
}; };
use esp_idf_hal; use esp_idf_hal;
use nmea_parser; use nmea_parser;
use nmea_parser::gnss::FaaMode; use nmea_parser::gnss::FaaMode;
use embedded_graphics::{
prelude::*,
image::{Image, ImageRaw},
mono_font::{ascii::FONT_7X13, MonoTextStyle},
pixelcolor::BinaryColor,
text::{Text, Alignment},
};
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
fn main() -> Result<(), EspError> { fn main() -> Result<(), EspError> {
// It is necessary to call this function once. Otherwise some patches to the runtime // It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
@ -20,26 +31,53 @@ fn main() -> Result<(), EspError> {
// Get Peripherals and sysloop ready // Get Peripherals and sysloop ready
let peripherals = Peripherals::take().unwrap(); let peripherals = Peripherals::take().unwrap();
let pins = peripherals.pins; let pins = peripherals.pins;
// Define program's pins + addresses
let scl = pins.gpio22;
let sda = pins.gpio21;
let gps_rx = pins.gpio16;
let _lcd_address: u8 = 0x3C;
// Setup UART to read serial data from GPS // Setup UART to read serial data from GPS
let config = uart::config::Config::default().baudrate(Hertz(9_600)); let config = uart::config::Config::default().baudrate(Hertz(9_600));
let uart: uart::UartRxDriver = uart::UartRxDriver::new( let uart: uart::UartRxDriver = uart::UartRxDriver::new(
peripherals.uart1, peripherals.uart1,
pins.gpio16, gps_rx,
None::<AnyInputPin>, None::<AnyInputPin>,
None::<AnyOutputPin>, None::<AnyOutputPin>,
&config &config
)?; )?;
// Setup I2C driver
let config = I2cConfig::new().baudrate(Hertz(921600));
let i2c = I2cDriver::new(
peripherals.i2c0,
sda,
scl,
&config
)?;
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
display.init().unwrap();
let raw: ImageRaw<BinaryColor> = ImageRaw::new(include_bytes!("./rust.raw"), 64);
let im: Image<'_, _> = Image::new(&raw, Point::new(32, 0));
im.draw(&mut display).unwrap();
let mut nmea_parser = nmea_parser::NmeaParser::new(); let mut nmea_parser = nmea_parser::NmeaParser::new();
let mut latest_data = GpsData{latitude: None, longitude: None, speed: None, direction: None}; let mut latest_data = GpsData{latitude: None, longitude: None, speed: None, direction: None};
loop { loop {
// Read buffer from UART // Read buffer from UART
let mut buf: Vec<u8> = (0..uart.count()? as u8).collect(); let mut buf: Vec<u8> = (0..uart.count()? as u8).collect();
uart.read(&mut buf[..], BLOCK)?; uart.read(&mut buf[..], BLOCK)?;
std::thread::sleep(std::time::Duration::from_millis(10)); std::thread::sleep(std::time::Duration::from_millis(10));
let nmea_raw = String::from_utf8(buf).unwrap_or_default(); let nmea_raw = String::from_utf8(buf).unwrap_or_default();
let nmea_vec: Vec<&str> = nmea_raw.split('$').collect(); let nmea_vec: Vec<&str> = nmea_raw.split('$').collect();
for nmea_line in nmea_vec { for nmea_line in nmea_vec {
@ -47,17 +85,17 @@ fn main() -> Result<(), EspError> {
if nmea_line.is_empty() { if nmea_line.is_empty() {
continue; continue;
} }
// Construct string that is in the correct format for parsing // Construct string that is in the correct format for parsing
let mut sentence = "$".to_string(); let mut sentence = "$".to_string();
sentence.push_str(nmea_line); sentence.push_str(nmea_line);
let nmea = match nmea_parser.parse_sentence(sentence.as_str()) { let nmea = match nmea_parser.parse_sentence(sentence.as_str()) {
Ok(nmea) => nmea, Ok(nmea) => nmea,
// Don't continue processin sentence if we know that it isn't supported // Don't continue processin sentence if we know that it isn't supported
Err(_) => { continue; } Err(_) => { continue; }
}; };
// print decoded gps data to serial // print decoded gps data to serial
match nmea { match nmea {
nmea_parser::ParsedMessage::Gll(gll) => { nmea_parser::ParsedMessage::Gll(gll) => {
@ -85,6 +123,20 @@ fn main() -> Result<(), EspError> {
_ => {} _ => {}
} }
} }
let style = MonoTextStyle::new(&FONT_7X13, BinaryColor::On);
display.clear(BinaryColor::Off).unwrap();
Text::with_alignment(
&latest_data.to_string().as_str(),
Point::new(64, 10),
style,
Alignment::Center,
)
.draw(&mut display).unwrap();
display.flush().unwrap();
} }
} }
@ -95,3 +147,14 @@ struct GpsData {
speed: Option<f64>, speed: Option<f64>,
direction: Option<f64> direction: Option<f64>
} }
impl GpsData {
pub fn to_string(&self) -> String {
format!("Latitude: {:.4?} \nLongitude: {:.4?} \nSpeed: {:.1?}mph \nDirection: {:.4?}deg",
self.latitude.unwrap_or_default(),
self.longitude.unwrap_or_default(),
self.speed.unwrap_or_default(),
self.direction.unwrap_or_default()
)
}
}

BIN
src/rust.raw Normal file

Binary file not shown.