ATtiny84 Nano Akım Ölçer

ATtiny84 Nano Akım Ölçer, nano seviyesinde akımları ölçmek için hazırlanmış bir devredir. ATtiny serisindeki bazı mikroişlemcilerin güç tüketimini ölçmek için kullanmıştık. 10µA ve 30nA arasımdanki akım değerlerini makul bir doğruluk seviyesinde ölçümler.

Çok küçük akımları doğru bir şekilde ölçmek, normal dijital multimetrelerle herkesin bildiği gibi zordur; ya hiç düşük bir akım aralığı sağlamazlar ya da sağlarlarsa, “yük gerilimi” olarak adlandırılan ve ekranı hatalı hale getirebilecek bir gerilim düşüşü yaratırlar. Bunu aşmanın bir yolu, düşük akımlar için tasarlanmış ölçüm aletlerini kullanmaktır.

Yüksek doğruluğu önemsemediğimiz için, ölçümü kondansatörün boşalması için geçen süreyi referans alarak hesaplayacağız. Dirençli bir yükte deşarj olan kondansatördün deşarj süresi tıpkı radyoaktif bozunma gibi üsteldir. Ardışık sabit zaman aralıkları içinde voltaj yarıya iner, bu nedenle voltaj 5V’da başlarsa, belirli bir t süresinden sonra bu değerin yarısına, 2.5V’a düşer. Bir süre sonra t 1.25V’a düşer ve bu böyle devam eder, bu t’ye yarılan ömrü denir.

t yarılanma ömrünü hesaplamak için: RC zaman sabitinin log2 ‘sini yani log2RC almak gerekiyor ya da 0.693 x RC yapmak gerekiyor. Dolayısıyla, sabit bir kondansatör C için, voltajın başlangıç ​​değerinin %50’sine düşmesi için geçen süreyi ölçerek, yükün etkin direncini ve dolayısıyla akım tüketimini R’yi hesaplayabiliriz.

ADC girişli bir mikro işlemci kullanarak bunu yapmak kolaydır ve kondansatör dışında birkaç başka bileşene ihtiyaç vardır; dezavantajı, kapasitör boşalırken nanoamperlerdeki akım ölçümlerinin birkaç saniye sürebilmesidir.

Devre Şeması

ATtiny84 Nano Akım Ölçer

Port A: PA0 – PA6 pinleri segmentleri sürmek için kullanılır ve Port B üzerindeki PB0 – PB2 rakamları sürmek için kullanılır. Kullanılabilir daha fazla pin olmadığı için PB2 ondalık nokta için bir sürücü olarak ikiye katlanır, bu da üçüncü basamakta ondalık basamağa ihtiyaç duyulmadığından çalışır. Kalan pin PA7, kapasitör üzerindeki voltajı ölçmek için analog giriş olarak kullanılır.

Kondansatör için ±%5 toleranslı bir DC film kondansatör kullandık. Herhangi bir kaliteli kondansatör muhtemelen uygun olacaktır, ancak geniş bir toleransa sahip oldukları için elektrolitik kondansatörleri kullanmamaya çalışın.

Bir buton reset pinine bağlanır, okumayı başlatmak için sıfırlama sinyali gönderilir.

Devreyi doğrudam bir 5V güç kaynağından besledik. Aküden ya da pilden çalıştırmak istiyorsanız, analog girişin doğruluğu besleme voltajına bağlı olduğundan, bir regülatör eklemelisiniz.

Kullanım Detayları

Test etmek istediğiniz devreyi Test ve Gnd terminalleri arasına bağlayın ve sıfırlama butonuna basın. Program önce 1µF kondansatörü şarj etmek için Test terminaline 5V uygular. Ardından, kısa bir gecikmeden sonra gücü keser ve test devresini kondansatörden güç çekmek üzere bırakır.

Kondansatör hedef voltaja deşarj olduğunda, program deşarj akımını hesaplar ve bunu nA veya µA olarak görüntüler; µA, bir “u” son eki ile gösterilir. Örneğin, bazı olası sonuçlar aşağıdaki gibidir:

