AREF | Arduino ADC Referans Değerini Değiştirme

    Arduino ile ADC ölçümlerinde hep 5V kullanıldığı dikkatinizi çekmiştir. İşin aslı AVR 'nin bize sunduğu analog reference voltage değişikliğini Arduino ile de yapmak mümkün. Bu değişiklik için 3 farklı seçeneğimiz var, birincisi herkesin bildiği 5V olarak kullanmak (DEFAULT), ikinci seçenek AVR çip üzerinde gömülü halde gelen 1.1V 'luk referans voltajı(INTERNAL), diğeri de AREF pini üzerinden harici bir değeri analog referans olarak belirleyebiliyor olmamız(EXTERNAL).

    Peki analog referans değerini neden değiştirmeye ihtiyaç duyarız? ADC kaç bit oluşuyla bağlantılı olarak referans voltajını 2^n (2 üzeri n) sayısına böler, ADC kanalındaki ölçülmek istenen gerilim ile bu bölmeden elde ettiği aralıklardan hangisine uygunsa o dönüşümü sayısal olarak çıkartır. Bu arduino UNO için 10 bitlik bir değerdir. Referans voltajımız 5v ise, her adımımız yaklaşık olarak 5mV olacaktır:

5V/1024 = 0.0048828125

0.0048828125 / 2 = 0.00244140625

Bunun anlamı da ADC için 0.5 LSB 'lik  bir kuantalama hatası olduğuna göre ölçtüğümüz her değer için yaklaşık yine 2.5mV 'luk hata payımız var demektir. Eğer ki ölçeceğimiz gerilim, bulunduğu noktada ASLA 1.1V 'u aşmıyorsa, bu durumda referans voltajını 1.1 'a değiştirmek hata payımızı 1/5 oranında düşürür ve daha az hatalı bir sonuç okumamızı sağlar:

1V/1024 = 0.0009765625

0.0009765625 / 2 = 0.00048828125



Eğer ki 1.1 V yeterli değilse ve 5v da uygulamanız için fazlaysa ve hassasiyetin önem arzettiği noktada kendi analog referans voltajınızı üretip (bir voltaj bölücü yardımıyla mesela) AREF pinine bağlayabilirsiniz, bu durumda AREF pinine uyguladığınız voltajı 1024 'e bölerek hesaplamalarınızı yapabilirsiniz:    

ADC = (Vin*1024) / AREF

bizim durumumuz için ADC bilinen Vin hesaplanmak istenen olduğu için :

Vin = (ADC * AREF)/1024 

olacaktır. Burada

Vin : okunmak istenen voltajı

ADC : dönüşüm sonunda elde edilen ADC değerini

AREF : analog referans voltajını

1024 ise 2^10, 'dan ADC 'nin 10 bit olması dolayısıyla elde edilen sabittir. 12 bit bir ADC 'miz olsaydı bu sabit 4096 olacaktı.



Gelelim uygulamaya ve detaylara; normal şartlar altında ADMUX registerinin 7 ve 6. bitleri [REFS1:0] bu ayarlamayı yapmamızı sağlıyor, ancak siz Arduino kodu içerisinde bu register ile bu ayarlamayı yaptıktan sonra analogRead fonksyionunu kullanıyorsanız, -bu fonksiyon her çağırıldığında AREF i default olarak 5V 'a ayarlıyor- yaptığınız bu değişikliği fonksiyon tekrar değiştirmiş olacak ve kullanamıyor olacaksınız. Bu noktada ya dönüşümü kendiniz yazmaçları kullanarak yapacaksınız ya da yine arduino wiring_analog.c dosyasında yer alan analogReference fonksiyonunu ADC okumanızı yapmadan önce kullanacaksınız.

Arduino Analog Referans Voltajını 1.1V a ayarlamak için analogRead fonksiyonundan hemen önce:

  analogReference(INTERNAL);

External ayarlamak için:

  analogReference(EXTERNAL);

5V ' a ayarlamak için

  analogReference(DEFAULT);

şeklinde kullanabilirsiniz. Hatırlatmakta fayda var bu fonksiyon analog referans voltajını değiştirdikten sonra tüm adc okumaları bu ayar üzerinden yapılır, eğer ki başka bir kanalda 5V kullanırken bir diğer kanalde 1.1V kullanmak isterseniz, her okumadan önce mutlaka bu fonksiyonla referans voltajını ayarlamanız gerekiyor. Bir diğer önemli konu da INTERNAL olarak set ettiğinizde AREF pinine herhangi bir voltaj uygulamadığınızdan emin olmanızdır.

EXTERNAL olarak ayarladığınızda da söylememiş olmayalım diye yazıyorum, AREF pinine uygulayacağınız voltaj 5v ' geçmemelidir. Yani oraya 20V uygulayıp 0-20V arası ölçüm yapayım diyemiyorsunuz, böyle bir ihtiyacınız varsa : Arduino İle Yüksek Voltaj Ölçme konusunu okumanızı öneririm.





Arduino ile Joystick Kullanımı

 Joystick Modül Nedir Nasıl Çalışır?

joystick module
        Arduino ile Joystick kullanımı oldukça basittir, bu yazıda joystik modülün devre şemasına çalışma mantığına ve arduino ile nasıl kullanılabileceğine örnek kodla birlikte bakıyor olacağız.

Joystik modül pin tanımları    

