Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SPI.h>
- #include <SD.h>
- #include <avr/wdt.h>
- // Constantes système
- #define PIN_CAPTEUR A2
- #define PIN_CS_SD 4
- #define DUREE_ACQUISITION_S 7
- #define BAUD_RATE 115200
- // Constantes de conversion pour l'accéléromètre ADXL335
- #define ZERO_G_VALUE 261
- #define SCALE_FACTOR 205
- // Constantes de buffer
- #define TAILLE_BUFFER 1024
- #define TAILLE_MAX_ENTREE 20
- #define ESPACE_SECURITE (TAILLE_BUFFER - TAILLE_MAX_ENTREE)
- // Variables globales
- File myFile;
- volatile bool acquisitionTerminee = false;
- volatile uint8_t compteurSecondes = 0;
- // Buffer d'acquisition pour mémoriser tous les échantillons
- char bufferDonnees[TAILLE_BUFFER];
- uint16_t indexBuffer = 0;
- uint32_t nbEchantillons = 0;
- unsigned long tempsDebutAcquisition;
- // Routine d'interruption du Watchdog
- ISR(WDT_vect) {
- if (++compteurSecondes >= DUREE_ACQUISITION_S) {
- acquisitionTerminee = true;
- wdt_disable(); // Désactivation du Watchdog
- }
- }
- // Lecture ADC optimisée avec accès direct aux registres
- inline uint16_t lectureADC(uint8_t pin) {
- // Sélection du canal ADC (A0-A5 correspond aux canaux 0-5)
- ADMUX = (ADMUX & 0xF0) | (pin & 0x07);
- // Démarrer la conversion
- ADCSRA |= (1 << ADSC);
- // Attendre la fin de la conversion
- while (ADCSRA & (1 << ADSC));
- // Lire le résultat (ADCL doit être lu en premier)
- uint8_t low = ADCL;
- uint8_t high = ADCH;
- return (high << 8) | low;
- }
- void setup() {
- // Initialisation de la communication série
- Serial.begin(BAUD_RATE);
- Serial.println(F("Initialisation..."));
- // Configuration de l'ADC pour une conversion plus rapide
- // Diviseur d'horloge = 64 au lieu de 128 (par défaut)
- ADCSRA = (ADCSRA & 0xF8) | 0x06;
- // Configuration de la carte SD
- if (!SD.begin(PIN_CS_SD)) {
- Serial.println(F("Echec carte SD"));
- return;
- }
- // Préparation du fichier
- if (SD.exists("MESURE.txt")) {
- if (!SD.remove("MESURE.txt")) {
- Serial.println(F("Erreur suppression fichier"));
- // Continuer malgré l'erreur
- }
- }
- // Configuration du Watchdog pour timing approximatif
- configurerWatchdog();
- // Marquage du temps initial
- tempsDebutAcquisition = millis();
- // Écriture de l'en-tête dans le buffer
- const char *entete = "Accel Z (g), Temps (ms)\n";
- strcpy(bufferDonnees, entete);
- indexBuffer = strlen(entete);
- Serial.println(F("Début acquisition"));
- }
- // Configuration du Watchdog comme timer approximatif
- void configurerWatchdog() {
- cli(); // Désactiver les interruptions
- // Effacer le flag de reset
- MCUSR &= ~(1 << WDRF);
- // Permettre la modification des registres du Watchdog
- WDTCSR |= (1 << WDCE) | (1 << WDE);
- // Mode interruption uniquement (pas de reset) avec intervalle ~1s
- WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1);
- sei(); // Réactiver les interruptions
- }
- // Fonction utilitaire pour compter le nombre de chiffres
- inline uint8_t numDigits(uint16_t valeur) {
- if (valeur < 10) return 1;
- if (valeur < 100) return 2;
- if (valeur < 1000) return 3;
- return 4;
- }
- // Fonction optimisée pour l'écriture d'une entrée accélération/temps
- void ecrireEntree(int16_t valeur, unsigned long timestamp) {
- // Partie entière de l'accélération (peut être négative)
- int16_t partieEntiere = valeur / 10000;
- itoa(partieEntiere, &bufferDonnees[indexBuffer], 10);
- indexBuffer += strlen(&bufferDonnees[indexBuffer]);
- // Séparateur décimal
- bufferDonnees[indexBuffer++] = '.';
- // Partie décimale (4 chiffres significatifs) - toujours positive
- int16_t partieDecimale = abs(valeur % 10000);
- // Gestion optimisée des zéros en tête (moins d'instructions)
- char* ptrDecimale = &bufferDonnees[indexBuffer];
- // Allocation d'espace pour 4 chiffres + null terminator
- memset(ptrDecimale, '0', 4);
- // Conversion de la partie décimale en chaîne
- itoa(partieDecimale, ptrDecimale + (4 - numDigits(partieDecimale)), 10);
- indexBuffer += 4;
- // Séparateur entre colonnes
- bufferDonnees[indexBuffer++] = ',';
- bufferDonnees[indexBuffer++] = ' ';
- // Conversion du timestamp
- itoa(timestamp, &bufferDonnees[indexBuffer], 10);
- indexBuffer += strlen(&bufferDonnees[indexBuffer]);
- // Retour à la ligne
- bufferDonnees[indexBuffer++] = '\n';
- }
- // Écriture du buffer complet sur la carte SD
- void sauvegarderDonnees() {
- myFile = SD.open("MESURE.txt", FILE_WRITE);
- if (myFile) {
- myFile.write(bufferDonnees, indexBuffer);
- myFile.close();
- Serial.println(F("Données sauvegardées"));
- } else {
- Serial.println(F("Erreur ouverture fichier"));
- }
- }
- void loop() {
- // Phase d'acquisition
- if (!acquisitionTerminee) {
- // Acquisition uniquement si le buffer n'est pas plein
- if (indexBuffer < ESPACE_SECURITE) {
- // Lecture et conversion optimisée
- uint16_t valeurADC = lectureADC(PIN_CAPTEUR - A0);
- int32_t acceleration = ((int32_t)ZERO_G_VALUE - (int32_t)valeurADC) * SCALE_FACTOR;
- // Capture du temps relatif
- unsigned long tempsRelatif = millis() - tempsDebutAcquisition;
- // Écriture formatée dans le buffer
- ecrireEntree(acceleration, tempsRelatif);
- // Comptage
- nbEchantillons++;
- }
- }
- // Phase de sauvegarde
- else {
- static bool sauvegardeFaite = false;
- if (!sauvegardeFaite) {
- sauvegarderDonnees();
- Serial.print(F("Échantillons acquis: "));
- Serial.println(nbEchantillons);
- Serial.print(F("Taille buffer (octets): "));
- Serial.println(indexBuffer);
- Serial.print(F("Fréquence moyenne (Hz): "));
- Serial.println((float)nbEchantillons / DUREE_ACQUISITION_S);
- } // sauvegardeFaite non réinitialisé car fin du programme
- } // Boucle infinie
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement