Girino - Hızlı Arduino Osiloskop

Ben bir fizikçiyim ve bu alanda çalışmanın en güzel yanı kendi enstrümanlarımı yapabilmem. Bu şekilde düşünerek, bir homebrew Arduino Osiloskop yapmaya karar verdim. Bu talimat, mikrodenetleyiciler ve veri toplama hakkında biraz bilgi vermek amacıyla yazılmıştır. Bu aşırı bir proje çünkü Arduino'dan olabildiğince hızlı bir şekilde sıkıştırmak istedim, bu kadar hızlı başka bir Arduino Osiloskop görmedim.

Bir süre önce bir Arduino projesi üzerinde çalışıyordum ve çıkış sinyalinin spesifikasyonlara uygun olup olmadığını görmem gerekiyordu. Böylece internette biraz zaman geçirdim, zaten uygulanmış Arduino Osiloskoplarını aradım, ama bulduğum şeyi sevmedim. Bulduğum projeler çoğunlukla İşleme'de yazılan bilgisayar için bir Grafik Kullanıcı Arayüzü ve çok basit bir arduino taslağından oluşuyordu. Eskizler şöyleydi: void setup () {

Serial.begin (9600);

}

void loop () {

int val = analogOkuma (ANALOG_IN);

Serial.println (val);

} Bu yaklaşım yanlış değildir ve kimseye hakaret etmek istemiyorum, ama bu benim için çok yavaş. Seri bağlantı noktası yavaştır ve bir analogRead () öğesinin her sonucunu içinden göndermek bir darboğazdır.

Bir süredir Dalgaform Sayısallaştırıcılar üzerinde çalışıyorum ve nasıl çalıştıklarını gayet iyi biliyorum, bu yüzden onlardan ilham aldım. Bunlar oluşturmak istediğim osiloskopun başlangıç ​​noktalarıydı:

  • gelen sinyalin korunması için arduinodan ayrılması gerekir;
  • sinyalin ofseti ile negatif sinyalleri görmek mümkündür;
  • veriler arabelleğe alınmalıdır;
  • sinyalleri yakalamak için bir donanım tetikleyicisi gereklidir;
  • dairesel bir tampon, tetiklemeden önce sinyal şeklini verebilir (bu noktada takip edilecek daha fazla bilgi);
  • standart olanların alt kol fonksiyonlarını kullanarak programı daha hızlı çalıştırmasını sağlar.

Arduino için taslak, yaptığım devrenin şemasıyla birlikte bu adıma eklenmiştir.

Ortaya koyduğum isim Girino, İtalyanca anlamsız bir kelime oyunu. Giro rotasyon anlamına gelir ve -ino son ekini ekleyerek küçük bir rotasyon alırsınız, ancak Girino da iribaş anlamına gelir. Bu şekilde bir isim ve maskot aldım.

1. Adım: Feragat

BU KULLANILABİLİR YAZAR, GEÇERLİLİK GARANTİSİ VERMEZ VE NE GARANTİ VERİR .

Ne yaptığınızı bilmiyorsanız ve yazar burada bulunan bilgilerin geçerliliğini garanti edemezse elektronik tehlikeli olabilir. Bu profesyonel bir tavsiye değildir ve bu talimatta yazılan herhangi bir şey yanlış, yanıltıcı, tehlikeli veya yanlış olabilir. Bağımsız doğrulama olmadan burada bulunan hiçbir bilgiye güvenmeyin.

Herhangi bir bilgiyi doğrulamak ve kendinizi ya da herhangi birini herhangi bir zarara maruz bırakmadığınızı ya da herhangi bir şeyi herhangi bir hasara maruz bırakmadığınızı iki kez kontrol etmek size kalmıştır; Sorumluluk almıyorum. Bu projeyi yeniden üretmek istiyorsanız, uygun güvenlik önlemlerini kendiniz takip etmelisiniz.

Bu kılavuzu kullanmak kendi sorumluluğunuzdadır!

2. Adım: Gerekenler

Bu proje için gerçekten ihtiyacımız olan şey bir Arduino kartı ve ATMega328P'nin veri sayfasıdır.
Veri sayfası, mikrodenetleyicinin nasıl çalıştığını söyleyen şeydir ve daha düşük bir kontrol kolu istiyorsak, bunu korumak çok önemlidir.

Veri sayfasını burada bulabilirsiniz: //www.atmel.com/Images/doc8271.pdf

Arduino'ya eklediğim donanım kısmen gerekli, amacı sadece ADC için sinyal oluşturmak ve tetik için bir voltaj seviyesi sağlamak. İsterseniz, sinyali doğrudan Arduino'ya gönderebilir ve bir voltaj bölücü veya hatta Arduino tarafından verilen 3, 3 V tarafından tanımlanan bir voltaj referansı kullanabilirsiniz.

3. Adım: Çıktıda Hata Ayıklama

Programlarıma genellikle çok sayıda hata ayıklama çıktısı koyarım çünkü gerçekleşen her şeyi takip etmek istiyorum; Arduino ile ilgili sorun, yazmak için bir stdout'umuz olmamasıdır. Seri bağlantı noktasını stdout olarak kullanmaya karar verdim.

Bununla birlikte, bu yaklaşımın her zaman işe yaramadığını unutmayın! Seri portuna yazmak, yürütme için biraz zaman gerektirir ve bir süre mantıklı rutinler sırasında bazı şeyleri önemli ölçüde değiştirebilir.

Ben genellikle bir önişlemci makrosu içinde hata ayıklama çıkışları tanımlamak, bu nedenle hata ayıklama devre dışı bırakıldığında, sadece programdan kaybolur ve yürütmeyi yavaşlatmaz:
  • dprint (x); - Seri bağlantı noktasına şöyle yazar: # x: 123
  • dshow ("Bazı dizeler"); - Dizeyi yazar

Bu tanım:

#if DEBUG == 1
#define dprint (expression) Serial.print ("#"); Serial.print (#expression); Serial.print (":"); Serial.println (ifade)
#define dshow (ifade) Serial.println (ifade)
#Başka
#define dprint (ifade)
#define dshow (ifade)
#endif

Adım 4: Kayıt Bitlerini Ayarlama

Hızlı olmak amacıyla mikrodenetleyici özelliklerinin Arduino IDE tarafından sağlanan standartlardan daha düşük kol fonksiyonları ile manipüle edilmesi gerekir. Dahili işlevler, her birinin belirli bir şeyi yönettiği sekiz bitlik koleksiyonlar olan bazı kayıtlar aracılığıyla yönetilir. ATMega328P 8 bit mimariye sahip olduğu için her kayıtta sekiz bit bulunur.

Kayıtların, ADC Ayar Kaydı A için ADCSRA gibi, anlamlarına göre veri sayfasında belirtilen bazı adları vardır. Ayrıca, kayıtların her anlamlı bitinin ADCSRA kaydındaki ADC Etkin Bit için ADEN gibi bir adı vardır.

Bitlerini ayarlamak için ikili cebir için normal C sözdizimini kullanabiliriz, ancak internette çok güzel ve temiz birkaç makro buldum:

// Kayıt bitlerini ayarlamak ve silmek için tanımlar
#ifndef cbi
#define cbi (sfr, bit) (_SFR_BYTE (sfr) & = ~ _BV (bit))
#endif
#ifndef sbi
#define sbi (sfr, bit) (_SFR_BYTE (sfr) | = _BV (bit))
#endif

Bunları kullanmak çok basit, eğer ADC'nin Etkin Bitini 1 olarak ayarlamak istiyorsak şunu yazabiliriz:

SBI (ADCSRA, ADEN);

Eğer 0 olarak ayarlamak istiyorsak ( id est clear) bunu yazabiliriz:

CBI (ADCSRA, ADEN);

5. Adım: Kesintiler Nelerdir

Sonraki adımlarda göreceğimiz gibi, bu projede kesintilerin kullanılması gerekmektedir. Kesmeler, mikro denetleyiciye ana döngünün yürütülmesini durdurmasını ve bazı özel işlevlere geçirmesini söyleyen sinyallerdir. Görüntüler program akışı hakkında bir fikir verir.

Yürütülen işlevlere Kesme Hizmeti Yordamları (ISR) denir ve az çok basit işlevlerdir, ancak bunlar bağımsız değişkenler gerektirmez.

Bir örnek görelim, bazı darbeleri saymak gibi bir şey. ATMega328P, bir sinyal bir referans voltajı aştığında etkinleştirilen bir kesintiye sahip bir Analog Karşılaştırıcıya sahiptir. Her şeyden önce, uygulanacak işlevi tanımlamanız gerekir:

ISR (ANALOG_COMP_vect)
{
sayaç ++;
}

Bu gerçekten basit, ISR () komutu derleyiciye aşağıdaki işlevin bir Kesinti Hizmeti Rutini olduğunu bildiren bir makrodur. ANALOG_COMP_vect'e Kesme Vektör denir ve derleyiciye hangi kesintinin o rutinle ilişkili olduğunu söyler. Bu durumda Analog Karşılaştırıcı Kesmesi'dir. Böylece, karşılaştırıcı referanstan daha büyük bir sinyal gördüğünde, mikro denetleyiciye bu kodu çalıştırmasını söyler, bu durumda id değişkenini bu değişkeni arttırır.

Bir sonraki adım, ilişkili kesmeyi etkinleştirmektir. Etkinleştirmek için ACSR (Analog Karşılaştırıcı Ayar Kaydı) kaydının ACIE (Analog Karşılaştırıcı Kesme Etkin) bitini ayarlamalıyız:

SBI (ACSR, acie);

Aşağıdaki sitede tüm Kesinti Vektörlerinin listesini görebiliriz:
//www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Adım 6: Dairesel Bir Tampon ile Sürekli Edinin

Dairesel Tampon kullanma kavramı oldukça basittir:

Bir sinyal bulunana kadar sürekli edin, ardından sayısallaştırılmış sinyali bilgisayara gönderin.

Bu yaklaşım, tetikleyici olaydan önce de gelen sinyal şeklinin alınmasına izin verir.


Kendimi açıklığa kavuşturmak için bazı diyagramlar hazırladım. Aşağıdaki noktalar görüntülere atıfta bulunmaktadır.
  • İlk görüntüde sürekli elde etme ile ne demek istediğimi görebiliyoruz. Verileri depolayacak bir tampon tanımladık, benim durumumda 1280 yuvalı bir dizi, daha sonra arabelleği verilerle dolduran ADC çıkış yazmacı (ADCH) reklamını sürekli olarak okumaya başlıyoruz. Tamponun sonuna geldiğimizde, temizlemeden yeniden başlıyoruz. Dairesel olarak düzenlenmiş diziyi immagine edersek ne demek istediğimi görmek kolaydır.
  • Sinyal eşiği aştığında, Analog Karşılaştırıcı Kesmesi etkinleştirilir. Daha sonra sinyali almaya devam ettiğimiz ancak Analog Karşılaştırıcı Kesmesinden geçen ADC döngülerinin bir sayısını tuttuğumuz bir bekleme aşamasına başlarız.
  • N döngüsünü (N <1280 ile) beklediğimizde, durumu dondurur ve ADC döngülerini durdururuz. Böylece sinyal zamansal şeklinin sayısallaştırılmasıyla dolu bir tampon ile sonuçlanır. Bunun büyük kısmı, tetikleyici olaydan önce de şekle sahip olduğumuzdur, çünkü ondan önce zaten alıyorduk.
  • Şimdi tek bir ADC okumasını göndermek yerine tüm tamponu bir seri veri bloğunda seri porta gönderebiliriz. Bu, verileri göndermek için gereken yükü ve internette bulduğum eskizlerin darboğazını azalttı.

Adım 7: Osiloskop Tetikleme

Bir osiloskop, ekranda hepimizin aynı fikirde olduğunu gösteren bir sinyal gösterir, ancak bunu sürekli olarak gösterebilir ve ekranın etrafında zıpladığını göstermez? Sinyali her zaman ekranın aynı konumunda (veya en azından çoğu zaman) gösterebilen ve kararlı bir arsa yanılsaması yaratabilen dahili bir tetikleyiciye sahiptir.

Tetikleyici, sinyal geçtiğinde bir süpürmeyi etkinleştiren bir eşik ile ilişkilidir. Tarama, osiloskopun sinyali kaydettiği ve görüntülediği evredir. Bir süpürmeden sonra başka bir faz meydana gelir: osiloskopun herhangi bir gelen sinyali reddettiği tutma . Uzaklaşma süresi, osiloskopun herhangi bir sinyali kabul edemediği ölü zamanın bir bölümü ve kullanıcı tarafından seçilebilen bir kısımdan oluşabilir. Ölü zaman, ekranda çizim yapmak veya verileri bir yerde saklamak gibi çeşitli nedenlerden kaynaklanabilir.

Görüntüye baktığımızda ne olduğuna dair bir fikir ediniriz.
  1. Sinyal 1 eşiği aşar ve süpürmeyi etkinleştirir;
  2. sinyal 2, süpürme süresinin içindedir ve birincisi ile yakalanır;
  3. ayırmadan sonra, sinyal 3 süpürmeyi tekrar etkinleştirir;
  4. bunun yerine sinyal 4 reddetme bölgesi içine düştüğü için reddedilir.