Yan tarafa resmini görmekte olduğunuz yakışıklı joystik modülün 5 adet pini bulunmakta:

  • GND ground pini
  • 5V 5v besleme pini
  • VRx Analog çıkış, 0-5V arası X yönündeki değişimi algılamak için
  • VRy Analog çıkış,0-5V arası Y yönündeki değişimi algılamak için
  • SW Digital Çıkış, Joystiğe tıklandığında pini GND ye aktaran butonun çıkış pini

Joystick Modül Yönleri ve Voltajları

joystick modül yönleri ve voltajları



Joystik Modul Nasıl Çalışır?

    Joystick modülde dikey ve yatay yönler için iki adet bir pinleri gnd'ye diğer pinleri 5v bağlı 10K 'lık potansiyometreler bulunur. Bu potansiyometreler birer voltaj bölücü olarak çalışırlar. Voltaj bölücü konusuna hakim değilseniz : Voltaj Bölücü Devresi konusunu okumanızı tavsiye ederim. Bu durumda joystick orta konumdayken, her iki potansiyometre de orta konumda olur ve giriş voltajının yarısı olan 2.5 'u üretirler, potansiyometrelerin kademesi arttıkça çıkıştaki voltajları artar, azaldıkça da çıkış voltajları azalır. Bu analog çıkışları mikrodenetleyicinin analog pinlerine bağlayıp ADC dönüşümü ile okumak suretiyle işlem yapılabilir. Okunan ADC değerine göre joystiğin hangi yöne ne kadar saptırıldığı anlaşılır.
    Modül üzerindeki buton GND'yi anahtarlamak için kullanılmıştır, bu nedenle butona basıldığında SW pininde 0V oluşur, normalde floating yani boştadır, devre şeması üzerindeki R1 direnci yerine 0805 kılıfında 10K bir direnç bağlayarak pull-up yapabilirsiniz, ya da mikrodenetleyicinizin butonu bağlayacağınız pinini internal olarak pull-up ayarlamalısınız.

Joystik Modülün Devre Şeması

Joystick Modül Devre Şeması





Joystik Modül Arduino Bağlantısı

Joystick Pini Arduino Uno Pini
GNDGND
5V5V
VRxAnalog Pin
VRyAnalog Pin
SWDigital Pin

VRx ve VRy pinlerini analog pinlerden sizin için uygun olanlara bağlayabilirsiniz
SW pini joystik üzerindeki butonu kullanmak için dijital pinlerden sizin için uygun olan birine bağlayabilirsiniz.


Arduino ile Joystik Örnek Kod


/*
   Arduino ile Joystick Kullanımı
   Örnek Kod

   Hakan ÖZMEN (hakkanr@gmail.com)
   01-12-2022

   https://www.devrelerim.com/2022/12/arduino-ile-joystick-kullanimi.html
*/
#define SWPIN 3
#define VRxPIN A0
#define VRyPIN A1
const char* dirNames[] = {
  "Sol Aşağı",
  "Aşağı",
  "Sağ Yukarı",
  "",
  "Sol",
  "OrtaKonum",
  "Sağ",
  "",
  "Sol Yukarı",
  "Yukarı",
  "Sağ Yukarı"
};
enum directions
{
  LeftDown,
  Down,
  RightDown,
  NC,
  Left,
  Center,
  Right,
  NC2,
  LeftUp,
  Up,
  RightUp
};
directions JoyDirection();
void setup() {
  Serial.begin(115200);
  pinMode(SWPIN, INPUT_PULLUP);

}
directions JoyDir;
void loop() {
  JoyDir = JoyDirection();
  Serial.println(dirNames[JoyDir]);
  if (buttonPressed()) /* butona basınca çalışacak kod*/
  {
    Serial.println("Butona basıldı!");
  }
    
  switch (JoyDir)
  {
    case LeftDown:
      /* joystick sol aşağı konumdayken çalışacak kod*/
      break;
    case Down:
      /* joystick aşağı konumdayken çalışacak kod */
      break;
      /*
       * tüm yönler için yazabilirsiniz
         ...
      */
  }
  delay(1000);
}

int adcX, adcY;
directions JoyDirection()
{
  adcX = analogRead(VRxPIN);
  adcY = analogRead(VRyPIN);
  int xPos = map(adcX, 0, 1023, 0, 3);
  int yPos = map(adcY, 0, 1023, 0, 3);
  directions dir = (directions)((xPos << 2) | (yPos));
  return dir;
}
bool buttonPressed()
{
  return (digitalRead(SWPIN) == LOW ? true : false);
}



Arduino SSD1306 Oled Ekran Grafik Fonksiyonları | SSD1306TUR Library

 Arduino ile OLED Ekran SSD1306 ile Grafik İşlemleri

    Arduino ile Oled ekranlarda SSD1306TUR kütüphanesi ile tüm grafik işlemleri fonksiyonlarına bakıyor olacağız. Ekranın kullanımı ve Arduino Uno 'ya bağlantısı gibi giriş seviyesi konulara hakim değilseniz : Arduino oled ekran kullanımı konusunu ziyaret edebilirsiniz. Bu yazıda yalnızca oled ekran ile grafiksel fonksiyonları inceliyor olacağız. Aşağıdaki fonksiyonları kullandıktan sonra ekranda yaptığınız değişikliklerin görüntülenmesi için display.display(); fonksiyonunu kullanmayı unutmayın.

writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)

fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) fonksiyonu da kullanılabilir.

İçi dolu bir dikdörtgen çizmenize olanak sağlar, kullanılan parametreler :

  • x : ekran üzerindeki yatay konum (en sol 0)
  • y: ekran üzerindeki dikey konum (en üst 0)
  • w: çizilecek dikdörtgenin genişliği (piksel)
  • h: çizilecek dikdörtgenin yüksekliği (piksel)
  • color: renk

display.writeFillRect(0,10,50,10,1);

İçi boş bir dikdörtgen çizmek için aynı parametrelerle 

display.drawRect(0, 10, 50, 10, 1);

fonksiyonunu kullanabilirsiniz.

setRotation (uint8_t x)

Ekran yönünü değiştirmenize olanak sağlar, farklı tasarımlarda ya da montaj durumuna göre ekranın yönünü çevirmek için kullanabilirsiniz. X parametresi, 
  • 0 : mevcut konumu,
  • 1 : 90 derece sağa, pinler sol tarafta ekrana bakarsanız düz konuma gelmiş olur
  • 2: 180 derece sağa, tam ters posizyonu alır ekran pinleri aşağıda kaldığında ekran düz konuma gelmiş olur
  • 3: 90 derece sola, pinler sağ tarafta kalacak şekilde ekran düz konumda olur.
ekran çevirme işlemi fonksiyon kullanıldıktan sonra kullanılan fonksiyonlar için geçerli olur.

display.setRotation(2);

fonksiyonu SSD1306 ekranı ters çevirir.

fillScreen(uint16_t color)

Ekranın tamamını tek renkle doldurmanıza olanak sağlar.

display.fillScreen(SSD1306_WHITE);

drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)

Ekrana çizgi çizmenize olanak sağlar, x0, y0 noktasından başlayan x1,y1 noktasında son bulan bir çizgi çizdirir :

display.drawLine(0,0,127,31,SSD1306_WHITE);

ekranın sol üstünden başlayan sağ altına kadar giden bir çizgi çizer.

drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)

Ekrana merkezi x0,y0 noktasında olan ve yarı çapı r pixel olan color renginde bir daire çizer. Eğer daireniz yeterince daireymiş gibi görünmüyorsa, bu ekranın dikey piksel aralığının yatay piksel aralığından daha fazla olmasından kaynaklanıyor olabilir ya da yüksekliğinizi düşük girmiş olabilirsiniz. Yüksekliği 64 piksel olan ekran için 32 piksel girerseniz ekranınız dikey olarak olduğundan geniş görüneceğinden daire değil de elips görüyor olacaksınız ekranda.

display.drawCircle(64,15,15,SSD1306_WHITE);

aynı patametrelerle fillCircle fonksiyonunu içi dolu bir daire çizmek için kullanabilirsiniz:

display.fillCircle(64,15,15,SSD1306_WHITE);

drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)

Ekrana merkezi x0,y0, notasında r piksel yarı çapında color renginde bir dairenin çeyreklerini çizmenize olanak sağlar, bu fonksiyon yardımıyla köşe noktaları yuvarlak olan dikdörtgen butonlar çizebilirsiniz, tabi drawLine falan da kullanmanız gerekecek, bunun için özel bir fonksiyon var, aşağılarda yazıyor olacak; cornername parametresini 4 bitlik ikili sayı sisteminde bir değer olarak düşünün 1 ler basamağınız 1 ise dairenin sol üst çeyreğini, 2 ler basamağınız 1 ise sağ üst çeyreğini, 4 ler basamağınız 1 ise sağ alt çeyreğini, 8 ler basamağınız 1 ise sol alt çeyreğini çizdirebilirsiniz. Daha kolayınıza gelsin diye kütüphanenin tanımlamalarını kullanabilirsiniz, köşe sayınız birden fazla ise aralarına | or koymanız işinizi çözecektir :

display.drawCircleHelper(63,15,5,CORNLUP | CORNRDN,SSD1306_WHITE);

merkezi x=63, y=15 te olan 5 piksel yarı çapındaki bir dairenin sol üst ve sağ alt çeyreğini ekrana çizer.


drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)

Ekranda x0,y0,x1,y1,x2,y2 noktalarında köşeleri bulunan color renginde içi boş bir üçgen çizer 

display.drawTriangle(0,0,63,31,127,0,SSD1306_WHITE);

aynı parametrelerle içi dolu bir üçgen çizmek için :

display.fillTriangle(0,0,63,31,127,0,SSD1306_WHITE);

kulanabilirsiniz.

drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)

Sol üst köşesi x,y noktasında olan w piksel genişliğinde h piksel yüksekliğinde kenarları r piksel yarı çapında oval olan içi boş bir dikdörtgen çizmenize olanak sağlar.

display.drawRoundRect(10,10,70,20,5,SSD1306_WHITE);

aynı parametrelerle içi dolu bir dikdörtgeni:

fillRoundRect(10,10,70,20,5,SSD1306_WHITE);

fonksiyonuyla çizebilirsiniz.




Arduino Oled Ekran Kullanımı | SSD1306 Detaylı Tüm Fonksiyonlar

ssd1306 drawbitmap

 

Bu yazıda, Arduino ile ssd1306 oled ekranın SSD1306TUR kütüphanesiyle kullanımına ve tüm fonksiyonlarına bakıyor olacağız. Arduino demişken;

  • ATmega328 : Arduino UNO, Adafruit Pro Trinket, Adafruit Metro 328, Adafruit Metro Mini
  • ATmega32u4 : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0, Adafruit Flora, Bluefruit Micro
  • ATmega2560 : Arduino Mega
  • ESP8266 : Adafruit Huzzah
  • ATSAM3X8E : Arduino Due
  • ATSAMD21 : Arduino Zero, M0 Pro, Adafruit Metro Express, Feather M0
  • ATtiny85 : Adafruit Gemma, Arduino Gemma, Adafruit Trinket
  • Particle: Particle Argon
tamamı ile testi yapılmış çalıştığı görülmüştür.

Kütüphane nasıl yüklenir ? : SSD1306TUR | SSD1306 Oled Ekran Türkçe Kütüphane linkini takip edebilirsiniz.

SSD1306 Arduino UNO I2c Bağlantısı

Arduino ssd1306 bağlantısı


    
    Ekranın I2c protokolü üzerinden Arduino Uno 'ya bağlantısı şu şekilde :

Ekran Pini Arduino Uno Pini
GNDGND
VDD5V
SCKA4
SDAA5

Ekranın Başlatılması

    Uygulamaya başlamadan önce tanımlarımızı sayfanın en üstünde yapıyoruz :

#include "SSD1306TUR.h"
#include "TrFonts/FreeSansBold12pt7bTR.h"

#define SCREEN_WIDTH 128 // OLED display genişlik piksel sayısı
#define SCREEN_HEIGHT 32 // OLED display yükseklik piksel sayısı
#define OLED_RESET -1    // varsa reset pini yoksa -1
#define SCREEN_ADDRESS 0x3C // Datasheete bakınız; 0x3D
                            // -> 128x64, 0x3C -> 128x32
SSD1306TUR display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

sonrasında setup fonksiyonu içerisinde ekranımızı başlatıyoruz :

void setup()
{
   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
  {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; // Don't proceed, loop forever
  }
  display.clearDisplay();
}

artık display nesnesiyle ekranımızı yönetmeye başlayabiliriz.

clearDisplay()

    Ekranın tampon datasını siler, tüm pikseller kapalı duruma gelir.

display.clearDisplay();

display()

Display fonksiyonu ekran için yaptığınız işlemlerin ekranda gösterilmesini sağlar, aşağıdaki ya da grafik işlemleri konusunda yazdığımız tüm fonksiyonlardan sonra bu fonksiyonu kullanmamız gerekiyor, aksi halde kullanılan fonksiyonlar uno'nun ram indeki buffer da saklanıyor, ekrana gönderilmiyor.

display.display();

String İşlemleri

Ekrana yazı yazdırmak için kullanabileceğimiz fonksiyonlara bakalım; 

setTextColor() 

setTextColor(uint16_t textColor)

    Ekrana herhangi bir şey yazdırmadan önce yazı rengini belirlemeniz gerekiyor, belirlemezseniz kütüphane varsayılan olarak SSD1306_WHITE olarak seçiyor, zaten monochrome bir ekran için başka bir şansınız yok, piksel ya görünüyordur açıktır yani, ya da kapalıdır, kapalı olma durumu da SSD1306_BLACK ile seçilebilir. 

display.setTextColor(SSD1306_WHITE);

    
setTextColor(uint16_t textColor, uint16_t bgColor)

Arka plan da belirlemek istiyorum derseniz bunu sadece yazı kapalı arka plan görünür olsun istediğiniz için kullanırsınız, diğer durumda arka plan zaten siyahtır, yani inverse text yapmak için: ilk parametre yazı rengi ikinci parametre yazı arka plan rengi olarak verilebiliyor :

display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);

setTextSize(uint8_t size)

Yazılacak metnin boyutunu ayarlar, bu karakter boyutunuzun bir çarpanı gibi düşünülebilir, karakterini 6x8 ise ve fonksiyona 2 değerini göndermişseniz, karakterleriniz 12x16 olarak basılır. Fonksiyonun kullanım zorunluluğu yoktur; kullanılmazsa karakter olduğu boyutlarda ekrana basılır.

display.setTextSize(2);

setFont(const GFXfont *f)

Yazılacak metnin fontunu belirlemenizi sağlıyor, metin yazılmadan önce belirtilmeli. İçerisine parametre olarak gfx fontlardan birinin adresini (font isminin yanında & olmalı) girmelisiniz. Font isimlerini nerden bulabilirim? kütüphanenin içinde TrFonts klasörünün içinde bulunan fontlardan, hangisini seçecekseniz onun dosya ismiyle font ismi aynı ayarlanmıştır, farklı olabilir mi? bunun için font dosyasını açtığında en altta font tanımlamasını göreceksin :

const GFXfont FreeSansBold12pt7bTR PROGMEM

fonksiyona parametre olarak vermen gereken şey tam olarak budur:

 display.setFont(&FreeSansBold12pt7bTR);

Ee bir tane font var başka yok mu? Türkçe karakter destekleyen henüz yok. Desteklemeyenlere de Adafruit GFX library içerisinde Fonts klasöründen ulaşabilirsin, projene bu fontları dahil etmek için :

#include "Fonts/FreeSans12pt7b.h"

Fonts/ yazıp font dosya adını yazman yeterli.

setCursor(int16_t x, int16_t y)

Yazılacak metnin ekrandaki pozisyonunu belirlemenizi sağlıyor, x yatay düzlemdeki genişliğe denk gelen değer y dikey düzlemde yüksekliğe denk gelen değer 0,0 ekranın sol üst köşesini ifade eder ve piksel cinsinden değerlerdir.

