7 Şubat 2018 Çarşamba

Mikrodenetleyici İle Uzaktan Kumandalı Araba


Çocukken muhtemelen oynamışsınızdır uzaktan kumandalı araba ile fakat azımız nasıl çalıştığını merak edip araştırmıştır. Bir cismi arada hiçbir kablo olmadan kontrol etmek heyecan verici olmalıydı oysaki. Fakat hiçbir şey için geç değil gelin bu merakınızı gidermiş olalım. Bu yazımızda araba devresini, kumanda devresini ve bunların programlama aşamalarını sizlere göstereceğiz.



Arabanın Özellikleri

Arabanın en önemli özelliği tabi kide uzaktan kablosuz olarak kontrol edilebilmesidir. Bunun yanında Ön ledlerin kumanda ile açılıp kapatılabilmesi, geriye giderken arka ledlerin yanması, kumanda ile korna çalabilmesi ve engel algılayınca engelden kaçma özelliğinin kumanda ile açılıp kapatılması özellikleri mevcut.

Kodları ve proteus dosyasını github sayfasından da inceleyebilirsiniz.

Malzemeler

Araba için;
1 x PIC18F45K22 Mikrodenetleyicisi (arabanın beyni için)
1 x PIC12F675 Mikrodenetleyicisi (engel algılamada kullanılacak)
1 x L293D Motor Sürücü
1 x HCSR04 Ultrasonik Sensör (engel algılama için)
1 x Buzzer (korna için)
1 x 7805 Voltaj Regülatörü
1 x 433Mhz RF Alıcı Modülü
2 x Redüktörlü DC Motor
2 x Tekerlek
1 x Sarhoş Tekerlek
1 x En az 6V pil
6 x LED (farlar için)
ve diğerleri...

Kumanda için;
1 x PIC16F877 Mikrodenetleyicisi
1 x 433Mhz RF Verici Modülü
1 x Joystik
3 x Anahtar
1 x Buton
1 x 7805 Voltaj Regülatörü
1 x 9V Pil ve Pil Yatağı

Araba Devresinin Çalışma Mantığı

Projenin en zor ve karmaşık kısmını kapsıyor. Gövde olarak bir tahta parçası kullanıldı. Motorlar 12V’a kadar çalışabilen motorlardan seçildi. Araba arkada iki motor ve önde bir tane sarhoş tekerlek kullanıldı. Böylece güç ve kontrol arkadaki iki motorlarla sağlanmış oldu. Motorları sürmek için L293D motor sürücü entegresi kullanıldı. Öne iki ve arkaya dört tane led konuldu. Öne bir tane HCSR-04 ultrasonik sensörü konularak ile engellerin algılanabilmesi sağlandı. Mikrodenetleyici olarak PIC18F45K22 ve PIC12F675 mikrodenetleyicileri kullanıldı. İki mikrodenetleyicinin kullanılmasındaki amaç ise; ultrasonik sensörün kontrolünü ayırmak. Devrenin gücü motor sürücü devresinde bulunan 7805 voltaj regülatörüne bağlı 11.1V 1350 mAh lik LiPo pilden sağlanmaktadır. Kumandadan verileri alabilmek için ise yine 433Mhz’lik RF alıcı modülü kullanıldı. Korna için bir tane buzzer devreye eklendi. Alıcıdan gelen veriler değerlendirilerek led, korna ve motorların durumu düzenlenir.

Engel Algılamanın Çalışma Prensibi

Engel algılamak için engel ile araba arasındaki mesafenin ölçülebilmesi gerek ve bunu da bir ultrasonik sensör ile sağlamış olduk. Ses sensörden çıkar, engele çarpar ve geri gelir. Bu gidip gelme süresini PIC12F675 mikrodenetleyicisinin TIMER0 modülü ile hesaplar ve bu süreyi sesin hızı olan 340m/s ile çarparsak elde edeceğimiz veri bu gidip gelme mesafesi olacaktır. Bunu da ikiye bölersek sonuç engel ile araba arasıda ki mesafe olacaktır. Engel aldılandığında ise engelin aldılandığına dair PIC18F45K22 mikrodenetleyicisine veri gönderilir ve kornanın çalınması sağlanır.

Kumanda Devresinin Çalışma Prensibi

Uzaktan kumandalı arabaların en önemli parçalarından birisidir. Kumanda gücünü 5V voltaj regülatörüne bağlı bir pilden alıyor. Voltaj regülatöre sayesinde gerilim 5V’a düşürülüyor ve mikrodenetleyicinin çalışması için uygun hale getiriliyor. Ek olarak bir anahtar ile güç kontrol altına alınmıştır. Mikrodenetleyici olarak Microchip firmasının PIC16F877 mikrodenetleyicisi kullanıldı. Buna harici olarak 8Mhz’lik kristal bağlantısı yapıldı. Joystik ile arabanın ileri-geri ve sağa-sola hareket etmesi sağlandı. Joystik iki ayarlı dirençten oluştuğundan gerilimde dirence göre değişir. Mikrodenetleyicinin analog girişi ile bu gerilim alınıp referans gerilimini 5V seçersek elde edeceğimiz veri ile joysikin konumunu hesaplayabiliriz. Bunu sonucunda arabanın motorlarını doğru yönde hareket ettirebiliriz. Bunun dışında 2 anahtar ve 1 buton mevcut. İki anahtardan birisi arabanın ön farlarını açıp kapatırken diğeri engel algıladığında (engel 15cm den küçükse engel algılanır) kornayı çalıp çalmamasını kontrol ediyor. Buton ile kornayı (buzzer) etkinleştirebiliriz. Son olarak elde edilen verileri arabanın alıcısına gönderebilmek için 433Mhz lik RF verici modülü kullanıldı.

İletişim Protokolü

Uzaktan kontrol kelime ikilisinin yapıtaşını oluşturan kısımdır. Kumandadan alınan verilerin bir protokole göre gönderilmesi gerekir.


Buda yukarıda gözüktüğü gibi bir şekilde gerçekleşir.
İlk sinyal ile verinin başladığı konumu belirtmiş oluruz. Sonraki 8 bit ise 1 bytelik veriyi ifade eder.  Görüldüğü gibi 5V sinyali 0 bit için ve 1 bit için aynı fakat 0V sinyali 0 bit için kısa 1 bit için uzun. İşte buna göre protokol belirlenmiş oluyor. Yani alıcı her aldığı uzun 0V sinyalini 1 bitlik veri, kısa sinyali ise 0 bitlik veri olarak algılayacaktır.

 

Proje Videosu




Proje: Bahtiyar Bayram
İletişim: bahtiyar.bayramov@gmail.com

Araba Devresi


















Engel Algılama Devresi


Kumanda Devresi

















Arabanın MPLAB XC8 Kodları

/*
 * Author: ElektroNEO
 *
 * Created on 07 Aralik 2017 Persembe, 22:44
 */

// PIC18F45K22 Configuration Bit Settings
// CONFIG1H - Konfigürasyon ayarları.
#pragma config FOSC = INTIO67   // Oscillator Selection bits (Internal
                                // oscillator block)
#pragma config PLLCFG = OFF     // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON    // Primary clock enable bit (Primary clock
                                // is always enabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit
                                // (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover
                                // bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (Power up
                                // timer disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out
                                // Reset enabled in hardware only
                                // (SBOREN is disabled))
#pragma config BORV = 190       // Brown Out Reset Voltage bits
                                // (VBOR set to 1.90 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bits (Watch dog
                                // timer is always disabled. SWDTEN has
                                // no effect.)
#pragma config WDTPS = 1        // Watchdog Timer Postscale Select bits (1:1)

// CONFIG3H
#pragma config CCP2MX = PORTB3  // CCP2 MUX bit (CCP2 input/output is
                                // multiplexed with RB3)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<5:0> pins are
                                // configured as digital I/O on Reset)
