Je dois convertir la valeur 'digitalSample' en une tension analogique en utilisant un DAC 12 bits or cette valeur est un entier signé sur 12bits et pour utiliser le DAC il faut lui envoyer des entiers non signés. Je pensais qu'il suffisait donc de faire '+2048' mais cela ne fonctionne pas avec le Serial.println.
Quelqu'un aurait une suggestion ?
void loop() {
// put your main code here, to run repeatedly:
int32_t digitalSample = 0;
size_t bytesRead = 0;
esp_err_t result = i2s_read(I2S_PORT,&digitalSample, sizeof(digitalSample), &bytesRead, portMAX_DELAY);
if (bytesRead > 0) {
Serial.println(digitalSample>>20);
}
pour fixer une valeur on fait MCP.setValue(valeur); // MCP est l'instance de MCP4725, ce n'est pas un print()
la valeur lue provient d'où ? est-ce que digitalSample peut être négative ?
si ce n'est pas le cas alors les bit dans digitalSample sont les même que si c'était un entier non signé
Voici mon code final. digitalSample est un entier signé sur 32 bits donc il peut être négatif, c'est pourquoi je fais ces deux opérations :
int valeur_12bits_signee = digitalSample>>20;
int valeur12bits_non_signee = valeur_12bits_signee + 2048;
pour avoir un entier non signé sur 12bits pour envoyer cette valeur au DAC. Seulement, mon DAC est relié à un haut parleur et aucun son ne sort de ce dernier.
// ajout des bibliothèques nécessaires au programme
#include <driver/i2s.h>
#include<cmath>
#include <driver/dac.h>
#include <Wire.h>
#include <MCP4725.h>
#include<esp_now.h>
// on définit les pins du micro
#define I2S_WS 15
#define I2S_SD 32
#define I2S_SCK 14
#define I2S_PORT I2S_NUM_0
MCP4725 MCP(0x60);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Wire.begin();
MCP.begin(21, 22);
Wire.setClock(3400000);
// on démarre le protocole i2s
delay(1000);
i2s_install();
i2s_setpin();
i2s_start(I2S_PORT);
delay(500);
}
void loop() {
// put your main code here, to run repeatedly:
int32_t digitalSample = 0;
size_t bytesRead = 0;
esp_err_t result = i2s_read(I2S_PORT,&digitalSample, sizeof(digitalSample), &bytesRead, portMAX_DELAY);
if (bytesRead > 0) {
int valeur_12bits_signee = digitalSample>>20; // on ne garde que les 12 bits de poids le plus fort
int valeur12bits_non_signee = valeur_12bits_signee + 2048; // on prend une valeur moyenne non nule pour avoir un signal toujours positif
Serial.println(valeur12bits_non_signee);
MCP.setValue(valeur12bits_non_signee);
}
}
void i2s_install(){
const i2s_config_t i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // ne fonctionne qu'avec 16 ou 32 bits
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false
};
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}
void i2s_setpin(){
const i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = -1,
.data_in_num = I2S_SD
};
i2s_set_pin(I2S_PORT, &pin_config);
}
si ton sample est codé sur un int32 , encore faut il connaitre la résolution utilisée par l’émetteur
(16 24 bits) et son stockage dans dans les 32 bits (justification) .
source de l'I²C ? , normalement es infos sont dispos dans son DS
En effet je récupère les données de mon micro INMP441 via le protocole i2s.
J'ai en partie réutilisé ce programme pour réaliser le mien (pas de bibliothèque particulière il me semble).
Tu es certain que les valeurs retournées sont alignées à gauche?
Si c'était le cas la dynamique de digitalSample sur ta courbe serait bien plus grande environ (±2147483648)
The slave serial-data port’s format is I²S, 24-bit, twos complement. There must be 64 SCK cycles in each WS stereo frame, or 32 SCK cycles per data-word.
ici l'exemple 'micro plotter' , I2S en 32 bits et affichage 'arrondi' des données '24bits signés ' issues d'un INMP441 configuré en 'canal gauche'
#include "driver/i2s.h"
const i2s_port_t I2S_PORT = I2S_NUM_0;
void setup() {
Serial.begin(115200);
esp_err_t err;
// The I2S config as per the example
const i2s_config_t i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX), // Receive, not transfer
.sample_rate = 16000, // 16KHz
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // could only get it to work with 32bits
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // canal gauche
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Interrupt level 1
.dma_buf_count = 4, // number of buffers
.dma_buf_len = 8 // 8 samples per buffer (minimum)
};
// The pin config as per the setup
const i2s_pin_config_t pin_config = {
.bck_io_num = 26, // Serial Clock (SCK)
.ws_io_num = 4, // Word Select (WS)
.data_out_num = I2S_PIN_NO_CHANGE, // not used (only for speakers)
.data_in_num = 17 // Serial Data (SD)
};
// Configuring the I2S driver and pins.
// This function must be called before any I2S driver read/write operations.
err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
if (err != ESP_OK) {
Serial.printf("Failed installing driver: %d\n", err);
while (true);
}
err = i2s_set_pin(I2S_PORT, &pin_config);
if (err != ESP_OK) {
Serial.printf("Failed setting pin: %d\n", err);
while (true);
}
Serial.println("I2S driver installed.");
}
void loop() {
// Read a single sample and log it for the Serial Plotter.
int32_t sample = 0;
int bytes_read = i2s_pop_sample(I2S_PORT, (char *)&sample, portMAX_DELAY); // no timeout
if (bytes_read > 0) {
Serial.println(sample/80000);
}
}