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 
Ses tonundan saat bilgisi iletilmektedir. Receiver ses çıkışı IRIG-B uyumlu saatlere bağlandığında, saat bilgisi otomatik olarak güncellenmektedir
ifadesi beni cezbedip haydi şunu yapalım deyip durmuştur.

Türksat Saat Kanalı


Bu iş için biraz vakit bulduğumda oturup üzerinde çalışma fırsatım oldu, bu yazımda IRIG-B nedir, bir ses sinyalinden data olarak iletilen bir bilgiyi nasıl alabiliriz ona bakıyor olacağız.

Türksat Saat Kanal Frekansı

Türksat Saat kanalı bugün (30.04.2023) tarihi ile turksatın resmi web sitesinde yer alan frekans listesinde şu bilgilerle yer almakta :
  • Frequency: 11916
  • Polarisation: Vertical (Dikay)
  • Symbol Rate : 30000
  • FEC 3/4

Türksat Saat Kanalının Ses Çıkış Sinyali

Televizyonda Türksat Saat kanalı açıkken, televizyonun kulaklık çıkışından, bir stereo audio jack (3,5mm) ile biri GND biri canlı uçlardan biri olmak üzere iki kablo çıkartıp televizyonun sesini sonuna kadar açıp osiloskopa bağladığımda karşılaştığım sinyal görseldeki gibi oldu:

Türksat Saat Kanalının Ses Çıkış Sinyali

Sinyal üzerinde benim ilk bakışta tespit edebildiğim özellikler şu şekilde:
  • Sinyal 1Khz'lik taşıyıcı sinyale sahip, her sinüsün tamamlanma süresi 1ms.
  • Tüm sinyal boyunca yalnızca iki tip Amplitude mevcut; birincisi -7v ile 7v arasında salınıyor, ikincisi -3v ile 3v arasında salınıyor.
  • Her iki, ilk yüksek sinyal arasında 10 sinus var
  • Bu onlu grup içinde yükseklerin sayısı ya 2 ya 5 ya da 8

IRIG-B Nedir?

IRIG-B, zaman bilgisinin ses sinyali üzerinden aktarımını sağlayan bir iletişim protokolüdür. İlk defa ABD Ordusu menzil komutanları(RCC) 'nın bir parçası olan Inter-Range Intrumentation Group (IRIG) tarafından geliştirilmiştir. Bir kaç revizeden sonra en son standart halini Eylül 2004 'te almıştır : IRIG Standard 200-04.
IRIG için IRIG-A, IRIG-D,IRIG-E,IRIG-G ve IRIG-H gibi formatlar da mevcuttur, ancak konumuz Türksat saat kanalı olduğundan yazının ilgilisi IRIG-B formatıdır. Pulse Rate' i ya da Bit Rate 'i 100 PPS 'dir(pulse per second). Index count interval değeri 10ms. Her index count, yani her 10 sinüs bir bilgi içeriyor olacak. Sonuç olarak her saniyede 100 bit bir veri bloğu (frame) elde etmiş olacağız.

IRIG-B verilerin anlamlandırılması

IRIG-B verilerin anlamlandırılması

Sinyal içerisindeki her 10 sinüs bir index count'u her index count da anlam verebileceğimiz bir bit lik veriye dönüşüyor. Formatın anlatıldığı dökümandan aldığım yukarıdaki görselde, bu index count için 8 sinüs yüksekse, ya da index count 'ın doluluk oranı olarak değerlendirirsek veriler şu şekilde olacak:
  • %80 Referans (8 sinüs yüksek 2 sinüs düşük)
  • %50 True, (High, 1 ne derseniz artık) (5 yüksek, 5 düşük)
  • %20 False, (Low ya da 0) (2 yüksek, 8 düşük)


IRIG-B Veri Bloğunun Formatı

Bu noktada referans dediğimiz bilgi veri blokları arasındaki ayraç olarak kullanılmış, ayrıca iki referans peş peşe gelmişse bu frame'in başladığını bildiriyor, Tüm frame için yapı şu şekilde olacak:

IRIG-B Time frame format

İlk iki bir referans olarak belirlenmiş, yani frame başlıyor,
sonraki 8 bit saniye bilgisi, sekiz bitin tamamında hangi bitler 1 gelmişse o bitlerin üzerindeki sayı değerlerini topluyoruz, görsel için konuşacak olursak: 2 ve 40 değerlikli bitler true gelmiş, 40+2 den saniyenin 42 olduğunu anlıyoruz, P1 isimli referans ile saniye bilgisi bitti, dakika bilgisine geçiyoruz, o da aynı şekilde true gelen bitlerin üzerindeki değerleri topluyoruz : 8 ile 10 true gelmiş yani dakikamız 8+10 = 18, sonra P2 ile dakika bilgisi bitiyor ve saat bilgisine geçiyoruz. saat için de 1 ve 20 değeri true gelmiş, yani sonuç olarak saat bilgimiz 21:18:42. Sonrasına da aynı mantıkla devam edebilirsiniz, biz sadece saati alacağımız için burada kalıyorum ben.


Standard ile ilgili dökümanın indirme linki:




Arduino BMP280 Basınç ve Sıcaklık Sensörü Kullanımı | HW-611 E/P 280

Arduino ile BMP280 basınç ve sıcaklık sensörünün bağlantısına, nasıl kullanıldığına ve örnek koduna bakıyor olacağız bu yazıda. Atmosferik basıncı ölçebilen bu minik dostumuz, basıncın yüksekliğe bağlı bir değişken olması sebebiyle yaklaşık (deniz seviyesinden) yüksekliği de ölçtüğünü hatta kendimizi biraz zorlarsak, dikey hızı bile ölçebileceğimizi söyleyebilirim.

bmp280 basınç ve sıcaklık sensör bordu

Yukarıdaki görsele göre konuşacak olursak, BMP280 pin isimleri yukarıdan aşağıya şu şekilde; 

  • SDD, -öyle yazıyor aslında SDO olmalı gibi geldi bana,
  • CSB
  • SDA I2C Data Hattı  Arduino SDA pinine, ya da A5 pinine
  • SCL I2C Clock Hattı Arduino SCL pinine , ya da A4 pinine
  • GND Ground Arduino GND pinlerinden herhangi birine
  • VCC Power Arduino 5V pinine bağlanacak.

BMP280 I2C ile Kullanımı

Bu sensör için değişik firmaların değişik formatlarda ürettiği kartlar mevcut, bendeki görseldekinin aynısı dolayısıyla ona göre yazıyor olacağım. Sensörün I2C adresinin donanımsal olarak belirlenmesi, SDD pininin dijital seviyesine bağlanmış vaziyette. SDD pini pull-up yapılmışsa, yani bir direnç ile VCC 'ye bağlanmışsa BMP280 I2C adresi 0x77 oluyor, pull-down yapılmışsa 0x76 oluyor. Dikkat etmeniz gereken ilk husus kartınızda donanımsal olarak I2c adresinin ne seçildiğine bakmaktır. 

Arduino i2c scanner ile i2c adres tespiti

Donanıma bakmasak ne olur, adresi bulamaz mıyız, tabii ki bulabiliriz, bağlantıları yapın, Arduino 'yu bilgisayara bağlayıp Arduino IDE 'den Dosya*Örnekler*Wire->i2c_scanner örneğini açın ve karta yükleyin. Serial Monitör 'ü açıp bakın, baud rate i 9600 e ayarlamayı unutmayın. Şöyle bir sonuç görüyor olmanız gerekiyor:

Scanning...
I2C device found at address 0x76  !
done

Bu durumda sensörümüz çalışıyor ve i2c adresi 0x76 'dır durumundan emin olabiliriz.

BMP280 Adafruit Kütüphanesinin Yüklenmesi

Arduino IDE 'de Araçlar menüsünden Kütüphaneleri Yönet seçeneğinden library manager 'a ulaşıyoruz. Arama barına BMP280 yazıp Adafruit 'in adının geçtiği -muhtemelen en üstte çıkar- kütüphaneyi yüklüyoruz.

BMP280 sensör test

Test için Arduino IDE Dosya*Örnekler*Adafruit BMP280->Bmp280test i seçiyoruz. Karşımıza çıkan kodu karta yükleyip Seri Monitore bakıyoruz (baud:9600). Herşey yolunda giderse sensörün bize sıcaklık hava basıncı ve tahmini yükseklik verilerini yazdırıyor olması gerekiyor, bu verileri görüyorsanız başardınız demektir. Görmüyorsanız ve sizi şöyle bir metin karşılamışsa :

BMP280 test
Could not find a valid BMP280 sensor, check wiring or try a different address!
SensorID was: 0x0
        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085
   ID of 0x56-0x58 represents a BMP 280,
        ID of 0x60 represents a BME 280.
        ID of 0x61 represents a BME 680.

yapmanız gereken şey : 
  status = bmp.begin();

satırını
  status = bmp.begin(0x76);

olarak değiştirmektir. ve bingo verilerimiz şu şekilde gelir :

BMP280 test
Temperature = 30.41 *C
Pressure = 99853.34 Pa
Approx altitude = 123.25 m

Eğer her iki durumda da sensörden veri alamıyorsanız sensörünüz çalışmıyor olabilir, tabii başka bir konu daha var: Eğer ki seri monitörde 
SensorID was: kısmından sonra bir değer görüyorsanız, sensörünüz BMP 280 değil demek oluyor, peki ne olabilir sensörünüz :
SensorID was: 0XFF  , adresiniz yanlış olabilir, ya da BMP180 BMP085 sensörlerinde biri var elinizde
SensorID was: 0X60 sensörünüz BME 280, bu sensör için de adafruit library si mevcut aynı yolları izleyerek sonuca ulaşabilirsiniz.
SensorID was: 0X61 sensörünüz BME680

Fonksiyonlara kısaca bakacak olursak :
    Serial.print(bmp.readTemperature());

Bizlere sıcaklık değerini döndürüyor,
    Serial.print(bmp.readPressure());

atmosferik hava basıncını döndürüyor,
    Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */

deniz seviyesinden olan yüksekliğinizi döndürüyor, artık bu verilerle ne yapacağınız sizin projenize ya da amacınıza bağlı, bir ekrana basabilir, nodemcu ile bir apiye gönderebilir vs gibi bir çok şey yapabilirsiniz.
Konuyu elimden geldiğince detaylıca yazmaya çalıştım, yine de içinden çıkamadığınız herhangi bir şey olursa yorumlarda sorabilirsiniz.
Herkese kolay gelsin!

Nodemcu Namaz Vakitlerini Çekme | namaz vakitleri api

 Nodemcu (esp8266) ile İnternetten Namaz Vakitlerini Çekme

Nodemcu ile nesnelerin interneti projelerinde yeni bir yazıdan herkese merhaba, İnternetten namaz vakitlerini çekebileceğimiz bir api servisi mevcut, biraz uğraştırıcı oldu ama api'yi nodemcu 'ya da çalıştırabildim. Uğraştırıcı olmasının nedeni api 'yi kullanırken bir cookie set etmek gerekiyor olması, neyseki bu sayede nodemcu ile cookie kullanımına da bir örnek niteliğinde olacak bu yazı.

    Servisimiz https://www.namazvakitleri.site adresinde yer alıyor, web sitesine girdiğinizde footer (web sitenin en alt kısmında yer alan link barı) linklerinden web api sayfasına ulaşabilirsiniz. Kısa bir kayıt işleminden sonra api-key'imiz mail adresimize ulaşıyor ve hemen kullanmaya başlayabiliyoruz.


Namazvakitleri api de iki tane servis mevcut biri, Türkiye iller listesini veren api servisi, ihtiyacınız olursa onu da kullanabilirsiniz, diğeri de api parametreleriyle belirlenen ile ait sorgunun yapıldığı gün tarihli ezan vakitlerini döndüren api servisi. Sonuçlar json formatında dönüyor, yani yine projemizde Arduino_json kütüphanesini kullanıyor olacağız. Ayrıca websitesinde slowAES koruması olduğu için test cookie bypass için slowAES kütüphanesini Arduino library manager ile indirmeniz gerekiyor.

Eğer servise kayıt olup api-key 'inizi aldıysanız devam edelim, apiyi browserda test edip api-key 'imizin çalıştığından emin oluyoruz, sitede belirtildiğine göre izlenmesi gereken url şu şekilde olmalı :

http://www.namazvakitleri.site/api/api.php?api=vakitler&il=istanbul&api-key=apikeyiniz

apikeyiniz ifadesini epostayla size ulaşan api-key ile değiştirin, görmeniz gereken sonuç şu şekilde :

{"imsak":"06:50:00","gunes":"08:21:00","ogle":"13:17:00","ikindi":"15:41:00","aksam":"18:03:00","yatsi":"19:28:00","tarih":"2023-01-13","iladienqs":"istanbul","activeTimeIndex":6}
İl isimlerini girerken türkçe karakter kullanmadan küçük harflerle yazmak gerekiyor, mesela Ağrı için agri, Afyon, afyonkarahisar, kahramanmaras, balikesir gibi..ActiveTimeIndex değeri sunucu saatine göre -Türkiye saatine ayarlanmış- sorgunun yapıldığı anda hangi vakit içerisindeyiz onun sayısal değerini veriyor; imsak için 1, yatsi için 6 değeri geliyor.


Koda gelecek olursak şu şekilde olacak : 

/**
 * @file infinityFree.ino
 * @author Hakan ÖZMEN (hakkanr@gmail.com)
 * @brief
 * the website given this example is hosted on InfinityFree Servers
 * You can use this example any of website hosted on InfinityFree.
 * This example get praytimes for Turkey/Istanbul city,
 * 
 * You should get an apikey from web site by registering apikey form:
 * http://www.namazvakitleri.site/api/apireg.php
 * 
 * when you've got an e-mail which contains your api key, put your
 * apiKey below. For more details about using api please visit :
 * http://www.namazvakitleri.site/api/index.php
 * 
 * @version 1.0.0
 * @date 2023-02-05
 *
 * @section for more information please visit :
 * https://www.devrelerim.com/2023/01/nodemcu-namaz-vakitlerini-cekme.html
 * https://www.youtube.com/HakkanR
 * https://github.com/HakkanR/slowAES
 *
 * @copyright BDS License, all above text must be included any redistribution.
 *
 */
#include <Arduino.h>
#include <slowAES.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Arduino_JSON.h>
const char *ssid = "";		  // Wifi SSID
const char *pwd = ""; // Wifi password
String apiKey = ""; //apiKey
String web = "http://www.namazvakitleri.site/api/api.php?api=vakitler&api-key=" + apiKey + "&il=istanbul";
HTTPClient http;
WiFiClient wfc;

