Récupérer les arguments d'un tableau renvoyé par une fonction

Bonjour à tous,

Je suis en train de faire un programme simple pour récupérer une accélération verticale à partir d'un accéléromètre/gyroscope (MPU6050).
Pour cela je calcule les angles de rotation puis je calcule l'accélération voulue.

Problème : une fonction renvoie un tableau contenant plusieurs variables que j'appelle tour à tour dans une autre fonction (voir le script).
Une erreur de typage est renvoyée : " cannot convert 'char (*)()' to 'double' for argument '1' to 'double cos(double)' ".

Je comprends pas à quoi elle correspond, ni comment la régler.

Merci d'avance pour votre aide !

PU6050 accel; // nom de l'accéléromètre
int16_t ax, ay, az, gx, gy, gz; // mesure brute des accélérations (sur 16bits)
int buzzer = 2; // Borne de sortie = borne 2
float alpha; // angle (x,g)
float beta; // angle (y,g)
float gamma; // angle (z,g)
bool booleen; // booléen !
float dt = 0.005; // intervalle de temps (en secondes) pour l'intégration
float accelx, accely, accelz; // accélérations calculées
float accelVerticale; // accélération verticale à t

// Initialisation :

void setup() {
  Wire.begin(); // débute la communication I2C
  pinMode(buzzer, OUTPUT); // le buzzer est la sortie du montage
 
  Serial.begin(9600); // permet l'affichage des données lues
  Serial.println("Initialisation I2C...");
  accel.initialize(); // initialisation I2C
  Serial.println("Test de la connexion du dispositif...");
  Serial.println(accel.testConnection() ? "Echec de la connexion" : "Connexion réussie"); // test de la connexion à l'accéléromètre

    // L'objectif est ici de tester si le variomètre est vertical, cela avec une erreur de 4%.
    // On utilise pour cela la mesure de la gravité terrestre : si l'accélération suivant
    // l'axe z est supérieure à 0.96*9,81, on peut initialiser l'angle gamma à 0, les deux
    // autres à pi.
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  while (abs(az) < 0.96*16384) {
    booleen = false;
  }
  alpha, beta, gamma = PI, PI, 0;
}



char integrationAngles(){
    // Ici, on va mesurer les angles des axes x,y,z de l'accéléromètre avec l'axe vertical.
    // Pour cela, on intègre les vitesses angulaires délivrées par le gyroscope.
    // Les angles renvoyés sont en rad.
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  alpha = alpha + (float(gx)*dt/131)*2*PI/360;
  beta = beta + (float(gy)*dt/131)*2*PI/360;
  gamma = gamma + (float(gy)*dt/131)*2*PI/360;
  float angles[3];
  angles[0] = alpha;
  angles[1] = beta;
  angles[2] = gamma;
  return(angles);
}

float acceleration(){
    // Renvoie l'accélération à un instant t
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  accelx = float(ax)*cos(integrationAngles[0]))9.81/16384;
  accely = float(ay)*cos(integrationAngles[1])*9.81/16384;
  accelz = float(az)*cos(integrationAngles[2])*9.81/16384;
  accelVerticale = sqrt(pow(accelx,2) + pow(accely,2) + pow(accelz,2));
  return(accelVerticale);
}

Salut

Et les bibliothèques que tu as utilisées, on est sensés deviner tout seuls ?

@+

Je peux déjà dire :

Pas de fonction loop()

  accelx = float(ax)*cos(integrationAngles[0]))9.81/16384;

integrationAngles est une fonction, pas un tableau.
integrationAngles renvoie un char alors qu'elle renvoie la variable angles qui est un tableau de float.
Si tu veux renvoyer l'adresse du tableau angles, angles devrait être "static".

Il y a peut-être d'autres coquilles mais comme le code n'est pas complet, difficile à dire.

@+

Bonsoir et merci de votre réponse !

La fonction loop() arrivera plus tard, je ne l'ai pas encore codée.
Si j'ai bien compris, il faut que je change le type de variable renvoyée par la fonction integrationAngles ? Un float donc, ou un static ?

Désolé de ne pas avoir mis tout le code, voici donc l'intégralité.

Merci encore.

#include "Wire.h" // Librairie Wire Arduino
#include "I2Cdev.h" // Librairie permettant les échanges par protocole I2C
#include "MPU6050.h" // Librairie propre à l'accéléromètre
#include "math.h" // Contient des fonctions mathématiques


// Definition des variables :

MPU6050 accel; // nom de l'accéléromètre
int16_t ax, ay, az, gx, gy, gz; // mesure brute des accélérations (sur 16bits)
int buzzer = 2; // Borne de sortie = borne 2
float alpha; // angle (x,g)
float beta; // angle (y,g)
float gamma; // angle (z,g)
bool booleen; // booléen !
float dt = 0.005; // intervalle de temps (en secondes) pour l'intégration
float accelx, accely, accelz; // accélérations calculées
float accelVerticale; // accélération verticale à t

// Initialisation :

void setup() {
  Wire.begin(); // débute la communication I2C
  pinMode(buzzer, OUTPUT); // le buzzer est la sortie du montage
  
  Serial.begin(9600); // permet l'affichage des données lues
  Serial.println("Initialisation I2C...");
  accel.initialize(); // initialisation I2C
  Serial.println("Test de la connexion du dispositif...");
  Serial.println(accel.testConnection() ? "Echec de la connexion" : "Connexion réussie"); // test de la connexion à l'accéléromètre

    // L'objectif est ici de tester si le variomètre est vertical, cela avec une erreur de 4%.
    // On utilise pour cela la mesure de la gravité terrestre : si l'accélération suivant
    // l'axe z est supérieure à 0.96*9,81, on peut initialiser l'angle gamma à 0, les deux
    // autres à pi.
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  while (abs(az) < 0.96*16384) {
    booleen = false;
  }
  alpha, beta, gamma = PI, PI, 0;
}



