• 1
  • 2

Riadenie Unipolárneho Krokového motora #2

. .

Rotácia v náhodnom smere, s náhodnou rýchlosťou a náhodným počtom krokov.

 

Doporučené preštudovať: Krokové Motory | Riadenie Unipolárneho Krokového motora #1



Ako podklad pre tento projekt použijem projekt Riadenie Unipolárneho Krokového motora #1, kde sme napísali program pre rotáciu motora v jednom smere a v konštantnej rýchlosti.

Typ motora + schémy použijem stávajúce z predošlého projektu.

Napíšem program, ktorý nám bude otáčať motor v náhodnom smere, náhodnou rýchlosťou a s náhodným počtom krokov.

stepper_diall.h


struct _unipolar_stepper_motor_ {
      struct __attribute__ ((packed)) {
             volatile unsigned int *Port;
             volatile unsigned int *Tris;
                }Direct;

      struct __attribute__ ((packed)) {
             int * Pins;
             int pin_size;
                }Config;

      struct __attribute__ ((packed)) {
             int from;
             int to;
             int routing;
             int left;
             int right;
                }Control;

     struct __attribute__ ((packed)) {
             int i;
             int a;
             int b;
                }Tmp;
}Stepper;

void Stepper_Init()
{
   int stepper_pins[] = {1,2,3,7};
   int err=1;

   if(*Stepper.Direct.Port == PORTA && PORTA != __No__Used__ && TRISA != __No__Used__)
    { Stepper.Direct.Tris = uintptr &TRISA; err=0; }
   if(*Stepper.Direct.Port == PORTB && PORTB != __No__Used__ && TRISB != __No__Used__)
    { Stepper.Direct.Tris = uintptr ⧍ err=0; }
   if(*Stepper.Direct.Port == PORTC && PORTC != __No__Used__ && TRISC != __No__Used__)
    { Stepper.Direct.Tris = uintptr &TRISC; err=0; }
   if(*Stepper.Direct.Port == PORTD && PORTD != __No__Used__ && TRISD != __No__Used__)
    { Stepper.Direct.Tris = uintptr &TRISD; err=0; }

   if(err==0)
    {
       Stepper.Config.pin_size = sizeof(stepper_pins)/sizeof(int);
       Stepper.Config.Pins = malloc(Stepper.Config.pin_size);
       Stepper.Control.left = 0;
       Stepper.Control.right = 1;

       for(Stepper.Tmp.i = 0; Stepper.Tmp.i < Stepper.Config.pin_size; Stepper.Tmp.i++)
          {
             Stepper.Config.Pins[Stepper.Tmp.i] = stepper_pins[Stepper.Tmp.i];
          }

       for(Stepper.Tmp.i = 0; Stepper.Tmp.i < Stepper.Config.pin_size; Stepper.Tmp.i++)
          {
             Init_Port(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.i],"digital");
             Config_OUT(*Stepper.Direct.Tris,Stepper.Config.Pins[Stepper.Tmp.i]);
             Bit_Clr(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.i]);
          }
     }
}

