📊
TPs CAN/CNA
3 Projets : Conversion Analogique-Numerique et Numerique-Analogique
📥 ADC
📤 DAC
📊 Acquisition
TP1 : CAN - Conversion Analogique-Numerique
Acquisition de signaux avec ADC
🎯 Objectifs
- Comprendre le principe de l'echantillonnage
- Calculer la resolution et le quantum
- Mesurer des signaux analogiques
- Respecter le theoreme de Shannon
Formules essentielles
CONVERSION ANALOGIQUE → NUMÉRIQUE (CAN/ADC)
┌─────────────────────────────────────────────────────────┐
│ │
│ Resolution (n bits) → 2ⁿ niveaux │
│ │
│ Quantum q = Vref / 2ⁿ │
│ │
│ Valeur numerique N = Vin / q = Vin × 2ⁿ / Vref │
│ │
│ Tension mesuree Vin = N × Vref / 2ⁿ │
│ │
└─────────────────────────────────────────────────────────┘
Exemple : ADC 10 bits, Vref = 5V
- Resolution : 2¹⁰ = 1024 niveaux
- Quantum : q = 5V / 1024 = 4.88 mV
- Si N = 512 → Vin = 512 × 5 / 1024 = 2.5V
Theoreme de Shannon : fe ≥ 2 × fmax
(Frequence d'echantillonnage ≥ 2 × frequence max du signal)
Code Arduino : Acquisition ADC
// TP1 : Acquisition ADC avec calcul de tension const float VREF = 5.0; // Tension de reference const int ADC_BITS = 10; // Resolution 10 bits const int ADC_MAX = 1023; // Valeur max (2^10 - 1) void setup() { Serial.begin(115200); Serial.println("TP1 : Conversion Analogique-Numerique"); Serial.print("Resolution: "); Serial.print(ADC_BITS); Serial.println(" bits"); Serial.print("Quantum: "); Serial.print(VREF / (ADC_MAX + 1) * 1000, 2); Serial.println(" mV"); } void loop() { // Lecture ADC int adc_value = analogRead(A0); // Conversion en tension float voltage = (adc_value * VREF) / ADC_MAX; // Affichage Serial.print("ADC: "); Serial.print(adc_value); Serial.print(" → Tension: "); Serial.print(voltage, 3); Serial.println(" V"); delay(500); }
Exercices
- Calculer la resolution d'un ADC 12 bits avec Vref = 3.3V
- Un ADC 8 bits mesure N = 200. Calculer Vin si Vref = 5V
- Quelle frequence d'echantillonnage pour un signal audio 20kHz ?
TP2 : CNA - Conversion Numerique-Analogique
Generation de signaux avec DAC
Principe du DAC
CONVERSION NUMÉRIQUE → ANALOGIQUE (CNA/DAC)
┌─────────────────────────────────────────────────────────┐
│ │
│ Vout = N × Vref / 2ⁿ │
│ │
│ ou : N = valeur numerique (0 a 2ⁿ-1) │
│ n = nombre de bits │
│ Vref = tension de reference │
│ │
└─────────────────────────────────────────────────────────┘
Types de DAC :
- R-2R Ladder (resistances)
- PWM filtre (simple, basse qualite)
- DAC integre (ex: MCP4725, ESP32)
Applications :
- Generation de signaux (sinus, triangle, etc.)
- Audio (lecture de fichiers WAV)
- Commande de moteurs analogiques
Code : DAC avec PWM filtre
// TP2 : DAC par PWM filtre - Generation sinusoidale const int PWM_PIN = 9; const int SAMPLES = 256; // Table de sinus precalculee (0-255) uint8_t sineTable[SAMPLES]; void setup() { pinMode(PWM_PIN, OUTPUT); // Generer table de sinus for (int i = 0; i < SAMPLES; i++) { sineTable[i] = 127 + 127 * sin(2 * PI * i / SAMPLES); } // PWM haute frequence (Timer1) TCCR1A = 0xA1; // Fast PWM 8-bit TCCR1B = 0x09; // No prescaler } void loop() { for (int i = 0; i < SAMPLES; i++) { analogWrite(PWM_PIN, sineTable[i]); delayMicroseconds(100); // ~40 Hz } }
Code : DAC MCP4725 (I2C)
// DAC 12 bits MCP4725 via I2C #include <Wire.h> #define MCP4725_ADDR 0x60 void setDAC(uint16_t value) { // Valeur 12 bits (0-4095) Wire.beginTransmission(MCP4725_ADDR); Wire.write((value >> 8) & 0x0F); // 4 bits MSB Wire.write(value & 0xFF); // 8 bits LSB Wire.endTransmission(); } void setup() { Wire.begin(); } void loop() { // Rampe 0 → 4095 → 0 for (uint16_t v = 0; v < 4096; v += 16) { setDAC(v); delay(1); } for (int16_t v = 4095; v >= 0; v -= 16) { setDAC(v); delay(1); } }
TP3 : Systeme d'acquisition complet
Chaine acquisition + conditionnement + affichage
Architecture du systeme
┌────────────────────────────────────────────────────────────┐
│ CHAÎNE D'ACQUISITION COMPLÈTE │
├────────────────────────────────────────────────────────────┤
│ │
│ CAPTEUR CONDITIONNEMENT ADC TRAITEMENT│
│ ┌───────┐ ┌─────────────┐ ┌───────┐ ┌─────────┐│
│ │ │ │ Ampli │ │ │ │ ││
│ │ LM35 ├────▶│ + Filtre ├───▶│ ADC ├───▶│ µC ││
│ │ │ │ passe-bas │ │ 12bit │ │ ││
│ └───────┘ └─────────────┘ └───────┘ └────┬────┘│
│ │ │
│ ┌──────────┴────┐│
│ │ AFFICHAGE ││
│ │ LCD / UART ││
│ └───────────────┘│
└────────────────────────────────────────────────────────────┘
Capteur LM35 : 10mV/°C (0°C = 0mV, 100°C = 1000mV)
Calcul temperature : T(°C) = (ADC × Vref / 4095) / 0.01
Exemple : ADC = 310 avec Vref = 3.3V
→ Tension = 310 × 3.3 / 4095 = 0.25V = 250mV
→ Temperature = 250mV / 10mV = 25°C
Code : Systeme complet
// TP3 : Systeme d'acquisition temperature LM35 const int LM35_PIN = A0; const float VREF = 5.0; const int ADC_MAX = 1023; const float LM35_COEF = 0.01; // 10mV/°C // Moyennage pour reduire le bruit const int NUM_SAMPLES = 10; float readTemperature() { long sum = 0; // Moyennage de NUM_SAMPLES lectures for (int i = 0; i < NUM_SAMPLES; i++) { sum += analogRead(LM35_PIN); delay(10); } float avg_adc = sum / (float)NUM_SAMPLES; float voltage = (avg_adc * VREF) / ADC_MAX; float temperature = voltage / LM35_COEF; return temperature; } void setup() { Serial.begin(115200); Serial.println("Systeme d'acquisition temperature"); } void loop() { float temp = readTemperature(); Serial.print("Temperature: "); Serial.print(temp, 1); Serial.println(" °C"); // Alarme si T > 30°C if (temp > 30.0) { Serial.println("⚠️ ALERTE: Temperature elevee!"); } delay(1000); }
Criteres d'evaluation
| Critere | Points |
|---|---|
| TP1 : Calculs CAN et mesures ADC | /6 |
| TP2 : Generation signal avec DAC | /6 |
| TP3 : Systeme acquisition complet | /8 |
| Total | /20 |