Pravih za rodjaka neki dan neki primer pa reko mozda bi bilo zgodno podeliti ga.

Shema - klikni za celu semu

Shema - klikni za celu semu

Shema sadrzi

  • mikrokontroler PIC16F887 koji radi na internom oscilatoru na 8MHz
  • reset kolo na MCLR pinu
  • primer kako kontrolisati 2 ledare preko samo jednog pina
  • karakter LCD u 4-bitnom modu (zakacena su paralelno dva, jedan sa jednom linijom i jedan sa dve)
  • unipolarni stepper motor vezan preko ULN2003 (koji je u stvari 7 darlingtona u jednoj kutiji)
  • bipolarni stepper motor sa L297+L298 drajver kombinacijom
  • servo motor

Sors je “samoobjasnjihv” tako da, evo ga:


// LCD pinovi
sbit LCD_EN at RD1_bit;
sbit LCD_RS at RD2_bit;
//sbit LCD_RW at RD3_bit; // MikroC ne koristi RW pin
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_RS_Direction at TRISD2_bit;
//sbit LCD_RW_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;

char txt1[] = "TEST TEKST";
char txt2[] = "neki tekst";
char txt3[] = "primer";
char txt4[] = "za lcd";
char txt5[] = "Vozi unapred";
char txt6[] = "UNIPOLARNI STEPP";
char txt7[] = "Vozi unazad";
char txt8[] = "STOP";
char txt9[] = "KRAJ";

// koraci stepper motora
char unipolar_step[] = {0b1100, 0b0110, 0b0011, 0b1001};

#define  Move_Delay() Delay_ms(200)

unsigned char i;