char integrationAngles(){
    // Ici, on va mesurer les angles des axes x,y,z de l'accéléromètre avec l'axe vertical.
    // Pour cela, on intègre les vitesses angulaires délivrées par le gyroscope.
    // Les angles renvoyés sont en rad.
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  alpha = alpha + (float(gx)*dt/131)*2*PI/360;
  beta = beta + (float(gy)*dt/131)*2*PI/360;
  gamma = gamma + (float(gy)*dt/131)*2*PI/360;
  float angles[3];
  angles[0] = alpha;
  angles[1] = beta;
  angles[2] = gamma;
  return(angles);
}

float acceleration(){
    // Renvoie l'accélération à un instant t
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  accelx = float(ax)*cos(integrationAngles[0]))9.81/16384;
  accely = float(ay)*cos(integrationAngles[1])*9.81/16384;
  accelz = float(az)*cos(integrationAngles[2])*9.81/16384;
  accelVerticale = sqrt(pow(accelx,2) + pow(accely,2) + pow(accelz,2));
  return(accelVerticale);
}


void loop(){
  
}

Si ta fonction integrationAngles() doit renvoyer l'adresse de la variable angles qui est un tableau de type float, d'une part la variable angles doit être static, d'autre part la fonction integrationAngles() doit bien évidemment renvoyer un float *.

float *integrationAngles()
// et
static float angles[3];

Et bien sûr, dans la fonction acceleration() :

 float angles = integrationAngles();
  accelx = float(ax)*cos(angles[0]))9.81/16384;
  accely = float(ay)*cos(angles[1])*9.81/16384;
  accelz = float(az)*cos(angles[2])*9.81/16384;

Mais tu vas vers un autre genre d'erreur : en C, une fonction ne peut pas renvoyer un tableau. Il faut jouer avec les pointeurs.

Exemple :

void loop()
{
 byte data[2];
 getdat(&data);
}

void getdat(byte *pdata)
{
 pdata[0] = 'a';
 pdata[1] = 'b';
}

Ou utiliser des variables globales.

J'imagine que le code n'est pas terminé puisque tu ne te sers pas de la fonction acceleration() ?

il y a une autre erreur :

  accelx = float(ax)*cos(angles[0]))9.81/16384;
// à remplacer par :
  accelx = float(ax)*cos(angles[0])*9.81/16384;

Comme le suggère lesept, passer par un pointeur en paramètre permet de se passer de variable static ou globale.

void integrationAngles(float *angles)
{
    // Ici, on va mesurer les angles des axes x,y,z de l'accéléromètre avec l'axe vertical.
    // Pour cela, on intègre les vitesses angulaires délivrées par le gyroscope.
    // Les angles renvoyés sont en rad.
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  alpha = alpha + (float(gx)*dt/131)*2*PI/360;
  beta = beta + (float(gy)*dt/131)*2*PI/360;
  gamma = gamma + (float(gy)*dt/131)*2*PI/360;
  angles[0] = alpha;
  angles[1] = beta;
  angles[2] = gamma;
}

Dans ce cas, integrationAngles() ne retourne rien.

ensuite :

float acceleration(){
  float angles[3];
    // Renvoie l'accélération à un instant t
  accel.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  integrationAngles(angles);
  accelx = float(ax)*cos(angles[0])*9.81/16384;
  accely = float(ay)*cos(angles[1])*9.81/16384;
  accelz = float(az)*cos(angles[2])*9.81/16384;
  accelVerticale = sqrt(pow(accelx,2) + pow(accely,2) + pow(accelz,2));
  return(accelVerticale);
}

hbachetti:
Comme le suggère lesept, passer par un pointeur en paramètre permet de se passer de variable static ou globale.

Oui, c'est bien mieux que d'utiliser un tableau static.
On crée le tableau vide sur la pile, on le passe à la fonction pour qu'elle le remplisse, et on peut alors utiliser les éléments du tableau. Un peu plus tard le tableau est détruit et on récupère la mémoire.

Bonjour à tous, et merci de votre aide !

Venant de python (et oui, comme tout newbie qui se respecte), je ne savais pas qu'une fonction en C ne pouvait pas renvoyer de tableau. C'est noté, merci.

Le code n'est effectivement pas terminé, j'avance petit à petit :slight_smile:
Mes fonctions seront toutes rassemblées dans mon loop.

J'ai remplacé le ( par *, merci @hbachetti... et bien vu !
J'ai refait mes fonctions en passant par des pointeurs comme tu me l'as proposé, un grand merci ! Je commence à comprendre leur fonctionnement.

Effectivement @biggil, la mémoire est précieuse.

Merci à tous pour votre aide.

malosellier:
je ne savais pas qu'une fonction en C ne pouvait pas renvoyer de tableau. C'est noté, merci.

Un tableau n'est rien d'autre qu'un pointeur sur le début de la mémoire allouée... Donc une fonction en C peut retourner un tableau....

Pour que la fonction puisse retourner ce pointeur et que ce soit valide, il faut bien sûr que la mémoire "pointée" soit bien réservée et ne disparaisse pas à la fin de la fonction

--> si vous voulez que votre fonction "retourne" un tableau, vous devez vous posez la question de savoir si vous voulez un nouveau tableau à chaque appel de la fonction (auquel cas il faudra allouer dynamiquement la mémoire dans la fonction) ou toujours retourner le même tableau (auquel cas ça peut être un tableau déclaré static dans la fonction, mais dont on retourne l'adresse pour que le reste du programme puisse l'utiliser)

Venant de python

Mon langage de prédilection depuis plus de dix ans.
A visiter : PYBOARD

@+