MPU6050 ile uyku düşük güç

Başlatan sarikayamusa, 10 Ocak 2019, 23:53:59

sarikayamusa

Bir proje tasarladım, özetle uzatmadan dağtmadan anlatayım nasıl bir çözüm bulabilirim? Bir fikir arıyorum. En uygun yöntem ne olabilirdi? Sonra yazdığım kodu da ekleyeceğim.

Sistem:
   Proje çok basit. cihaz yukarı çevrildiyse led flash yapacak. Aşağı çevrildiyse uykuya dalacak ve uyku modunda tüm devrem komple en fazla max 40uA çekmelidir. İki adet kalem pille çalışıyor. Mantık basit ama tıkandım. Nasıl bir sistem kursam?

Kurduğum Devre şeması:


  Arduino power down modunda ölçtüm 3uA çekiyro gayet iyi. MPU6050 ise aktif modda 5mA civarı bir güç  tüketiyor işte bu çok.

Bunun için yaptıklarım:
- Düşük akım çeksin diye MPU6050'nin beslemesini arduinoya bağladım, gerektiğinde LOW yapıp MPU6050'nin beslemesini tamamen kapatıyorum.
- Arduinoyu uyandırmak için bir sinyale ihtiyacım vardı onun içinde arduino D2 pinine tilt switch koydum
   Cihaz yukarı çevrildiğinde kod:
   1.Tilt switch Ext int ile arduinoyu uyandırıyor, ( Tilt sw içinde bilya var, buton gibi düşünün on off yani)
   2.Arduino MPU6050'nin beslemesini veriyor ve MPU6050 açı ölçmeye başlıyor,
   3.Cihaz yukarıda ise led flash yapıyor,
   4.Cihaz aşağı çevrildiyse arduino MPU6050'nin beslemesini kapatıyor,Power down modunda uykuya dalıyor, ta ki tilt switchten gelecek siyale kadar uyuyor.

Sorularım:

 1)  Arduinoyu başka nasıl uyandırabilirdim? uyandırmak için tilt switch kullanmaktan başka ne yapabilirdim?  Burada kritik nokta düşük güç tüketimi.
 2.) MPU6050'yi sürekli okuma modunda çalışır bıraksaydım yüksek güç tüketimi oluyor. Bunun yerine mpu6050'nin beslemesini arduino pininden kapatıp açıyorum bu sefer de kod kilitleniyor (kodda kilitlendiği yeri kodda yazdım). MPU6050'nin beslemesini arduino pininden vermekle yanlış mı yapıyorum?  Oysa MPU'nun beslemesini kendim manuel açıp kapatırsam kilitlenmiyor.

Kod:
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "Wire.h"
#include "I2Cdev.h"     // kütüphaneler eklendi
#include "MPU6050.h"
 
 
int ledPin1 = 10;
int wakePin = 2;                     
int mpu_beslemesi = A3;   //  sensör 3V beslemesini arduino pinden alıyor.


MPU6050 mpu;

int acix,aciy,aciz;    
int16_t ax, ay, az;             
int16_t gx, gy, gz;

 
void setup()
{
  
  pinMode(mpu_beslemesi, OUTPUT);       // sensöre besleme veren pini çıkış tanımla.
  digitalWrite(mpu_beslemesi, HIGH);    // ilk basta sensörün beslemesini aç ki cihazın konumunu ölçsün.
  
  pinMode(ledPin1, OUTPUT);       // flash ledini çıkış olarak tanımla  

  
      Wire.begin();         // SPI ayarlarını yap                    
      mpu.initialize();     // MPU'yu hazırla


    mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);   // ilk konumu çölç     
    aciz = map(az, 0, 17000, 0, 360);               // z kkordinatı 0-360 ölçekle    


   pinMode(wakePin, INPUT);   // uyanma pini yani D2'yi giriş tanımla. 

   
   attachInterrupt(0, uyku_fonku, CHANGE); // use interrupt 0 (pin 2) and run function. uyku_fonku when pin 2 gets LOW

   
    if (0>aciz  && aciz>=-360)       //   ilk başta cihaz aşağıda ise uyku                                                         
    {
      uyu();
    }

    if (0<aciz && aciz<=360)  ;       // enerjilendiğinde ilk başta cihaz yukarıda ise birşey yapma
}
 
 
//-----------------------------------------------------------------------------------------------------------------------------------

 
void uyu()         
{   
    digitalWrite (mpu_beslemesi, LOW);   // Mpu sensörün beslemesini kapat. ( bu komutu kaldırırsam kilitlenme olmuyor çünü voltajı sürekli var oluyor)

    
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // power down uyku modu ayarlarını yap
 
    sleep_enable();                        // power down modunda uyku ayarı.
                                 
  
    attachInterrupt(0,uyku_fonku, CHANGE);   // ext int ayarlarını yap. D2 pinini kullan
                                             

                                             

//-------------------  MCU işte tam burada uyuyor    -------------------------------------------------------------------
    
      sleep_mode();                // power down modunda uykuya dal. Ext interrupt gelinceye kadar  burada uyur.
    
//-------------------  Uyanınca kod ilk buradan başlıyor    --------------------------------                                

   
    sleep_disable();             // power down uyku modunu iptal et.
                                 
    detachInterrupt(0);          // interruptı disable yap ki bir daha gereksiz interrupt oluşmasın.
                                

      
      digitalWrite (mpu_beslemesi,HIGH);      //  sensörün enerjisini ver  

      
      Wire.begin();                          // SPI ayarları yap
      

      
      mpu.initialize();                       // işte tam burada kilitleniyor. Sensörün voltajı sürekli varsa klitlenmiyor.
      
 
}

 
void loop()
{
    

    mpu.initialize();                                 // bunu koymazsam sçı 0 geliyor
    
    mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);      //  sensör açı verilerini al.
    aciz = map(az, 0, 17000, 0, 360);                  // z açısını 0-360 arasına ölçekle

 
  if (0>aciz  && aciz>=-360)             // eğer cihaz aşağı çevrildiyse
  {            
     
     digitalWrite(ledPin1, LOW);         // Ledi söndür.
     uyu();                              // uyu  fonkuna git.
    

  }

  

   if (0<aciz && aciz<=360)         // cihaz yukariya çevrildi ise ledi flash yap 
   {   
       digitalWrite(ledPin1, millis()>>9 &1);    // ledi flash yap
   }        
     


}

void uyku_fonku()                         // ext int oluşunca ilk önce buraya gelir.      
{
   

}
 


certy

Uykudan çıktıktan sonra mpu.initialize(); satırından hemen önce 5-10mS'lik bir delay koyun.
TA1USS

MrDarK

#2
Uykudan uyanmak için tilt bilye yerine periyodik ölçüm yapılabilir. Yani saniyede 1 uyan ölçüm yap uyu şeklinde. Tabi bunu arduino'da yapmak için donanım müsait mi bilemiyorum. STM'de bu iş için Low Power Timer mekanizması kullanıyoruz. Lptimer diye geçer.

Birde bu sensörlerin hem düşük güç tüketimli ( aktif ölçümlü 1uA) hemde interrupt üreten türevleri var. O ürünlerin bazıları ölçümlerinde belli bir değişim olduğunda ext int üretebiliyorlar. Bu durumda seviye değişimi varsa uyanır sensörün seviyelerini kontrol edip ilgili işi yapıp tekrar uyuyabilirsin.

Low power uygulamalarında sensörlerin ve çevre birimlerin beslemesini chip üzerinden kontrol etmek en doğru olaydır. O konuda bir tereddütün olmasın. certy'ninde dediği gibi sensörün beslemesi oturmadan işlem yapmak doğru değil. Datasheet'de ne kadar süre beklemen gerektiği yazar oradaki değere göre gecikme verebilirsin.

Birde mcu'nun pininden çıkabilecek max akımın yarısına yaklaşma derim :) Böyle durumlarda chipten gelecek komutla beslemeyi aktif edecek mosfet yapıları tercih edilebliir.
Picproje Eğitim Gönüllüleri ~ MrDarK

sarikayamusa

#3
Alıntı yapılan: MrDarK - 12 Ocak 2019, 09:24:58Uykudan uyanmak için tilt bilye yerine periyodik ölçüm yapılabilir. Yani saniyede 1 uyan ölçüm yap uyu şeklinde. Tabi bunu arduino'da yapmak için donanım müsait mi bilemiyorum. STM'de bu iş için Low Power Timer mekanizması kullanıyoruz. Lptimer diye geçer.

Birde bu sensörlerin hem düşük güç tüketimli ( aktif ölçümlü 1uA) hemde interrupt üreten türevleri var. O ürünlerin bazıları ölçümlerinde belli bir değişim olduğunda ext int üretebiliyorlar. Bu durumda seviye değişimi varsa uyanır sensörün seviyelerini kontrol edip ilgili işi yapıp tekrar uyuyabilirsin.

Low power uygulamalarında sensörlerin ve çevre birimlerin beslemesini chip üzerinden kontrol etmek en doğru olaydır. O konuda bir tereddütün olmasın. certy'ninde dediği gibi sensörün beslemesi oturmadan işlem yapmak doğru değil. Datasheet'de ne kadar süre beklemen gerektiği yazar oradaki değere göre gecikme verebilirsin.

Birde mcu'nun pininden çıkabilecek max akımın yarısına yaklaşma derim :) Böyle durumlarda chipten gelecek komutla beslemeyi aktif edecek mosfet yapıları tercih edilebliir.

Cevap yazanlara tesekkurler.
Mpu datasheette start up time 30ms yaziyor. Beslemeyi verdikten sonra 50ms hatta 100ms koydum yine kilitleniyor. Mpu6050 kutuphanesinde initialize() içinde takip ettim tamda uykudan uyandirma komutunda takildigini gördüm Malum Mpu sensörü ilk başta uygu modunda açılıyor.Fakat kod eğer tekrar bastan başlarsa çalışıyor. işin içinden çıkamayınca bir çözüm buldum ben de. İşlemci external interrupt ile (tilt switchten gelen Falling sinyali ile) uyandığında isr içine software reset satırı ekledim. Bu sayede işlemci her uyandığında kod baştan başlıyor,kilitlenmedi gayet de iyi çalışıyor. Belki optimum çözüm değil ama işimi görecek gibi görünüyor.

Kodun tam halini paylaşacağım. Proje insan hayatı ile ilgili bir alanda kullanilacak.
Ayrıca detaylı akım ölçümlerini yapıp buraya yazacağım.

sarikayamusa

Alıntı yapılan: MrDarK - 12 Ocak 2019, 09:24:58Uykudan uyanmak için tilt bilye yerine periyodik ölçüm yapılabilir. Yani saniyede 1 uyan ölçüm yap uyu şeklinde. Tabi bunu arduino'da yapmak için donanım müsait mi bilemiyorum. STM'de bu iş için Low Power Timer mekanizması kullanıyoruz. Lptimer diye geçer.
Bu benim de aklıma geldi ancak sistem sürekli hareket eden bir sistem değil ayda yılda belki cihaz yukarı çevrilecek. Sürekli uyanip gereksiz yere pil tüketecek diye vazgeçtim.

Alıntı yapılan: MrDarK - 12 Ocak 2019, 09:24:58Birde bu sensörlerin hem düşük güç tüketimli ( aktif ölçümlü 1uA) hemde interrupt üreten türevleri var. O ürünlerin bazıları ölçümlerinde belli bir değişim olduğunda ext int üretebiliyorlar. Bu durumda seviye değişimi varsa uyanır sensörün seviyelerini kontrol edip ilgili işi yapıp tekrar uyuyabilirsin.
Aslında tam aradığım sensör. Modeli ne acaba?

Alıntı yapılan: MrDarK - 12 Ocak 2019, 09:24:58Birde mcu'nun pininden çıkabilecek max akımın yarısına yaklaşma derim :) Böyle durumlarda chipten gelecek komutla beslemeyi aktif edecek mosfet yapıları tercih edilebliir.
Bu dikkatimi çekti. Neden yarısına yaklaşmıyım? Devremde baktiysan 3 led var 3V ve 20mA lik ledler bunlar. Beslemem de 3Volt. ledden geçebilecek max akım için led dirençlerimin değerlerini kaç seçebilirdim? Benimkiler uygunmu?

RaMu

20mA max akım olsa gerek,
tabiki çok çeşitli ledler var,
durum göstergesi amacıyla kullanılacak bir led ise
3~5 mA akım için direnci ayarlayabilirsin,
cree marka idi sanırım kaliteli bir led kullanırsan 1mA de gayet parlak bir ışıma sağlayabilirsin.
Tabi ledin rengine göre çalışma gerilimini hesaba katarsın.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

hwdesigner

https://www.digikey.com/product-detail/en/sunled/XZMOK54W-8/1497-1433-1-ND/8259110

Millicandela Rating burada önemli olan kısım bu.

1mA ile göz alacak bir ışık yayabilir. 5V da 15K direnç ile kullanıyorum. Harcadığı gücü bir hesapla istersen