void setup()
{
	Serial.begin(115200);
	Serial.print(ssid);
	Serial.println(" connecting.");
	WiFi.begin(ssid, pwd);
	while (WiFi.status() != WL_CONNECTED)
	{
		Serial.print(".");
		delay(500);
	}
	Serial.println(" connected.");
	http.begin(wfc, web);

	int httpCode = http.GET();
	Serial.println(httpCode);
	String payload = http.getString();

	/* getting abc vars */
	int loc = payload.indexOf("var a=toNumbers(");
	String temp = payload.substring(loc, temp.length());
	temp.replace("var a=toNumbers(\"", "");
	String a = temp.substring(0, 32);

	temp.replace(a + "\"),b=toNumbers(\"", "");
	String b = temp.substring(0, 32);

	temp.replace(b + "\"),c=toNumbers(\"", "");
	String c = temp.substring(0, 32);

	uint8_t aNums[16];
	uint8_t bNums[16];
	uint8_t cNums[16];

	toNumbers(a.c_str(), aNums);
	toNumbers(b.c_str(), bNums);
	toNumbers(c.c_str(), cNums);

	uint8_t finalCookie[33];
	slowAES _slowAES;
	uint8_t resNums[16];
	_slowAES.decrypt(cNums, aNums, bNums, resNums);
	toHex(resNums, finalCookie);
	String str = (char *)finalCookie;

	web = web + "&i=1";
	Serial.println(web);
	http.begin(wfc, web);
	String fullCookieStr = "__test=" + str;
	http.addHeader("Cookie", fullCookieStr, true);
	http.addHeader("Host", "www.namazvakitleri.site", true);
	http.addHeader("Connection", "Keep-Alive", true);

	httpCode = http.GET();
	Serial.println(httpCode);
	payload = http.getString();
	Serial.println(payload);
	// and parse the JSON
 JSONVar jsonData = JSON.parse(payload);
  if (JSON.typeof(jsonData) == "undefined")
  {
    Serial.println("Json data ayıklanamadı.");
    return;
  }
  String imsak = (const char*)(jsonData["imsak"]);
  String gunes = (const char*)(jsonData["gunes"]);
  String ogle = (const char*)(jsonData["ogle"]);
  String ikindi = (const char*)(jsonData["ikindi"]);
  String aksam = (const char*)(jsonData["aksam"]);
  String yatsi = (const char*)(jsonData["yatsi"]);
  Serial.print("imsak : "); Serial.println(imsak);
  Serial.print("gunes : "); Serial.println(gunes);
  Serial.print("ogle : "); Serial.println(ogle);
  Serial.print("ikindi : "); Serial.println(ikindi);
  Serial.print("aksam : "); Serial.println(aksam);
  Serial.print("yatsi : "); Serial.println(yatsi);
  delay(1000000);
}

void loop()
{
	// nothing goes here!
}


Kafanıza takılan herhangi bir şeyi yorumlarda sorabilirsiniz, herkese kolay gelsin.


NodeMcu Internetten veri çekme | Hava Durumu openweather.org api

 Esp8266 Api ile Hava Durumunu Çekme

    Nodemcu (esp8266) ile openweathermap.org 'un sağlamış olduğu api hizmeti ile illerin hava durumlarını nasıl çekebiliriz ona bakıyor olacağız. Daha önce youtube kanalımda bu konuyla alakalı bir video çekmiştim yazının sonuna video eklerim dileyenler videolu anlatımı da takip edebilirler.
    openweather.org sitesine api-key için kaydolmanız gerekiyor. Kayıt işleminden sonra sisteme giriş yapıp Api-Keys menusunden yeni api-key'inizi oluşturabilirsiniz. Api-key 'iniz oluştuktan sonra bir web browser ile api-key'inizi test etmenizi öneririm çünkü aktif olması bazen 24 saati bulabiliyor. Web browser ile api-key'iniz ile veri çekebiliyorsanız keyiniz aktif olmuş ve kullanıma hazır demektir. Test etmek için aşağıda verdiğim url 'yi kullanabilirsiniz :

http://api.openweathermap.org/data/2.5/weather?units=metric&q=istanbul&appid=apikeyiniz

apikeyiniz ifadesi yerine api-key'inizi yazmanız gerekiyor. Eğer key aktif olmuşsa görmeniz gereken sonuç şu şekilde olacaktır :

