Décaler un signal

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);
  }

:warning:

Post mis dans la mauvaise section, on parle anglais dans les forums généraux. ➜ déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans "Les bonnes pratiques du Forum Francophone”

quel DAC ?

postez un code complet

il s'agit d'un DAC MCP4725. Voici le code complet.
NB : je travaille sur un esp32

// ajout des bibliothèques nécessaires au programme 
#include <driver/i2s.h>
#include<cmath>
#include <driver/dac.h>
#include <MCP4725.h>
MCP4725 dac(0x60);
#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


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  dac.begin();

// 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 veleur12bits_non_signee = valeur_12bits_signee + 2048;
    Serial.println(veleur12bits_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);
}

c'est quelle librairie que vous utilisez ?

Celle de Rob Tillaart

celle là ?

(un lien c'est quand même plus simple)

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);
}

d'un point de vue type il est en entier signé, mais d'un point de vue pratique quelle est sa variation ?

bonjour
A priori tu travaille avec de l'I²S

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

quelle(s) lib utilisée (lien) pour l'I²S

ci joint les variations de digitalSample en pratique :

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).

en utilisant utilisant ce lien pour configurer le protocole i2s
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2s.html

OK donc entre -100 Mega quelque chose et +100 Mega quelque chose à la louche (c'est qui l'échelle?)

votre MCP4725 est configuré entre 0 et 5V ? comment voulez vous traiter la partie négative ?

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)

faudrait aussi connaître l'endianness de la source

INMP441 : 24 bits

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.

le drivers I2S d'Espressif pour Arduino est décrit ici I2S — Arduino-ESP32 2.0.14 documentation

La courbe donnée plus haut correspondrait à un signal codé sur 28 bits signés.
±1,2e8 c'est environ ±227

Il y a un loup quelque part.

alignement et endianness en sortie du INMP441

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);
 }
}

lors d'un bruit conséquent le signal varie plutot entre -2^31 et 2^31 ce qui correspond bien à un entier signé de 32bits