Uzaklaştırma aşamasının varoluş nedeni, bazı istenmeyen sinyallerin tarama bölgesine girmesini önlemektir. Bu noktayı açıklamak biraz uzun ve bu talimatın amacından kaçınıyor.

Bu hikayenin ahlaki şeye ihtiyacımız var:
  1. gelen sinyali karşılaştırabileceğimiz bir eşik seviyesi;
  2. mikrodenetleyiciye bekleme aşamasını başlatmasını söyleyen bir sinyal (bkz. önceki adım).
1. nokta için birkaç olası çözümümüz var:
  • bir düzeltici kullanarak manuel olarak bir voltaj seviyesi ayarlayabiliriz;
  • Arduino'nun PWM'sini kullanarak seviyeyi yazılımla ayarlayabiliriz;
  • Arduino tarafından sağlanan 3.3 V kullanılarak;
  • dahili bangap referansını kullanarak sabit bir seviye kullanabiliriz.
2. nokta için doğru çözüme sahibiz: mikrodenetleyicinin dahili Analog Karşılaştırıcısının kesilmesini kullanabiliriz.

Adım 8: ADC Nasıl Çalışır?

Arduino mikrodenetleyici tek bir 10 bit ardışık yaklaşık ADC'ye sahiptir. ADC'den önce, ADC'ye farklı pimler ve kaynaklardan gelen sinyalleri göndermemizi sağlayan analog bir çoklayıcı var (ancak her seferinde yalnızca bir tane).

Ardışık Yaklaşım ADC, ADC'nin dönüşümü tamamlamak için 13 saat döngü (ve ilk dönüşüm için 25 saat döngü) aldığı anlamına gelir. ADC'ye adanmış Arduino'nun ana saatinden "hesaplanan" bir saat sinyali vardır; çünkü ADC biraz yavaştır ve mikrodenetleyicinin diğer parçalarının hızına ayak uyduramaz. Maksimum çözünürlük elde etmek için 50 kHz ile 200 kHz arasında bir giriş saat frekansı gerektirir. 10 bit'ten daha düşük bir çözünürlük gerekiyorsa, daha yüksek örnekleme hızı elde etmek için ADC'ye giriş saat frekansı 200 kHz'den yüksek olabilir.

Fakat ne kadar yüksek oranlar kullanabiliriz? Okumanızı önerdiğim Open Music Labs'de ADC hakkında birkaç iyi rehber var:
  • //www.openmusiclabs.com/learning/digital/atmega-adc/
  • //www.openmusiclabs.com/learning/digital/atmega-adc/in-depth/
Amacım hızlı bir osiloskop elde etmek olduğundan, hassasiyeti 8 bit ile sınırlamaya karar verdim. Bunun birkaç bonusu vardır:
  1. veri arabelleği daha fazla veri depolayabilir;
  2. veri başına 6 bit RAM harcamazsınız;
  3. ADC daha hızlı kazanabilir.
Ön ölçekleyici, ADCSRA kaydının ADPS0-1-2 bitlerini ayarlayarak frekansı bazı faktörlere göre bölmemize izin verir. Open Music Labs Makalesindeki hassasiyetin grafiğini gördüğümüzde, 8 bitlik hassasiyet için frekansın 1, 5 MHz'e kadar çıkabileceğini görebiliriz! Ancak, ön ölçekleyici faktörünü değiştirme yeteneği, edinim oranını değiştirmemize izin verdiğinden, osiloskopun zaman ölçeğini değiştirmek için de kullanabiliriz.

Çıkış kayıtları hakkında iyi bir özellik vardır: ADMUX kaydındaki ADLAR bitini ayarlayarak dönüşüm bitlerinin ayarlanmasına karar verebiliriz. Eğer 0 ise doğru ayarlanmış ve viceversa (resme bakınız). 8-bit hassasiyet istediğim için sadece 1'e ayarladım, böylece sadece ADCH kaydını okuyabilir ve ADCL'yi görmezden gelebilirim.

Her dönüşümde kanalı ileri ve geri değiştirmek zorunda kalmamak için sadece bir giriş kanalım olmasına karar verdim.

ADC ile ilgili son bir şey, her biri farklı bir tetikleme kaynağına sahip farklı çalışma modlarına sahiptir:
  • Serbest Çalışma modu
  • Analog Karşılaştırıcı
  • Harici Kesme İsteği 0
  • Timer / Counter0 Maç A'yı Karşılaştırın
  • Zamanlayıcı / Sayıcı0 Taşma
  • Timer / Counter1 Maç B'yi Karşılaştırın
  • Zamanlayıcı / Sayıcı1 Taşma
  • Zamanlayıcı / Sayaç1 Yakalama Etkinliği
ADC'nin sürekli olarak girdiyi dönüştürdüğü ve her dönüşümün sonunda bir Kesme (ilgili vektör: ADC_vect) attığı bir mod olan serbest çalışma modu ile ilgileniyordum.

Adım 9: Dijital Giriş Arabellekleri

Arduino'nun analog giriş pinleri dijital I / O pinleri olarak da kullanılabilir, bu nedenle dijital fonksiyonlar için bir giriş tamponuna sahiptirler. Bunları analog pin olarak kullanmak istiyorsak, bu özelliği devre dışı bırakmalısınız.

Dijital bir pime bir analog sinyal göndermek, özellikle sinyal iki durum arasındaki sınıra yakınsa, YÜKSEK ve DÜŞÜK durumlar arasında geçiş yapmaya neden olur; bu geçiş, ADC'nin kendisi gibi yakın devrelere biraz gürültü çıkarır (ve daha yüksek bir enerji tüketimine neden olur).

Dijital arabelleği devre dışı bırakmak için DIDR0 kaydının ADCnD bitlerini ayarlamalıyız:

SBI (DIDR0, ADC5D);
SBI (DIDR0, ADC4D);
SBI (DIDR0, ADC3D);
SBI (DIDR0, ADC2D);
SBI (DIDR0, ADC1D);
SBI (DIDR0, ADC0D);

Adım 10: ADC'yi Kurma

Çizimde, ADC işlevinin tüm parametrelerini ayarlayan bir başlatma işlevi yazdım. Temiz ve yorumlanmış kod yazma eğiliminde olduğu için, ben sadece burada fonksiyonu geçmiş olacak. Bir önceki adıma ve kayıtların anlamı için yorumlara atıfta bulunabiliriz. void initADC (geçersiz)
= (ADCPIN & 0x07);