#pragma config CCP3MX = PORTB5  // P3A/CCP3 Mux bit (P3A/CCP3 input/output
                                // is multiplexed with RB5)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC output
                                // and ready status are not delayed by the
                                // oscillator stable status)
#pragma config T3CMX = PORTC0   // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTD2   // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = INTMCLR  // MCLR Pin Enable bit (RE3 input pin enabled;
                                // MCLR disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit
                                // (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply
                                // ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit
                                // (Instruction set extension and Indexed
                                // Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0
                                // (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1
                                // (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2
                                // (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3
                                // (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block
                                // (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data
                                // EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF

// CONFIG6H
#pragma config WRTC = OFF
#pragma config WRTB = OFF
#pragma config WRTD = OFF

// CONFIG7L
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTR2 = OFF
#pragma config EBTR3 = OFF

// CONFIG7H
#pragma config EBTRB = OFF

// 8 Mhz dahili osilatör kullanılıyor.
#define _XTAL_FREQ 8000000
#include <xc.h>


unsigned char rxdat[5];  // (global var) Gelen RF verisini tutar.

//=======================================================================
//   RECEIVE_RF_PACKET // 1 bytelik veri alma fonksiyonu.
//=======================================================================
void receive_rf_packet(void)
{
  //-------------------------------------------------------
  // Bu fonksiyon gelen veriyi çozer ve rxdat[] dizisine kaydeder.
  // Ard arda 5 tane geçerli 1 bytelik bilgi alınmak zorundadır.
  // Fonksiyon bu 3 bilgiyi alıncaya kadar tekrar eder.
  // global değişken; unsigned char rxdat[10] 3 bylelik sonucu tutar.
  // Not: TMR0 500kHz frekansta çalışıyor, bu yüzden 200uS = 100 TMR0 sayacı
  //-------------------------------------------------------
  unsigned char rrp_data;
  unsigned char rrp_period;
  unsigned char rrp_bits;
  unsigned char rrp_bytes;

  rrp_bytes = 0;
  while(rrp_bytes < 3) // Geçerli 3 byte veri alıncaya kadar döngüde kal.
  {
    //-----------------------------------------
    // Başlangıç biti için bekle.
    while(1)
    {
      TMR0L = 0;                          // Zamanlayıcıyı sıfırla.
      while(!PORTCbits.RC4) continue;     // Yükselen kenar (/) için bekle.
      while(PORTCbits.RC4) continue;      // Düşen kenar (\) için bekle.
      rrp_period = TMR0L;                 // Geçen süreyi kaydet.

      if(rrp_period < 150) rrp_bytes = 0; // Geçerli veri değerini sıfırla
                                          // eğer hala gurultu varsa.
      else break;                         // Eğer süre >300uS ise döngüden çık.
    }

    //-----------------------------------------
    // Şimdi 8 bitlik veriyi alabiliriz.
    rrp_bits = 8;
    // rrp_bits 0 oluncaya kadar döngüde kal.
    while(rrp_bits)
    {
      TMR0L = 0; // Zamanlayıcıyı sıfırla.
      while(!PORTCbits.RC4) continue;    // Yükselen kenar (/) için bekle.
      while(PORTCbits.RC4) continue;     // Düşen kenar (\) için bekle.
      rrp_period = TMR0L;                // Geçen süreyi kaydet.

      if(rrp_period >= 150) break;       // Eğer sure >=300uS ise döngüden çık.
                                         // Bu beklenmedik bir sinyaldir.
      if(rrp_period < 100)               // Eger sure <200uS ise gelen veri 0'dir.
          rrp_data &= (unsigned char)254;// 100 = 200uS
      else if(rrp_period < 150)
          rrp_data |= (unsigned char)1;  // Eger sure >75uS ise gelen veri 1'dir.
      else break;
      // En son biti aldıktan sonra kaydırma işlemini yapmasın.
      if (rrp_bits == 1) {
          rrp_bits--;
          break;
      }
      rrp_data = (rrp_data << 1);   // Veriyi 1 bit sola kaydır.
      rrp_bits--;                   // Bir sonraki bit için yer aç.
    }

    //-----------------------------------------
    if(rrp_bits)      // Hata varsa...
    {
      rrp_bytes = 0;  // Geçerli byteleri sıfırla ve tekrar
                      // veriyi almak için başa dön.
    }
    else              // Hata yoksa 8 bitlik veriyi diziye kaydet.
    {
      rxdat[rrp_bytes] = rrp_data;
      rrp_bytes++;    // Bir sonraki veriyi almaya hazırla.
    }
  }
}
//-----------------------------------------------------------------------------

