Created
January 11, 2024 20:40
-
-
Save remy/506f44454eff34848fe9601baf55664d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from machine import I2S, I2C, Pin, SPI | |
from ssd1306 import SSD1306_I2C | |
import array | |
import math | |
import time | |
import sdcard | |
import os | |
import struct | |
import rp2 | |
time.sleep(3) | |
DISPLAY_SD_PIN = Pin(0) | |
DISPLAY_SCK_PIN = Pin(1) | |
SCK_PIN = Pin(3) | |
WS_PIN = Pin(4) | |
SD_PIN = Pin(2) | |
I2S_ID = 1 | |
i2cOled=I2C(0, sda=DISPLAY_SD_PIN, scl=DISPLAY_SCK_PIN, freq=400_000) | |
display = SSD1306_I2C(128,32,i2cOled) | |
# Assign chip select (CS) pin (and start it high) | |
cs = machine.Pin(13, machine.Pin.OUT) | |
spi = SPI(1,baudrate=40000000,sck=Pin(14),mosi=Pin(11),miso=Pin(12)) | |
# Initialize SD card | |
try: | |
sd = sdcard.SDCard(spi, cs) | |
except: | |
display.text("Failed sd card", 0, 0, 1) | |
display.text("Insert & restart", 0, 12, 1) | |
display.show() | |
# button = Pin(23, Pin.IN, Pin.PULL_DOWN) | |
vfs = os.VfsFat(sd) | |
os.mount(vfs, "/sd") | |
filename = "/sd/doggie.log" | |
# Initialize I2S | |
i2s = I2S( | |
I2S_ID, | |
sck=SCK_PIN, | |
ws=WS_PIN, | |
sd=SD_PIN, | |
mode=I2S.RX, | |
bits=16, | |
format=I2S.MONO, | |
rate=44100, | |
ibuf=20000 | |
) | |
# Define the size of the input buffer | |
buffer_size = 1024 | |
# Create an input buffer (array of signed integers) | |
ibuf = array.array('h', [0]*buffer_size) | |
y_max = 0 | |
base = 60 | |
tick = 0 | |
def Run(tmr): | |
global y_max | |
global tick | |
tick = tick + 1 | |
# Read data from microphone into the buffer | |
num_read = i2s.readinto(ibuf) | |
# Convert buffer to sound pressure levels | |
# Simple RMS calculation (you may need a more sophisticated approach for accurate results) | |
rms = math.sqrt(sum([x**2 for x in ibuf]) / num_read) | |
# Convert to decibels | |
# Reference pressure for decibel calculation - may require calibration | |
ref_pressure = 1e-2 | |
decibels = 20 * math.log10(rms/ref_pressure) | |
y = int((int(decibels) - base) / 2); | |
if y < 0: y = 0 | |
height = 32 - y | |
if y > y_max: y_max = y | |
d = int(round(decibels, 2)) | |
file = open(filename,"ab") | |
file.write(struct.pack('>B', y)) | |
file.close() | |
display.scroll(-1, 0) # scroll to the left | |
display.vline(120, height, y, 1) | |
display.fill_rect(0, 0, 120, 12, 0) | |
if tick < 60: | |
runtime = "{}s".format(tick) | |
else: | |
runtime = "{}m{:02}s".format(math.floor(tick/60), tick % 60) | |
display.text("{} {}".format(runtime, round(decibels, 2)), 0,0, 1) | |
display.show() | |
timer = machine.Timer() | |
# timer.init(period=1000, callback=Run) # run Run every 1 second | |
running = False | |
def toggleRun(): | |
global running | |
global file | |
running = not running | |
if running: | |
# create a start marker | |
file = open(filename,"ab") # append binary | |
file.write(struct.pack('>B', 255)) # start byte | |
file.close() | |
# reset the display | |
display.fill(0) | |
display.text("Starting...", 0,0, 1) | |
display.show() | |
time.sleep_ms(3000) | |
# kick off the timer and fire immediately | |
timer.init(period=1000, callback=Run) | |
Run(timer) | |
else: | |
# cancel and remove callback | |
timer.deinit() | |
time.sleep_ms(1000) | |
display.fill(0) | |
display.text("Stopping...", 0,0, 1) # just show a message | |
display.show() | |
time.sleep_ms(3000) | |
display.fill(0) | |
display.text("Waiting to start", 0,0, 1) | |
display.show() | |
display.fill(0) | |
display.text("Waiting to start", 0,0, 1) | |
display.show() | |
while True: | |
if rp2.bootsel_button(): | |
toggleRun() | |
time.sleep_ms(100) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment