C++ Dersleri | Bit İşlemleri | Bitwise XOR, Özel Veya Operatörü

 C++ bitwise Xor (exclusive or operator) operatörü ^ , diğer bit operatörleri gibi dijital elektronik xor yapısıyla aynıdır. Doğruluk tablosunu yine görselde paylaşalım :

xor truth table

kodlarken de aynı değişkenleri kullanalım:

int main()
{
	int a = 7;			//0111
	int b = 13;			//1101
	int aXORb = a ^ b;	        //1010
	cout << "a= " << a << ", b=" << b << ", a^b=" << aXORb;
}

çıktımız : a= 7, b=13, a^b=10

10 elde ettik, binary formatındaki sayıları alt alta yazarak soldan sağa doğru sütunları XOR işlemine tabi tutuyoruz en solda: 0 ^ 1 den 1 geldi, bir sonrakinden 1 ^ 1 den 0 geldi, bir sonrakinden : 1 ^ 0 dan 1 geldi, bir sonrakinden  1 ^ 1 den 0 geldi. Benim xor anlatırken akılda kalması için anlattığım bir hikaye var, patron sekreterine bana yalnızca bir kişi çağır demiştir. Kimse gelmezse patron bu işi sevmez. Ahmet gelirse patron için tamamdır, Mehmet gelirse de patron için tamamdır, İkisi de gelirse patron bunu sevmez, bana bir kişi lazım der. A ya da B önemi yok ama mutlaka biri lazımdır.

Hatırlatmış olayım : bu operatör bir değişkene eşitlenmediği sürece bir değişikliğe yol açmaz, ne demeye çalışıyorum şöyle örneklendirelim :

int main()
{
	int a = 7;
	a ^ 5;			
	cout << "a= " << a;
}

Bu kod ile a değişkeni hala 7 değerindedir, a yı 5 ile Xor işlemine tabi tutup a 'nın değerine eşitlersek :

a = a ^ 5;   ya da kısaca a ^ = 5; dersek, a yı 5 ile xor işlemine tabi tutup oluşan değeri a ya atamış oluruz.

Haydi bir deneme de size, finalde ne yaptığını anlayanları sonuçlarla birlikte yorumlara bekliyoruz:

int main()
{
	int x = 5;
	int y = 7;
	x = x ^ y;
	y = x ^ y;
	x = x ^ y;
	cout << x << " " << y << endl;
}

Son bir bilgi verip konuyla vedalaşıyorum : a ^ b şu şekilde de elde edilebilir -> ~(a&b)&(a|b); bu karmaşık oldu ya, a ^ b candır :)

Şimdilik herkese kolay gelsin!



Önceki konu : Bit İşlemleri | Bitwise OR

Sonraki konu : C++ Bitwise And "ve" operatörü &

C++ Dersleri | Bit İşlemleri | Bitwise OR

 C++ bitwise OR operatörü dijital elektronikten bildiğimiz VEYA ile aynı şeydir, doğruluk tablosunu hatırlamayanlar için bir görsel ekleyelim :

Veya doğruluk tablosu

kodlarken de aynı değişken isimlerini kullanalım :

int main()
{
    int a = 7;          // 0111
    int b = 13;         // 1101
    int aORb = a | b;   // 1111
    cout << "a = " << a << ", b= " << b << ", a | b = " << aORb << endl;
}

çıktımız : a = 7, b= 13, a | b = 15 

Peki neler oldu nasıl 15 elde ettik, binary formatındaki sayıları alt alta yazarak soldan sağa doğru sutunları OR işlemine tabi tutuyoruz : en soldan yukarda 0 aşağıda 1 sonuç 1, bir sonrakinde yukarda 1 aşağıda 1, sonuç 1, bir sonrakinde, yukarda 1 aşağıda 0, sonuç 1, en sonda da yukarda 1 aşağıda 1, den sonuç 1 gelmiş oldu.

Hatırlatmış olayım : bu operatör bir değişkene eşitlenmediği sürece bir değişikliğe yol açmaz, ne demeye çalışıyorum şöyle örneklendirelim :

int a = 7;          // 0111
a | 5;
cout << "a = " << a << endl;

a değişkeni hala 7 değerindedir. a | 5 değerinin, a nın yeni değeri olmasını istiyorsak : a = a | 5; yazabilir ya da daha kısa olacak şekilde : a |= 5; yazabiliriz.

Peki gömülü sistemlerde nerde karşımıza çıkar, AVR programlarken Atmega328p için yazmış olalım port durumu ayarladığımız: DataDirectionRegister{PortName} kısaca DDRB (B portunu kullanıyor olalım) bir pini çıkış olarak ayarlamak istediğimizde o pine ait bit i 1 yapmamız gerekiyor, pinimiz de 3 olsun : DDRB = 0b00001000; yazarsak 3 numaralı pinimiz çıkış olur, ama evvelden 2 numaralı pini çıkış yapmışsak artık o konfigurasyonu kaybetmiş oluruz, bunun önüne geçmek için bitwise OR imdadımıza yetişiyor : DDRB |= 0b00001000; yazdığımız vakit eski konfigurasyon aynen korunur, indekse göre (soldaki ilk bit 0 olarak kabul edilir) sadece 3. bitin 1 olması sağlanmış olur. Evvelce sadece 2 pini çıkış olarak ayarladığımızı varsayalım DDRB : 00000100 durumundayken : 

00000100

00001000 | 

-------------

00001100 halini almış olur.

Örneklerde bunu genellikle şöyle görüyor oluruz : 

PORTB |= (1<<PORTB3);

bit shift operatöründe detaylarına bakarız, ama olan şudur PORTB3 avr.io içerisinde 0b00001000 olarak define edilmiştir, bu şekilde kullanılarak, geri dönüp bu satırda hangi pini aktif ettiğimizi anlamak adına, okunabilirliğin kolaylaşması için bu yöntem kullanılır.

Herkese Kolay gelsin!

Video Anlatımı :



Önceki konu : Bit İşlemleri - bitwise Operators

Sonraki konu: Bit İşlemleri | Bitwise XOR, Özel Veya Operatörü