void main(void) {
    // Osilatör ayarı.
    OSCCONbits.IRCF = 6; // 110 - 8 Mhz
    // RF alıcı girişi.
    TRISCbits.TRISC4 = 1;
    ANSELCbits.ANSC4 = 0;
    PORTCbits.RC4 = 0;

    // Korna çıkışı.
    TRISAbits.TRISA1 = 0;
    ANSELAbits.ANSA1 = 0;

    // Engel algılayıcı girişi.
    TRISAbits.TRISA5 = 1;
    ANSELAbits.ANSA5 = 0;
    PORTAbits.RA5 = 0;

    // Ön far cıkışları.
    // 1. far
    TRISAbits.TRISA7 = 0;
    PORTAbits.RA7 = 0;
    // 2. far
    TRISCbits.TRISC0 = 0;
    PORTCbits.RC0 = 0;

    // Arka far çıkışları
    // 1. far
    TRISBbits.TRISB3 = 0;
    ANSELBbits.ANSB3 = 0;
    PORTBbits.RB3 = 0;
    // 2. far
    TRISBbits.TRISB5 = 0;
    ANSELBbits.ANSB5 = 0;
    PORTBbits.RB5 = 0;

    // Motor kontrol.
    // PWM1
    TRISCbits.RC2 = 0;
    ANSELCbits.ANSC2 = 0;
    PORTCbits.RC2 = 0;
    // PWM2
    TRISCbits.RC1 = 0;
    PORTCbits.RC1 = 0;
    // PWM3
    TRISEbits.RE0 = 0;
    ANSELEbits.ANSE0 = 0;
    PORTEbits.RE0 = 0;
    // PWM4
    TRISDbits.RD1 = 0;
    ANSELDbits.ANSD1 = 0;
    PORTDbits.RD1 = 0;


    T0CONbits.T08BIT = 1;   // TMR0'ı 8 bit olarak ayarla.
    T0CONbits.T0CS = 0;
    T0CONbits.PSA = 0;
    T0CONbits.T0PS = 0b001; // Prescaler = 1:4 = 500Khz
    T0CONbits.TMR0ON = 1;

    unsigned char data;     // Verinin kaydedileceği değişken.

    while(1) {
        // Veriyi al.
        receive_rf_packet();
        data = rxdat[1]; // Alınan veriyi data değişkenine ata.

        // Korna
        if (data & (0b01000000)) {
            LATAbits.LA1 = 1;
        }
        else {
            LATAbits.LA1 = 0;
        }

        // Engel
        if((data & (0b10000000)) && !(data & (0b01000000))) {
            if(PORTAbits.RA5 == 1) {
                LATAbits.LA1 = 1;
                // Geri
                LATCbits.LATC2 = 0;
                LATCbits.LATC1 = 1;
                LATEbits.LATE0 = 0;
                LATDbits.LATD1 = 1;
                LATBbits.LATB3 = 1;
                LATBbits.LATB5 = 1;
                __delay_ms(100);
            }
            else {
                LATAbits.LA1 = 0;
            }
        }
        // Ön farlar
        if (data & (0b00100000)) {
            LATAbits.LA7 = 1;
            LATCbits.LC0 = 1;
        }
        else {
            LATAbits.LA7 = 0;
            LATCbits.LC0 = 0;
        }
        // Motor kntrolü
        if ((data & (0b00001111)) == 0b0000) {
            // İleri-Sol
            LATCbits.LATC2 = 0;
            LATCbits.LATC1 = 0;
            LATEbits.LATE0 = 1;
            LATDbits.LATD1 = 0;
            LATBbits.LATB3 = 0;
            LATBbits.LATB5 = 0;
        }
        else if ((data & (0b00001111)) == 0b0001) {
            // İleri
            LATCbits.LATC2 = 1;
            LATCbits.LATC1 = 0;
            LATEbits.LATE0 = 1;
            LATDbits.LATD1 = 0;
            LATBbits.LATB3 = 0;
            LATBbits.LATB5 = 0;
        }
        else if ((data & (0b00001111)) == 0b0011) {
            // İleri-Sağ
            LATCbits.LATC2 = 1;
            LATCbits.LATC1 = 0;
            LATEbits.LATE0 = 0;
            LATDbits.LATD1 = 0;
            LATBbits.LATB3 = 0;
            LATBbits.LATB5 = 0;
        }
        else if ((data & (0b00001111)) == 0b1100) {
            // Geri-Sol
            LATCbits.LATC2 = 0;
            LATCbits.LATC1 = 0;
            LATEbits.LATE0 = 0;
            LATDbits.LATD1 = 1;
            LATBbits.LATB3 = 1;
            LATBbits.LATB5 = 0;
        }
        else if ((data & (0b00001111)) == 0b1101) {
            // Geri
            LATCbits.LATC2 = 0;
            LATCbits.LATC1 = 1;
            LATEbits.LATE0 = 0;
            LATDbits.LATD1 = 1;
            LATBbits.LATB3 = 1;
            LATBbits.LATB5 = 1;
        }
        else if ((data & (0b00001111)) == 0b1111) {
            // Geri-Sağ
            LATCbits.LATC2 = 0;
            LATCbits.LATC1 = 1;
            LATEbits.LATE0 = 0;
            LATDbits.LATD1 = 0;
            LATBbits.LATB3 = 0;
            LATBbits.LATB5 = 1;
        }
        else if ((data & (0b00001100)) == 0b1000) {
            // Dur
            LATCbits.LATC2 = 0;
            LATCbits.LATC1 = 0;
            LATEbits.LATE0 = 0;
            LATDbits.LATD1 = 0;
            LATBbits.LATB3 = 0;
            LATBbits.LATB5 = 0;
        }
    }
    return;
}

Engel Algılamanın MPLAB XC8 Kodları

/*
 * Author: ElektroNEO
 *
 * Created on 20 Aralik 2017 Çarsamba, 14:27
 */

// PIC12F675 Configuration Bit Settings
// CONFIG- Konfigürasyon ayarları
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC
                                // oscillator: I/O function on GP4/OSC2/CLKOUT
                                // pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin
                                // function is digital I/O, MCLR internally
                                // tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code
                                // protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code
                                // protection is disabled)

// 4 Mhz dahili osilator kullaniliyor.
#define _XTAL_FREQ 4000000
#include <xc.h>

void main(void) {

    OSCCALbits.CAL = 0b111111; // 4Mhz
    TRISIObits.TRISIO5 = 0; // Trigger
    TRISIObits.TRISIO4 = 1; // Echo
    TRISIObits.TRISIO1 = 0; // Cikis

    ANSELbits.ANS = 0b0000;

    T1CONbits.T1CKPS = 0b00; // 1:1 Prescale Degeri
    T1CONbits.TMR1CS = 0; // Internal clock (Fosc/4) = 1Mz

    // Uzaklığı kaydetmek için değişken.
    int distance;

    while(1) {
        // TMR1'i sıfırla.
        TMR1H = 0;
        TMR1L = 0;

        // Trigger pinine 10uS lik sinyal gönder.
        GPIObits.GP5 = 1;
        __delay_us(10);
        GPIObits.GP5 = 0;

        // Sesin gidip gelme süresini TMR1'e kaydet.
        while(!GPIObits.GP4);
        T1CONbits.TMR1ON = 1;
        while(GPIObits.GP4);
        T1CONbits.TMR1ON = 0;

        // Ölçülen süreyi distance değişkenine ata.
        distance = (TMR1L | (TMR1H<<8));
        // Bu süreyi 88 değerine bölerek mesafeyi cm cinsinden hesapla.
        // 88 değeri hesaplamalar ve denemeler sonucu bulunmuştur.
        distance = ((double)distance / 88);

        // Mesafe 2cm ile 15cm arasında ise çıkişa 1 sinyalini gönder.
        if((distance > 2) && (distance < 20)) {
            GPIObits.GP1 = 1;
        }
        // Değilse çıkışa 0 sinyalini gönder.
        else {
            GPIObits.GP1 = 0;
        }
        __delay_ms(10); // 10ms bekle.
    }

    return;
}

Kumandanın MPLAB XC8 Kodları

/*
 * Author: ElektroNEO
 *
 * Created on 16 Kasım 2017 Perşembe, 23:38
 */

// PIC16F877 Configuration Bit Settings
// CONFIG - Konfigürasyon ayarları.
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config CP = OFF         // FLASH Program Memory Code Protection bits
                                // (Code protection off)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low Voltage In-Circuit Serial Programming
                                // Enable bit (RB3 is digital I/O, HV on MCLR
                                // must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection (Code
                                // Protection off)
#pragma config WRT = ON         // FLASH Program Memory Write Enable
                                // (Unprotected program memory may be written
                                // to by EECON control)

// 8 Mhz kristal kullanılıyor.
#define _XTAL_FREQ 8000000

#include <xc.h>

//=======================================================================
//   SEND_RF_BYTE: 1 bytelik veri gonderme fonksiyonu.
//=======================================================================
void send_rf_byte(unsigned char txdat)
{
  //-------------------------------------------------------
  // Bu fonksiyon ile bir verinin herbir bitini teker teker verici
  // module gonderir.
  // Zamanlama;
  //   HIGH pulse uzunlugu; her zaman 100uS
  //   0 bit, LOW pulse uzunlugu; 50uS (toplam 0 bit pulse periyodu 150uS)
  //   1 bit, LOW pulse uzunlugu; 150uS (toplam 1 bit pulse periyodu 250uS)
  //   byteler arası boşluk, LOW pulse uzunluğu; 100uS , HI pulse uzunluğu
  //   250uS (toplam boşluk periyodu 350uS)
  //-------------------------------------------------------
  unsigned char tbit;

  // 350 us lik başlangıç biti gönderiliyor.
  // Alıcı bu biti aldığında veriyi almaya başlar.
  __delay_us(100);      // 100uS LOW
  PORTCbits.RC5 = 1;
  __delay_us(250);     // 250uS HIGH
  PORTCbits.RC5 = 0;

  // 8 bitlik veri gönderiliyor.
  for(tbit=0; tbit<8; tbit++)
  {
    __delay_us(50);         // varsayılan 0 bit LOW pulse periyodu: 50uS
    if((txdat >> 7) & (0b1))
        __delay_us(100);    // bit değeri 1 ise LOW pulse periyodunu
                            // 100uS arttır.
    PORTCbits.RC5 = 1;
    __delay_us(100);        // HIGH pulse değeri: 100uS
    PORTCbits.RC5 = 0;
    txdat = txdat << 1;     // Veri 1 sola kaydırılıyor.
  }
}