// ------------------------------------------------ ---------------------
// ADCSRA ayarları
// ------------------------------------------------ ---------------------
// Bu biti birine yazmak ADC'yi etkinleştirir. Sıfıra yazarak,
// ADC kapalı. Bir dönüşüm gerçekleşirken ADC'yi kapatma
// progress, bu dönüşümü sonlandıracak.
CBI (ADCSRA, ADEN);
// Tek Dönüştürme modunda, her birini başlatmak için bu biti birine yazın
// dönüştürmek. Serbest Çalışma modunda, başlatmak için bu biti birine yazın
// ilk dönüşüm. ADSC yazıldıktan sonraki ilk dönüşüm
// ADC etkinleştirildikten sonra veya ADSC aynı anda yazıldıysa
// ADC etkinleştirildiği zaman, 25 ADC saat döngüsü yerine
// normal 13. Bu ilk dönüşüm,
// ADC. ADSC, bir dönüşüm devam ettiği sürece bir tane okuyacaktır.
// Dönüştürme tamamlandığında sıfıra döner. Yazma sıfır
// bu bitin bir etkisi yoktur.
CBI (ADCSRA, ADSC);
// Bu bit bir taneye yazıldığında, ADC'nin Otomatik Tetiklenmesi
// etkin. ADC, dönüşümün pozitif bir kenarında bir dönüşüm başlatır
// seçilen tetikleme sinyali. Tetikleyici kaynağı ayarlanarak seçilir
// ADC Tetikleyici Seçim bitleri, ADCSRB'deki ADTS.
SBI (ADCSRA, ATarih);
// Bu bit bir taneye yazıldığında ve SREG'deki I-bit ayarlandığında,
// ADC Dönüştürme Tamamlandı Kesmesi etkinleştirildi.
SBI (ADCSRA, ADIE);
// Bu bitler sistem saati arasındaki bölme faktörünü belirler
// frekansı ve ADC'ye giriş saati.
// ADPS2 ADPS1 ADPS0 Bölüm Faktörü
// 0 0 0 2
// 0 0 1 2
// 0 1 0 4
// 0 1 1 8
// 1 0 0 16
// 1 0 1 32
// 1 1 0 64
// 1 1 1 128
SBI (ADCSRA, ADPS2);
SBI (ADCSRA, ADPS1);
SBI (ADCSRA, ADPS0);

// ------------------------------------------------ ---------------------
// ADCSRB ayarları
// ------------------------------------------------ ---------------------
// Bu bit bir mantık yazıldığında ve ADC kapatıldığında
// (ADCSRA'daki ADEN sıfır), ADC çoklayıcı negatif
// Analog Karşılaştırıcıya giriş. Bu bit mantıksal sıfır yazıldığında,
// Analog Karşılaştırıcı'nın negatif girişine AIN1 uygulanır.
CBI (ADCSRB, ACME);
// ADCSRA'daki ADATE birine yazılırsa, bu bitlerin değeri
// hangi kaynağın bir ADC dönüşümünü tetikleyeceğini seçer. ADATE ise
// silindiğinde, ADTS2: 0 ayarlarının hiçbir etkisi olmayacaktır. Bir dönüşüm olacak
// seçilen Kesme Bayrağının yükselen kenarı tarafından tetiklenir. Not
// bir tetikleyiciden temizlenmiş bir tetikleyici kaynağından geçiş
// ayarlanan kaynak, tetikte pozitif bir kenar oluşturur
// sinyali. ADCSRA'da ADEN ayarlanırsa, bu bir dönüşüm başlatır.
// Serbest Çalışma moduna (ADTS [2: 0] = 0) geçmek,
// ADC Kesme Bayrağı ayarlanmış olsa bile tetikleme olayı.
// ADTS2 ADTS1 ADTS0 Tetikleyici kaynağı
// 0 0 0 Serbest Çalışma modu
// 0 0 1 Analog Karşılaştırıcı
// 0 1 0 Harici Kesme İsteği 0
// 0 1 1 Zamanlayıcı / Sayıcı0 Karşılaştırma A
// 1 0 0 Zamanlayıcı / Sayıcı0 Taşma
// 1 0 1 Zamanlayıcı / Sayaç1 Maç B'yi Karşılaştırın
// 1 1 0 Zamanlayıcı / Sayıcı1 Taşma
// 1 1 1 Zamanlayıcı / Sayaç1 Yakalama Etkinliği
CBI (ADCSRB, ADTS2);
CBI (ADCSRB, ADTS1);
CBI (ADCSRB, ADTS0);

// ------------------------------------------------ ---------------------
// DIDR0 ayarları
// ------------------------------------------------ ---------------------
// Bu bit mantık bir olarak yazıldığında,
// karşılık gelen ADC pini devre dışı. İlgili PIN Kaydı
// bu bit ayarlandığında bit her zaman sıfır olarak okunur. Bir analog olduğunda
// ADC5.0.0 pinine sinyal uygulanır ve bundan dijital giriş
// pin gerekli değil, bu bit azaltmak için mantık bir yazılmalıdır
// dijital giriş arabelleğinde güç tüketimi.
// ADC pinleri ADC7 ve ADC6'nın dijital giriş tamponları olmadığını unutmayın,
// ve bu nedenle Dijital Giriş Devre Dışı Bırakma bitleri gerektirmez.
SBI (DIDR0, ADC5D);
SBI (DIDR0, ADC4D);
SBI (DIDR0, ADC3D);
SBI (DIDR0, ADC2D);
SBI (DIDR0, ADC1D);
SBI (DIDR0, ADC0D);

Adım 11: Analog Karşılaştırıcı Nasıl Çalışır

Analog Karşılaştırıcı, mikro denetleyicinin dahili bir modülüdür ve pozitif pin (Dijital Pin 6) ve negatif pin (Dijital Pin 7) üzerindeki giriş değerlerini karşılaştırır. Pozitif pim üzerindeki voltaj negatif pim AIN1'deki voltajdan daha yüksek olduğunda, Analog Karşılaştırıcı ACSR kaydının ACO bitinde 1 verir.

İsteğe bağlı olarak, karşılaştırıcı Analog Karşılaştırıcıya özel bir kesmeyi tetikleyebilir. İlişkili vektör ANALOG_COMP_vect'tir.

Kesmeyi, yükselen bir kenarda, düşen kenarda veya devletin bir geçişinde başlatılacak şekilde de ayarlayabiliriz.

Analog Karşılaştırıcı, giriş sinyalini pim 6'ya bağlayan tetikleyici için ihtiyacımız olan şeydir, şimdi kalan şey pim 7'deki bir eşik seviyesidir.

Adım 12: Analog Karşılaştırıcının Ayarlanması

Çizimde, Analog Karşılaştırıcı işlevinin tüm parametrelerini ayarlayan başka bir başlatma işlevi yazdım. ADC dijital arabellekleri ile ilgili aynı sorun, rutinin altında görebildiğimiz gibi Analog Karşılaştırıcı için de geçerlidir.

void initAnalogComparator (geçersiz)
{
// ------------------------------------------------ ---------------------
// ACSR ayarları
// ------------------------------------------------ ---------------------
// Bu bit mantık bir olarak yazıldığında, Analog'a güç
// Karşılaştırıcı kapalı. Bu bit herhangi bir zamanda döndürmek için ayarlanabilir
// Analog Karşılaştırıcıdan. Bu, güç tüketimini azaltacaktır.
// Aktif ve Bekleme modu. ACD bitini değiştirirken, Analog
// Karşılaştırıcı Kesmesi, ACIE bitini temizleyerek devre dışı bırakılmalıdır.
// ACSR. Aksi takdirde, bit değiştirildiğinde bir kesinti meydana gelebilir.
CBI (ACSR ACD);
// Bu bit ayarlandığında, sabit bir bant aralığı referans voltajı
// Analog Karşılaştırıcıya pozitif giriş. Bu bit silindiğinde,
// Analog Karşılaştırıcı'nın pozitif girişine AIN0 uygulanır. Ne zaman
// bant aralığı referansı Analog Karşılaştırıcıya giriş olarak kullanılır,
// voltajın stabilize olması belirli bir zaman alacaktır. Eğer değilse
// stabilize edildiğinde, ilk dönüşüm yanlış bir değer verebilir.
CBI (ACSR, Prospektif);
// ACIE biti Durum'a bir ve I biti mantık yazıldığında
// Kayıt ayarlanır, Analog Karşılaştırıcı kesmesi etkinleştirilir.
// Mantık sıfır yazıldığında, kesme devre dışı bırakılır.
CBI (ACSR, acie);
// Birinci mantık yazıldığında, bu bit giriş yakalama işlevini etkinleştirir
// Zamanlayıcı / Sayaç1'de Analog Karşılaştırıcı tarafından tetiklenecektir.
// karşılaştırıcı çıkışı bu durumda doğrudan girişe bağlanır
// karşılaştırıcının gürültüyü kullanmasını sağlayarak ön uç mantığını yakalayın
// Zamanlayıcı / Sayıcı1 Girişinin iptal ve kenar seçme özellikleri
// Yakalama kesintisi. Sıfır mantık yazıldığında,
// Analog Karşılaştırıcı ve giriş yakalama işlevi mevcut. için
// karşılaştırıcının Zamanlayıcı / Sayaç1 Giriş Yakalamasını tetiklemesi
// interrupt, Zamanlayıcı Kesme Maskesi Kaydındaki ICIE1 biti
// (TIMSK1) ayarlanmalıdır.
CBI (ACSR, ACIC);
// Bu bitler, Analog'u hangi karşılaştırma karşılaştırma olaylarını tetiklediğini belirler
// Karşılaştırıcı kesintisi.
// ACIS1 ACIS0 Modu
// 0 0 Değiştir
// 0 1 Rezerve edildi
// 1 0 Düşen kenar
// 1 1 Yükselen kenar
SBI (ACSR, ACIS1);
SBI (ACSR, ACIS0);

// ------------------------------------------------ ---------------------
// DIDR1 ayarları
// ------------------------------------------------ ---------------------
// Bu bit mantık bir olarak yazıldığında,
// AIN1 / 0 pin devre dışı. İlgili PIN Kaydı biti
// bu bit ayarlandığında daima sıfır olarak okunur. Analog bir sinyal olduğunda
// AIN1 / 0 pinine uygulanır ve bu pinten gelen dijital giriş
// gerekli, bu bit gücü azaltmak için mantık bir tane yazılmalıdır
// dijital giriş arabelleğinde tüketim.
SBI (DIDR1, AIN1D);
SBI (DIDR1, AIN0D);
}

Adım 13: Eşik

Tetikleyici hakkında söylediklerimizi hatırlatarak, eşik için bu iki çözümü uygulayabiliriz:
  • bir düzeltici kullanarak manuel olarak bir voltaj seviyesi ayarlayabiliriz;
  • Arduino'nun PWM'sini kullanarak seviyeyi yazılımla ayarlayabiliriz.
Görüntüde, eşiğin her iki yoldaki donanım uygulamasını görebiliriz.

Manuel seçim için +5 V ve GND arasına yerleştirilmiş çok turlu bir potansiyometre yeterlidir.

Yazılım seçimi için Arduino'dan gelen bir PWM sinyalini filtreleyen düşük geçişli bir filtreye ihtiyacımız var. PWM sinyalleri (bundan sonra daha fazlası) sabit frekanslı ancak değişken bir darbe genişliğine sahip kare sinyallerdir. Bu değişkenlik, düşük geçişli bir filtreyle çıkarılabilen sinyalin değişken ortalama değerini getirir. Filtre için iyi bir kesme frekansı PWM frekansının yaklaşık yüzde biri ve ben yaklaşık 560 Hz seçtim.

İki eşik kaynağından sonra, istediğim kaynağı bir jumper ile seçmeye izin veren birkaç pim yerleştirdim. Seçimden sonra kaynakları Arduino pininden ayırmak için bir yayıcı takipçisi ekledim.

Adım 14: Darbe Genişliği Modülasyonu Nasıl Çalışır?

Daha önce belirtildiği gibi, bir Darbe Genişlik Modülasyonu (PWM) sinyali sabit frekansa sahip ancak değişken genişliğe sahip bir kare sinyaldir. Resimde bir örnek görüyoruz. Her satırda farklı görev döngüsüne sahip bu tür sinyallerden biri vardır ( id est, sinyalin Yüksek olduğu dönem kısmı). Bir süre boyunca ortalama sinyali alarak, maksimum sinyale göre görev döngüsüne karşılık gelen kırmızı çizgiyi elde ederiz.

Elektronik olarak "bir sinyalin ortalamasını almak", önceki adımda görüldüğü gibi "bir düşük geçişli filtreye geçirilmesi" olarak çevrilebilir.

Arduino nasıl PWM sinyali üretir? Burada PWM hakkında gerçekten iyi bir öğretici var:
//arduino.cc/en/Tutorial/SecretsOfArduinoPWM
Sadece bu proje için gereken noktaları göreceğiz.

ATMega328P'de PWM sinyalleri üretmek için kullanılabilecek üç zamanlayıcı vardır, bunların her biri kullanabileceğiniz farklı özelliklere sahiptir. Her bir zamanlayıcı için, sinyal görev döngüsünü ayarlamak için kullanılan Çıkış Karşılaştırma Kayıtları A / B (OCRnx) adı verilen iki kayıt karşılık gelir.