C++ Dersleri | Bit İşlemleri - Bitwise Operators

    C++ Bit işlemleri mikrodenetleyici programlarken çokça ihtiyaç duyacağımız önemli bir konudur. C++ 'ı özellikle gömülü sistemler geliştirmek için öğrenmek ve kullanmak istiyorsanız naçizane tavsiyem bu konu üzerinde ağırlık vermeniz olacaktır. Bunun sebebi mikro denetleyicilerin kontrolünün register kullanarak yapılabilmesidir. Buna hiç gerek duymadığımız Arduino gibi sistemler ya da STM için konuşacak olursak HAL kütüphaneleri gibi register kullanımından soyutlandırılmış yapılar, ancak hobiciler için performans/hafıza optimizasyonuna ihtiyaç duymayan uygulamalarda kullanılabilir. Temel yapı register kullanımıdır ve buna hakim olan programcılar için kullandıkları mikrodenetleyici her ne olursa olsun, ihtiyaç duyacakları tek şey: mikrodenetleyicinin veri sayfası olacaktır. Ben arduino biliyorum diyen biri STM programlamak istediğinde HAL öğrenmelidir, ancak register level kodlayabilme yeteneğine sahipse buna gerek duymayacak ve geçişlerde herhangi bir zorluk yaşamayacaktır. Mikrodenetleyicinin anladığı dil temelde budur çünkü :) BEnim de anlatmayı yazmayı kullanmayı en sevdiğim konudur. Ben bilgisayarın dışına çıkmıyorum ne işim var mikrodenetleyici ile diyen için, eğer işletim sistemi yazmayacaksan bunlara hiç ihtiyacın olmayak diyelim ve sizi yormayalım bunlarla.

    Register kullanımıyla, arduino ide kullanımı arasındaki farkı : Arduino UNO, Atmel Studio üzerinden programlamak başlıklı yazımda anlatmaya çalışmıştım dileyenler onu da okuyup konuyu daha iyi anlayabilirler diyelim ve başlayalım.

Şimdilik herkese kolay gelsin!

Önceki Konu : C++ Floating Point Aritmetik

Sonraki Konu: Bit İşlemleri | Bitwise OR

C++ Floating Point Aritmetik

 C++ 'ın ondalık sayılardaki davranışını, pardon garip davranışını inceliyoruz. Biraz bildiğiniz ve anlamlandırabileceğiniz aritmetiğin dışına çıkmış olacağız. Bakalım neler var; bir for döngümüz olsun, 0 dan başlasın ve 2 ye eşit olmadığı sürece dönmeye devam etsin, adımlarımızda 0.01f olsun, beklentimiz ne olurdu bu durumda 0, 0.01, 0.02 ... şeklinde devam ederek 1.98, 1.99 ve son olarak 2.0 olur ve döngümüz sonlanır diye hayal ediyoruz, ancak beklenmedik şekilde döngümüz asla sonlanmıyor 😱  

kodumuz şöyle isteyen deneyebilir :

float total = 0;
for (float a = 0; a != 2; a += 0.01f) {
	total += a;
}

net bir ifade olan a != 2 dediğimiz yeri biraz daha yumuşatalım ve  a < 2; yapalım, bu durumda a 2 den illaki büyük olacak ve döngü sonlanacak, sonlanacak sonlanmasına da burda da bir sürpriz bekliyor bizi, total değişkeni 199 değil 201 olacak, bu olan bilgisayarlar işlemciler için IEEE754-Compliant standard yayınlamıştır. Bunun olmasının sebebi ondalıklı sayıların değerlendirildikleri değerlere yakın bir sayıyla temsil edilebiliyor olmalarıdır şöyle bir görsel paylaşayım da netleşsin mevzu:


0.1, 0.2 ve 0.3 için aslında yapılan değerlendirmeler şekildeki gibi oluyor, haydi test edelim mi

double a = 0.1;
double b = 0.2;
double c = 0.3;
if (a + b == c)
	//This never prints on IEEE754-compliant machines
	std::cout << "This Computer is Magic!" << std::endl;
else
	std::cout << "This Computer is pretty normal, all things considered." << std::endl;

matematiksek olarak c = a + b doğru olmalı ama malesef değil, bu durumu float double kullanırken mutlaka göz önünde bulundurun demiş olayım. 

Olayın sebebine bakalım mı? Bizler insan evlatları olarak 10 luk sayı sistemini kullanır ve ondan anlarız, ancak işlemciler/mikrodenetleyiciler elektronik sistemler olmaları sebebiyle ancak voltaj kontrolü yapabilirler ve voltaj bulurlarsa bunu 1, bulamazlarsa 0 olarak değerlendirirler, yani anladıkları tek sayısal sistem binary system 'dir. 0.1, 0.2 gibi sayılar 10'a bölme gerektirdiğinden, (1/10 yapılarak elde edilmiştir) ve bölümün kusursuz olması (yani sonsuza gitmemesi) gerektiğinden, ikili sistemde ifade edilmesi imkansızdır, sayı bu değere asla ulaşamaz ancak çok yaklaşabilir. Eğer ki 0.5 den bahsediyor olsaydık bu mümkündü : binary sistemde noktadan sonraki ilk hane 0.1 -> 1/2 ile çarpılıyor bu da bize tam olarak 0.5 değerini verir, bir sonraki basamak 1/4 ile çarpılıyor, bu durumda 0.25 sayısı da binary sistemde kusursuz olarak ifade edilebilir -> 0.01 ya da her ikisinin toplamı olan 0.75 sayısı 0.11 ile tam ve kusursuz ifade edilebilir. Basamaklar sağa doğru ilerledikçe hep 1 bölü 2 üzeri bir rakam şeklinde dolayısıyla 2 nin üs katları şeklinde ilerliyor ve her ne şekilde olursa olsun oluşan sayının içerisinde 5 olamayacağından (5 nerden geldi? 10 'un çarpanlarından, 10 = 2*5) dolayı bir imkansızlık söz konusu. Ee 0.5 de 5/10 değil mi orda da 5 var? var mı gerçekten ? 5/(5*2). Bizim de onluk sistemde 1/3 için yaşadığımız kusursuz olamama probleminin binary sistemdeki karşılığından bahsediyorum: 0.33333333 elde ettikten sonra, sonsuza doğru giden 3 'ler yerine, hata payının kabul edilebilir olduğu bir yerde durup, hayatımıza kaldığımız yerden devam ediyor olmamıza benzetebiliriz bu durumu. Sözü geçen kabul edilebilir de olsa hata payı ifadesi sayıyı tam olarak kusurlu/hatalı İngilizce deyimle imperfect hale sokuyor. Double için konuşuyorsak noktadan sonra 23 haneye kadar tutması mümkün olduğundan hata payı çoğu zaman çok çok kabul edilebilir olacaktır. Çok takılmayın ama aklınızda kalsın float varsa bölme vardır bölme varsa sıkıntı vardır :) deyip mevzu kontrolden çıkmadan ufak ufak uzaklaşayım.

bu arkadaşların hafızada nasıl saklandıklarına bakalım son olarak :

double a = 0.1 : 0011111110111001100110011001100110011001100110011001100110011010

double b = 0.2 : 0011111111001001100110011001100110011001100110011001100110011010

double c = 0.3 : 0011111111010011001100110011001100110011001100110011001100110011

iken; 

a + b : 0011111111010011001100110011001100110011001100110011001100110100

şeklinde yer buluyor hafızada, hocam bunlara nasıl ulaştınız? tarif edeyim : if satırına bir adet breakpoint yerleştirip kodumuzu çalıştırıyoruz, program breakpoint te durduğu zaman, Visual Studio 2022 için konuşuyorsak : Debug->Windows->Memory-> Memory 1 ya da Ctrl + Alt + M, 1 kısa yolu ile hafıza penceremize ulaşıyoruz Address: yazan yere &a yazıp enter a basıyoruz :

cpp floating point numbers storage

double kardeşimiz 8bytes; çıkan ilk 8 haneyi (her hane bir byte ifade eder) kopyalıyoruz : 9a 99 99 99 99 99 b9 3f   buradan elde ettiğimiz sayı hex formatında olmanın yanında little-endian da formatında yani ikişerli grupları yer değiştirip en sonrakini en başa alacak şekilde yer değiştirerek aslında ifade edilen sayıyı elde ediyoruz, bu c++ nin veriyi hafızada saklama rutiniyle alakalı bir durum. Değişimden sonra elimizde olan : 3fb999999999999a bunu da windows calc ile programmer modundayken HEX seçili vaziyette yazarsan, binary halini görüyor olacaksın ona da bir görsel bırakalım :



Önceki konu : C++ Aritmetik Operatörler ve öncelikleri

Sonraki konu : C++ Dersleri | Bit İşlemleri - Bitwise Operators

Video :



C++ Aritmetik Operatörler ve öncelikleri

    C++ 'da aritmetik operatörler öncelik sıralaması matematikteki gibidir. Çarpma ve bölme toplama ve çıkarmaya göre daha yüksek önceliklidir, işlemler her yerde olduğu gibi burada da soldan sağa doğru yapılır. Öncelikli yapmak istediğimiz işlemleri paranteze alarak öncelik sıralamasında yukarı taşımak mümkündür, dediğimiz gibi matematikte nasılsa C++ da da öyledir.

    Örneklendirelim :

// bir küresel kabuğun hacmini hesaplamak için dıştan hesaplanan hacimden
// içten hesaplanan hacim çıkartılır
double R = 13;
double r = 11;
double pi = 3.1415f;
double vol = 4.0 * pi * R * R * R / 3.0 - 4.0 * pi * r * r * r / 3.0;

sırasıyla, dış kürenin hacmini hesaplayacak, sonra iç kürenin hacmini hesaplayacak, sonrasında sonuçları birbirinden çıkartacak. Sonuç : 3627.39 

toplama için : 

int x = 4 + 4 / 2; // 6 döner
int y = (5 + 5) / 2; // 5 döner

çarpım için :

int x = 3 + 6 / 3 * 2; // 3+((6/3)*2) -> 7 döner
int y = (3 + 6) / 3 * 2; // ((3+6)/3)*2 -> 6 döner 

bölme ve kalan (modulus) için :

int x = 4 - 4 % 1; // 4 - ( 4 % 1 ) -> 4 - 0 = 4 döner
int y = 4 - 4 / 1 % 3; // 4 - ((4/1) % 3) 3 döner
 
int w = 4 - (4 / 1) % 3; // yorumlarda görüşelim
int q = 4 - (4 / (1 % 3)); // bu ikisini size bırakıyorum 


Herkese kolay gelsin!


Önceki konu : C++ Unary Operatörler ve öncelikleri

Sonraki konu : C++ Floating Point Aritmetik

C++ Unary Operatörler, Değer Artırma-Azaltma

    C++ Unary operatörler, tek operandları olmaları sebebiyle bu ismi almışlardır diye düşünüyorum, zira unary : tekli olarak dilimize dönüyor. Bu arkadaşlar yüksek önceliğe sahiptirler. Basit bir konu olmakla beraber dikkat edilmesi gereken hususları yok değil. Postfix ve prefix olarak kullanımları mevcut, ikisinin arasındaki farksa prefix olduklarında önce operasyon gerçekleşiyor sonra aksiyon gerçekleşiyor, postfix olduklarında önce aksiyon sonra operasyon gerçekleşiyor, ne demeye çalışıyorum bir örnekle bakalım; örneğimizde increment operatorumuz olan ++ operatorunu ya da decrement operatorumuz olan -- ' yi kullanabiliriz: 

int i = 0;
cout << i++ << endl;
cout console içine verdiğimiz herneyse yazdırır söylemiş olalım, burada operasyondan kasıt i değerinin mevcut değerine 1 eklenmesi, aksiyondan kasıt da bu değerin konsol ekranına yazdırılmasıdır. Postfixden kasıt ++ operatörünün değişkenden sonra yazılması, prefix 'den kasıt ++i şeklinde değişkenden önce yazılmasıdır. Yukarıdaki örnekte, postfix kullanılmış olup çıktı olarak 0 yazdırılması beklenir, yazdırıldıktan sonra i değeri 1 artırılır. Aynı durum decrement operatör için de geçerlidir. 

Örnekleri çoğaltabiliriz :
int i = 11;
int r = --i / 2; 
bizim için önce i değerini 10 a düşürüp, sonra 2 ye böler ve 5 sonucunu üretir.
Pointer konusuna hakim olmayan arkadaşlar buraya fransız kalabilirler, ben biliyorum diyenlere sorum aşağıdaki kod parçacığı ne çıktı üretir yorumlara bekliyoruz kendisini :

int nums[4] = { 1,2,3,4 };
int* ptr1 = &nums[0];
int* ptr2 = ptr1++;
cout << *ptr2 << endl;
Yukardaki kodu es geçenler için biraz basitleşelim :

int nums[4] = { 1,2,3,4 };
int next = ++nums[1];
cout << next << endl;
dizimiz var 4 elemanlı; elemanları 1,2,3,4 dizilerde detaylı yazıyor oluruz bunu, dizinin ilk elemanına ulaşmak için yapmamız gereken nums[0] yazmak; ikinci satırdaki next değişkeni istiyor ki bana nums dizisinin elemanlarından indeksi 1 olandan sonrakini ver, yani çıktımız 3 oluyor. Üzerinde biraz çalışırsanız herşey netleşecektir :)

Son olarak da NOT ! operatörümüz güzide bir unary operatör olup bool veri tipindeki değişkenlerin değerini mevcut değerinin tersine çevirmektedir, yani true ise false, false ise true yapar:

bool state = true;
state = !state;
 
if (state)
{
 
}
if (!state)
{
 
}
state ilk satırda true iken ikinci satırda false olmuştur. If le kullanımına örnek olsun diye if durumlarını da ekledim ilk if (state == true) ile ikinci if (state == false) ifadesiyle aynı anlama gelmekte, ayrıca state doğru değilse gibi de kontrol yapılabilir : if(state != true) burada da eşittiri eşit değildir yapmış olur NOT operatörü.

Kafanızdaki takılanları yorumlarda sormaktan lütfen çekinmeyin!

Herkese kolay gelsin!

C++ Mantıksal AND ve Mantıksal OR Operatörlerinde Öncelik

C++ && ve || ne anlama gelir?  

Mantıksal AND && operatörünün mantıksal OR || operatörüne göre önceliği vardır. Mantıksal demişken C++, bu operatörler için gerçekten mantıklı davranır, yazının devamında bu dediğime hak vereceksiniz. Şöyle ki; bu iki operatörün de iki operandı vardır bunlara A ve B dersek şimdilik, A ve B durumlarının && operatörü için her ikisinin de DOĞRU olması gerekir. Yani (A && B) ifadesinin doğru çıktı üretebilmesi hem A 'nın hem B 'nin DOĞRU olmasıyla oluşur. C++ bu operandların kontrollerini soldan başlayarak yapar, önce A durumunu kontrol eder, eğer A doğru ise B yi denetler, burası önemli, demek ki A doğru değilse B 'yi denetlemek için enerji ve zaman sarf etmez. Bu da performansımızı doğrudan etkileyen bir durumdur. Bu durumu lehimize kullanmak gerekirse A ve B 'nin yeri önemli olmaya başlar, ne demeye çalışıyorum, (A && B) ile (B && A) aynı performansla çalışmayabilir. Burada önsezilerinizde hangi durumun FALSE üretme olasılığı daha yüksekse onu ilk önce yazarak performans artışı sağlayabilirsiniz gibi bir trick karşımıza çıkmış oluyor. Bu duruma literatürde short-circuit deniyor.

    Durumun tam tersi OR || operatörü için de geçerli: (A || B) 'nin DOĞRU çıktı üretebilmesi için, operandlardan herhangi birinin DOĞRU olması yeterli oluyor. C++ 'ın buradaki davranışı yine AND ile benzerlik gösteriyor, A doğru ise B 'yi kontrol etmiyor, çünkü B her ne olursa olsun YANLIŞ ya da DOĞRU, operatör için sonucu değiştirmiyor. Yukarıdaki mantığa göre OR operatörü için de DOĞRU olma olsılığı yüksek olanı ilk önce yazarak performans artışı sağlamamız mümkün. Unutmayın ki bazı durumlarda çok kısa süreler içerisinde çok fazla iş yaptırmamız gerekir mikrodenetleyicimize ya da işlemcimize, zamanla yarıştığımız yerlerde hayat kurtaran yapılardan biridir kendileri.

    Mevzuyu örneklendirelim;

     Öncelik derken ne demek istediğimize bakalım önce, burası yanlış anlaşılmaya müsait bir konu, aslında konu öncelikten çok nerenin parantez içindeymiş gibi düşünüleceğidir,  falseX || falseY && falseZ   gibi kaba bir örnek üzerinde konuşmamız gerekirse,  ifade C++ tarafından  falseX || ( falseY && falseZ )   olarak değerlendirilir. Soldan sağa hareketle, FalseX || olduğunda operandın diğerini mutlaka kontrol etme gereksinimi doğar, yani bir short-circuit durumu oluşmamıştır, ikinci operand parantez içinde AND işleminin ilk operandının FALSE olması münasebetiyle AND in ikinci operandı yani falseZ kontrol edilmez. Finalde FALSE döndürür.

    X true olsaydı işler nasıl yürürdü sizce? trueX || falseY && falseZ ; OR operatörü için ilk operand olan trueX, doğru olduğu için ifadenin gerisi kontrol edilmeksizin DOĞRU döndürürdü. Bu durumda AND operatörünün öncelikli meselesi anlaşılmıştır diye düşünüyorum, çünkü aksi olsaydı OR paranteze alınır, DOĞRU döndürür, OR dan dönen DOĞRU ile falseZ AND işleminden YANLIŞ olarak çıkar, final değerimiz YANLIŞ olurdu.

    Özlü sözlerde bugün 'e gelecek olursak, bir kodu yazarsınız, çalışır da, ancak bazen sadece çalışması yetmez vaktinde işi bitirmesi gerekir :) Emin olun bunu kullandığım ve işin içinden sıyrıldığım durumlarla karşılaştım.

Herkese kolay gelsin!

Önceki Konu : C++ Operatör Öncelikleri

Sonraki Konu : C++ Unary Operatörler

Arduino ile voltaj okuma | Arduino ile voltmetre | Arduino ADC örnek Kod

 

Arduino ile voltaj okuma

    Arduino güç özellikleri konusunda detaylıca anlattığımız üzere, Arduino UNO için konuşuyorsak; mikro denetleyicimizin anlamlandırabildiği maksimum potansiyel fark +5V 'tur. Bunun konumuzu ilgilendiren kısmı da standart olarak bir Arduino UNO ile ölçebileceğimiz en fazla potansiyel farkın 5V olmasıdır. Daha yüksek seviyelerdeki voltajların Arduino ile ölçülebilmesi için ek elemanlara ve devrelere ihtiyaç duyulmaktadır, ileride bu konuyla ilgili yazı yayınlarsam linkini buralarda paylaşıyor olurum. Voltaj Bölücü Devresi şimdilik size yardımcı olacaktır. Gerekli hesapları yapıp Vout için maksimumda 5v gelecek şekilde dirençlerinizi seçip devrenizi tasarlayabilirsiniz. Bu yazı Arduino UNO ile daha önce hiç voltaj ölçmemiş, nasıl ölçüldüğü konusunda fikri olmayan okuyucularımızı hedef almaktadır :) 

       Arduino ADC ölçümlerinde yalnızca 0-5V arası DC gerilim ölçülebilir!

    Devre şemamız görseldeki gibi, biraz anlatmamız gerekirse, potansiyometremizin dış uçlarından birini 5V pinine diğerini de GND pinine bağlıyoruz, yerleri farkeder mi? aslına bakarsanız hiç farketmez, peki ne gibi bir değişikliğe sebep olur? şöyle : şekilde gördüğünüz potansiyometrenin kadranı Kırmızıya yakın bu durumda orta pinden çıkan voltaj 5v 'a yakın olur, yaani saat yönünde çevirdikçe voltajımız 0 dan 5V ' a doğru yükselir. Tam tersi bağlamış olsaydık olay tam olarak ters şekilde gerçekleşiyor olacaktı. Potansiyometrenin de buradaki fonksiyonu anlaşılmıştır diye tahmin ediyorum, bizim için 0v ile 5v arasını kademelendirmiş oluyor. Sağdaki pini 5V 'a değil de hemen yanındaki 3.3v 'a bağlamış olsaydık, A0 pinine bağlı olan terminalinde 0 v ile 3.3v arasında bir voltaj değişimine şahit olacaktık. Soldakini 3.3V 'a sağdakini 5V 'a bağlasaydık ne olurdu ki? 😲 cevabı bilenleri yorumlarda görmek isteriz :) Potansiyometremiz 1K - 10 K -100K vs olabilir, sorun yok.

    Harici bir kaynaktaki voltajı ölçmek için kaynağın GND 'sini Arduino kartın GND 'sine, + ucunu da kullanmak istediğiniz analog pine bağlayıp ölçüm yapabilirsiniz. Tekrar etmek gerekirse yalnızca 0-5v arası DC!

Kod kısmına gelecek olursak kurgumuz şöyle olsun A0 pinindeki voltajı okuyup Arduino Serial Ekran 'a belirli zaman aralıklarıyla yazdıralım. Aşağıdaki kod kurgumuzu tam olarak gerçekleştirecektir :

void setup()
{
  Serial.begin(115200);
}
void loop()
{
  int adcVal = analogRead(0);
  float voltage = adcVal * 5.0f / 1023.0f;
  Serial.println(voltage);
  delay(10);
}

gördüğünüz üzere gayet basit bir kod, açıklamaya çalışalım dilimiz döndüğünce:

Serial.begin(115200); seri iletişimi 115200 hızında başlatmayı hedefler

int adcVal = analogRead(0); satırı konumuzun göz bebeği, adcVal adında int tipinde bir değişken oluşturup,analogRead(0) fonksiyonuyla A0 pinindeki voltajın okunmasını sağlamış oluyoruz, neden int? çünkü Arduino UNO için ADC çeviricisi 10 bittir. Bunun anlamı nedir? 10 haneli binary sayı tutabilir. Yaani 2^10 değeri için maksimum seviyedir diyebiliriz. Bu da bizim numerik 10 sisteminde 1023 e denk gelir, uint8_t char gibi 8 bitlik tamsayı değişkenlerine sığmaz demeye çalışıyorum. Özetle anlamlandırabildiği maksimum voltaj olan 5V 'u bizim için sayısal olarak 1023 değeriyle ifade eder. Bir sonraki satırdaki matematik kafanıza oturmuş olmalı bu noktada!

float voltage = adcVal * 5.0f/ 1023.0f; satırıyla okumuş olduğumuz adc değerini voltaja çeviriyoruz, basit bir dil ile 5.0V u 1023 ise adcVal neye denk gelir? doğrusal denkleminin cevabını arıyoruz, klasik içler dışlar meselesi. 5 i 1023 e bölerek 1 adc değerinin ne ettiğini hesaplamış oluyoruz, bu değeri de okunan adc değeri ile çarpınca voltaj tipinde bir değer elde etmiş oluyoruz, bu kadar basic. Bu bölmedeki .0f ler nerden geliyor diyenleri C++ Intreger Literal konusunu okumaya davet ediyoruz.. He bir de neden float? çünkü biraz detay istiyoruz yani voltaj seviyesini en azından virgülden sonra iki hane de olsa görelim değil mi.

Serial.println(voltage); ile nihai voltaj değerimizi seri ekrana yazıdırıyoruz, ln olması yazdırdıktan sonra bir sonraki satıra geçişi sağlıyor, print de yazabilirsiniz, o zaman yan yana yazıyor olur, inanmıyorsanız deneyin :)

delay(10); ile 10ms lik bir gecikme ekliyoruz, 100 olabilir 1000 olabilir keyfinize göre ayarlayın.

Artık Seri Ekranda değerleri görebilirsiniz, aynı zamanda Serial Plotter ile çizim halini de görebilirsiniz. Tinkercad gibi simulasyonlarda bu çizim çok düzgün bir şekilde çıkarken, gerçek bir uygulamada çok da düzgün çıkmayabilir, hiç dokunmadığınız halde oynamalar düşmeler çıkmalar, sakallar görülebilir, bunları da atlamanın yöntemleri var ancak bu yazıda değil de daha sonra yazar ve paylaşıyor oluruz. 

250ms lik beklemelerle benim tinkercad ile aldığım çıktı şu şekilde :

Arduino voltaj ölçme

Tinkercad Simulasyonu için tıklayınız!

Detaylıca anlatmaya çalıştım, yine de kafanıza takılan herşeyi yorumlarda sorabilirsiniz!

Okuduğumuz voltaj değerini bir ekrana yazdırmak istersek diye ekran kullanımıyla alakalı yazıların linkleri : 

16x2 LCD Arduino ile 4 bit Paralel modda sürülmesi

Arduino ADC Referans Voltajı Değiştirme konusunu okuyarak, daha hassas ölçümleri nasıl yapabileceğinizi öğrenebilirsiniz.

Herkese kolay gelsin!

Arduino buton ile led yakmak | Örnek kod

Arduino buton ve led bağlantısı

 

Arduino button ile led yakma uygulamasına geçmeden önce buton nedir kısaca ona bakalım. Buton iki veya bazen ikişerli ortak olmak üzere 4 adet terminalden oluşan anahtarlama elemanıdır diyebiliriz. Anahtarlama elemanı olması sebebiyle elektrik devresine seri olarak bağlanırlar. yani devreyi herhangi bir yerinden keserler, butona basıldığı anda terminaller fiziksel olarak temas eder ve devre buton üzerinden tamamlanmış olur.


Yukarıdaki animasyona bakıldığında çalışma prensibini anlamak gayet basittir. Söz konusu animasyon Sparkfun 'un web sitesinden alınmıştır. 

    Sayfanın girişinde yer alan Arduino buton ve led bağlantısının gösterildiği görselden biraz bahsedelim. Arduino 'nun 13 üncü pinine bir ader direnç üzerinden (Buradaki direncin nasıl hesaplandığını öğrenmek için lütfen tıklayınız) ledin anod (+) ucu bağlanmıştır. Ledin diğer ucu (katot) da Arduino 'nun GND pinine bağlanmıştır. Butona gelince, görsele göre konuşmak gerekirse solda kalan terminaller birbirine içerden fiziksel olarak bağlıdır, sağdaki terminaller de içerden birbirine bağlıdır, soldaki ve sağdaki terminaller butona basıldığında birleşir ve devre tamamlanmış olur. Burada butonun bir terminalini soldakilerden üstteki ya da alttaki olabilir, Arduino 'nın digital pinlerinden birine, diğer terminali de Arduino 'nun GND pinine bağlanmıştır. Bu durumda pin üzerinde LOW kontrolü yapıyor olacağız, pinimizi kod kısmında INPUT_PULLUP olarak belirleyebildiğimiz için buton için fazladan bir direnç kullanmaktan kurtulmuş oluyoruz. Eğer ki butonda +5V anahtarlamak istiyor olsaydık, ki gördüğünüz üzere gereksiz fantastik bir durum olur bu durumda, o zaman GND' ye bağladığımız terminali 5V 'a bağlamamız ve de Arduino 'nın dijital pinine bağladığımız terminalini de bir pull down direnci ile GND 'ye bağlamamız gerekiyor olacaktı, neden ? çünkü Arduino input modlar içerisinde INPUT_PULLDOWN diye bir seçeneğimiz yok. Her iki durum için de Pull-up ya da pull-down yapmamızın nedeni digital pinin giriş seviyesinin kararsız kalmasını engellemektir. Kararsız kaldığı zaman, butona basılmasa da etraftan alacağı gürültü sebebiyle zaman zaman butona basılmış gibi davranması kaçınılmazdır. Devre ve kurgu anlaşıldıysa kod kısmına geçebiliriz.


Arduino ile buton yakmak örnek kod:


#define LED 13
#define BUTTON 7
void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
}

void loop()
{
  if (digitalRead(BUTTON) == LOW)
  {
    digitalWrite(LED, HIGH);
  }
  else
  {
    digitalWrite(LED, LOW);
  }
}

Şimdi satır satır bakalım neler yazdık, 

#define LED 13 satırıyla 13 yazmamız gereken yerlere artık LED yazabiliriz demiş olduk

aynı şekilde 7 yerine BUTTON yazabiliriz demiş olduk, define kullanımı hakkında detaylı bilgi sahibi olmak istiyorsanız arduino ve c++ için define kullanımını anlattığım youtube videoma bakabilirsiniz.

Geldik setup kısmına, Led imizin bağlı olduğu pini çıkış olarak ayarladık, bunda sorun yok, dikkat edeceğimiz nokta butonun bağlı olduğu pindeki INPUT_PULLUP ibaresi dikkat edin yalnızca INPUT değil, yine youtube da yayınladığım Arduino digital pinlere erişim videosunu izlemenizi tavsiye ederim tüm detayları orada bulacaksınız. Bu kısmı INPUT olarak belirlerseniz, digital pini bir dirençle pull-up yapmanız gerekmekte. 

Loop içerisinde, kod enerji kesilene kadar dönüp duracaktır, if ibaresine yabancı olanlar için yine detaylı C++ Arduino If kullanımı Videosu youtube kanalımda mevcut, digitalRead fonksiyonu ile butonun bağlı olduğu pinin seviyesini okuyoruz, eğer ki pin seviyesi LOW ise-bu durumun oluşabilmesi için butona basılmış olması gerekiyor- digitalWrite ile led in bağlı olduğu pin seviyesini HIGH yaparak ledin yanmasını sağlamış oluyoruz. Bu durumda ledimizin sürekli yanık kalmaması için butondan el çekildiğinde sönmesi için de else kısmında ledin bağlı olduğu pin seviyesini LOW yapıyoruz. 

    Konu bu kadar basit bir konu olsa da mevzuya uzak olan kimseler için anlaşılması zor olabilir, herşeyi detaylıca yazmaya çalıştım, yine de kafanızda soru işareti oluşturysa lütfen yorumlarda sormaktan çekinmeyiniz

    Herkese kolay gelsin!

Tinkercad proje linki

C++ Operatör Öncelikleri

 C++ siz bir ifadeyi yazdığınızda bunu nasıl değerlendirir, hangi işlemi önce yapar ve bunu nasıl anlayabiliriz örnekleriyle beraber konu içerisinde bakıyor olacağız.

Sonraki Konu : C++ Mantıksal AND ve Mantıksal OR Operatörleri

Önceki Konu : C++ nullptr nedir nasıl kullanılır 

C++ nullptr Nedir? Nasıl kullanılır?

 nullptr, adından da tahmin edilebileceği üzerine henüz hiçbirşeyi göstermeyen bir göstericiye astanabilecek bir literaldir. this konusunda verdiğimiz örnekle gidecek olursak orada class 'a ait bir instance oluşturmuş ve söz konusu instance 'ı işaret etmesi için bir de pointer oluşturmuştuk ancak oluşutururken hiçbirşeye eşitlememiş/eşitleyememiştik.

DCEngine Engine;
DCEngine *enginePtr;

yoğurdu doğru yemek gerekirse burda pointer için bir boş gösterici atamak gerekiyor ki kullanırken, göstericinin gerçekten bizim erişmek istediğimiz instance 'ı gösterip göstermediğinden emin olabilelim, söz konusu satır şöyle olsaydı :

DCEngine *enginePtr = nullptr;

erişmeye çalıştığımız anda instance 'ı göstermeye başlamış mıdır ki diye kontrol etmek için:

