Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
NOVATEK-ELECTRO POLSKA SP. Z O.O.NOVATEK-ELECTRO POLSKA SP. Z O.O.
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

silnik krokowy,graf,stopniowy wzrost prędkości

26 Oct 2010 20:30 6587 81
  • Level 38  
    To graf:
    silnik krokowy,graf,stopniowy wzrost prędkości
    A to kod:(fragment)
    Code:

    //*****sterowanie silnikiem w zależności od stanu foto i stanu poprzedniego obrotów

    void ster_silnika (void)
    {
       static uint8_t stan_prawo;
       static uint8_t stan_lewo;
       static uint8_t stan_stop;
    //******************
       if(napiecie[1]+15<napiecie[3]) stan_prawo=1;   
       else stan_prawo=0;
    //********************
       if(napiecie[3]+15<=napiecie[1])   stan_lewo=1;
       else stan_lewo=0;
    //****************
       if((abs(napiecie[3]-napiecie[1])<=15)) stan_stop=1;
       else stan_stop=0;
    //****************
       if((stan_prawo)&&(!stan_stop))
       {
       if(g_accel_decel_counter++ >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(1)|0x0f);
       twistop();
       }
    //****************
       if((stan_lewo)&&(!stan_stop))
       {
       if(g_accel_decel_counter++ >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(-1)|0x0f);
       twistop();
       }
    //***************
       if(stan_stop)
       {
       if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
       TCNT2=g_accel_decel_counter;
       }
    }

    Prędkość ładnie się zwiększa- ale nie zmniejsza się stopniowo.
    Gdzie jest błąd w rozumowaniu?
    A potem- może ładniejszy kod?
  • NOVATEK-ELECTRO POLSKA SP. Z O.O.NOVATEK-ELECTRO POLSKA SP. Z O.O.
  • Helpful post
    Level 38  
    Jedna uwaga:

    Code:
    if(g_accel_decel_counter++ >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
    
    TCNT2=g_accel_decel_counter;


    Jedna uwaga:

    Chcesz żeby g_accel_decel_counter miało wartość MAX_OBR, jednak tak nie jest bo:

    W warunku najpierw zostaje sprawdzona wartość g_accel_decel_counter, a dopiero potem zwiększona w wyniku czego dostajesz max_obr = MAX_OBR + 1

    a resztę kodu oglądam :P

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

    A jest zapewnione, że nie zostaną przyciśnięte na raz przyciski stan lewo i stan prawo ? Gdy tak by się stało to wówczas nastąpi inkrementacja zmiennej a potem dekrementacja i tak w kółko... w wyniku czego prędkość nie zmieni się w ogóle, przy pełnej parze będziesz tylko w kółko zmieniał polaryzację na przeciwną, musiał byś dać chyba jeszcze

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

    Co do lepszego kodu to Ci nie dam, bo moje kody Ci się nie podobają :P


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

    Wybacz nie zauważyłem, że stany zależą od napięcia, chyba, że na kanałach coś jest skopane :) spróbuj ręcznie
  • NOVATEK-ELECTRO POLSKA SP. Z O.O.NOVATEK-ELECTRO POLSKA SP. Z O.O.
  • Level 38  
    No to zmieniłem- na ++g_accel_decel_counter.
    Ale to mały problem.
    Przy 250 chodzi i przy 251.
    Popatrz na graf.
    Jak silnik osiągnął pewne obroty (max albo nie) i jeśli ma stanąć albo zmienić kierunek- to najpierw ma dążyć do obrotów 0.
    A potem zmienić kierunek.
    Ale jak osiągnął max w prawo (albo tylko trochę) i dostaje 0 ale potem znowu w prawo to licznik ma się najpierw zmniejszać a potem- zanim osiągnie 0- zwiększać.
  • Helpful post
    Level 38  
    Wszystko ładnie pięknie tylko dlaczego nie wysyłasz tej zmniejszonej prędkości przy stan_stop do układu ? :)
  • Level 38  
    No właśnie- podstawowy błąd.
    Zacząłem- ale się zaplątałem.
    Funkcja jest taka- albo w prawo albo w lewo:
    Code:

    //***********************Program Dr_Vee do sterowania silnika- nieco zmieniony
    enum { NUM_STEPS = 8 };
    enum { STEP_MASK = 0xf0 };
    // Układ I2C: A B C D x x x x
    static const uint8_t steps[NUM_STEPS] =
    {
       0b10000000, 0b11000000, 0b01000000, 0b01100000, 0b00100000, 0b00110000, 0b00010000, 0b10010000
    };

    // obrót o 1/2 kroku w prawo: advance_step(1)
    // obrót o 1/2 kroku w lewo:  advance_step(-1)
    uint8_t advance_step(int8_t nsteps)
    {
        static uint8_t stepNum;
       static uint8_t kroczek;
        kroczek = (kroczek & ~STEP_MASK) | steps[stepNum];
        stepNum += nsteps;
        stepNum %= NUM_STEPS;
       return kroczek;
    }

    No i właściwie w rozumowaniu się zaplątałem.
    A Twoje rozwiązanie z pętlą for jest dobre- nie obrażaj się.
    Ale nie pozwala wstawić nazw- tylko miejsca z tablicy.
    A dopóki nie opanuję programu to wygodniej wstawiać nazwy niż przepinać kabelki.
    Teraz jest tak- Twoja pętla zakomentowana:
    Code:

          if(gflaga_pomiaru)//***************Tu sprawdzamy flagę i dlatego ten fragment wykonuje się co 1/4s      
          {         
    /*         for(i = 0; i < LICZBA_KANALOW; i++)//pętla pomysłu gaskoina- trochę niewygodna- ale co zrobić jak dobra
             {
                 if(i<2)
                {
                     LCD_GoTo(0,i);
                     LCD_GoTo(0,i);
                  }
                else
                {
                    LCD_GoTo(7,i-2);
                     LCD_GoTo(7,i-2);
                 }
                 LCD_WriteText(dtostrf(napiecie[i]/50.0,5,2,buffer_nap));
             }
    */
          napiecie_foto_1=napiecie[0];   
          LCD_GoTo(0,0);
           LCD_WriteText(dtostrf(napiecie_foto_1/=50.0,5,2,buffer_nap));

          napiecie_solar=napiecie[1];
          LCD_GoTo(0,1);
          LCD_WriteText(dtostrf(napiecie_solar/=50.0,5,2,buffer_nap));

          napiecie_aku=napiecie[2];
          LCD_GoTo(7,0);
          LCD_WriteText(dtostrf(napiecie_aku/=50.0,5,2,buffer_nap));

          napiecie_foto_2=napiecie[3];
          LCD_GoTo(7,1);
          LCD_WriteText(dtostrf(napiecie_foto_2/=50.0,5,2,buffer_nap));

           gflaga_pomiaru=0;   // A tu flagę kasujemy- po 1/4s znowu się ustawi
          SetAdcKanal();
          }      //Tu się kończy ten fragment co się wykonuje co 1/4s
             
  • Helpful post
    Level 38  
    Code:
    LCD_WriteText(dtostrf(napiecie_foto_1/=50.0,5,2,buffer_nap)); 


    już się raz na to nadziałeś co tam robi to /= ? chyba, że jest celowe

    Poza tym jak chcesz się odwołać do nazwy to zrób

    Code:

    #define    SOLAR                                  0
    #define    BATERIA                               1
    #define    GNIAZDKO_ELEKTRYCZNE        2
    #define    SLUP_WYSOKIEGO_NAPIECIA    3
    #define    ELEKTROWNIA                        4
    #define    OGNIWO_TERMOJADROWE        5

    (coś się tabulacje wykrzaczyły)
    i odwołasz się poprzez:

    Code:
    Voltage[ELEKTROWNIA]


    możesz też zrobić enuma, ale musisz się upewnić, że nie popieprzą się indeksy tablicy

    Przy okazji będziesz mógł także zmienić kanał tak:

    Code:
    SetADCKanal(OGNIWO_TERMOJADROWE)


    ale to tylko takie tam moje gdybanie.

    Do definiowania stałych polecam jednak define a nie enumy :P Nie obrażam się, tylko śmieję się z komentarza w kodzie :P
  • Level 38  
    Już poprawiłem- już jest bez podstawiania- napiecie_foto_1/50.0.
    Teraz jest tak w stanie stop:
    Code:

    //***************
       if(stan_stop)
       {
       if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
       TCNT2=g_accel_decel_counter;
       if(stan_prawo)
       {
       TCNT2=g_accel_decel_counter;
       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(1)|0x0f);
       twistop();
       }
       if(stan_lewo)
       {
       TCNT2=g_accel_decel_counter;
       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(-1)|0x0f);
       twistop();
       }

    Ale dalej nie tak.
    Narasta ładnie.
    Niemożliwe jest aby naraz był stan_lewo, stan_prawo albo stan_stop.
    Jest histereza- to raz.
    Dwa- nie może być naraz większe napięcie na obu fotoopornikach.
    Na którymś musi być mniejsze.
    To nie przyciski.
  • Helpful post
    Level 38  
    a tak poza tym to już wszystko działa ?

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

    Ja w to zerknę jutro albo najchętniej pojutrze lub w piątek bo dzisiaj już się słaniam na nogach, do piątku pewnie ktoś mądrzejszy coś napisze. Wiem, że nie przyciski, zmęczony jestem już :P
  • Level 38  
    No to co miało działać- działa.
    Sterowanie kierunkiem obrotów silnika, wyświetlacz, pomiar z fotooporników na ADC,uśrednianie pomiarów, I2C- którym steruję PCF8574 i z niego ULN i silnik i Twoja funkcja zmiany kanałów.
    A teraz mnie podkorciło zrobić stopniowe zwiększanie i zmniejszanie obrotów silnika.
    Tak rzut monetą wypadł.
    I tak się kręci- ale trzeba się tego nauczyć.
    Potem zegarek.
    Albo coś innego.
  • Helpful post
    User removed account  
  • Level 38  
    Na razie zrobiłem tak:
    Code:

    //*****sterowanie silnikiem w zależności od stanu foto i stanu poprzedniego obrotów

    void ster_silnika (void)
    {
       static uint8_t stan_prawo;
       static uint8_t stan_lewo;
       static uint8_t stan_stop;
       static int8_t flaga_kierunku;
    //******************
       if(napiecie[1]+15<napiecie[3]) stan_prawo=1,flaga_kierunku=1;   

       else stan_prawo=0;
    //********************
       if(napiecie[3]+15<=napiecie[1])   stan_lewo=1,flaga_kierunku=-1;

       else stan_lewo=0;
    //****************
       if((abs(napiecie[3]-napiecie[1]))<=15) stan_stop=1;

       else stan_stop=0;
    //****************
       if(stan_prawo)
       {
       if(++g_accel_decel_counter >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(1)|0x0f);
       twistop();
       }
    //****************
       if(stan_lewo)
       {
       if(++g_accel_decel_counter >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(-1)|0x0f);
       twistop();
       }
    //***************
       if(stan_stop)
       {

       if(flaga_kierunku==1)
       {
       if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
       TCNT2=g_accel_decel_counter;
       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(1)|0x0f);
       twistop();
       }

       if(flaga_kierunku==-1)
       {
       if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
       TCNT2=g_accel_decel_counter;
       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(-1)|0x0f);
       twistop();
       }

       }
    }

    Zwiększa i zmniejsza obroty stopniowo.
    Ale pomimo że wyświetla TCNT2==0 to silnik się kręci.
    No i przy szybkiej zmianie lewo/prawo nie przechodzi przez 0.
  • Helpful post
    User removed account  
  • Level 38  
    Kolejna poprawa działania- silnik się zatrzymuje stopniowo do 0.
    A także jeśli w trakcie zmniejszania obrotów ponownie otrzymuje sygnał prawo/lewo to zwiększa ponownie obroty.
    Muszę jeszcze zrobić tak aby przy zmianie kierunku przechodził przez 0.
  • Helpful post
    User removed account  
  • Level 38  
    Teraz jest tak:
    Code:

    //*****sterowanie silnikiem w zależności od stanu foto i stanu poprzedniego obrotów

    void ster_silnika (void)
    {
       static uint8_t stan_prawo;
       static uint8_t stan_lewo;
       static uint8_t stan_stop;
       static int8_t flaga_kierunku;
    //******************
       if(napiecie[1]+15<napiecie[3])   
       {
          if(g_accel_decel_counter==0)
          {
          stan_prawo=1;
          flaga_kierunku=1;
          }
          else
          {   
           if(flaga_kierunku==1) stan_prawo=1;
           else stan_stop=1;
           }
       }
    //********************
       if(napiecie[3]+15<=napiecie[1])
       {
          if(g_accel_decel_counter==0)
          {
          stan_prawo=1;
          flaga_kierunku=-1;
          }
          else stan_lewo=0;
          {   
           if(flaga_kierunku==-1) stan_lewo=1;
           else stan_stop=1;
          }
        }
    //****************
       if((abs(napiecie[3]-napiecie[1]))<=15) stan_stop=1;

       else stan_stop=0;
    //****************
       if(stan_prawo)
       {
       if(++g_accel_decel_counter >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;
       stan_prawo=0;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(1)|0x0f);
       twistop();
       }
    //****************
       if(stan_lewo)
       {
       if(++g_accel_decel_counter >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;
       stan_lewo=0;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(-1)|0x0f);
       twistop();
       }
    //***************
       if(stan_stop)
       {
          if(flaga_kierunku==1)
          {
          if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
          TCNT2=g_accel_decel_counter;
             if(g_accel_decel_counter > 0 )
             {
             twistart();
             twiwrite(0x40 | (PCF8574ADDR << 1));
             twiwrite(advance_step(1)|0x0f);
             twistop();
             }
          }
          if(flaga_kierunku==-1)
          {
          if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
          TCNT2=g_accel_decel_counter;
             if(g_accel_decel_counter > 0 )
             {
             twistart();
             twiwrite(0x40 | (PCF8574ADDR << 1));
             twiwrite(advance_step(-1)|0x0f);
             twistop();
             }
          }
       }
    }

    A zachowanie jest takie:
    Silnik przyspiesza i zwalnia prawidłowo.
    Ale gdy kręci się w jednym z kierunków i zmieniam mu kierunek zatrzymuje się-
    g_accel_decel_counter pokazuje jakąś wartość a silnik stoi.
    Gdy ponownie odsłonię fotoopornik zwalnia do 0.
    Gdy ten fotoopornik zasłaniam i odsłaniam kilkakrotnie w czasie hamowania to silnik zwalnia- zatrzymuje się- ponownie zwalnia i tak do 0.
    Ale jeśli w trakcie tego skokowego zwalniania ponownie każę mu kręcić się w początkowym kierunku to mimo że stał zaczyna kręcić się od obrotów które miał- a nie od zera.
    W nocie Atmela 446 jest opis jak sterować stopniowym przyspieszaniem silnika- ale tylko w jednym kierunku.
    Może ten graf jest nie taki?
  • Helpful post
    User removed account  
  • Level 38  
    Tam są głownie skomplikowane obliczenia rampy akceleracji i deceleracji.
    A ja to chciałem uprościć- acc i dec mają te same nachylenia prędkości.
    W dodatku przyspieszenie nie musi być liniowe- tylko zależne od czasu przerwania.
    Ale o ile graf rozumiem- to mam wrażenie że powyżej 10 if zagnieżdżonych program zaczyna żyć własnym życiem.
  • User removed account  
  • Level 38  
    Teraz zrobiłem tak:
    Code:

    //ster_silnika()- funkcja mająca powodować stopniowy wzrost i malenie prędkości obrotowej silnika krokowego
    //w prawo i w lewo
    //g_accel_decel_counter- zmienna której wartość wpisujemy do licznika2
    //advance_step()- funkcja sterująca krokami- działa dobrze
    //flaga_napięcie_foto- na którym fotooporniku jest większe napięcie- pomiar z ADC- działa dobrze
    //sterowanie przez I2C też działa
    void ster_silnika (void)
    {
       static uint8_t stan_prawo;
       static uint8_t stan_lewo;
       static uint8_t stan_stop;
       volatile int8_t flaga_napiecie_foto;
    //*****************
       if(napiecie[1]+15<napiecie[3])//w prawo   
       {
       stan_prawo=1;
       flaga_napiecie_foto=PRAWO;
       }
    //   else stan_prawo=0;
    //**************************
       if(napiecie[3]+15<=napiecie[1])//w lewo
       {
       stan_lewo=1;
       flaga_napiecie_foto=LEWO;
       }
    //   else stan_lewo=0;
    //****************
       if((abs(napiecie[3]-napiecie[1]))<=15)
       {
       stan_stop=1;
       flaga_napiecie_foto=STOP;
       }
    //   else stan_stop=0;
    //****************
       if(stan_prawo && flaga_napiecie_foto==PRAWO)//działa
       {
       if(++g_accel_decel_counter >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;
    //   stan_prawo=0;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(1)|0x0f);
       twistop();
       }
    //****************
       if(stan_lewo && flaga_napiecie_foto==LEWO)//działa
       {
       if(++g_accel_decel_counter >= MAX_OBR) g_accel_decel_counter=MAX_OBR;
       TCNT2=g_accel_decel_counter;
    //   stan_lewo=0;

       twistart();
       twiwrite(0x40 | (PCF8574ADDR << 1));
       twiwrite(advance_step(-1)|0x0f);
       twistop();
       }
    //*******************
       if(stan_lewo && flaga_napiecie_foto==PRAWO)//nie działa
         //obroty zmiejszyć do 0 i stopniowo zwiększać w przeciwnym kierunku
       {
       if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
          TCNT2=g_accel_decel_counter;
             if(g_accel_decel_counter > 0 )
             {
             twistart();
             twiwrite(0x40 | (PCF8574ADDR << 1));
             twiwrite(advance_step(-1)|0x0f);
             twistop();
             }
             else
             {
             stan_prawo=0;
             stan_stop=1;
             }
       }

    //************
       if(stan_prawo && flaga_napiecie_foto==LEWO)//j.w.
       {
       if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
          TCNT2=g_accel_decel_counter;

             if(g_accel_decel_counter > 0 )
             {
             twistart();
             twiwrite(0x40 | (PCF8574ADDR << 1));
             twiwrite(advance_step(1)|0x0f);
             twistop();
             }
             else
             {
             stan_lewo=0;
             stan_stop=1;
             }
       }

    //*************
       if(flaga_napiecie_foto==STOP)//działa
       {
          if(stan_prawo)
          {
          if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
          TCNT2=g_accel_decel_counter;

             if(g_accel_decel_counter > 0 )
             {
             twistart();
             twiwrite(0x40 | (PCF8574ADDR << 1));
             twiwrite(advance_step(1)|0x0f);
             twistop();
             }
             else
             {
             stan_prawo=0;
             stan_stop=1;
             }
          }

          if(stan_lewo)
          {
          if(g_accel_decel_counter--<=0) g_accel_decel_counter=0;
          TCNT2=g_accel_decel_counter;
             if(g_accel_decel_counter > 0 )
             {
             twistart();
             twiwrite(0x40 | (PCF8574ADDR << 1));
             twiwrite(advance_step(-1)|0x0f);
             twistop();
             }
             else
             {
             stan_lewo=0;
             stan_stop=1;
             }
          }
       }
    }

    Kod rozwlekły i bez sztuczek- ale trochę rozumiem- no bo sam napisałem.
    Tzn- wydaje mi się że rozumiem.
    Ale dalej nie działa dobrze.
    Może ktoś sprawdzi błędy w rozumowaniu.
    Dopóki nie zmienię kierunku- działa dobrze.
    Przy próbie zmiany kierunku silnik staje i nie zmniejsza obrotów.
  • Helpful post
    Level 24  
    No a jak ma działać skoro niedziałające warunki nigdy nie dają prawdy. Z resztą przedstawiony kod to jakiś koszmar. Proszę zredukować ilość zmiennych o połowę.
  • Level 38  
    No- ale które zmienne?
    I gdzie?
    Jeśli mam stan_prawo/lewo/stop to muszę zapamietać że tak było.
    Silnik powoli zwiększa/ zmniejsza swoje obroty.
    Tylko flaga_napiecie_foto jest do sprawdzania jako volatile.
    Nie mam pomysłu w którym miejscu zmieniać stan flaga_stan
    A to że koszmarny kod- to wiem.
    Ale dopóki tego nie przebrnę- sterowania silnika ze stopniowym wzrostem/ maleniem prędkości to dalej nie pójdę w C.
    Taki upór.
    Muszę to zrobić.
    I nie patrz na funkcję sterowania krokami i wysyłania tego przez I2C- to działa.
    Pewnie dlatego że nie moje- ale sprawdzone.
  • User removed account  
  • Helpful post
    Level 24  
    stan_prawo/lewo/stop to jest jedna zmienna (np stan_kierunek).
    Druga to jest flaga_napiecie_foto.
    Trzecia to jest g_accel_decel_counter. Koniec kropka.

    I teraz wchodząc do funkcji ustalamy wartość napięcia foto.
    I teraz sprawdzamy, czy flaga_napiecia_foto == stan_kierunek.
    Jeśli tak, przyśpieszamy silnik. Jeśli nie, zwalniamy.
    Jeśli flaga_napięcia_foto != stan_kierunek to najpierw zwalniamy, po wyhamowaniu zmieniamy kierunek, po czym zaczyna działać już inny warunek wymieniony wcześniej.

    Polecam się także zastanowić, co w rzeczyywistości oznacza flaga_napiecia_foto == STOP.
  • Level 38  
    Przerabiam, grzebię w kodzie- zgodnie ze wskazówkami.
    Może coś zrobię.
    Ale nie zostawiajcie mnie z tym samego.
  • Helpful post
    Level 24  
    Za komentarze z i2c trzeba wstawic odpowiedni kod. Pisałem w gedit, bez kompilacji, ale powinno być dobrze. Gdybym czegoś nie przewidział lub o czymś zapomniał, proszę pytać dalej lub zgłaszać błędy. Może któryś z kolegów z forum zauważy jakieś moje niedopatrzenie.

    Code:
    //ster_silnika()- funkcja mająca powodować stopniowy wzrost i malenie prędkości obrotowej silnika krokowego 
    
    //w prawo i w lewo
    //g_accel_decel_counter- zmienna której wartość wpisujemy do licznika2
    //advance_step()- funkcja sterująca krokami- działa dobrze
    //flaga_napięcie_foto- na którym fotooporniku jest większe napięcie- pomiar z ADC- działa dobrze
    //sterowanie przez I2C też działa
    void ster_silnika (void)
    {
       // zakladam, ze 0 - lewo, 1 - stop, 2 - prawo
       // oraz ze silnik po uruchomieniu stoi
       static uint8_t kierunek_silnika = 1;
       int8_t kierunek_napiecia_foto = 1;

    //*****************
       if(napiecie[1]+15<napiecie[3])//w prawo   
       {
          kierunek_napiecia_foto = 2;
       }
    //**************************
       if(napiecie[3]+15<=napiecie[1])//w lewo
       {
          kierunek_napiecia_foto = 0;
       }
    //****************
       // nic do roboty, dowidzenia
       if (kierunek_napiecia_foto == 1 && kierunek_silnika == 1) return;

       if (kierunek_napiecia_foto == kierunek_silnika)
       {
          if (g_accel_decel_counter < MAXOBR) g_accel_decel_counter++;
          // przyspieszamy, i2c itd
       }
       else
       {
          if (g_accel_decel_counter > 0)
          {
             g_accel_decel_counter--;
             //zwalniamy, i2c itd
          }
          else
          {
             ++i;
             if (i > 2) i = 0;
          }
       }
    }
  • User removed account  
  • Helpful post
    Level 24  
    Jeden błąd popełniłem na pewno. Drugi prawdopodobnie.

    Code:
    else
    
       {
          if (g_accel_decel_counter > 0)
          {
             g_accel_decel_counter--;
             //zwalniamy, i2c itd
          }
          else
          {
             ++i;
             if (i > 2) i = 0;
          }
       }


    Code:
    ++i;
    
             if (i > 2) i = 0;
    Zamieniamy "i" na kierunek_silnika. Albo lepiej całkiem na
    Code:
    kierunek_silnika = kierunek_napiecia_foto;
    To był błąd na pewno.

    Drugi, prawdopodobny, to nie mam pewności co do miejsca "//zwalniamy, i2c itd". Być może musi to być w innym miejscu, ale poczekam na test autora. Zobaczymy co wyjdzie.
  • Level 38  
    Jutro- muszę to sprawdzić.
    Na spokojnie- już taki szybki jak Wy nie jestem.
    Chyba za stary.
    Ale jutro Was będę pytał- jak sprawdzę.
    Silnik i fotooporniki są włączone.
    Tak szybko jak Wy to ja nie jestem w stanie działać.
    Ale dzięki- MUSZĘ to zrobić.
    Dobrze- wstawiam zapałki w oczy i dalej...
  • Level 38  
    Teraz jest tak:
    Code:

    //by _sulfur
    void ster_silnika (void)
    {
       // zakladam, ze 0 - lewo, 1 - stop, 2 - prawo
    //zostało zrobione w #define
       // oraz ze silnik po uruchomieniu stoi
       static uint8_t kierunek_silnika = 1;
       uint8_t kierunek_napiecia_foto = 1;


       if(napiecie[1]+15<napiecie[3])//w prawo   
       {
          kierunek_napiecia_foto = PRAWO;
       }

       if(napiecie[3]+15<=napiecie[1])//w lewo
       {
          kierunek_napiecia_foto = LEWO;
       }

       // nic do roboty, dowidzenia
       if (kierunek_napiecia_foto == STOP && kierunek_silnika == STOP ) return;

       if (kierunek_napiecia_foto == kierunek_silnika)
       {
          if (g_accel_decel_counter < MAX_OBR)
          {
          g_accel_decel_counter++;
          // przyspieszamy- w lewo albo w prawo, i2c itd
         }
         TCNT2=g_accel_decel_counter;
        
          if(kierunek_napiecia_foto==PRAWO)//przyspieszamy w prawo
          {
           twistart();
           twiwrite(0x40 | (PCF8574ADDR << 1));
           twiwrite(advance_step(1)|0x0f);//+1 oznacza w prawo
           twistop();
          }
          if(kierunek_napiecia_foto==LEWO)//przyspieszamy w lewo
          {
          twistart();
           twiwrite(0x40 | (PCF8574ADDR << 1));
           twiwrite(advance_step(-1)|0x0f);//-1 oznacza w lewo
           twistop();
          }   
         //}
       }
       else
       {
          if (g_accel_decel_counter > 0)
          {
          g_accel_decel_counter--;
          //zwalniamy- od prawej albo od lewej, i2c itd
          TCNT2=g_accel_decel_counter;   
          if(kierunek_napiecia_foto==PRAWO)//zwalniamy od lewej do 0 i potem być może przyspieszamy w prawo
          {
          twistart();
           twiwrite(0x40 | (PCF8574ADDR << 1));
           twiwrite(advance_step(1)|0x0f);//czyli silnik kręci się w prawo coraz wolniej
           twistop();
          }
          if(kierunek_napiecia_foto==LEWO)//zwalniamy od prawej do 0 i potem być może przyspieszamy w lewo
          {
          twistart();
           twiwrite(0x40 | (PCF8574ADDR << 1));
           twiwrite(advance_step(-1)|0x0f);//czyli silnik kręci się w lewo coraz wolniej
           twistop();
          }   
          }
          else
          {
    //         ++i;
    //         if (i > 2) i = 0;
          kierunek_silnika = kierunek_napiecia_foto;
          }
       }
    }

    Objawy są takie- dobrze zmienia kierunek.
    Obroty od istniejących maleją do 0 i powoli rosną w przeciwną stronę.
    Ale po wystąpieniu stanu STOP silnik zatrzymuje się gwałtownie a nie stopniowo.
    Chociaż na wyświetlaczu widzę że g_accel_decel_counter maleje powoli a nie od razu.
    Gdzieś tego nie przepisuje do TCNT2.
    A to że tak może robić jest spowodowane histerezą- no ale jest konieczna.
    A kodu funkcji sterowania silnikiem razem z I2C jeszcze nie wsadziłem- przepraszam.
    Ale enkapsulacja to może potem.
  • Level 24  
    Niesłusznie zastosowana zmienna "kierunek_napiecia_foto" zamiast "kierunek_silnika". To niedopatrzenie występuje w dwóch miejscach w kodzie dopisanym przez kolegę.

    A tak swoją drogą, już całkiem luźniej co do radosnej twórczości, to czy nie lepiej kod
    Code:
    if(kierunek_napiecia_foto==PRAWO)//przyspieszamy w prawo 
    
      {
      twistart();
      twiwrite(0x40 | (PCF8574ADDR << 1));
      twiwrite(advance_step(1)|0x0f);//+1 oznacza w prawo
      twistop();
    }
    if(kierunek_napiecia_foto==LEWO)//przyspieszamy w lewo
    {
      twistart();
      twiwrite(0x40 | (PCF8574ADDR << 1));
      twiwrite(advance_step(-1)|0x0f);//-1 oznacza w lewo
      twistop();
    }   

    zastąpić
    Code:
    twistart(); 
    
    twiwrite(0x40 | (PCF8574ADDR << 1));
    if(kierunek_napiecia_foto==PRAWO)//przyspieszamy w prawo
    {
      twiwrite(advance_step(1)|0x0f);//+1 oznacza w prawo
    }
    if(kierunek_napiecia_foto==LEWO)//przyspieszamy w lewo
    {
      twiwrite(advance_step(-1)|0x0f);//-1 oznacza w lewo
    }   
    twistop();

    Proszę zauważyć, ile zbędnego kodu odpada (nie dublujemy go). Proszę się także zastanowić, co trzeba byłoby zmienić, aby odpadły nam instrukcje warunkowe i zastosować konstrukcję typu
    Code:
    twiwrite(advance_step(kierunek_silnika)|0x0f);
pcbway logo