7 Segment LEDAçıklama
LoAkım < 30nA
45Akım = 45nA
750Akım = 750nA
2.5uAkım = 2.5µA
10uAkım = 10µA
HiAkım > 10µA

Nano akım ölçerin 30nA kadar düşük akımları ölçmesinin 100 saniyeye kadar sürebileceğini unutmayın.

Uyku durumundaki bir devrenin akım tüketimini test ediyorsanız, devreye Nano Akım Ölçerin Test terminalinden güç verin ve devre uyku moduna geçtiğinde sıfırla butonuna basın.

Program Detayları

Önceki projelerimizin birçoğunda olduğu gibi, görüntü, Buffer[] dizisinin içeriği kullanılarak kesme(interrupt) altında oluşturulur. Örneğin, “123” sayısını 7 segmentte göstermek için bu kodu kullanabilirisiz.

Buffer[0]=1; Buffer[1]=2; Buffer[2]=3;

Program, ekranı çoklamak için kullanılan 200 Hz’de bir kesme oluşturmak için Timer/Counter1’i kullanır.

void SetupDisplay () {
  TCCR1A = 0<<WGM10;
  TCCR1B = 1<<WGM12 | 2<<CS10;  // 8'e bölme
  OCR1A = 4999;                 //  200Hz kesmesi
  TIMSK1 = 1<<OCIE1A;           // kesmeyi aktifleştirmek
}

Kesme işlem rutini basitçe DisplayNextDigit() öğesini çağırır :

ISR(TIM1_COMPA_vect) {
  DisplayNextDigit();
}

Bu kod bloğu ise sonraki basamağı seçer, basamaktaki uygun segment modelini ayarlar ve ardından basamağın ortak anodunu aktifleştirir:

void DisplayNextDigit () {
  DDRB = 0;                                    // hepsi düşük
  digit = (digit+1) % ndigits;
  char segs = charArray[Buffer[digit]];
  DDRA = DDRA & 0x80;                          // her pini input yapmak
  // 7 segment ayarları
  if (dp == digit && dp != 2) DDRB = 1<<DDB2;
  PORTA = (PORTA & 0x80) | (~segs & 0x7F);     // 1 = düşük
  DDRA = (DDRA & 0x80) | (segs & 0x7F);        // 1 = çıkış
  DDRB = DDRB | 1<<digit;                      
  PORTB = 1<<digit;                           
}

PORTA’nın üst biti, Test sinyaline müdahaleyi önlemek için maskelenmiştir.

Kondansatör Deşarjını Zamanlama

Bir okuma başlatmak için Sıfırla butonuna bastığımızda ana program çalışır. Kondansatörü şarj etmek için önce PA7 çıkışını yüksek alır. Daha sonra bunu bir giriş olarak yeniden tanımlar ve girişteki azalan voltajı izlemek için analogRead()’ i çağırır.

Voltaj Target tarafından tanımlanan değere düştüğünde, program aşağıdaki denklemi kullanarak deşarj hızına karşılık gelen RC zaman sabitine dayanarak yükün direncini hesaplar:

yarı ömür = log(2) RC

Değişen voltajın izlenen devre üzerindeki etkisini en aza indirmek için hedefi yarı ömrün yarısına, yani voltajın başlangıç ​​değerinin 1/√2’sine veya yaklaşık 3.5V’a düştüğü zamana ayarlamayı seçtkm. Programda 1/√2’ye iyi bir yaklaşım olan 29/41 kullandık. Gerçek yarı ömrü elde etmek için bu zamanı ikiye katlamamız gerekiyor.

Program daha sonra bunu 5V’luk deşarj akımına dönüştürür, bu şu şekilde verilir:

deşarj akımı = (5 x log(2) x 10 -6 ) / t

burada deşarj akımı amper cinsindendir, 5 volt cinsinden besleme voltajıdır, 10 -6 deşarj kondansatörünün kapasitansıdır, 1µF ve t saniye cinsinden yarı ömürdür.

  nA = 1732868 / Time;

burada nA , nA cinsinden deşarj akımıdır ve  Zaman , milisaniye cinsindendir.

Programı Derlemek

