Я работаю над проектом Raspberry Pi, в котором я перешел от использования HiFi DAC HAT на базе I2C (PCM5122) к ЦАП на основе SPI (Boost 8568). Моя цель — вывести аналоговые сигналы из обработанных данных ЭЭГ с ЦАП, но я сталкиваюсь со значительными различиями в качестве выходного сигнала. Когда я проверяю выходы с помощью осциллографа, выход нового ЦАП SPI искажается по сравнению с чистым сигналом, вырабатываемым I2C DAC HAT.
Изображение выходного сигнала HiFi ЦАП
Изображение выходного сигнала BOOST DAC 8568
Я попробовал снизить как частоту дискретизации сигнала, так и максимальную скорость, чтобы посмотреть, поможет ли это решению, однако проблема все еще там. Я начинаю задаваться вопросом, связано ли это с тактовым компонентом повышающего ЦАП или необходимо изменить другие параметры SPI, чтобы обеспечить такой же чистый выходной сигнал, как предыдущий ЦАП и интерфейс i2C.
import spidev
import numpy as np
import time
import RPi.GPIO as GPIO
from scipy.io import wavfile
# Define DAC channels and their corresponding addresses (assuming 8 channels)
CHANNELS = {
'A': 0b0000, # Channel A address
'B': 0b0001, # Channel B address
'C': 0b0010, # Channel C address
'D': 0b0011, # Channel D address
'E': 0b0100, # Channel E address
'F': 0b0101, # Channel F address
'G': 0b0110, # Channel G address
'H': 0b0111, # Channel H address
}
# LDAC GPIO pin (adjust as needed)
LDAC_PIN = 17
def initialize_ldac():
GPIO.setmode(GPIO.BCM)
GPIO.setup(LDAC_PIN, GPIO.OUT)
GPIO.output(LDAC_PIN, GPIO.HIGH) # Default to inactive state
def trigger_ldac():
GPIO.output(LDAC_PIN, GPIO.LOW)
time.sleep(0.001)
GPIO.output(LDAC_PIN, GPIO.HIGH)
CHANNEL_MAP = {
"A": 0,
"B": 1,
"C": 2,
"D": 3,
"E": 4,
"F": 5,
"G": 6,
"H": 7
}
def build_command(channel, data):
if isinstance(channel, str):
channel = CHANNEL_MAP[channel.upper()] # Map channel to integer
data = int(data) & 0xFFFF # Ensure data is a 16-bit value
command = 0b0011 12) & 0x0F) # Upper nibble of data
lsb = (data >> 4) & 0xFF # Middle 8 bits of data
return [msb, lsb]
def send_to_dac(spi, channel, value):
command = build_command(channel, value)
spi.xfer2(command)
def update_channels_with_ldac(spi, channel_values):
for channel, value in channel_values.items():
send_to_dac(spi, channel, value)
trigger_ldac()
def set_all_channels_to_zero(spi):
channel_values = {channel: 0 for channel in CHANNELS}
update_channels_with_ldac(spi, channel_values)
def load_wav_file(file_path, desired_duration_seconds):
# Load WAV file and normalize the signal
sample_rate, signal = wavfile.read(file_path)
if signal.ndim > 1: # Handle multi-channel audio (stereo)
signal = signal[:, 0] # Use only the first channel
max_amplitude = np.max(np.abs(signal))
normalized_signal = signal / max_amplitude
# Determine how many samples fit within the desired duration
num_samples = int(sample_rate * desired_duration_seconds)
if len(normalized_signal) > num_samples:
normalized_signal = normalized_signal[:num_samples]
else:
# Repeat the signal to fit the desired duration
repeated_signal = np.tile(normalized_signal, int(np.ceil(num_samples / len(normalized_signal))))
normalized_signal = repeated_signal[:num_samples]
# Clip and convert to 16-bit integers
normalized_signal = np.clip(normalized_signal * 32767, -32768, 32767).astype(int)
return normalized_signal, sample_rate
def play_wav_file(spi, wav_file, target_channel, desired_duration_seconds):
audio_data, sample_rate = load_wav_file(wav_file, desired_duration_seconds)
num_samples = len(audio_data)
sample_interval = 1 / sample_rate # Time interval between samples
start_time = time.time() # Record the start time
for i, value in enumerate(audio_data):
# Send data to the DAC
channel_values = {channel: 0 for channel in CHANNELS}
channel_values[target_channel] = value
update_channels_with_ldac(spi, channel_values)
# Ensure proper timing
elapsed_time = time.time() - start_time
expected_time = (i + 1) * sample_interval
if elapsed_time < expected_time:
time.sleep(expected_time - elapsed_time)
# Stop playback if exceeded the desired duration
if elapsed_time >= desired_duration_seconds:
break
if __name__ == "__main__":
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 500000
spi.mode = 0b00
initialize_ldac()
try:
target_channel = input("Enter the target channel (A, B, C, D, E, F, G, H): ").strip().upper()
if target_channel not in CHANNELS:
raise ValueError("Invalid channel.")
wav_file = 'wav file dest here'
desired_duration_seconds = 7
play_wav_file(spi, wav_file, target_channel, desired_duration_seconds)
finally:
set_all_channels_to_zero(spi)
spi.close()
GPIO.cleanup()
Подробнее здесь: https://stackoverflow.com/questions/792 ... ed-signals
SPIDEV на Raspberry Pi для TI DAC8568, создающего искаженные сигналы ⇐ Python
Программы на Python
1732486966
Anonymous
Я работаю над проектом Raspberry Pi, в котором я перешел от использования HiFi DAC HAT на базе I2C (PCM5122) к ЦАП на основе SPI (Boost 8568). Моя цель — вывести аналоговые сигналы из обработанных данных ЭЭГ с ЦАП, но я сталкиваюсь со значительными различиями в качестве выходного сигнала. Когда я проверяю выходы с помощью осциллографа, выход нового ЦАП SPI искажается по сравнению с чистым сигналом, вырабатываемым I2C DAC HAT.
Изображение выходного сигнала HiFi ЦАП
Изображение выходного сигнала BOOST DAC 8568
Я попробовал снизить как частоту дискретизации сигнала, так и максимальную скорость, чтобы посмотреть, поможет ли это решению, однако проблема все еще там. Я начинаю задаваться вопросом, связано ли это с тактовым компонентом повышающего ЦАП или необходимо изменить другие параметры SPI, чтобы обеспечить такой же чистый выходной сигнал, как предыдущий ЦАП и интерфейс i2C.
import spidev
import numpy as np
import time
import RPi.GPIO as GPIO
from scipy.io import wavfile
# Define DAC channels and their corresponding addresses (assuming 8 channels)
CHANNELS = {
'A': 0b0000, # Channel A address
'B': 0b0001, # Channel B address
'C': 0b0010, # Channel C address
'D': 0b0011, # Channel D address
'E': 0b0100, # Channel E address
'F': 0b0101, # Channel F address
'G': 0b0110, # Channel G address
'H': 0b0111, # Channel H address
}
# LDAC GPIO pin (adjust as needed)
LDAC_PIN = 17
def initialize_ldac():
GPIO.setmode(GPIO.BCM)
GPIO.setup(LDAC_PIN, GPIO.OUT)
GPIO.output(LDAC_PIN, GPIO.HIGH) # Default to inactive state
def trigger_ldac():
GPIO.output(LDAC_PIN, GPIO.LOW)
time.sleep(0.001)
GPIO.output(LDAC_PIN, GPIO.HIGH)
CHANNEL_MAP = {
"A": 0,
"B": 1,
"C": 2,
"D": 3,
"E": 4,
"F": 5,
"G": 6,
"H": 7
}
def build_command(channel, data):
if isinstance(channel, str):
channel = CHANNEL_MAP[channel.upper()] # Map channel to integer
data = int(data) & 0xFFFF # Ensure data is a 16-bit value
command = 0b0011 12) & 0x0F) # Upper nibble of data
lsb = (data >> 4) & 0xFF # Middle 8 bits of data
return [msb, lsb]
def send_to_dac(spi, channel, value):
command = build_command(channel, value)
spi.xfer2(command)
def update_channels_with_ldac(spi, channel_values):
for channel, value in channel_values.items():
send_to_dac(spi, channel, value)
trigger_ldac()
def set_all_channels_to_zero(spi):
channel_values = {channel: 0 for channel in CHANNELS}
update_channels_with_ldac(spi, channel_values)
def load_wav_file(file_path, desired_duration_seconds):
# Load WAV file and normalize the signal
sample_rate, signal = wavfile.read(file_path)
if signal.ndim > 1: # Handle multi-channel audio (stereo)
signal = signal[:, 0] # Use only the first channel
max_amplitude = np.max(np.abs(signal))
normalized_signal = signal / max_amplitude
# Determine how many samples fit within the desired duration
num_samples = int(sample_rate * desired_duration_seconds)
if len(normalized_signal) > num_samples:
normalized_signal = normalized_signal[:num_samples]
else:
# Repeat the signal to fit the desired duration
repeated_signal = np.tile(normalized_signal, int(np.ceil(num_samples / len(normalized_signal))))
normalized_signal = repeated_signal[:num_samples]
# Clip and convert to 16-bit integers
normalized_signal = np.clip(normalized_signal * 32767, -32768, 32767).astype(int)
return normalized_signal, sample_rate
def play_wav_file(spi, wav_file, target_channel, desired_duration_seconds):
audio_data, sample_rate = load_wav_file(wav_file, desired_duration_seconds)
num_samples = len(audio_data)
sample_interval = 1 / sample_rate # Time interval between samples
start_time = time.time() # Record the start time
for i, value in enumerate(audio_data):
# Send data to the DAC
channel_values = {channel: 0 for channel in CHANNELS}
channel_values[target_channel] = value
update_channels_with_ldac(spi, channel_values)
# Ensure proper timing
elapsed_time = time.time() - start_time
expected_time = (i + 1) * sample_interval
if elapsed_time < expected_time:
time.sleep(expected_time - elapsed_time)
# Stop playback if exceeded the desired duration
if elapsed_time >= desired_duration_seconds:
break
if __name__ == "__main__":
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 500000
spi.mode = 0b00
initialize_ldac()
try:
target_channel = input("Enter the target channel (A, B, C, D, E, F, G, H): ").strip().upper()
if target_channel not in CHANNELS:
raise ValueError("Invalid channel.")
wav_file = 'wav file dest here'
desired_duration_seconds = 7
play_wav_file(spi, wav_file, target_channel, desired_duration_seconds)
finally:
set_all_channels_to_zero(spi)
spi.close()
GPIO.cleanup()
Подробнее здесь: [url]https://stackoverflow.com/questions/79221180/spidev-on-raspberry-pi-for-ti-dac8568-producing-distorted-signals[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия