MPU9255 haberleşme kesilmesi

Başlatan esdevhk, 09 Ekim 2019, 21:52:23

esdevhk

Cümleten kolay gelsin,

STM32F4 Disco ile MPU9255 sensör board'dan veri okuma işlemi yapıyorum. Okuma/yazma işlemlerinde bir sorunum yok. Sorun şu ki; haberleşme esnasında mikrodenetleyiciyi resetlediğimde (hep değil ama genel olarak 4-5 kere resetlendiğinde bazen ilk resette) haberleşme kesilmekte. Sensör ile haberleşme kesildikten sonra sensörün gücünü kesmeden haberleşme hattı düzelmemektedir.

Sensörün dökümanını dikkatlice okudum ve çoğu örneğe baktığımda sensörün power işlemleri ile ilgili registerlarına doğru müdahele ettiğimi düşünüyorum. Mikrodenetleyiciyi resetlediğimden dolayı haberleşme hattı mı çöküyor? Fikir ve düşüncelerinizi bekliyorum.

Teşekkürler.

Merak edenler için sensörün başlangıç ayarlarını yaptığım fonksiyon.
void MPU9255_Init()
{
		 uint8_t giden_veri_u8 = 0;

		 giden_veri_u8 = 0x80;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,PWR_MGMT_1,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); // register adresleri default degerlerine cekilir.
		 HAL_Delay(100);

		 giden_veri_u8 = 0x01;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,PWR_MGMT_1,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); // uyku modundan çikartilir.

		 giden_veri_u8 = 0x00;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,PWR_MGMT_2,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); 
		 HAL_Delay(200);

		 giden_veri_u8 = 0x0D;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,I2C_MST_CTRL,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50);

		 giden_veri_u8 = 0x03;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,CONFIG,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50);

		 giden_veri_u8 = 0x04;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,SMPLRT_DIV,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); // sample rate 1kHz ayarlanir.

		 giden_veri_u8 = 0x10;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,GYRO_CONFIG,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); // gyro +/-1000dps

		 giden_veri_u8 = 0x00;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,ACCEL_CONFIG,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); // accel +/-2g

		 giden_veri_u8 = 0x03;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,ACCEL_CONFIG2,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50);

		 giden_veri_u8 = 0x02;
	 	 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,INT_PIN_CFG,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50); // magnetometer aktif edilir.

		 giden_veri_u8 = 0x01;
		 HAL_I2C_Mem_Write(&hi2c2,MPU9255_ADDRESS,INT_ENABLE,I2C_MEMADD_SIZE_8BIT,&giden_veri_u8,1,50);

}


OptimusPrime

Haberlesme esnasinda mikroyu resetlediginde olur oyle isler  :D

Sensorun cevap vermedigini anladiginda SCL yi 9 kez salla. Bu sensore kendine gel mesaji verecektir. Klasik recovery modu.

https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

esdevhk

Alıntı yapılan: OptimusPrime - 09 Ekim 2019, 23:41:06Haberlesme esnasinda mikroyu resetlediginde olur oyle isler  :D

Sensorun cevap vermedigini anladiginda SCL yi 9 kez salla. Bu sensore kendine gel mesaji verecektir. Klasik recovery modu.



Sebebi nedir bu durumun? Çünkü gücü kesmezsem eğer sensör katiyen cevap vermiyor. Kesin çözüm olmasa da bazen data veya clock pinini tak çıkar yapıp mcu resetlediğimde yeniden veri gelmeye başlıyor.

Cemre.

#3
MPU6050 kullanmıştım ancak böyle bir problemle karşılaşmamıştım. Sensörün power enable bitleri vs vardı. Bunları önce sensörü disable edecek şekilde ilklendirip tekrar init döngüsüne girmek çözüm olabilir sanırım.
 İmkan varsa yazma yaptıktan sonra reg değeri istenen değere gelmiş mi diye okuyup olmadıysa tekrar yazmayı denemek de denenebilir...

OptimusPrime

Alıntı yapılan: huseyink - 09 Ekim 2019, 23:49:35Sebebi nedir bu durumun? Çünkü gücü kesmezsem eğer sensör katiyen cevap vermiyor. Kesin çözüm olmasa da bazen data veya clock pinini tak çıkar yapıp mcu resetlediğimde yeniden veri gelmeye başlıyor.

I2C slave in icerisinde donanimsal bir state machine var. Ve bu arkadasin master ile senkron calismasi gerekiyor. Haberlesmenin herhangi bir yerinde ozelliklede slave den master a data aktarilirken master in clk u kesmesi durumunda slave in state machine i ilk durumuna donemiyor ve ara statelerden birinde sikisip kaliyor. Derdi bu. O yuzden master tarafinda fake clk uretip slave in masterdan ack alamamasini sagliyorsun. Buda slave in state machine ini ilk duruma donduruyor.
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

e-zeki