display.setCursor(20, 22);

metninizi 20 piksel sağa 22 piksel aşağıya kaydırmış olur.

print(const __FlashStringHelper *ifsh)

Fonksiyonun görünümü sizi korkutmasın, içine çift tırnak içinde yazacağınız metni yazmanız yeterli

display.print("Türkçe");

yazdıktan sonra metnin sonuna satır bitirme eklemek isterseniz ki bu durumda bundan sonra yazdıracağınız metin bir alt satırdan başlar, bu durumda println kullanabilirsiniz:

 display.println("SSD1306");


Grafik İşlemleri

invertDisplay(bool i)

Parametresi true ise ekrandaki açık olan pikselleri kapalı, kapalı olan pikselleri açık duruma getirir, false ise eski haline döndürür:

display.invertDisplay(true);

dim(bool dim)

Parametresi true ise ekranın daha az parlaklıkla çalışmasını sağlar, false ise, tam parlaklık durumudur, varsayılan olarak ekran tam parlaklık modunda çalışır.

display.dim(true);

drawPixel(int16_t x, int16_t y, uint16_t color)

Ekran üzerinde sadece bir pikseli açmak kapatmak ya da inverse etmek için kullanılır :

display.drawPixel(5,5,1);

5,5 koordinatındaki pikseli 1 ile açabiliriz, bunun yerine SSD1306_WHITE tanımlaması da kullanılabilir.

drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)

Ekran üzerinde yatay bir çizgi çizmenizi sağlar, x parametresi hangi x pikselinden başlayacağınızı, y hangi y satırını kullanacağınızı, w parametresi kaç piksel uzunluk istediğinizi, color parametresi rengi belirmenizi sağlar:

display.drawFastHLine(5,31,123,SSD1306_WHITE);

5. x pikselinden başlayan 31. numaralı yatay satırda, 123 piksel genişliğinde bir çizgi çizer.

drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)

Ekran üzerinde dikey bir çizgi çizmenizi sağlar, x parametresi çizginin olacağı piksel sütununu, y parametresi hangi y pikselinden başlayacağınızı, h parametresi kaç piksel yükseklik istediğinizi, color parametresi rengi belirler.

display.drawFastVLine(2,0,32,SSD1306_WHITE);

2. kolonda 0. cı y pikselinden başlayan 32 piksel yüksekliğinde beyaz renkli bir çizgi çizer.

startscrollright(uint8_t start, uint8_t stop)

Ekranının tamamını ya da bir bölümünü sağa doğru kaydırmanızı sağlar. start ilk satırı stop son satırı ifade eder, satır demişken 8 piksel yüksekliğinde bir bloktan bahsediyoruz, ekranın yukardan aşağıya doğru 4 e bölündüğünü düşünebilirsiniz, 0,0 en üstteki 1,1 bir altındakini 2,2 alttan ikinciyi, 3,3 de en alttaki satırı sağa kaydırır: 

display.startscrollright(2,2);

ekranın 16. pikselinden başlayıp 23. pixeline kadar uzanan bloğu sağa kaydırır. Aynı mantıkla :

display.startscrollleft(3,3);

de en sondaki satırı sola doğru kaydırıyor, hem sağa hem sola farklı satırları da olsa kaydıramıyoruz. kaydırmayı sonlandırmak için :

display.stopscroll();

fonksiyonunu çağırmamız yeterli.



Şimdilik herkese kolay gelsin.



Arduino Hareket Sensörü Kullanımı | PIR Sensör Örnek Kod

 Arduino ile Hareket Sensörü (PIR Sensör) Kullanımı

    HC-Sr501 sensörü kullanacağımız bu uygulamada sensörün Arduino Uno 'ya bağlanmasını ve basit bir kod ile nasıl çalıştırılabildiğine bakıyor olacağız. Sensörün nasıl çalıştığını özelliklerini ya da modifikasyonlarını merak ediyorsanız sensörü detaylıca yazdığım : Hc-SR501  Sensör İncelemesi konusuna bakıp gelebilirsiniz.
    Bu sensörü basitçe bir anahtar (switch) gibi düşünebilirsiniz, tek yaptığı şey bir hareket algıladığında sinyal pini üzerinden 5v vermesidir.

Arduino PIR sensör bağlantısı


    Görselde gördüğünüz bağlantıyı yapmanız yeterli, ben sinyal pinini Arduino 'nun ikinci pinine bağladım, siz dilediğiniz herhangi boş bir pine bağlayabilirsiniz, 1 ve 0 pinlerinden birini tercih etmenizi önermem, seri iletişim için o pinler kullanılıyor zira.


Kod kısmına gelecek olursak o da gayet basitçe şu şekilde olacak

// C++ code
//
#define MOTION 2
void setup()
{
  pinMode(MOTION, INPUT);
  Serial.begin(115200);
}