Programı Spence Konde’nin geliştirdiği ATTiny Core kullanarak derledik. Board menüsünde ATTinyCore başlığı altında bulunan ATtiny24/44/84 seçeneğini seçiniz. Ardından, sonraki seçeneklerin aşağıdaki gibi ayarlanıp ayarlanmadığını kontrol edin (diğer seçenekleri yok sayın):

Çip: “ATtiny84”
Saat: “8 MHz (dahili)”
B.O.D: “BOD Devre Dışı”

Pin Eşleme: “Saat yönünde (damellis çekirdeği gibi)”

ATtiny84 varsayılan olarak 1MHz’de çalışır. 8MHz çalışması için sigortaları ayarlamak gerekir bunu yapmak için önyükleyiciyi yüklemeyi seçin. Ardından her hangi bir ISP programlayıcı ile programı ATtiny84’e yükleyin.

ATtiny84 Nano Akım Ölçer
ATtiny84 Nano Akım Ölçer

Program Kodu

const int charArrayLen = 17;
char charArray[] = {
//  ABCDEFG  Segments
  0b1111110, // 0
  0b0110000, // 1
  0b1101101, // 2
  0b1111001, // 3
  0b0110011, // 4
  0b1011011, // 5
  0b1011111, // 6
  0b1110000, // 7
  0b1111111, // 8
  0b1111011, // 9
  0b0000000, // 10  Space
  0b0000001, // 11  '-'
  0b0001110, // 12  'L'
  0b0011101, // 13  'o'
  0b0110111, // 14  'H'
  0b0000100, // 15  'i'
  0b0011100  // 16  'u'
};

const int Space = 10;
const int Dash = 11;
const int Lo = 12;
const int Hi = 14;
const int uA = 16;
const int ndigits = 3;
volatile int Buffer[] = {Dash, Dash, Dash};
char dp = 2;  // Decimal point position 2 (off) or 0 to 1
int digit = 0;

// Display multiplexer **********************************************

void DisplayNextDigit () {
  DDRB = 0;                                    // All low
  digit = (digit+1) % ndigits;
  char segs = charArray[Buffer[digit]];
  DDRA = DDRA & 0x80;                          // All inputs
  // Set display segments
  if (dp == digit && dp != 2) DDRB = 1<<DDB2;
  PORTA = (PORTA & 0x80) | (~segs & 0x7F);     // 1 = low
  DDRA = (DDRA & 0x80) | (segs & 0x7F);        // 1 = output
  DDRB = DDRB | 1<<digit;                      // Current digit output
  PORTB = 1<<digit;                            // Current digit high
}

// Display a three digit decimal number
void Display (int i) {
  for (int d=2; d>=0 ; d--) {
    Buffer[d]=i % 10;
    i = i / 10;
  }
}

// Set up Timer/Counter1 to multiplex the display
void SetupDisplay () {
  TCCR1A = 0<<WGM10;
  TCCR1B = 1<<WGM12 | 2<<CS10;  // Divide by 8
  OCR1A = 4999;                 // Compare match at 200Hz
  TIMSK1 = 1<<OCIE1A;           // Enable compare match interrupt
}

// Timer interrupt - multiplexes display
ISR(TIM1_COMPA_vect) {
  DisplayNextDigit();
}

// Setup **********************************************
  
void setup() {
  SetupDisplay();
}

void loop() {
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  delay(500);
  pinMode(7, INPUT);
  unsigned long Start = millis(), Time, nA;
  unsigned int Initial = analogRead(7);
  unsigned int Target = (Initial * 29) / 41;
  do {
    Time = millis() - Start;
  } while (analogRead(7) > Target && Time < 100000);
  nA = 1732868 / Time;
  dp = 2;
  if (Time >= 100000) { Buffer[0] = Lo; Buffer[1] = Lo+1; Buffer[2] = Space; }
  else if (nA < 1000) { dp = 2; Display(nA); }
  else if (nA < 10000) { dp = 0; Display(nA/10); Buffer[2] = uA; }
  else if (nA < 100000) { dp = 2; Display(nA/100); Buffer[2] = uA; }
  else { Buffer[0] = Hi; Buffer[1] = Hi+1; Buffer[2] = Space; }
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  for (;;);
}