Bonjour à tous,
Je suis en train de réaliser des prises de mesures sur les suspensions d'un velo pour un projet d'études à l'aide de 2 accelerometres et un capteur ultrason.
J'ai dans un premier temps réalisé un programme arduino qui communique les valeurs mesurées et qui les affichent dans la console. Je les récupère par un programme python en temps réellles et les enregistre dans un fichier. Ce programme fonctionne parfaitement.
Pour plus de simpliciter lors de l'acquisition de données, je souhaite que la carte enregistre les données dans une carte SD.
Le module SD fonctionne avec le protocole SPI, comme l'accelerometre ADXL345 (le second accelerometre fonctionne par le protocole I2C).
Cependant, lorsque j'execute mon nouveau programme, je recupere sur la carte toutes les données, sauf que celle de l'ADXL sont toutes à 0. Or j'ai vérifié les branchements et le programme ADXL seul fonctionne et aussi le programme lié à python.
Mon matériel : Arduino UNO, Shield carte SD V4 103030005, ADXL 345, MPU 6050, capteur ultrason HC-SR05
Merci de votre aide,
//Shield SD
#include <SD.h>
//Add the SPI library so we can communicate with the ADXL345 sensor and the SD module
#include <SPI.h>
//I2C
#include <Wire.h>
#include <Adafruit_MPU6050.h>
/*
Liste des branchements à faire :
- ADXL345 : fil n9
- GND : (Orange)
- VCC : 5V (marron)
- CS : 8 (jaune)
- SDO : 12 (violet)
- SDA : 11 (blanc)
- SCL : 13 (gris)
- Module SD :
- Rien de particulier
- (pin 4 utilisé)
- MPU 6050 : fil n3
- GND : (gris)
- VCC : 5V (orange)
- SCL : A5 (violet)
- SDA : A4 (jaune)
- Capteur ultrason : fil n0
- GND : (Bleu)
- VCC : 5V (marron)
- Trigger : 10 (gris)
- Echo : 9 (rose)
- Dispositif LED :fil n9 (gnd uniquement) et n3
- Led verte : 3 (bleu) + resistance 220ohm
- Led rouge : 2 (rose) + resistance 220ohm
- Bouton : 5 (blanc) + resistance 220ohm
- VCC : (orange) + resistance 220ohm
- GND : n9 (bleu)
*/
//SD
File myFile;
const int CS_SD = 4;
// temps
unsigned long time;
float temps_sec;
unsigned long debut_prise_mesure; //pas possible mettre const car on ne la definie par maintenant. Const permet d'avoir accès à la variable qu'en lecture
//led
const int pinLEDR = 2; // pin de la LED et du bouton
const int pinLEDV = 3;
const int boutonPin = 5 ;
int compteur = 45; // compteur comptant le nombre de mesures envoyées et réinitialise à 45 en changeant l'etat de la LED verte
int etat_led = LOW;
int temps_defini = 6000; // Temps de l'appiui long pour stoper le programme
unsigned long debut_appui, temps_appui;
int etat_bouton = LOW;
//SPI
//https://www.sparkfun.com/tutorials/240
//http://forum.arduino.cc/index.php/topic,159313.0.html
//Assign the Chip Select signal to pin 8.
int CS=8;
//This is a list of some of the registers available on the ADXL345.
//To learn more about these and the rest of the registers on the ADXL345, read the datasheet!
char POWER_CTL = 0x2D; //Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
char DATAY0 = 0x34; //Y-Axis Data 0
char DATAY1 = 0x35; //Y-Axis Data 1
char DATAZ0 = 0x36; //Z-Axis Data 0
char DATAZ1 = 0x37; //Z-Axis Data 1
//This buffer will hold values read from the ADXL345 registers.
unsigned char values[10];
//These variables will be used to hold the x,y and z axis accelerometer values.
int x,y,z;
float X_out_SPI= 2.0 ,Y_out_SPI =1.0 ,Z_out_SPI =9.0; // Les varibales stockant les valeurs de sortie
const int precision = 6;
const float coeff_adap = -9.81 * pow(10,precision)/128;
//I2C
Adafruit_MPU6050 mpu;
float ax_I2C, ay_I2C, az_I2C,gx_I2C, gy_I2C, gz_I2C = 0.0;
//Ultrason
/* Constantes pour les broches */
const byte TRIGGER_PIN = 10; // Broche TRIGGER
const byte ECHO_PIN = 9; // Broche ECHO
/* Constantes pour le timeout */
const unsigned long MEASURE_TIMEOUT = 3*pow(10,-3); // 6ms = ~2m à 340m/s
/* Vitesse du son dans l'air en mm/us */
const float SOUND_SPEED = 340.0 / 1000;
float distance_mm;
long measure = 0;
void setup(){
Serial.begin(115200);
pinMode(pinLEDR, OUTPUT);
pinMode(boutonPin, INPUT);
pinMode(pinLEDV, OUTPUT);
digitalWrite(pinLEDR, HIGH);
digitalWrite(pinLEDV, HIGH);
delay(1000);
digitalWrite(pinLEDR, LOW);
digitalWrite(pinLEDV, LOW);
//SPI
//Initiate an SPI communication instance.
SPI.begin();
//Configure the SPI connection for the ADXL345.
SPI.setDataMode(SPI_MODE3);
//Set up the Chip Select pin to be an output from the Arduino.
pinMode(CS, OUTPUT);
pinMode(CS_SD, OUTPUT);
//Before communication starts, the Chip Select pin needs to be set high.
digitalWrite(CS, HIGH);
digitalWrite(CS_SD, HIGH);
//Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
writeRegister(DATA_FORMAT, 0x01);
//Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
writeRegister(POWER_CTL, 0x08); //Measurement mode
//I2C
if (!mpu.begin()) {
digitalWrite(pinLEDR,HIGH);
while (1) {
delay(10);
Serial.println("error");
}
}
//ultrason
/* Initialise les broches */
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW); // La broche TRIGGER doit être à LOW au repos
pinMode(ECHO_PIN, INPUT);
debut_prise_mesure = millis();
// SD
if (!SD.begin(CS_SD)) {
Serial.println("initialization failed!");
digitalWrite(pinLEDR,HIGH);
digitalWrite(pinLEDV, HIGH);
while (1);
//Possible de signifier une erreur dans le programme
}
}
void loop(){
compteur = compteur + 1;
// Differenciation entre appui long et cours
if (digitalRead(boutonPin) == HIGH){
Serial.println("bouton on");
digitalWrite(pinLEDV, LOW);
etat_led = LOW;
digitalWrite(pinLEDR, HIGH);
debut_appui = millis();
while (digitalRead(boutonPin) == HIGH){
delay(1);
}
temps_appui = millis()-debut_appui;
if (temps_appui > temps_defini){
digitalWrite(pinLEDV, LOW);
while (1){ // boucle led clignotante indiquant "l'arret du programme" et de la prise de mesure
digitalWrite(pinLEDR,LOW);
delay(500);
digitalWrite(pinLEDR,HIGH);
delay(500);
}
}
else{
digitalWrite(pinLEDR,LOW);
delay(500);
digitalWrite(pinLEDR,HIGH);
digitalWrite(pinLEDV,HIGH);
delay(1000);
digitalWrite(pinLEDR,LOW);
digitalWrite(pinLEDV,LOW);
//possible action à faire si appui court
//1 seul cligonetement des DEUX leds pour le moment
}
}
// la lecture est après pour que la conditions du bouton soit prioritaire sur l'annalyse de données
time = millis() - debut_prise_mesure;
lecture_acc_spi();
lecture_ultrason();
lecture_calcul_acc_I2C();
calcul_spi();
calcul_ultrason();
enregistrement_fichier();
// LED verte clignotante lors de l'acquisition marquant que le programme n'est pas en erreur
if (compteur > 30){ // toutes les 50 mesures, changement de l'etat de la led verte
change_etatLED();
compteur = 0;
}
}
//fonction lecture capteur
void lecture_ultrason(){
/* 1. Lance une mesure de distance en envoyant une impulsion HIGH de 10µs sur la broche TRIGGER */
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
/* 2. Mesure le temps entre l'envoi de l'impulsion ultrasonique et son écho (si il existe) */
measure = pulseIn(ECHO_PIN, HIGH, MEASURE_TIMEOUT);
}
void lecture_calcul_acc_I2C(){
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
ax_I2C = a.acceleration.x; // Accélération en m/s²
ay_I2C = a.acceleration.y;
az_I2C = a.acceleration.z;
gx_I2C = g.gyro.x; // Vitesse angulaire en degrés par seconde
gy_I2C = g.gyro.y;
gz_I2C = g.gyro.z;
}
void lecture_acc_spi(){
//Reading 6 bytes of data starting at register DATAX0 will retrieve the x,y and z acceleration values from the ADXL345.
//The results of the read operation will get stored to the values[] buffer.
readRegister(DATAX0, 6, values);
//The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
//The X value is stored in values[0] and values[1].
x = ((int)values[1]<<8)|(int)values[0];
//The Y value is stored in values[2] and values[3].
y = ((int)values[3]<<8)|(int)values[2];
//The Z value is stored in values[4] and values[5].
z = ((int)values[5]<<8)|(int)values[4];
}
//fonction calul
void calcul_spi(){
X_out_SPI = x * coeff_adap * pow(10,-precision);
Y_out_SPI = y * coeff_adap * pow(10,-precision);
Z_out_SPI = z * coeff_adap * pow(10,-precision);
Serial.print(X_out_SPI, 2);
Serial.print(',');
Serial.print(Y_out_SPI, 2);
Serial.print(',');
Serial.println(Z_out_SPI, 2);
}
void calcul_ultrason(){
distance_mm = measure / 2.0 * SOUND_SPEED;
}
void enregistrement_fichier(){
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
//Heure
temps_sec = time*pow(10,-3); // reconversion du temps milliseconde en seconde
myFile.print(temps_sec,3);
myFile.print(";");
//SPI affichage console
myFile.print(X_out_SPI, DEC);
myFile.print(";");
myFile.print(Y_out_SPI, DEC);
myFile.print(";");
myFile.print(Z_out_SPI, DEC);
myFile.print(";");
//I2C affichage console
myFile.print(ax_I2C , 2); // Afficher avec 2 décimales
myFile.print(";");
myFile.print(ay_I2C , 2);
myFile.print(";");
myFile.print(az_I2C , 2);
myFile.print(";");
//partie du gyroscope
myFile.print(gx_I2C , 2);
myFile.print(";");
myFile.print(gy_I2C , 2);
myFile.print(";");
myFile.print(gz_I2C , 2);
myFile.print(";");
//Ultrason affichage
// Affiche les résultats en mm
myFile.println(distance_mm,2);
// close the file:
myFile.close();
Serial.println("done");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
// Fonction SPI
//Fonction copiée
//This function will write a value to a register on the ADXL345.
//Parameters:
// char registerAddress - The register to write a value to
// char value - The value to be written to the specified register.
void writeRegister(char registerAddress, char value){
//Set Chip Select pin low to signal the beginning of an SPI packet.
digitalWrite(CS, LOW);
//Transfer the register address over SPI.
SPI.transfer(registerAddress);
//Transfer the desired register value over SPI.
SPI.transfer(value);
//Set the Chip Select pin high to signal the end of an SPI packet.
digitalWrite(CS, HIGH);
}
//This function will read a certain number of registers starting from a specified address and store their values in a buffer.
//Parameters:
// char registerAddress - The register addresse to start the read sequence from.
// int numBytes - The number of registers that should be read.
// char * values - A pointer to a buffer where the results of the operation should be stored.
void readRegister(char registerAddress, int numBytes, unsigned char * values){
//Since we're performing a read operation, the most significant bit of the register address should be set.
char address = 0x80 | registerAddress;
//If we're doing a multi-byte read, bit 6 needs to be set as well.
if(numBytes > 1)address = address | 0x40;
//Set the Chip select pin low to start an SPI packet.
digitalWrite(CS, LOW);
//Transfer the starting register address that needs to be read.
SPI.transfer(address);
//Continue to read registers until we've read the number specified, storing the results to the input buffer.
for(int i=0; i<numBytes; i++){
values[i] = SPI.transfer(0x00);
}
//Set the Chips Select pin high to end the SPI packet.
digitalWrite(CS, HIGH);
}
// change etat led V
void change_etatLED(){
if (etat_led == LOW){
digitalWrite(pinLEDV,HIGH);
etat_led = HIGH;
}
else{
digitalWrite(pinLEDV, LOW);
etat_led = LOW;
}
}
//