{"coord":{"lon":28.9833,"lat":41.0351},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"base":"stations","main":{"temp":8.73,"feels_like":5.25,"temp_min":7.81,"temp_max":9.09,"pressure":1018,"humidity":87},"visibility":10000,"wind":{"speed":7.2,"deg":350},"clouds":{"all":100},"dt":1673541249,"sys":{"type":1,"id":6970,"country":"TR","sunrise":1673501281,"sunset":1673535355},"timezone":10800,"id":745042,"name":"Istanbul","cod":200}

Api 'nin veri dönüş tipi json 'dur. Bilmeyenler için kısaca yazmış olalım; 

Json Nedir?

JSON, JavaScript Object Notation 'ın kısaltılmış hali olup, basit veri yapılarını temsil etmek için tasarlanmış bağımsız bir veri değişim formatıdır. Apilerden elde edilen veriler genellikle json, xml gibi standartlaştırılmış veri tipleri olarak döner, Bir gömülü sistem mühendisi olarak bu tipe asla ihtiyaç duymayız ancak iş gömülü sistem ile dış dünyadan, internetten veya başka bir uygulamadan veri-alıp vermeye döndüğünde bu yapıları da bilmek gerekiyor.

Arduino ile json datayı ayıklamak için de bir kütüphanemiz mevcut, kod üzerinde projeye dahil ettiğim kütüphaneyi library manager ile yüklemeniz gerekiyor.


Kod şu şekilde olacak :
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Arduino_JSON.h>

const char* ssid = ""; // Wifi kullanıcı adını yazın
const char* pwd = ""; //Wifi parolanızı yazın
String city = "istanbul"; // hava bilgisini almak istediğiniz şehri yazın

String Apikey = ""; //openweathermap.org apikeyinizi girin
String owmWeb = "http://api.openweathermap.org/data/2.5/weather?units=metric&q=" + city + "&appid=" + Apikey;
void setup() {
  Serial.begin(115200);
  Serial.print(ssid);
  Serial.println(" bağlanıyor.");
  WiFi.begin(ssid, pwd);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println(" bağlandı.");
}

void loop() {
 String owmJson = getWebPage(owmWeb.c_str());
 JSONVar jsonData = JSON.parse(owmJson);
 if (JSON.typeof(jsonData) == "undefined")
 {
  Serial.println("Json data ayıklanamadı.");
  return;
 }
 Serial.print ("Şehir : ");
 Serial.println(city);
 Serial.print("Sıcaklık : ");
 double temp = (jsonData["main"]["temp"]);
 Serial.println(temp);
 Serial.print("Hissedilen : ");
 double feels_like = (jsonData["main"]["feels_like"]);
 Serial.println(feels_like);
 Serial.print("Nem : ");
 double humidity = (jsonData["main"]["humidity"]);
 Serial.println(humidity);
 Serial.print ("Rüzgar Hızı : ");
 double windSpeed = (jsonData["wind"]["speed"]);
 Serial.println(windSpeed);
 Serial.print("Rüzgar Yönü : ");
 double windDeg = (jsonData["wind"]["deg"]);
 Serial.println(windDeg);
 //weather altında bir nesneye ulaşmak için
 JSONVar whDescJ = (jsonData["weather"][0]["description"]);
 Serial.print("description");
 Serial.println(whDescJ);
 delay(5000);
}

String getWebPage(const char* address)
{
  WiFiClient wfc;
  HTTPClient http;
  http.begin(wfc,address);
  int httpCode = http.GET();
  Serial.println(httpCode);
  String payload = http.getString();
  return payload;
}


Nodemcu ile api kullanımında farklı ihtiyaçlarınız ya da çözemediğiniz apiler olursa yorumlarda yazabilirsiniz, vakit bulduğumda inceleyip yardımcı olmaya çalışırım.




Eğer videodaki kodu yazıp;

call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)

gibi bir hata alıyorsanız, getWebPage fonksiyonunu yukarıda yazıldığı gibi güncelleyin.

Herkese kolay gelsin!

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.




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...