ADC'ye gelince, PWM frekansını hassas bir şekilde kontrol etmek için ana saati yavaşlatan bir ön ölçekleyici (resme bakın) vardır. Yavaşlatılmış saat, Zamanlayıcı / Sayaç Kaydı'nı (TCNTn) artıran bir sayaca beslenir. Bu kayıt sürekli olarak OCRnx ile karşılaştırılır, eşit olduklarında Dalga Pili Jeneratörüne çıkış piminde bir darbe üreten bir sinyal gönderilir. Yani hile, OCRnx kaydını sinyalin ortalama değerini değiştirmek için bir değere ayarlıyor.

5 V'luk bir sinyal (maksimum) istiyorsak, OCRnx'te% 100'lük bir görev döngüsü veya 255'lik bir değer (8 bitlik bir sayı için maksimum) ayarlamalıyız, 0, 5 V'luk bir sinyal istiyorsak% 10'luk bir görev döngüsü ayarlamalıyız veya OCRnx'te 25.

Saat, yeni bir darbe için baştan başlamadan önce TCNTn kaydını doldurmak zorunda olduğundan, PWM'nin çıkış frekansı:

f = (Ana saat) / ölçeklendirici / (maksimum TCNTn)

Zamanlayıcı 0 ve 2 (8 bit) için ön ölçekleyici olmadan örnek gratia : 16 MHz / 256 = 62.5 KHz, Zamanlayıcı 1 (16 bit) için 16 MHz / 65536 = 244 Hz olacaktır.

Zamanlayıcı 2'yi kullanmaya karar verdim çünkü
  • Zamanlayıcı 0, Arduino IDE tarafından millis ();
  • Zamanlayıcı 1'in çıkış frekansı çok yavaş çünkü 16 bitlik bir zamanlayıcı.

ATMega328P'de zamanlayıcıların farklı çalışma modu vardır, ancak istediğim en yüksek çıkış frekansını elde etmek için ön ölçekleme yapılmayan Fast PWM'di.

Adım 15: PWM'yi Kurma

Çizimde, Zamanlayıcı işlevinin tüm parametrelerini ayarlayan ve birkaç pimi başlatan başka bir başlatma işlevi yazdım. void initPins (void)
{
// ------------------------------------------------ ---------------------
// TCCR2A ayarları
// ------------------------------------------------ ---------------------
// Bu bitler Çıktı Karşılaştırma pimi (OC2A) davranışını kontrol eder. Biri veya
// COM2A1: 0 bitlerinin her ikisi de ayarlanır, OC2A çıkışı
// bağlı olduğu G / Ç piminin normal bağlantı noktası işlevselliği.
// Ancak, Veri Yön Kaydı (DDR) bitinin
// etkinleştirmek için OC2A pinine karşılık gelen
// çıkış sürücüsü.
// Pime OC2A bağlandığında, COM2A1'in fonksiyonu: 0 bit
// WGM22: 0 bit ayarına bağlıdır.
//
// Hızlı PWM Modu
// COM2A1 COM2A0
// 0 0 Normal port çalışması, OC2A bağlantısı kesildi.
// 0 1 WGM22 = 0: Normal Bağlantı Noktası Çalışması, OC0A Bağlantısı Kesildi.
// WGM22 = 1: Karşılaştırma Maçında OC2A'yı aç / kapat.
// 1 0 Karşılaştırma Maçında OC2A'yı Temizle, BOTTOM'da OC2A'yı ayarlayın
// 1 1 Karşılaştırma Maçında OC2A'yı temizle, BOTTOM'da OC2A'yı temizle
CBI (TCCR2A, COM2A1);
CBI (TCCR2A, COM2A0);
SBI (TCCR2A, COM2B1);
CBI (TCCR2A, COM2B0);

// TCCR2B Kaydında bulunan WGM22 biti ile birleştiğinde, bu bitler
// sayacın sayım sırasını, maksimum kaynak
// (TOP) sayaç değeri ve ne tür dalga formu üretimi kullanılacak
// Zamanlayıcı / Sayıcı birimi tarafından desteklenen çalışma modları:
// - Normal mod (sayaç),
// - Karşılaştırma Karşılaştırma (CTC) modunda Zamanlayıcıyı Temizle,
// - iki tip Darbe Genişlik Modülasyonu (PWM) modu.
//
// Mod WGM22 WGM21 WGM20 Çalışma ÜST
// 0 0 0 0 Normal 0xFF
// 1 0 0 1 PWM 0xFF
// 2 0 1 0 CTC OCRA
// 3 0 1 1 Hızlı PWM 0xFF
// 4 1 0 0 Ayrılmış -
// 5 1 0 1 PWM OCRA
// 6 1 1 0 Saklıdır -
// 7 1 1 1 Hızlı PWM OCRA
CBI (TCCR2B, WGM22);
SBI (TCCR2A, WGM21);
SBI (TCCR2A, WGM20);

// ------------------------------------------------ ---------------------
// TCCR2B ayarları
// ------------------------------------------------ ---------------------
// FOC2A biti yalnızca WGM bitleri PWM olmayan bir değer belirttiğinde etkindir
// modu.
// Ancak, gelecekteki cihazlarla uyumluluğu sağlamak için bu bit
// PWM'de çalışırken TCCR2B yazıldığında sıfıra ayarlanmalıdır
// modu. FOC2A bitine mantıklı bir tane yazarken, hemen
// Karşılaştırma, Dalga Formu Oluşturma biriminde zorla çalıştırılır. OC2A
// çıkış, COM2A1: 0 bit ayarına göre değiştirilir. Bunu not et
// FOC2A biti flaş olarak uygulanır. Bu nedenle değer
// COM2A1'de mevcut: 0 bit,
// karşılaştırmaya zorla.
// Bir FOC2A flaşı herhangi bir kesinti oluşturmayacak veya netleşmeyecek
// TOP olarak OCR2A kullanarak CTC modunda zamanlayıcı.
// FOC2A biti daima sıfır olarak okunur.
CBI (TCCR2B, FOC2A);
CBI (TCCR2B, FOC2B);

// Üç Saat Seçim biti, tarafından kullanılacak saat kaynağını seçer
// Zamanlayıcı / Sayıcı.
// CS22 CS21 CS20 Ön Ölçekleyici
// 0 0 0 Saat kaynağı yok (Zamanlayıcı / Sayaç durdu).
// 0 0 1 Ön ölçekleme yok
// 0 1 0 8
// 0 1 1 32
// 1 0 0 64
// 1 0 1 128
// 1 1 0256
// 1 1 1 1024
CBI (TCCR2B, CS22);
CBI (TCCR2B, CS21);
SBI (TCCR2B, CS20);

pinMode (errorPin, OUTPUT);
pinMode (eşikPin, ÇIKIŞ);

analogWrite (eşikPin, 127);
}

Adım 16: Uçucu Değişkenler

Nerede olduğunu hatırlayamıyorum, ancak ISR içinde değiştirilen değişkenlerin geçici olarak bildirilmesi gerektiğini okudum.