if(enginePtr != nullptr)
    {
            // Instance ı güvenle kullanabiliriz
    }

aksi halde henüz işleyici instance'ın pointer 'a atandığı satıra gelmeden erişmeye çalışıyor olabiliriz. Basitçe hiçbirşey göstermeyen ama bize kontrol olanağı sağlayan bir yapıdır kendisi.

Önceki Konu : C++ true false nedir nasıl kullanılır

Sonraki Konu: C++ Operatör Öncelikleri


C++ true false Nedir Nasıl kullanılır?

 bool tipindeki değişkenin değeridir diye tanımlayabiliriz, true false 'ı. Türkçeye çevirildiğinde kolayca işlevi anlaşılabilir, if / while gibi kontrol mekanizmalarında kullanılır ve doğru yanlış olarak ifade edebildiğimiz veri tipi olan bool 'un değerlendirilmesinde/değer verilmesi anlamında :) ya da değerinin okunmasında kullanılırlar.

 bool isReady = true;
    if (isReady)
    {
        // falan filan
    }

isReady true ise bloğu işlet demek ister isReady == true da kullanılabilir.

   bool isReady = true;
    if (!isReady)
    {
        // falan filan
    }

derken isReady == false kontrolü yapmış oluruz, yani yukarıdaki if durum kontrolü tam olarak aşağıdaki ile aynıdır:

if (isReady == false)
    {
        // falan filan
    }

Önceki Konu : C++ Integer Literal | Tam sayı hazır bilgileri

Sonraki Konu : C++ nullptr nedir nasıl kullanılır

C++ Integer Literal | Tam sayı hazır bilgileri

Tam sayılar için bildirim ifadeleridir diyebiliriz. 

Decimal Literal

Hiçbirşeyi olmayan literal :) bizim de kullandığımız sayı sistemi olan 10 luk sisteme ait olandır, 10luk sistemi kullanırken bir literal 'e ihtiyaç yoktur aslında, nasıl yani? 21 sayısını ifade edeceksek sadece 21 yazarız :

int x = 21;

ifadesinde 21 ile birlikte ne önüne ne arkasına hiçbirşey yazmayız, ne demek 21 yazarken önüne ne yazabiliriz ki? dikkat etmeniz gereken nokta başına 0 kullanmıyor olduğumuzdur, aslında 21 ile 021 bize göre aynı şeyken C++ için aynı şey değildir! Kural basit (1-9) ile başlayabilir (0-9) ile devam edebilirsin. Bu duruma decimal literal denir. 

Octal Literal Octal-sekizlik- sistemde 21 sayısını ifade etmemiz gerekirse : 

int x = 025;

yazmamız gerekir, bu noktada yukarda neden başına sıfır yazamıyoruz anlaşılmıştır. Kuralımız : 0 ile başlıyoruz, 1-7 arasındaki sayılarla devam ediyoruz, devamı varsa 0 da kullanıyoruz elbette, sonuç olarak değerin 8 lik sayı sistemine göre ifade edildiğini bir literal ile C++ 'a bildirmiş oluyoruz.

Hex Literal  

int x = 0x15;

yine 21 'i ifade ediyoruz ancak bunu yaparken 16 lık sayı sistemini kullandığımızı, 16lık sayı sistemine ait sayının başına 0x ifedesini ekliyoruz, 0X da kabuldür.

Binary Literal

int x = 0b0010101;

ikili sistemde 21 sayısını ifade ederken ikili ifadenin önüne 0b ekliyoruz, 0B olarak da kullanabiliriz.

Unsigned Literal

int x = 25u;

C++ 'ta bir değerin sonuna gelen u nedir? ne anlam ifade eder sorusunun yanıtı burada geliyor, C++ 'a benim tam sayım, 0 dan başlayıp ileriye doğru gidiyor, eksiye gitmiyor demek için sonuna u ekliyoruz, unsigned ifadesinin ilk harfinden gelir kendisi.

Long literal

long x = 25l;

benim sayım long;

long x = 25lu;

benim sayım long ama aynı zamanda işaretsiz, genellikle mcu frekansının tanımlandığı mhz seviyelerinde  #define F_CPU 16000000UL milyonluk sayıların ifade edilmesinde karşımıza çıkar:

long long x = 25llu;

long long unsigned

Float literal

double x = 25.0f;

ben ondalıklı sayıyım, diğerleri çok kullanılmaz ama float için dikkat etmek gerek, bir bölmenin sonucunun atandığı değişkenimizin böleni eğer float olmayan bir değişkenden geliyorsa float a haricen cast ederek işi çözebilirken sabitse ve tam sayıysa sonuna .0f eklemeden float sonuç elde edemiyoruz, ne diyorum? 

double x = 99/25;

bize x değişkenimiz double olmasına rağmen 3 sonucunu üretirken,

double x = 99/25.0f;

3.96 sonucunu üretir.


Önceki Konu : C++ this nedir ne işe yarar | C++ this keyword kullanımı

Sonraki Konu: C++ true false nedir nasıl kullanılır

C++ Literals

 C++ Literals böylece Türkçe' ye çevirmeye çalışmadan anlaşılması gereken bir konudur bana göre. Basitçe değişken olmayan bir değerin tipini belirtmek için kullanılır diyebilir miyiz bilemedim, kullandığınız zaman algılamanız daha kolay olacaktır onu söyleyebilirim. Nasıl diyelim, türü ve değeri yazılışından belli olan ifade türüdür demek yanlış olmaz sanırım. Hafıza yönetiminde önemli ve dikkat edilmesi gereken bir konudur, ve zaman zaman söylediğimiz gibi kullanmasak da ne olduğunu mutlaka bilmemiz gereken şeylerden biridir, ne diyoruz? her zaman kod yazmayız bazen de bir başkasının yazdığı kodu anlamamız gerekir/beklenir. Konu bir bölüm başlığı olup ilerleyen sayfalarda detaylıca incelenecektir. Ancak burada da kısaca bahsetmek gerekirse bir sabit için bir literaldir diyebiliriz : mesela 15 bir literaldir, x bir değişken ancak bellek tarafından olaya bakacak olursak, 15 ile x 'in bir tipi ve değeri vardır ve değişken olmasalar da bellek de yer alırlar, bellekte nasıl saklanacakları konusunu belirleyen parametreler de tipi ve değeridir diyebiliriz. Aynı değerin farklı şekillerde ifade edilebilmesine imkan sağlar da diyebiliriz : 15 'in 16 lık sistemde F ile ya da ikili sistemde 1111 şeklinde ifade edilebilmesi gibi. 

