diff --git a/audio-logger/Cargo.toml b/audio-logger/Cargo.toml index 1719fe2..dc1dfaa 100644 --- a/audio-logger/Cargo.toml +++ b/audio-logger/Cargo.toml @@ -10,16 +10,7 @@ cpal= { version = "0.13.5", features = ["jack"] } anyhow = "1.0.61" clap = "3.2.17" hound = "3.4.0" - - -[target.'cfg(target_os = "android")'.dev-dependencies] -ndk-glue = "0.7" - -[target.'cfg(target_os = "windows")'.dependencies] -windows = { version = "0.37", features = ["Win32_Media_Audio", "Win32_Foundation", "Win32_System_Com", "Win32_Devices_Properties", "Win32_Media_KernelStreaming", "Win32_System_Com_StructuredStorage", "Win32_System_Ole", "Win32_System_Threading", "Win32_Security", "Win32_System_SystemServices", "Win32_System_WindowsProgramming", "Win32_Media_Multimedia", "Win32_UI_Shell_PropertiesSystem"]} -num-traits = { version = "0.2.6", optional = true } -parking_lot = "0.12" -once_cell = "1.12" +chrono = "0.4.22" [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"))'.dependencies] alsa = "0.6" @@ -27,27 +18,3 @@ nix = "0.23" libc = "0.2.65" parking_lot = "0.12" jack = { version = "0.9", optional = true } - -[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] -core-foundation-sys = "0.8.2" # For linking to CoreFoundation.framework and handling device name `CFString`s. -mach = "0.3" # For access to mach_timebase type. - -[target.'cfg(target_os = "macos")'.dependencies] -coreaudio-rs = { version = "0.10", default-features = false, features = ["audio_unit", "core_audio"] } - -[target.'cfg(target_os = "ios")'.dependencies] -coreaudio-rs = { version = "0.10", default-features = false, features = ["audio_unit", "core_audio", "audio_toolbox"] } - -[target.'cfg(target_os = "emscripten")'.dependencies] -stdweb = { version = "0.1.3", default-features = false } - -[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] -wasm-bindgen = { version = "0.2.58", optional = true } -js-sys = { version = "0.3.35" } -web-sys = { version = "0.3.35", features = [ "AudioContext", "AudioContextOptions", "AudioBuffer", "AudioBufferSourceNode", "AudioNode", "AudioDestinationNode", "Window", "AudioContextState"] } - -[target.'cfg(target_os = "android")'.dependencies] -oboe = { version = "0.4", features = [ "java-interface" ] } -ndk = "0.7" -ndk-context = "0.1" -jni = "0.19" \ No newline at end of file diff --git a/audio-logger/src/main.rs b/audio-logger/src/main.rs index ac6b1f1..3121f9f 100644 --- a/audio-logger/src/main.rs +++ b/audio-logger/src/main.rs @@ -2,71 +2,25 @@ //! //! The input data is recorded to "$CARGO_MANIFEST_DIR/recorded.wav". -use clap::arg; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use std::fs::File; use std::io::BufWriter; +use std::path::Path; use std::sync::{Arc, Mutex}; - -#[derive(Debug)] -struct Opt { - #[cfg(all( - any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"), - ))] - jack: bool, - - device: String, -} - -impl Opt { - fn from_args() -> Self { - let app = clap::Command::new("record_wav").arg(arg!([DEVICE] "The audio device to use")); - #[cfg(all( - any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"), - ))] - let app = app.arg(arg!(-j --jack "Use the JACK host")); - let matches = app.get_matches(); - let device = matches.value_of("DEVICE").unwrap_or("default").to_string(); - - #[cfg(all( - any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"), - ))] - return Opt { - jack: matches.is_present("jack"), - device, - }; - - #[cfg(any( - not(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd")), - ))] - Opt { device } - } -} +use chrono::prelude::*; fn main() -> Result<(), anyhow::Error> { - let opt = Opt::from_args(); - - // Manually check for flags. Can be passed through cargo with -- e.g. - // cargo run --release --example beep --features jack -- --jack - let host = if opt.jack { - cpal::host_from_id(cpal::available_hosts() - .into_iter() - .find(|id| *id == cpal::HostId::Jack) - .expect( - "make sure --features jack is specified. only works on OSes where jack is available", - )).expect("jack host unavailable") - } else { - cpal::default_host() - }; + // Use jack host, requires the jack server to be running + let host = cpal::host_from_id(cpal::available_hosts() + .into_iter() + .find(|id| *id == cpal::HostId::Jack) + .expect( + "make sure feature jack is specified for cpal. only works on OSes where jack is available", + )).expect("jack host unavailable"); // Set up the input device and stream with the default input config. - let device = if opt.device == "default" { - host.default_input_device() - } else { - host.input_devices()? - .find(|x| x.name().map(|y| y == opt.device).unwrap_or(false)) - } - .expect("failed to find input device"); + let device = host.default_input_device() + .expect("failed to find input device"); println!("Input device: {}", device.name()?); @@ -75,47 +29,55 @@ fn main() -> Result<(), anyhow::Error> { .expect("Failed to get default input config"); println!("Default input config: {:?}", config); - // The WAV file we're recording to. - const PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/recorded.wav"); + // Location where files will be outputted + let path = Path::new("/home/shared/logger-raspi-setup/data/audio/"); let spec = wav_spec_from_config(&config); - let writer = hound::WavWriter::create(PATH, spec)?; - let writer = Arc::new(Mutex::new(Some(writer))); - // A flag to indicate that recording is in progress. - println!("Begin recording..."); + for _ in 0..5 { + // The WAV file we're recording to. + let ts: String = Utc::now().format("%Y-%m-%dT%H-%M-%S.%f").to_string(); + let file: String = path.to_str().unwrap().to_owned() + &ts + "_audio_data.wav"; - // Run the input stream on a separate thread. - let writer_2 = writer.clone(); - - let err_fn = move |err| { - eprintln!("an error occurred on stream: {}", err); - }; - - let stream = match config.sample_format() { - cpal::SampleFormat::F32 => device.build_input_stream( - &config.into(), - move |data, _: &_| write_input_data::(data, &writer_2), - err_fn, - )?, - cpal::SampleFormat::I16 => device.build_input_stream( - &config.into(), - move |data, _: &_| write_input_data::(data, &writer_2), - err_fn, - )?, - cpal::SampleFormat::U16 => device.build_input_stream( - &config.into(), - move |data, _: &_| write_input_data::(data, &writer_2), - err_fn, - )?, - }; - - stream.play()?; - - // Let recording go for roughly three seconds. - std::thread::sleep(std::time::Duration::from_secs(3)); - drop(stream); - writer.lock().unwrap().take().unwrap().finalize()?; - println!("Recording {} complete!", PATH); + let writer = hound::WavWriter::create(file.clone(), spec)?; + let writer = Arc::new(Mutex::new(Some(writer))); + + // Run the input stream on a separate thread. + let writer_2 = writer.clone(); + + let config_2 = config.clone(); + + let err_fn = move |err| { + eprintln!("an error occurred on stream: {}", err); + }; + + let stream = match config.sample_format() { + cpal::SampleFormat::F32 => device.build_input_stream( + &config_2.into(), + move |data, _: &_| write_input_data::(data, &writer_2), + err_fn, + )?, + cpal::SampleFormat::I16 => device.build_input_stream( + &config_2.into(), + move |data, _: &_| write_input_data::(data, &writer_2), + err_fn, + )?, + cpal::SampleFormat::U16 => device.build_input_stream( + &config_2.into(), + move |data, _: &_| write_input_data::(data, &writer_2), + err_fn, + )?, + }; + + // Start recording + println!("Begin recording at {}", Utc::now()); + stream.play()?; + + // Let recording go for roughly five seconds. + std::thread::sleep(std::time::Duration::from_secs(5)); + drop(stream); + writer.lock().unwrap().take().unwrap().finalize()?; + println!("Recording {} complete!", file); + } Ok(()) } diff --git a/audio-logger/target/.rustc_info.json b/audio-logger/target/.rustc_info.json deleted file mode 100644 index fe74c33..0000000 --- a/audio-logger/target/.rustc_info.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc_fingerprint":1011063074445675614,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.62.1 (e092d0b6b 2022-07-16)\nbinary: rustc\ncommit-hash: e092d0b6b43f2de967af0887873151bb1c0b18d3\ncommit-date: 2022-07-16\nhost: x86_64-unknown-linux-gnu\nrelease: 1.62.1\nLLVM version: 14.0.5\n","stderr":""},"15697416045686424142":{"success":false,"status":"exit status: 1","code":1,"stdout":"","stderr":"error: `-Csplit-debuginfo` is unstable on this platform\n\n"},"10376369925670944939":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/julius/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/depth-logger/record-depth-temp.py b/depth-logger/record-depth-temp.py new file mode 100644 index 0000000..a1afa26 --- /dev/null +++ b/depth-logger/record-depth-temp.py @@ -0,0 +1,52 @@ +#!/usr/bin/python3 + +import board +import time +import busio +import adafruit_ads1x15.ads1015 as ADS +from adafruit_ads1x15.analog_in import AnalogIn +from time import sleep, strftime + +# Create the I2C bus +i2c = busio.I2C(board.SCL, board.SDA) + +# Create the ADC object using the I2C bus +ads = ADS.ADS1015(i2c) + +# Create single-ended input on channel 0 +tmp36 = AnalogIn(ads, ADS.P0) + +# Attempting to create a single-ended input on channel 1 +depthS = AnalogIn(ads, ADS.P1) + +# Subtract the offset from the sensor voltage +# and convert chan.voltage * (1 degree C / 0.01V) = Degrees Celcius +temperatureC = (tmp36.voltage - 0.5) / 0.01 + +# Open the file to write down the results +timestr = time.strftime("%Y-%m-%dT%H-%M-%S") +filename = "/home/shared/logger-raspi-setup/data/depth-temp/" + timestr + "depth_temperature_data.csv" + +#depthM = ((depthS.voltage * 31.848) - 22.93) + +#Attempting to round the figure to a more intelligible figure +#rounddepth = round(depthM, ndigits) +#psi = depthS.voltage * 104.1666667 - 75 + +#bar = psi * 14.503773800722 + +with open(filename, "w") as f: + f.write("time and date, temperature (C), Voltage of depth sensor (V), Depth (m)\n") + + while True: + depthM = ((depthS.voltage * 31.848) - 22.93) + rounddepth = round(depthM, 2) + roundtemp = round(temperatureC, 2) + roundvolts = round(depthS.voltage, 3) + + print((str(roundtemp) + " °C ") + (str(roundvolts) + " V ") + (str(rounddepth) + " m")) + + f.write(time.strftime("%Y-%m-%d %H:%M:%S") + ",") + f.write((str(roundtemp) + " °C ") + "," + (str(roundvolts) + " V ") + "," + (str(rounddepth) + " m\n")) + + time.sleep(3) diff --git a/gps-logger/record-gps.py b/gps-logger/record-gps.py new file mode 100644 index 0000000..7d944d2 --- /dev/null +++ b/gps-logger/record-gps.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 + +from gps import * +from time import sleep, strftime + +filename = "/home/shared/logger-raspi-setup/data/gps/" + time.strftime("%Y-%m-%dT%H-%M-%S") + "_GPS_data.csv" +# filename = "/mnt/myssd/GPS_Data" + timestr +".csv" + +with open(filename, "w", 1) as f: + gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE) + f.write("GPStime utc,latitude,longitude,speed,sats in view\n") + + try: + while True: + report = gpsd.next() + if report["class"] == "TPV": + GPStime = str(getattr(report,"time","")) + lat = str(getattr(report,"lat",0.0)) + lon = str(getattr(report,"lon",0.0)) + speed = str(getattr(report,"speed","nan")) + sats = str(len(gpsd.satellites)) + + f.write(GPStime + "," + lat +"," + lon + "," + speed + "," + sats + "\n") + + time.sleep(5) + + except (KeyboardInterrupt, SystemExit): # when you press ctrl+c + print("Done.\nExiting.") + f.close() diff --git a/resources.md b/resources.md index 4ede914..cf41b0d 100755 --- a/resources.md +++ b/resources.md @@ -2,4 +2,8 @@ # Raspberry Pi water pressure sensor -https://www.circuito.io/app?components=9443,200000,267055 \ No newline at end of file +https://www.circuito.io/app?components=9443,200000,267055 + +# Setting up Jack on Raspberry Pi + +https://wiki.linuxaudio.org/wiki/raspberrypi \ No newline at end of file diff --git a/scripts/audio-setup.sh b/scripts/audio-setup-utils.sh old mode 100644 new mode 100755 similarity index 100% rename from scripts/audio-setup.sh rename to scripts/audio-setup-utils.sh diff --git a/scripts/list-usb-devices.sh b/scripts/list-usb-devices.sh new file mode 100755 index 0000000..8bb091f --- /dev/null +++ b/scripts/list-usb-devices.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do + ( + syspath="${sysdevpath%/dev}" + devname="$(udevadm info -q name -p $syspath)" + [[ "$devname" == "bus/"* ]] && exit + eval "$(udevadm info -q property --export -p $syspath)" + [[ -z "$ID_SERIAL" ]] && exit + echo "/dev/$devname - $ID_SERIAL" + ) +done diff --git a/scripts/setup-audio.sh b/scripts/setup-audio.sh new file mode 100755 index 0000000..936a568 --- /dev/null +++ b/scripts/setup-audio.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +# Install jackd + +# Audio setup utils \ No newline at end of file diff --git a/scripts/setup-gps.sh b/scripts/setup-gps.sh new file mode 100755 index 0000000..051d067 --- /dev/null +++ b/scripts/setup-gps.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +sudo apt-get update && sudo apt-get install -y \ + gpsd gpsd-clients + +sudo systemctl stop gpsd.socket +sudo systemctl disable gpsd.socket + +device="/dev/ttyUSB0" + +sudo gpsd ${device} -F /var/run/gpsd.sock + +sudo sed -i "s|DEVICES=\"\"|DEVICES=\"${device}\"|g" /etc/default/gpsd + +echo "START_DAEMON=\"true\"" | sudo tee -a /etc/default/gpsd + diff --git a/scripts/start-all.sh b/scripts/start-all.sh new file mode 100755 index 0000000..17cbbb4 --- /dev/null +++ b/scripts/start-all.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +(trap 'kill 0' SIGINT; ./scripts/start-gps.sh & ./scripts/start-audio.sh) diff --git a/scripts/start-audio.sh b/scripts/start-audio.sh new file mode 100755 index 0000000..c82669e --- /dev/null +++ b/scripts/start-audio.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Start jack server + +sh scripts/start-jack.sh + +# Start recording + +cd audio-logger && cargo run \ No newline at end of file diff --git a/scripts/start-gps.sh b/scripts/start-gps.sh new file mode 100755 index 0000000..be7cf51 --- /dev/null +++ b/scripts/start-gps.sh @@ -0,0 +1,3 @@ +#!/usr/bin/sh + +python /home/shared/logger-raspi-setup/gps-logger/record-gps.py diff --git a/scripts/start-jack.sh b/scripts/start-jack.sh new file mode 100755 index 0000000..c587dcf --- /dev/null +++ b/scripts/start-jack.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Get soundcard name +soundcard=$(grep USB /proc/asound/cards | grep -oe "\[.*]" | tr -d "[] ") + +# Start jack server +/usr/bin/jackd -P75 -d alsa -d hw:${soundcard} -r 44100 -p 512 -n 3 & diff --git a/setup.md b/setup.md index e0b072d..5e38c38 100755 --- a/setup.md +++ b/setup.md @@ -34,9 +34,9 @@ -## Set up logging +## Set up recording -### 1. Sound recording +### 1. Audio @@ -47,3 +47,7 @@ ### 3. Water pressure + +## Test & run + +