Uçucu değişkenler, çalışan program bunları değiştirmese bile, zaman içinde değişebilen değişkenlerdir. Tıpkı bazı harici müdahalelerin değerini değiştirebilen Arduino kayıtları gibi.

Derleyici neden bu değişkenleri bilmek istiyor? Çünkü derleyici yazdığımız kodu her zaman daha hızlı hale getirmek için optimize etmeye çalışır ve anlamını değiştirmemeye çalışarak biraz değiştirir. Bir değişken kendi başına değiştiğinde, derleyiciye, örneğin bir döngünün yürütülmesi sırasında hiçbir zaman değiştirilmediği görülebilir ve görmezden gelebilir; değişkenin değerini değiştirmesi çok önemli olabilir. Böylece, değişken değişkenler bildirilmesi derleyicinin bunlarla ilgili kodu değiştirmesini önler.

Daha fazla bilgi için Wikipedia sayfasını okumanızı tavsiye ederim: //en.wikipedia.org/wiki/Volatile_variable

Adım 17: Eskiz Çekirdeğinin Yazılması

Sonunda programın çekirdeğine geçtik!

Daha önce gördüğümüz gibi, sürekli bir edinme istedim ve ADC Kesinti Hizmeti Rutini verileri sürekli olarak arabellekte saklamak için yazdım. StopIndex değerine eşit olan dizine ulaştığında durur. Tampon, modulo operatörü kullanılarak dairesel olarak uygulanır.

// ------------------------------------------------ -----------------------------
// ADC Dönüştürme Tamamlandı Kesmesi
// ------------------------------------------------ -----------------------------
ISR (ADC_vect)
{
// ADCL okunduğunda, ADC Veri Kaydı ADCH'ye kadar güncellenmez
// okunur. Sonuç olarak, sonuç ayarlanmış olarak bırakılırsa ve artık
// 8-bit hassasiyet gerekiyorsa, ADCH okumak yeterlidir.
// Aksi takdirde, önce ADCL sonra ADCH okunmalıdır.
ADCBuffer [ADCCounter] = ADCH;

ADCCounter = (ADCCounter + 1)% ADCBUFFERSIZE;

eğer (bekle)
{
eğer (stopIndex == ADCCounter)
{
// Donma durumu
// ADC'yi devre dışı bırak ve Serbest Çalışan Dönüşüm Modunu durdur
cbi (ADCSRA, ADEN);

donma = doğru;
}
}
}

Analog Karşılaştırıcı Kesme Servisi Rutini (bir sinyal eşiği geçtiğinde çağrılır) kendini devre dışı bırakır ve ADC ISR'ye bekleme aşamasını başlatmasını ve stopIndex'i ayarlamasını söyler.

// ------------------------------------------------ -----------------------------
// Analog Karşılaştırıcı kesmesi
// ------------------------------------------------ -----------------------------
ISR (ANALOG_COMP_vect)
{
// Analog Karşılaştırıcı kesintisini devre dışı bırak
cbi (ACSR, ACIE);

// errorPin'i aç
// digitalWrite (errorPin, HIGH);
sbi (PORTB, PORTB5);

bekleyin = doğru;
stopIndex = (ADCCounter + waitDuration)% ADCBUFFERSIZE;
}


Tüm bu topraklamalardan sonra bu gerçekten kolaydı!

Adım 18: Gelen Sinyali Oluşturma

Şimdi donanıma geçelim. Devre karmaşık görünebilir, ancak gerçekten basittir.
  • Sinyale kütle referansı vermek ve yüksek empedans girişine sahip olmak için girişte 1 MΩ direnç vardır. Yüksek empedans, daha düşük bir empedans devresine bağlarsanız açık bir devreyi "simüle eder", böylece Girino'nun varlığı ölçmek istediğiniz devre ile çok fazla karışmaz.
  • Dirençten sonra sinyali ayırmak ve aşağıdaki elektroniği korumak için bir yayıcı takipçisi vardır.
  • Bir voltaj bölücü ile 2.5 V seviyesi üreten basit bir ofset vardır. Sabitlemek için bir kapasitöre bağlanır.
  • Gelen sinyali ve ofseti toplayan ters çevirmeyen bir toplam yükseltici vardır. Bu tekniği kullandım çünkü Arduino ADC sadece 0 V ila 5 V arasındaki sinyalleri görebildiğinden, negatif sinyalleri de görmek istedim.
  • Toplam amplifikatörden sonra başka bir yayıcı takipçisi var.
  • Bir jumper, sinyali bir ofset ile besleyip beslemeyeceğimize karar vermemizi sağlar.
Kullanmayı amaçladığım İşlemsel Amplifikatör, 0 V - 5 V arasında ve aynı zamanda, örneğin, -12 V - 12 V arasında çalışabilen bir LM324 idi. Bu, bize güç kaynakları ile daha fazla olasılık sağlar. Ayrıca LM324'ten çok daha hızlı olan ancak çift güç kaynağı gerektiren bir TL084 denedim. Her ikisi de aynı pin çıkışına sahiptir, bu nedenle devrede herhangi bir değişiklik yapılmadan değiştirilebilir.

Adım 19: Kapasitörleri Baypas Et

Bypass Kapasitörleri, Entegre Devrelerin (IC) güç kaynaklarını filtrelemek için kullanılan kapasitörlerdir ve IC'nin besleme pimlerine mümkün olduğunca yakın yerleştirilmelidirler. Genellikle çift, bir seramik ve bir elektrolitik olarak kullanılırlar, çünkü farklı frekansları filtreleyebilirler.

Adım 20: Güç Kaynakları

TL084 için LM324 için tek bir güç kaynağına dönüştürülebilen bir çift güç kaynağı kullandım.

Resimde, +12 V için bir 7812 ve -12 V için bir 7912 voltaj regülatörü kullandığımı görebiliyoruz. Kondansatörler her zamanki gibi seviyeleri stabilize etmek için kullanılıyor ve değerleri önerilenler veri sayfalarında.

Açıkçası ± 12 V'a sahip olmak için, girişte en az yaklaşık 30 V olması gerekir, çünkü voltaj regülatörleri stabilize bir çıkış sağlamak için daha yüksek bir giriş gerektirir. Böyle bir güç kaynağım olmadığından seri olarak iki adet 15 V güç kaynağı kullanma hilesini kullandım. İkisinden biri Arduino güç konektörüne bağlanır (böylece hem Arduino'yu hem de devrimi besler) ve diğeri doğrudan devreye bağlıdır.

İkinci güç kaynağının +15 V'unu birincinin GND'sine bağlamak hata değildir! İzole güç kaynakları ile bir -15 V elde ederiz.