void loop()
{
  if(digitalRead(MOTION))
  {
    Serial.println("Motion Detected!");
  }
}


    Burada Arduino 'nun yapacağı iş; sensör bir hareket algıladığında seri ekrana seri bir şekilde "Motion Detected!" yazacak. Sanki başka hiç işimiz yokmuş gibi :) Tamam başka işlerimiz de olabilir, örneğin hareket algılandığında alarm çalabiliriz buzzer kullanarak, ya da bir ikaz lambası da yakabiliriz aynı zamanda, ya da yanan sönen lambalar kullanabiliriz, örnekler çoğaltılabilir. Bu yapmayı hayal ettiğimiz herşeyi if bloğunun içine yazarsak işimizi görür, ancak şöyle bir durum var, hareketin algılanması tek bir durumdur, dolayısıyla hareket algılandığında tek bir işler serisi yapmak isteriz. Eğer yukarıdaki kodu kullanacak olursanız, nasıl ki seri ekrana seri şekilde defalarca ( bu aslında sensörün hareket algıladığı andan sonra sinyal pinini ne süreyle HIGH seviyede tuttuğuyla alakalı ) "Motion Detected!" yazıyorsa, oradaki tüm işleri de sinyal kesilene kadar yapacak demektir.


    Peki ne yapalım, kesme kullanabiliriz, kesme tetikleyicisi olarak da RISING seçersek yani yükselen kenarda tetiklensin, bu durumda sadece bir kez istediğimiz tüm fonksiyonları çalıştırabiliriz :

// C++ code
//
#define MOTION 2
void setup()
{
  pinMode(MOTION, INPUT);
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(MOTION), MotionRoutine, RISING);
}

void loop()
{
 
}
void MotionRoutine()
{
 Serial.println("Motion Detected!");  
 playAlarm();
 FlashLeds();
 doOtherStaff();
}
void playAlarm()
{
  // play Alarm code
}
void FlashLeds()
{
  //Flash Leds code
}
void doOtherStaff()
{
  // do sth 
}

    Yukarıdaki kod ile sadece bir defa MotionRoutine fonksiyonu yürütülür. Diğer fonksiyonları dilediğiniz işler için kullanabilirsiniz. Interrupt konusunda henüz birşeyler yazmadım ancak kısaca bahsedelim; bu noktada artık dilediğiniz pini kullanabilirsiniz lüksüne sahip değilsiniz, arduino uno için yalnızca 2 ve 3 numaralı pinlerin kesme özelliği var, yani ya 2 ya 3 başka şansınız yok.
    
Kesme için diğer seçenekler de :
  • FALLING : hareket bittiğinde yürütülür.
  • HIGH : ilk örnekle aynı şekilde HIGH iken peşpeşe yürütülür.
  • LOW : hareket bittikten sonre bir sonraki harekete kadar peşpeşe yürütülür.
  • CHANGE : lazım olur mu bilmem ama 5 iken 0 olursa, ya da 0 iken 5 olursa bir kez yürütülür.
Eğer olur da sensörünüz düzgün çalışmazsa hareket algılanmadığında da fonksiyonlarını çalışıyorsa mesela; sensörün sinyal pininden arduino GND 'ye 1k 'lık bir direnç bağlarsanız bu sorunu yaşamazsını diye ümid ediyorum, Bir dikkat etmeniz gereken şey de, sensörün düzgün çalışmaya başlaması çalışmaya başladığı andan sonra bie dakikayı buluyor olması, bunu da aklınızda bulundurun derim.

Tinkercad simulasyonu :



Herkese kolay gelsin!


Arduino ile Yüksek Voltaj Ölçme | SMPS DC Bara Ölçümü

    Arduino ile 5v 'tan daha yüksek bir voltajı ölçmek için; ya da herhangi bir mikro denetleyici için analog referans değerinin üzerindeki bir gerilimi ölçmek istediğimizde linkteki yazıda anlattığım gerilim bölücüleri kullanırız. Henüz okumadıysanız, okuyup buraya geri dönmenizi tavsiye ederim. Örnek olsun diye 9V 'luk bir pili ölçmeye çalışalım, bu aynı zamanda en fazla 9V dc çıkışı olan farklı bir kaynak da olabilir.

Arduino ile daha yüksek voltaj ölçme



    Burada teorik olarak yaptığımız şey en fazla 5v olan arduino ölçme kapasitesini 9V a çıkartmaktır. Dirençleri seçerken GND 'ye bağlı olan 5 in kaç katıysa (4) kaynağın + sına bağlı olan direncin de 4'ün o katı olduğuna dikkat edin.. Toplamda dirençlerimizin GND ve arduino analog pin arasında olan üzerinde 5V diğer direnç üzerinde de 4v olmasını istiyoruz, 12V ölçüyor olsaydık ikinci direnç 4'ün değil 7'nin 4 katı olacaktı, 9 da 4, 12 'de 7 nerden geldi? Kaynak voltajı - 5v (arduino adc max) 'tan geldi. Basitçe üstteki direnç 5x, alttaki direnç 4x olmalı, 9v 'luk bir kaynak için. Bulunabilirliği göz önüne alarak 20 ve 16 yı seçmiş bulunduk.


Arduino ile voltaj okuma konusunu okumadıysanız, şimdi okumanın tam zamanı. Gelelim oradan ne farkımız var noktasına, artık ADC 'den okuduğumuz veriyi 5v üzerinden değil, gerilim bölücünün çarpanı üzerinden değerlendirmemiz gerekiyor, gerilim bölücü en basit haliyle; kaynaktaki voltaj değerini bir şeye ('x') bölmüş ve A0 noktasındaki gerilimi elde etmiş. Bizim örneğimiz için şöyle olacak:

    9V / x = 5V    => 9v/5v = x    => x = 1.8 

