Skip to content

Instantly share code, notes, and snippets.

@remy
Created January 11, 2024 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remy/506f44454eff34848fe9601baf55664d to your computer and use it in GitHub Desktop.
Save remy/506f44454eff34848fe9601baf55664d to your computer and use it in GitHub Desktop.
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