void main(){
  //////////////////////////////////////
  //   INICIJALIZACIJA                //
  //////////////////////////////////////

  // Ugasi ADC (konfigurisi AN pinove kao digital IO)
  ANSEL  = 0;
  ANSELH = 0;

  // Ugasi komparatore
  C1ON_bit = 0;
  C2ON_bit = 0;

  //////////////////////////////////////
  //   PALI, GASI LEDARU              //
  //////////////////////////////////////

  // Na D0 su nam charlieplexed ledare
  TRISD0_bit=1; //postavi D0 na imput - gasi obe ledare
  for (i = 0; i < 10; i++){ //20 puta se izvrti
     //upali prvu ledaru
     RD0_bit=0; //D0 je GND
     TRISD0_bit=0; //D0 je "izlaz"
     Delay_ms(100); //sacekaj 500ms

     //Ugasi ledare
     TRISD0_bit=1;
     Delay_ms(100); //sacekaj 500ms

     //upali drugu ledaru
     RD0_bit=1; //D0 je 5V
     TRISD0_bit=0; //D0 je "izlaz"
     Delay_ms(100); //sacekaj 500ms

     //Ugasi ledare
     TRISD0_bit=1;
     Delay_ms(100); //sacekaj 500ms
  }

  //////////////////////////////////////
  //   LCD  tekstualni                //
  //////////////////////////////////////

  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Cmd(_LCD_CURSOR_OFF);

  Lcd_Out(1,6,txt3);

  Lcd_Out(2,6,txt4);
  Delay_ms(2000);
  Lcd_Cmd(_LCD_CLEAR);

  Lcd_Out(1,1,txt1);
  Lcd_Out(2,5,txt2);

  //iskuliraj 2 sekunde
  Delay_ms(2000);

  //Mrducaj malo tekst na lcd-u
  for(i=0; i<4; i++) {
    Lcd_Cmd(_LCD_SHIFT_RIGHT);
    Move_Delay();
  }

  for(i=0; i<8; i++) {
    Lcd_Cmd(_LCD_SHIFT_LEFT);
    Move_Delay();
  }

  for(i=0; i<8; i++) {
    Lcd_Cmd(_LCD_SHIFT_RIGHT);
    Move_Delay();
  }

  //////////////////////////////////////
  //   UNIPOLARNI STEPPER MOTOR       //
  //////////////////////////////////////

  //mrducaj malo stepper

  //SPREMI RC4 - RC7 da budu izlaz
  TRISC4_bit=0;
  TRISC5_bit=0;
  TRISC6_bit=0;
  TRISC7_bit=0;

  //sacekaj sekund
  Delay_ms(1000);

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,txt5);
  Lcd_Out(2,1,txt6);

  //UNAPRED
  for(i=0;i<100;i++){ // 100 koraka
     RC4_bit =  unipolar_step[i%4] >> 3;
     RC5_bit = (unipolar_step[i%4] >> 2) & 1;
     RC6_bit = (unipolar_step[i%4] >> 1) & 1;
     RC7_bit =  unipolar_step[i%4]       & 1;
     Delay_ms(80); //pauza izmedju koraka, sto manja pauza, brze se vrti stepper
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,txt8);

  //sacekaj sekund
  Delay_ms(1000);

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,txt7);
  Lcd_Out(2,1,txt6);

  //UNAZAD
  for(i=100;i>0;i--){ // 100 koraka
     RC4_bit =  unipolar_step[i%4] >> 3;
     RC5_bit = (unipolar_step[i%4] >> 2) & 1;
     RC6_bit = (unipolar_step[i%4] >> 1) & 1;
     RC7_bit =  unipolar_step[i%4]       & 1;
     Delay_ms(80); //pauza izmedju koraka, sto manja pauza, brze se vrti stepper
  }
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,txt8);
  //sacekaj sekund
  Delay_ms(1000);

  //////////////////////////////////////
  //   BIPOLARNI STEPPER MOTOR        //
  //////////////////////////////////////

  //SPREMI RC0, RC1 da budu izlaz
  RC0_bit = 0;
  RC1_bit = 0;
  TRISC0_bit=0;
  TRISC1_bit=0;
  RC0_bit = 0;

  //vozi unapred
  Delay_ms(1000);
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"Vozi unapred");
  Lcd_Out(2,1,"BIPOLARNI STEPP");

  RC1_bit = 1; // u smeru kazaljke na satu
  for (i=0;i<200;i++){//200 koraka
    RC0_bit = 1;
    Delay_ms(20);
    RC0_bit = 0;
    Delay_ms(20);
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,txt8);
  //sacekaj sekund
  Delay_ms(1000);

  //vozi unazad
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"Vozi unazad");
  Lcd_Out(2,1,"BIPOLARNI STEPP");

  RC1_bit = 0; // suprotno smeru kazaljke na satu
  for (i=0;i<200;i++){//200 koraka
    RC0_bit = 1;
    Delay_ms(20);
    RC0_bit = 0;
    Delay_ms(20);
  }

  //////////////////////////////////////
  //  SERVO MOTOR - DIREKTNA KONTROLA //
  //////////////////////////////////////

  TRISC2_bit = 0; //izlaz
  RC2_bit = 0;

  //DUZINA PULSA ODREDJUJE POZICIJU SERVO MOTORA
  //STANDARD JE 1500us je "centar" 900us je "skroz levo", 2100us je "skroz desno"
  //MADA TO ZAVISI OD MOTORA DO MOTORA, OBICNO PISE U DOKUMENTACIJI MOTORA ALI
  //SE UVEK MOZE EXPERIMENTALNO UTVRDITI

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - CENTAR");
  Lcd_Out(2,2,"DIREKTNO");

  for (i=0;i<50;i++){
     //posalji puls
     RC2_bit = 1;
     Delay_us(1500);
     RC2_bit = 0;
     //cekaj do sledeceg pulsa
     Delay_ms(25);
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - -90");
  Lcd_Out(2,2,"DIREKTNO");

    for (i=0;i<50;i++){
     //posalji puls
     RC2_bit = 1;
     Delay_us(900);
     RC2_bit = 0;
     //cekaj do sledeceg pulsa
     Delay_ms(25);
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - +90");
  Lcd_Out(2,2,"DIREKTNO");

    for (i=0;i<50;i++){
     //posalji puls
     RC2_bit = 1;
     Delay_us(2000);
     RC2_bit = 0;
     //cekaj do sledeceg pulsa
     Delay_ms(25);
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - -45");      //53 1200
  Lcd_Out(2,2,"DIREKTNO");

    for (i=0;i<50;i++){
     //posalji puls
     RC2_bit = 1;
     Delay_us(1250);
     RC2_bit = 0;
     //cekaj do sledeceg pulsa
     Delay_ms(25);
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - +45");               //36 1700
  Lcd_Out(2,2,"DIREKTNO");

    for (i=0;i<50;i++){
     //posalji puls
     RC2_bit = 1;
     Delay_us(1750);
     RC2_bit = 0;
     //cekaj do sledeceg pulsa
     Delay_ms(25);
  }

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - CENTAR");
  Lcd_Out(2,2,"DIREKTNO");

  for (i=0;i<50;i++){
     //posalji puls
     RC2_bit = 1;
     Delay_us(1500);
     RC2_bit = 0;
     //cekaj do sledeceg pulsa
     Delay_ms(25);
  }

  //////////////////////////////////////
  //  SERVO MOTOR - PWM               //
  //  Ovaj uC je suvise brz tako da   //
  //  ne moze da nam da dovoljno spor //
  //  PWM da bi imali full range od   //
  //  min do max. minimalni PWM na    //
  //  8MHZ je 489Hz sto je prebrzo    //
  //  idealan pwm bi bio negde ~100Hz //
  //////////////////////////////////////

  TRISC2_bit = 0; //izlaz
  RC2_bit = 0;
  PWM1_Init(489); //Hz
  PWM1_Set_Duty(0);
  PWM1_Start();

  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"SERVO - SETAJ");
  Lcd_Out(2,2,"PWM");
  for (i=0;i<200;i+=2){
    PWM1_Set_Duty(i);
    Delay_ms(100);
  }
  PWM1_Stop();

  //KRAJ
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,txt9);
  Lcd_Out(2,4,txt9);
  while(1){
    for(i=0; i<4; i++) {
      Lcd_Cmd(_LCD_SHIFT_RIGHT);
      Move_Delay();
    }
    for(i=0; i<4; i++) {
      Lcd_Cmd(_LCD_SHIFT_LEFT);
      Move_Delay();
    }
  }
}