biz de tam tersi yol izleyerek yani ADC den okuduğumuz voltaj değerini bu çarpan ile çarparak kaynak voltajına ulaşmış olacağız. Başka türlü hesaplanabilir miydi? 

    (R1 + R 2) / R2  (R2 gnd ye bağlı olan direnç)
    (20 + 16) / 20    => 1.8

yani maksimum direncin "toplam direnç" R2 ye oranıyla, maksimum gerilimin orta ucta oluşan ADC gerilimine oranı aynı. Koda bakacak olursak, işin matematiği dışında değişen bir şey yok :

// C++ code
//
void setup()
{
 Serial.begin(115200);
}

void loop()
{
  int ADC_Value = analogRead(A0);
  float vOnDivider = ADC_Value * 5.0 /1023;
  Serial.print(vOnDivider);
  float vOnSource = vOnDivider *1.8f;
  Serial.print(" ");
  Serial.println(vOnSource);
}

aslına bakarsanız ölçeceğimiz maksimum gerilimi 1023 e bölüp devam etsek de olurdu. Dikkat ederseniz, vOnDivider değerini yani 5 'i 1.8 le çarpıyoruz o da 9 ediyor 😁


Haydi biraz yükselip bir SMPS devresinde giriş voltajı olan 220v AC den doğrultularak elde edilmiş DC Bara denen voltajı ölçmek istiyor olalım; 220v * √(2) = 312V DC ölçeceğiz yani, bu durumda R2 miz 5x ken R1 'imizin de 312-5 'ten 307x olması lazım. Bu noktada voltaj yükseldiği için devrenin güç değerlerini de işin içine katmak gerekecek. Önce ne direnç kullanabiliriz ona bakalım, 307 k direnç arasak bulur muyuz, bulabiliriz belki ama, 307 bizim için alt limit, bu da ne demek 220v olaki yükselirse, bizim A0 da 5v u geçecektir o yüzden daha yüksek bir direnç kullanmak daha güvenli olacaktır. Maksimumda kaça kadar çıkabilsin noktasını düşünürsek 250v AC için 354v dc demek, 355 diyelim düz hesapla; 5x e 350x kullanabiliriz, yani 5k kullanacaksak diğerini 350k k kullanmamız gerekecek.
Devreden geçen akımı hesaplayalım :

I = V / Rtop    => 355V / 355K  = 1mA

350K direnç üzerinde 350V oluşacak, gücü hesaplarsak;

P = I * V    => 0.001 * 350 = 0.350w 

burada bir sıkıntı var,  nedir? piyasadan alacağımız dirençler 1/4w yani 0.25w, biz bu direnç için 0.350w harcar diyoruz, yani bizim dirence elveda bu noktada; ne yapmalıyız, ya daha yüksek güçlü bir direnç almalıyız ya da direnç sayısını artırarak dirençlerin güç tüketimlerini de dağıtabiliriz, 350K yerine iki tane 175K seri kullansak; direnç başına 0.175w güç tüketimi söz konusu olacak bu işimize yarar, ya da K lardan çıkıp M lere geçeceğiz ki devrenin akımı daha da düşsün, R2 yi 20 K 'ya çıkartalım, bu durumda R1 in de 345*4 'ten 1380K olması lazım, olmadı, olabilen ne var 1.5M ohm olabilir. Bu durumda toplam direncimiz 1520k oldu, orta noktada 5v maksimum için artık kaynakta 380V a kadar ölçüm yapabiliyor olacağız. Güç değerimiz kurtarıyor mu peki?

devre akımı; 380V/ 1520K = 250µA
1.5M direnç için güç tüketimi : "380-5" => 375V*0.25mA = 0.093w.

 Umarım mevzu net olarak anlaşılmıştır, dirençlerle alakalı daha fazla detay isterseniz Direnç Parametreleri konusunu okumanızı öneririm, kafanıza takılan herhangi bir şeyi lütfen yorumlarda sormaktan çekinmeyin!

Herkese kolay gelsin!


HC-SR501 PIR Sensör İncelemesi ve Modifikasyonlar

 HC-SR501 PIR Sensör

    Arduino ve diğer gömülü sistemler uygulamaları ile hareket algılamak için tasarlanmış olan HC SR501 PIR Motion Sensör 'ün özelliklerine ve çalışma prensibine kısaca bakıyor olacağız.

PIR Ne demek?

PIR: Passive InfraRed, kelimelerinin baş harfleri alınarak oluşturulmuş bir kısaltma olarak karşımıza çıkıyor. Çoğunlukla alarm devrelerinde kullanılan PIR sensörleri, bina girişlerinde, ara katlarda ya da umumi WC lerde başımıza kısa yanma süresiyle bela olan, hareket algıladığında yanan lamba devrelerinde de görmek mümkün. 

hc sr501 PIR sensör

HC-SR501 Hareket Sensörünün Özellikleri

  • Çalışma Voltajı : 5V - 20V (aldığınız ürünün bilgi sayfasını kontrol edin, üzerinde 3.3V 'luk voltaj regülatörü var, bu aralık biraz daha aşılabilir ancak 12V 'u geçmemenizi tavsiye ederim, regülatör için giriş-çıkış arasındaki fark regülatör üzerinde ısıya dönüşür.)
  • Akım sarfiyatı : 65mA maksimum (5v ile kullanınca µA seviyelerinde)
  • TTL çıkışı : 3.3V (5V mikro denetleyiciler için de HIGH olarak kabul edilir)
  • Gecikme Süresi : ayarlanabilir 5 - 300 saniye (ilk bir dakika geçerli değil)
  • Tetikleme Metodu: tekli ya da çoklu olarak seçilebilir.
  • Algılama aralığı 7 metre içerisinde 120° 'den az.
  • Çalışma sıcaklığı  -15 ~ +70 °C