Önceki Konu : C++ Preprocessor (Ön işleyici)

İçerik : C++ Dersleri Konu Başlıkları ~ İçerik

Sonraki Konu : C++ this nedir ne işe yarar | C++ this keyword kullanımı

C++ this nedir ne işe yarar | C++ this keyword kullanımı

 this keyword -anahtar kelimesi, aynen ingilizcede olduğu gibi bu anlamına gelir ve mevcut nesne instance 'ını işaret eder, işaret eder ibaresinden, arkadaşın bir pointer olduğunu anlayabiliriz. Pointer konusunu ileride yazıyor oluruz, çok kafaya takılacak bir durumu yoktur, kendisi de bir değişken olup işaret ettiği değişken ya da nesnenin bellek adresini tutar sadece. Ne diyorum, nedir "nesne" nin instance 'ı, bunu bilmek ne işimize yarayacak ya da nasıl kullanacağız bakalım.

Bir class 'ım var, sistemimdeki motoru sürdüğüm ve ona bağlı değişkenleri parametreleri fonksiyonları/işlevleri barındırdığım. Motora sistemin bir çok modülünden erişmem ve yönetmem ya da parametrelerini okuyup değiştirmem gerekiyor. Bu class 'ımı da bir cpp dosyasında barındırıyorum, bir de header dosyam var. 

Header dosyam şu şekilde olsun:

#ifndef _ENGINE_H_
#define _ENGINE_H_
#include "enums.h"

class DCEngine
{
public:
    DCEngine();
    void Start(DirectionOfRotation Rotation, engineTurnFor TurnFor);
    bool checkIsSafe();
    void Stop();
    void setSpeed(uint8_t pwmVal);
    void setMotor(DirectionOfRotation dir, uint8_t power);
    void EmergencySTOP();

public:
    EngineState State = (EngineState)STOP;
    DirectionOfRotation direction = CW;
    uint8_t pwmVal = 40;
    RCFilter filtRpmA, filtRpmB;
    volatile double rpmA, rpmB, rpmZ = 0;
    volatile double rpmAfiltered, rpmBfiltered = 0;
};
#endif

header dosyamızda fonksiyon prototiplerimiz ve değişkenlerimiz var. Cpp dosyamız da şu şekilde


#include "engine.h"

DCEngine Engine;
DCEngine *enginePtr;

DCEngine::DCEngine()
{
    enginePtr = this;
}
bool DCEngine::checkIsSafe()
{
    /* Check If any problem with Running the engine */
}
void DCEngine::Start(DirectionOfRotation Rotation, engineTurnFor TurnFor)
{
}
void DCEngine::setSpeed(uint8_t pwmVal)
{
}
void DCEngine::setMotor(DirectionOfRotation dir, uint8_t power)
{

}
void DCEngine::Stop()
{
    /* setup engine driver to stop condition */
}

Buradaki asıl olayımız motoru sürmek olmadığından fonksiyonları boş bıraktım. Konu itibariyle dikkat etmeniz gereken yerlere bakalım : cpp dosyasındaki 

DCEngine Engine;
DCEngine *enginePtr;

ilk satır DCEngine class 'ına ait bir instance oluşturur, ikinci satır tipi DCEngine nesnesi olan bir pointer oluşturur ancak henüz işaret ettiği bir instance yoktur bu pointer için. Class 'ın constructor 'ı dediğimiz ve class ile aynı ismi taşıyan fonksiyon, class instance 'ını oluşturuğumuz anda çalışan kod parçasıdır, yani yukardaki ilk satır işleme alındığında bu kod bloğu yürütülür :

DCEngine::DCEngine()
{
    enginePtr = this;
    RCFilter_Init(&filtRpmB, 10.0f, 0.00065f);
}

instance oluşturulduğunda, evvelce oluşturduğumuz class pointer 'ının (enginePtr) içi dolmuş ve en son oluşturulan DCEngine class 'ının instance ına ait bellek adresini taşımaya başlar. Tam değişiyle Engine nesnesini işaret eder / gösterir / erişim hakkı tanır.

Artık diğer herhangi bir cpp dosyasının içerisinden 

extern DCEngine *enginePtr;

yazarak sayfanın herhangi bir yerinden bu DCEngine Instance 'ına şu şekilde ulaşabiliyor olacağız

enginePtr->Start();
enginePtr->pwmVal = 45;

peki neden bu yolu izliyoruz? Lazım olan sayfada bu instance 'ı oluşturup pekala erişebilirim, evet erişebilirsin ancak amacımız tek bir instance 'a sahip olmak ve heryerden aynı instance 'a erişmek. Diğer türlü her instance için ayrı bir bellek ayırmış olursun ve her instance 'ın parametreleri birbirinden farklı olabilir, bir diğer önemli olan noktaysa bu şekilde bir nesne instance'ına static bir fonksiyonun içinden de erişebiliyor olman olacaktır. Son olarak neden oluşturulan son instance 'ı işaret eder dediğime dikkat edin, eğer başka bi yerde başka bir instance oluşturursanız enginePtr artık oluşturduğunuz son instance ' ı işaret ediyor olacak.

Bir örnek daha verelim de olay biraz daha netleşsin mi?

class deneme
{
private:
    int x = 0;

public:
    void setX(int x)
    {
        this->x = x;
    }
};

class 'ıma ait bit x var, class 'ıma ait bir fonksiyonun parametresi olarak da x var, Fonksiyona parametre olarak gönderilen x değerini class 'ıma ait x değerine ataması için bir fonksiyon yazmışım, fantastik mi görünüyor? neden ikisi de x birinin adını değiştirip çözerim ben bu işi, tabii ki öyle ama her zaman kod yazmazsınız, bazen başkasının yazdığı kodu anlamanız gerekir ve o da böyle yazmıştır kodu :) aslında bu yapı c# daki bir class property 'sinin get set edilmesinin temelidir. Koddan anlaşılacağı üzere class 'a ait x değişkenine this ile erişiriz. this->x class 'ın x idir, yalın x parametreden gelen x 'tir.


Önceki Konu : C++ Literals

İçerik : C++ Dersleri Konu Başlıkları ~ İçerik

Sonraki Konu : C++ Integer Literal | Tam sayı hazır bilgileri

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