void main(void) {
    // Giriş - çıkışlar.
    // Joystik için girişler.
    TRISAbits.TRISA0 = 1; // A0 giriş.
    TRISAbits.TRISA1 = 1; // A2 giriş.
    ADCON1bits.PCFG = 0;  // PORTA analog giriş.
    ADCON1bits.ADFM = 0;  // Left justified. 6 Least Significant bits of
                          // ADRESL are read as ?0?.

    // Korna, far ve engel girişi.
    TRISBbits.TRISB1 = 1; // Korna
    TRISBbits.TRISB2 = 1; // Far
    TRISBbits.TRISB4 = 1; // Engel

    // Verici çıkışı.
    TRISCbits.TRISC5 = 0; // RF-RX
    PORTCbits.RC5 = 0;

    unsigned char data = 128;
    while(1) {

        // Sağ - Sol ayarı.
        ADCON0bits.CHS = 0b001; // Channel 1
        ADCON0bits.ADCS = 0b01; // Fosc/8
        ADCON0bits.ADON = 1;    // ADC modülünü aç.
        __delay_us(20);
        ADCON0bits.GO_nDONE = 1;
        while(ADCON0bits.GO_nDONE);
        ADCON0bits.ADON = 0;    // ADC modülünü kapat.

        if(ADRESH > 250) {
            asm("BANKSEL main@data");
            asm("bsf main@data,3");
            asm("bsf main@data,2");
        }
        else if(ADRESH < 5 ) {
            asm("BANKSEL main@data");
            asm("bcf main@data,3");
            asm("bcf main@data,2");
        }
        else {
            asm("BANKSEL main@data");
            asm("bsf main@data,3");
            asm("bcf main@data,2");
        }

        // Ileri - Geri ayarı.
        ADCON0bits.CHS = 0b000; // Channel 0
        ADCON0bits.ADCS = 0b01; // Fosc/8
        ADCON0bits.ADON = 1;    // ADC modülünü aç.
        __delay_us(20);
        ADCON0bits.GO_nDONE = 1;
        while(ADCON0bits.GO_nDONE);
        ADCON0bits.ADON = 0;    // ADC modülünü kapat.

        if(ADRESH > 200) {
            asm("BANKSEL main@data");
            asm("bcf main@data,1");
            asm("bcf main@data,0");
        }
        else if(ADRESH < 50) {
            asm("BANKSEL main@data");
            asm("bsf main@data,1");
            asm("bsf main@data,0");
        }
        else {
            asm("BANKSEL main@data");
            asm("bcf main@data,1");
            asm("bsf main@data,0");
        }

        // Korna
        if(PORTBbits.RB1 == 1) {
            asm("BANKSEL main@data");
            asm("bcf main@data,6");
        }
        else if(PORTBbits.RB1 == 0){
            asm("BANKSEL main@data");
            asm("bsf main@data,6");
        }
        // Ön farlar
        if(PORTBbits.RB2 == 1) {
            asm("BANKSEL main@data");
            asm("bsf main@data,5");
        }
        else if(PORTBbits.RB2 == 0){
            asm("BANKSEL main@data");
            asm("bcf main@data,5");
        }

        // Engel
        if(PORTBbits.RB4 == 1) {
            asm("BANKSEL main@data");
            asm("bsf main@data,7");
        }
        else if(PORTBbits.RB4 == 0){
            asm("BANKSEL main@data");
            asm("bcf main@data,7");
        }

        // 1 bytelik veri gönderilir.
        send_rf_byte(data);
    }
}

4 yorum:

  1. İyi günler abi benim de uzaktan kumandalı araba projem var okul için abi yukarda bulunan kodları ben hangi programla kodu pic e yüklerim

    YanıtlaSil
  2. MPLABX programı ile kodları derlyip hex disyasını pickit ile microdenetleyiciye yükleyeceksiniz.

    YanıtlaSil
  3. merhabalar, mikroişlemci olarak pic18f4620 ya da pic18f452 kullansam olur mu?

    YanıtlaSil
    Yanıtlar
    1. Olur tabi ki ama yazılımı ona göre düzenlemen gerekiyor.

      Sil