Sensörün düzgün çalışmaya başlaması bir dakikayı buluyor, bu süre içerisinde yapacağınız testlerde çıkış seviyesinin süresi 0-3 saniye aralığında olabilir bozuk olduğunu düşünmeyin bu tamamen normal.

Single Trigger Repeating Trigger Arasındaki Fark

Üzerinde bulunan jumper ile çıkış seviyesini tekrarlanabilir ya da tekli hale getirebiliyorsunuz. Bu ne demek; diyelim ki hareket sensörümüzü 20 saniye açık olacak şekilde ayarladık, hareketi aldığında 20 saniye boyunca açık kalır ve bu süre içerisindeki yeni hareket algılamaları sensörü etkilemez, 20 saniye bittiğinde kapalı konuma geçer ve yeni hareket bekliyor olur. Repeating Trigger Modda ise açık kaldığı 20 saniye içerisinde yeni bir hareket algılarsa, yeni bir 20 saniye başlatır. Ayarlanmasına gelince, ilk görselde bulunan sarı jumper, orta ve dış pine bağlı olduğunda tekrarlama modu iç tarafa ve orta pine bağlıysa tekli moda ayarlanmış oluyor.

hc-sr501 single ve repeating trigger



HC SR501 Devre Şeması

HC-SR501 Sensör Devre Şeması




HC SR501 Sensöre LDR Bağlanması

hc-sr501 ldr termistör bağlama
    Soldaki resim üzerinde pin headerların hemen arkasında bulunan morla kare içerisine aldığım alana (RL) ile referans verilmiş ancak elinizdekinde yazmıyor da olabilir, LDR, kırmızıyla işaretlediğim alana da termistör bağlanabiliyor.

Sensörü aydınlatma amacıyla kullanacaksak, ortam ışığını ölçüp ortam ışık yakmak için aydınlıksa ışığı yakmasını engelleyebiliriz. Bunun için sensörün devresi üzerinde LDR bağlamak için bir alan bırakılmış. Şemada gördüğünüz CDS2 referansıyla yer alan eleman bord üzerinde takılı değil ancak kendimiz bu özelliği kullanmak istiyorsak, bord üzerinde bırakılmış bu alana LDR bağlayarak bu özelliği elde edebiliyoruz. Gördüğünüz gibi eleman bir ucu GND 'ye diğer ucu BISS0001 entegresinin 9 nolu bacağına gidiyor, bu bacak aynı zamanda 1Mohm 'luk bir dirençle (R3) VDD 'ye gidiyor. Burada anladığımız LDR ile 1Mohm 'luk direnç, direnç bölücü olarak kullanılacak. Entegrenin datasheet ine baktığımız zaman 9 nolu bacağın (VC) Trigger disable input pini olduğunu görüyoruz, ve şöyle bir özellik verilmiş: ( VC > 0.2VDD = enable, Vc<0.2Vdd = disabled). Burdan ne anlıyoruz, Vdd 'miz 3,3V, 
3,3 * 0.2 = 0,66v 'dan daha düşük bir voltajı 9 pinde sağlarsak triggerimiz disable olur. Bunu Sağlamak için de en yüksek 250K lık bir direnç değeri elde etmeliyiz, Nasıl hesapladık : Direnç İle Voltaj Bölücü Devreleri ve Hesaplamaları konusunu okuyabilirsiniz. Şimdi bize ışığın yanmasını istemediğimiz aydıklık seviyesinde değeri 250K 'yı geçmeyen, bir LDR lazım, LDR parametrelerini incelediğimiz zaman 10 Lux başına direnç değeri 100 Lux başıne direnç değeri 1 saniyedeki karanlık resistansı ya da 5 saniyedeki karanlık resistansı gibi değerler görürüz. Bu dark resistance değerleri genellikle 1 Mohm a yakın ya da daha yüksek değerlerdedir, devremizde de 1Mohm 'luk ortak direncimiz olduğu için hemen hemen bir çok LDR buraya uyum sağlayabilir. Aslında gün ışığının 30000 lux ile 130000 lux arasında olduğu kabulünden yola çıkarsak tam uygun olabilecek LDR yi hesaplamak da mümkündür, Bunları LDR konusunu detaylıca yazdığımızda anlatıyor oluruz. Ancak burada bu detayda bir hesaplamaya gerek kalmıyor.

    Oldu ki elinizdeki "herhangi bir LDR" devrenize uyum sağlamadı farklı seviyelerde yanıyor sönüyor falan, bu durumda devre üzerindeki R3 ü söküp yerine bir potansiyometre takarak, ışık şiddettini LDR ye bağlı olmaktan çıkartıp pota bağlı hale getirebilir ve oradan ayarlama yapabilirsiniz.

Gökhan Ünal'ın yorumlarda eklediği modifikasyon :
Hc-sr501 ldr



Türksat Saat Kanalı ve IRIG-B Time Code

Türksat Saat Kanalından Saat Bilgisi Nasıl Alınır? Uyduda kanalları dolaşırken, şu Türksat Saat kanalı hep dikkatimi çekmiştir. Özellikle  S...