[RESOLU] Communications série/I²C dans une classe

Bonsoir,

Est-ce que quelqu'un sait ou a déjà utilisé les communications séries et I²C dans une classe ? Et pourrait me dire comment faire, malgré tous mes tests je n'aboutis à rien !
Impossible de faire marcher mon MPU6050 par I²C et impossible de voir d'où ça vient parce que je n'arrive pas à faire fonctionner les com série à l'intérieur de ma classe.

Merci d'avance,

Bonne nuit :slight_smile:

Si ça peut servir le prog principal et la class incriminée:

#include <Wire.h>
#include <Servo.h>
#include "configuration.h"
#include "def.h"
#include <RADIOCOMMAND.h>
#include <QUADRICOPTER.h>

RADIOCOMMAND Radio(THROTTLE_PIN, YAW_PIN, PITCH_PIN, ROLL_PIN, MOT_LOCK_PIN);
QUADRICOPTER Quadri(MOT_A_PIN, MOT_B_PIN, MOT_C_PIN, MOT_D_PIN, PULSE_MOTOR_WIDTH_MIN, PULSE_MOTOR_WIDTH_MAX, BATT_PIN, LED_BATT_PIN);

void setup()
{
  /*Serial.begin(9600); 
Wire.begin();
  while (!Serial);
  
  Serial.println("TEST");*/
}

void loop()
{
  // Petit Check batterie
  if (Quadri.etatBatterie() == Q_BAT_HS)
    Quadri.LED_etatBatterie(Q_BLINK);
  
  // Condition de mise route
 // if (Quadri.motorsRotate() == false) // si tous les moteurs sont arrêtés
   // while (Radio.isRTF() == Q_NOT_READY_TO_FLY);// et que l'inter est actif : on attend
  
  /***************************/
  /* PHASE DE CONTROL DE VOL */
  /***************************/
  Quadri.setConsignesDeVol(/*quelque chose*/);
  Quadri.CorrectionsDeVol(/* éventuellement quelques chose *unknown 4 the moment* */);
  
  Serial.println("bah ouai ca marche =) ");
  
  delay(1000);
  
}
#ifndef GYROSCOPE_H
#define GYROSCOPE_H

#include <Arduino.h>
#include <Wire.h>

//définition des adresses de registres
#define MPU6050_GYRO_XOUT_H 0x43   // R  
#define MPU6050_GYRO_XOUT_L 0x44   // R  
#define MPU6050_GYRO_YOUT_H 0x45   // R  
#define MPU6050_GYRO_YOUT_L 0x46   // R  
#define MPU6050_GYRO_ZOUT_H 0x47   // R  
#define MPU6050_GYRO_ZOUT_L 0x48   // R

#define MPU6050_PWR_MGMT_1 0x6B   // R/W
#define GYRO_CONFIG 0x1B  // RW

#define MPU6050_I2C_ADDRESS 0x68

class GYROSCOPE
{
	public:
		GYROSCOPE(void); // only 4 motors
	
		void Update(void);
		void Initialisation(void);
		
		void request_Xout(void);
		void request_Yout(void);
		void request_Zout(void);
		
	private:
		uint16_t Xout;
		uint16_t Yout;
		uint16_t Zout;
};

#endif //GYROSCOPE_H
// gyroscope.cpp

#include <Arduino.h>
#include <Wire.h>
#include "gyroscope.h"

GYROSCOPE::GYROSCOPE(void)
{
Serial.begin(9600); 
Serial.println("azertyuio");
	Wire.begin();
	Initialisation();
}

void GYROSCOPE::Update(void)
{
	request_Xout();
	request_Yout();
	request_Zout();
}

void GYROSCOPE::Initialisation(void)
{
//Wire.begin();
	// COPIÉ COLLÉ DE MULTI WII
	TWBR = ((16000000L / 400000L) - 16) / 2; // change the I2C clock rate to 400kHz
	Serial.println("1");
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Serial.println("2");
	Wire.write(MPU6050_PWR_MGMT_1);
	Serial.println("3");
	Wire.write(0x80);
	Serial.println("4");
	Wire.endTransmission(true);
	Serial.println("5");
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_PWR_MGMT_1);
	Wire.write(0x03);	//PWR_MGMT_1    -- SLEEP 0; CYCLE 0; TEMP_DIS 0; CLKSEL 3 (PLL with Z Gyro reference)
	Wire.endTransmission(false);
	
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(GYRO_CONFIG);
	Wire.write(0x18);	//GYRO_CONFIG   -- FS_SEL = 3: Full scale set to 2000 deg/sec
	Wire.endTransmission(true);
}

void GYROSCOPE::request_Xout(void)
{	
	// Récupération des 8 bits de poids fort
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_GYRO_XOUT_H);
	Wire.endTransmission(false);
	
	Wire.requestFrom(MPU6050_I2C_ADDRESS, 1, false);
	while(Wire.available() < 0);
	Xout = Wire.read() << 8;
	
	// Récupération des 8 bits de poids faible
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_GYRO_XOUT_L);
	Wire.endTransmission(false);
	
	Wire.requestFrom(MPU6050_I2C_ADDRESS, 1, true);
	while(Wire.available() < 0);
	Xout |= Wire.read();
}