Alıntı yapılan: OptimusPrime - 10 Ekim 2019, 08:07:05O yuzden master tarafinda fake clk uretip slave in masterdan ack alamamasini sagliyorsun. Buda slave in state machine ini ilk duruma donduruyor.

hocam fake clk'la çözümleme kısmını biraz açabilir misin? tam olarak ne demek istediğini anlamadım. Bu sorunu ben de yaşamıştım zamanında da, belki tutarlı bir çözüm getirebilirim sayende.

mufitsozen

#6
Alıntı yapılan: e-zeki - 10 Ekim 2019, 10:39:18hocam fake clk'la çözümleme kısmını biraz açabilir misin? tam olarak ne demek istediğini anlamadım. Bu sorunu ben de yaşamıştım zamanında da, belki tutarlı bir çözüm getirebilirim sayende.

NXP AN10216-01






Internetde google'layinca birde soyle bir aciklama buldum:

"You can reset the STM32's I2C module by setting and then clearing the respective I2CxRST bit in RCC_APByRSTR.
Maybe even easier, you can use the SWRST bit in I2C_CR1."

Birde soyle bir cozum onermis birisi:

Reliable Startup for I2C Battery Backed RTC
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

esdevhk

Alıntı yapılan: Cemre. - 10 Ekim 2019, 05:14:27MPU6050 kullanmıştım ancak böyle bir problemle karşılaşmamıştım. Sensörün power enable bitleri vs vardı. Bunları önce sensörü disable edecek şekilde ilklendirip tekrar init döngüsüne girmek çözüm olabilir sanırım.
 İmkan varsa yazma yaptıktan sonra reg değeri istenen değere gelmiş mi diye okuyup olmadıysa tekrar yazmayı denemek de denenebilir...

Cemre hocam sorun da şu ki; haberleşme hattı kesildikten sonra katiyen haberleşme kendine gelmiyor. Haberleşme durunca Data ve Clock bacaklarının gerilimini ölçtüğümde SDA bacagının 0V, SCK bacağının ~3.3V oldugunu gördüm. Hat kilitleniyor yani.

Bazen data veya clock hattını tak çıkar yapıp mcu resetlediğimde düzeldiği oluyordu.

OptimusPrime

@huseyink

SDA in low da kalmasi zaten kilitlendigine delalet eder  :)

@e-zeki
@mufitsozen hocam vermis.  ;)
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

esdevhk

Alıntı yapılan: OptimusPrime - 10 Ekim 2019, 16:34:09@huseyink

SDA in low da kalmasi zaten kilitlendigine delalet eder  :)

@e-zeki
@mufitsozen hocam vermis.  ;)

Evet hocam söylemek istedim. Teşekkürler yardımlarınız için. Artık bu sensörü kullanmaya devam edeceksek mecbur sensöre de reset attırıcaz. Sensör board'da reset pini bulunmaması çok kötü.

OptimusPrime

 ;)

Hangisinin kilitlendigindende emin olmak lazim bu arada; slave de gitmis olabilir, slave yuzunden master da gitmis olabilir veya ikisi ayni anda siyirmis da olabilir.  :D

Bunu anlamanin en temiz yolu; SDA yi kopartip kimin assagi cektigini tespit etmektir.  ;)
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

ecunnu

Merhaba arkadaşlar,

İşlemci reset attığında, aşağıdaki gibi bir fonksiyon çağrırsanız sonunuz belki düzelebilir. Fonksiyonu çağırmadan önce I2C pinlerini output open drain olarak ayarlamayı unutmayın. Fonksiyonu çağırdıktan sora I2c konfigürasyon ayarlarını yapıp kullanmaya devam edebilirsiniz. Eğer deneme yapan arkadaşlar olursa sonuçlarını yazmayı ihmal etmesinler.

void I2C_Recovery(void)
{
	uint8_t i;
	
	GPIO_ResetBits( I2C1_SCL_PORT, I2C1_SCL_PIN );nop();nop();
	GPIO_SetBits( I2C1_SDA_PORT, I2C1_SDA_PIN );nop();nop();
	for ( i = 0; i < 9; i++)
	{			
		GPIO_SetBits( I2C1_SCL_PORT, I2C1_SCL_PIN );nop();nop();
		GPIO_ResetBits( I2C1_SCL_PORT, I2C1_SCL_PIN );nop();nop();
	}
	
  GPIO_ResetBits( I2C1_SDA_PORT, I2C1_SDA_PIN );nop();nop();	   			//STOP flag
  GPIO_SetBits( I2C1_SCL_PORT, I2C1_SCL_PIN );nop();nop();
  GPIO_SetBits( I2C1_SDA_PORT, I2C1_SDA_PIN );nop();nop();             //SCL:HIGH  SDA:LOW_to_HIGH
  GPIO_ResetBits( I2C1_SCL_PORT, I2C1_SCL_PIN );nop();nop();
  GPIO_SetBits( I2C1_SCL_PORT, I2C1_SCL_PIN );nop();nop();	
}