void Stepper_Go(int way, int timer_ms, int rount)
{
   if(way == Stepper.Control.left)
    {
       Stepper.Control.from = 0;
       Stepper.Control.to = Stepper.Config.pin_size;
       Stepper.Control.routing = BACKWARD;

    } else if(way == Stepper.Control.right)
               {
                  Stepper.Control.from = Stepper.Config.pin_size-1;
                  Stepper.Control.to = -1;
                  Stepper.Control.routing = FORWARD;
               }

   for (Stepper.Tmp.b=0;Stepper.Tmp.b<rount;Stepper.Tmp.b++)     
       {
          for(Stepper.Tmp.i = Stepper.Control.from; Stepper.Tmp.i!=Stepper.Control.to;)
             {
                for(Stepper.Tmp.a=Stepper.Control.from; Stepper.Tmp.a!=Stepper.Control.to;)
                   {
                      if(Stepper.Tmp.i==0) //1.takt - start
                       {
                          if(Stepper.Tmp.a==0 || Stepper.Tmp.a==1)
                           {
                              Bit_Set(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                           } else
                                {
                                   Bit_Clr(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                                }
                       }

                       if(Stepper.Tmp.i==1) //2.takt - start
                        {
                           if(Stepper.Tmp.a==1 || Stepper.Tmp.a==2)
                            {
                               Bit_Set(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                            } else
                                {
                                   Bit_Clr(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                                }
                       }

                      if(Stepper.Tmp.i==2) //3.takt - start
                       {
                          if(Stepper.Tmp.a==2 || Stepper.Tmp.a==3)
                           {
                              Bit_Set(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                           } else
                                {
                                   Bit_Clr(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                                }
                       }

                      if(Stepper.Tmp.i==3) //4.takt - start
                       {
                          if(Stepper.Tmp.a==3 || Stepper.Tmp.a==0)
                           {
                              Bit_Set(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                            } else
                                 {
                                    Bit_Clr(*Stepper.Direct.Port,Stepper.Config.Pins[Stepper.Tmp.a]);
                                 }
                       }

                     if(Stepper.Control.routing == Stepper.Control.left) //prechadzanie pola pinov /urcenie smeru/
                      { Stepper.Tmp.a++; } else { Stepper.Tmp.a--; }
                   }

            Delay_ms(timer_ms);

            if(Stepper.Control.routing == Stepper.Control.left)
             { //prechadzanie taktov /urcenie smeru/
                Stepper.Tmp.i++;
             } else {
                         Stepper.Tmp.i--;
                       }
             }
       }
   Delay_ms(1500);
}




Úpravou pôvodného kódu sme pridali jeden parameter rount do funkcie Stepper_Init. Parameter je ako premenná použitý v ďalšom cykle "for".
Je potrebné si uvedomiť, že pri predošlom projekte sme veľa vecí neriešili, nakoľko funkcia beží v cykle while, v súbore main ako slučka. Jeden krok pozostáva zo štyroch taktov. Tento fakt je v slučke zacyklený, preto počekt taktov nie je nutné neakým spôsobom ďalej riešiť.

V tomto projekte však potrebujeme, aby sa nám motor otočil v náhodnom smere, náhodnou rýchlosťou a urobil náhodný počet krokov.
Jedna otočka okolo svojej osy - 48 krokov. Budeme požadovať, aby sa motor otočil minimálne o 4 kroky a maximálne o 48 - celá otočka.
Túto úlohu má pridaný cyklus "for", ktorý pracuje so spomenutým parametrom rount .

Isto prichádza otázka, k čomu je nám ďalšie spomalenie Delay_ms(1500); .
Predstavte si, že cheme vykonať jednu celú otočku pri jednej rýchlosti. V zápätí sa nám generuje polovičná otáčka pri tej istej rýchlosti. Aby sme sa vyhli tomu, že motor urobí jednu a pol otáčky bez zastavenia, každú jednu sekvenciu generovania odseba časovo oddelíme.
Zabránime tomu, aby sa nám motor točil bez zastávky a zaručíme, že motor sa nemusí točiť vôbec.


main.c


  #define __NoTypeDefh__

#include "config_diall.h"
#include "stepper_diall.h"
#include "config_words.h"

char *PageSys(void)
{
   return "0x21";
}


int main(void)
{
   Stepper.Direct.Port = uintptr &PORTB;
   Stepper_Init();

   while(1)
    {
       Stepper_Go(way_tracking[Randoming(0,2)],Randoming(23,200),Randoming(4,48));
    }
}




Obsah súbora main.c sa od predošlého projektu moc nelíši. Upravená je len funkcia Stepper_Go.

Pole way_tracking[] je globálne definované pole v konfiguračnóm súbore config_diall.h .
Obsahuje globálne premenné FORWARD,BACKWARD,UP,DOWN.
Funkciou Randoming(0,2) sa generujú náhodne čísla od 0-2, ktoré reprezentujú indexy poľa. Pri generovaní indexu "2" sa smer vo funkcií nerozozná a motor sa nepohybuje.

Ako hodnota druhého parametra je generovaná rýchlosť, Randoming(23,200).

V tretie v poradí sa generuje počet krokov - od 4 do 48, Randoming(4,48).


Jadrom náhodného výberu je funkcia Randoming(x,y) ktorú som zakomponoval do prostredia
config_diall pri návrhu tochto projektu. Ide o LFSR náhodný generátor.

Celý článok je k dispozícií >> Tu <<