Bir Arduino ve iki güç kaynağı taşımak istemezsem, Arduino tarafından sağlanan +5 V'yi yine de bu jumper'ları değiştirerek (ve LM324'ü kullanarak) kullanabilirim.

Adım 21: Kalkan Konektörü Hazırlama

Bir Arduino kalkanı yapmak için bulabildiğim konektörlerden her zaman rahatsız oldum, çünkü her zaman çok kısa pimlere sahipler ve kullandığım tahtalar sadece bir tarafa lehimlenebilir. Bu yüzden pinleri daha uzun yapmak için biraz hile yaptım, böylece Arduino'ya lehimlenebilir ve yerleştirilebilirler.

Resimdeki gibi pim şeridini tahtaya yerleştirerek, pimleri siyah plastiğin sadece bir tarafında tutmak için itebiliriz. Sonra onları Arduino'ya yerleştirilecekleri aynı tarafa lehimleyebiliriz.

Adım 22: Lehimleme ve Test Etme

Devrenin tüm lehimleme prosedürünü gösteremiyorum çünkü çok fazla deneme yanılma işlemi yaptı. Sonunda biraz dağınık ama çok kötü değil, ama altını göstermeyeceğim, çünkü bu gerçekten dağınık.

Bu aşamada söylenecek çok şey yok çünkü devrenin tüm parçalarını ayrıntılı olarak açıkladım. Devrenin her noktasındaki sinyalleri görmek için bir arkadaşımın ödünç aldığı bir osiloskopla test ettim. Görünüşe göre her şey yolunda gidiyor ve oldukça memnunum.

Gelen sinyalin konektörü, Yüksek Enerji Fiziğinden gelmeyen biri için biraz garip görünebilir, bu bir LEMO konektörüdür. En azından ABD'de çoğunlukla BNC konektörlerini gördüğüm gibi, nükleer sinyaller için standart konektördür.

Adım 23: Test Sinyalleri

Devreyi ve Veri Toplama'yı (DAQ) test etmek için, farklı uzunluklarda kare darbeler üreten basit bir taslağa sahip ikinci bir Arduino kullandım. Ayrıca Girino ile konuşan ve bazı veri serileri edinmesini söyleyen ve bunlardan birini bir dosyaya kaydeden bir python betiği yazdım.
Her ikisi de bu adıma bağlıdır.

Ekler

  • TaraturaTempi.ino İndir
  • readgirino.py İndir

Adım 24: Zaman Kalibrasyonu

Test sinyallerini kullanarak grafiklerin yatay ölçeğini kalibre ettim. Bakliyatların genişliklerini (üretildiği için bilinen) ölçerek ve ölçülen bakliyat genişliklerini bilinen değerlere göre çizerek, umarım doğrusal bir grafik elde ederiz. Bunu her ön ölçekleyici ayarı için tüm çekim hızları için zaman kalibrasyonuna sahibiz.

Görüntülerde analiz ettiğim tüm verileri görebiliriz. "Donatılı eğimler" grafiği en ilginç olanıdır çünkü bize her ön ölçekleyici ayarında sistemimin gerçek edinim hızını söyler. Eğimler [ch / ms] sayısı olarak ölçüldü, ancak bu bir [kHz] 'e eşdeğerdir, bu nedenle eğim değerleri aslında kHz veya ayrıca kS / s'dir (saniyede kilo Örnek). Bu, ön ölçekleyicinin 8 olarak ayarlanmasıyla, bir kazanım oranı elde ettiğimiz anlamına gelir:

(154 ± 2) kS / s

Fena değil, değil mi?

"Fitted y-intercepts" grafiğinden sistem doğrusallığı hakkında bir fikir ediniriz. Tüm y-kesişmeleri sıfır olmalıdır, çünkü sıfır uzunluğunda bir sinyalde sıfır uzunluğunda bir darbeye karşılık gelmelidir. Grafikte görebildiğimiz gibi, hepsi sıfır ile uyumludur, ancak 18 ön ölçekleyici veri kümesiyle uyumlu değildir. Bu veri kümesi, en kötüsüdür, çünkü sadece iki veriye sahiptir ve kalibrasyonuna güvenilemez.

Aşağıda, her ön ölçekleyici ayarı için edinme oranlarını içeren bir tablo bulunmaktadır.

ön derecelendiriciEdinme oranı [kS / s]
1289.74 ± 0.04
6419.39 ± 0.06
3237.3 ± 0.6
1675.5 ± 0.3
8153 ± 2
Belirtilen hatalar Gnuplot fit motorundan geliyor ve ben onlardan emin değilim.

Ayrıca oranların ağırlıksız bir uyumunu denedim çünkü ön ölçekleme yarıya indiğinde kabaca iki katına çıktıklarını görebilirsiniz, bu ters orantılılık yasasına benziyor. Bu yüzden oranları basit bir yasa ile

y = a / x

İçin bir değer aldım

a = 1223

χ² = 3.14 ve 4 serbestlik derecesine sahip olması, yasanın% 95 güven düzeyinde kabul edildiği anlamına gelir!

Adım 25: Bitti! (Neredeyse)

Bu uzun deneyimin sonunda kendimi çok memnun hissediyorum
  • Genel olarak mikrodenetleyiciler hakkında çok şey öğrendim;
  • Arduino ATMega328P hakkında çok daha fazla şey öğrendim;
  • Veri Toplama konusunda uygulamalı bir deneyim yaşadım, zaten yapılmış bir şeyi kullanarak değil, bir şeyler yaparak;
  • O kadar da kötü olmayan amatör bir osiloskop fark ettim.
Umarım bu rehber, okuyan herkes için faydalı olacaktır. Bunu çok ayrıntılı yazmak istedim çünkü tüm bunları zor yoldan öğrendim (internette gezinmek, veri sayfasını okumak ve çok fazla deneme yanılma yoluyla) ve bu deneyimden herkesi kurtarmak istiyorum.

Adım 26: Devam Edilecek ...

Ancak proje tamamlanmaktan uzaksa. Eksik olan şey:
  1. Farklı analog sinyalleri olan bir test (analog sinyal üretecini kaçırıyorum);
  2. Bilgisayar tarafı için bir Grafik Kullanıcı Arayüzü.
1. noktaya gelince, ne zaman tamamlanacağından emin değilim, çünkü yakın gelecekte bir tane almayı / inşa etmeyi planlamıyorum.

2. nokta için durum daha iyi olabilir. Bana bu konuda yardım etmek isteyen var mı? Burada güzel bir Python Osiloskop buldum:
//www.phy.uct.ac.za/courses/python/examples/moreexamples.html#oscilloscope-and-spectrum-analyser
Girino'ya uyacak şekilde değiştirmek istiyorum, ancak önerileri kabul ediyorum.

İlgi̇li̇ Makaleler