void GYROSCOPE::request_Yout(void)
{	
	// Récupération des 8 bits de poids fort
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_GYRO_YOUT_H);
	Wire.endTransmission(false);
	
	Wire.requestFrom(MPU6050_I2C_ADDRESS, 1, false);
	while(Wire.available() < 0);
	Yout = Wire.read() << 8;
	
	// Récupération des 8 bits de poids faible
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_GYRO_YOUT_L);
	Wire.endTransmission(false);
	
	Wire.requestFrom(MPU6050_I2C_ADDRESS, 1, true);
	while(Wire.available() < 0);
	Yout |= Wire.read();
}

void GYROSCOPE::request_Zout(void)
{	
	// Récupération des 8 bits de poids fort
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_GYRO_ZOUT_H);
	Wire.endTransmission(false);
	
	Wire.requestFrom(MPU6050_I2C_ADDRESS, 1, false);
	while(Wire.available() < 0);
	Zout = Wire.read() << 8;
	
	// Récupération des 8 bits de poids faible
	Wire.beginTransmission(MPU6050_I2C_ADDRESS);
	Wire.write(MPU6050_GYRO_ZOUT_L);
	Wire.endTransmission(false);
	
	Wire.requestFrom(MPU6050_I2C_ADDRESS, 1, true);
	while(Wire.available() < 0);
	Zout |= Wire.read();
}

Il n'y a pas de soucis pour utiliser de l'I2C dans une classe.
J'ai moi même une classe qui encapsule le PCF8574 (attachée) et Skywodd en a aussi une autre sur son blog.
Je te laisse y jeter un coup d'oeil.

pcf8574.zip (2.39 KB)

Bonjour !

Quand le téléchargement du zip nous renvoie une magnifique erreur 503 on doit faire quoi ^^

Prier ?
Crier sur le modo ?
Aller à la concurrence ?

XD
http://www.barbudor.net/files/pcf8574.zip

Hmm j'hésite !

Je vais me contenter de cliquer sur le petit lien je crois x)

J'ai étudié les deux lib pour le pcf (skywodd et toi),

Chez skywodd il n'y a pas le Wire.begin() dans le constructeur. Chez toi il n'y a pas de Wire.begin() tout court XD

J'ai donc fait plein de test et les résultats de tous mes tests indiquent que de l'I²C dans le constructeur de ma classe ça ne marche pas du tout... le programme plante tout le temps (même quand je met pas le Wire.begin()).
La seule solution que j'ai trouvé est de d'initialiser tout ça à la main, hors constructeur... J'aime pas je trouve pas ça très propre :frowning:

Une idée pour pouvoir utiliser l'i²C dans le constructeur ?

PS: ligne 40 de ta lib est-ce normal les double point virgule ? " return Wire.read();; "

barbudor:
Il n'y a pas de soucis pour utiliser de l'I2C dans une classe.
J'ai moi même une classe qui encapsule le PCF8574 (attachée) et Skywodd en a aussi une autre sur son blog.
Je te laisse y jeter un coup d'oeil.

Je conseille celle de Barbudor, du moins pour le moment :grin:
La mienne est vraiment pas optimisé et plein de truc sont à reprendre, c'était ma toute première librairie arduino et ça se ressent au niveau code ...
Une nouvelle version est en cours de préparation mais il va me falloir un peu de temps pour tout finir :sweat_smile:

Reynosa:
J'ai donc fait plein de test et les résultats de tous mes tests indiquent que de l'I²C dans le constructeur de ma classe ça ne marche pas du tout... le programme plante tout le temps (même quand je met pas le Wire.begin()).
La seule solution que j'ai trouvé est de d'initialiser tout ça à la main, hors constructeur... J'aime pas je trouve pas ça très propre :frowning:

En I2C tu peut avoir plusieurs modules sur un même bus.
Tu peut donc avoir plusieurs objet PCF8574 instancié dans un même code.
Mettre Wire.begin() dans le constructeur reviendrai à initialiser le bus I2C plusieurs fois inutilement.

Reynosa:
PS: ligne 40 de ta lib est-ce normal les double point virgule ? " return Wire.read();; "

fôte de phrape

Le Wire.begin n'est pas dans la lib car on peut avoir plusieurs instances ou plusieurs chips sur l'I2C
Donc dans mon exemple d'utilisation il est dans setup()

De même je n'accède pas à l'I2C dans le constructeur.

En effet il faut être conscient que pour tous les objets instanciés en variable globale, le constructeur est appellé AVANT setup() !!!!!

Je pense que ton problème est là.

Je suggère :

  1. Vire tout accès à l'I2C des constructeurs de tes classes. Dans les constructeurs ne touche pas au hard d'une manière générale (même pas pinmode ou digitalRead/digitalWrite), contente toi d'initialiser tes variables uniquement.
    Met toute l'init hard dans une fonction begin().

  2. dans setup() appelle Wire.begin
    puis appelle la fonction begin() de tes objets.

Bonne nuit =)

Hé bien voici une de magnifiques réponses ! :slight_smile:

C'est vrai que du point de vue "qui est fait quand" c'est tout à fait logique !
Je pense qu'il va falloir que j'adopte cette manière de raisonner moi :wink:

Encore merci !