Elektroda.pl
Elektroda.pl
X
Relpol
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

ATMEGA8 - Symulacja obrotów silnika

e11 22 Wrz 2013 12:25 2262 16
  • #1 22 Wrz 2013 12:25
    e11
    Poziom 17  

    Witam serdecznie. Mam taki problem, chciałem zrobić układ symulacji obrotów silnika elektrycznego, aby móc testować układy automatyki bez konieczności uruchamiania silnika. Chodzi oto, że jest maszyna i sterownik podejmuje decyzje miedzy innymi na podstawie obrotów silnika głównego i teraz, aby przetestować całe sterowanie „na stole” podając sygnały z krańcówek i chciałbym zasymulować obroty. I zablokowało mnie nie radze sobie z zaprogramowaniem kontrolera, aby symulował mi te obroty.
    Przyjmijmy, że
    Obroty 2000/ min
    Minuta = 60 000 ms
    Czyli czas jednego obrotu to 30 ms = okres
    Czas trwania „1” =15 ms
    Czas trwania „0” =15 ms
    Przyjąłem też żeby „jedynka” trwała cały czas te 15 ms
    A do czasu „zera” dodawałbym pewna wartość no i tu zaczynają się schody, bo ta wartość nie jest jednak stał a. Na początku do czasu trwania „zera” dodaje 15 mikrosekund i to jakoś się pokrywa, ale później już lipa.
    Dodam, że wyjście atmegi mam podłączone poprzez układ dopasowujący do miernika obrotów Lumela. Może ktoś podpowie jak to zrobić albo może jakąś funkcje, którą dałoby się zaprogramować w mikrokontrolerze. Programowanie w C
    W załączeniu plik z przeliczeniami

    0 16
  • Relpol
  • #2 22 Wrz 2013 12:43
    pbuhne
    Poziom 14  

    Pokaż kod, bo bez tego to nikt nic nie wywróży. Podejrzewam że używasz delay_ms(15) ?

    0
  • #3 22 Wrz 2013 12:59
    e11
    Poziom 17  

    Podam kod jak najbardziej, tylko może nie koniecznie chodzi o kod tylko o metodę symulacji czy jest poprawna.

    0
  • Relpol
  • #4 22 Wrz 2013 13:04
    excray
    Poziom 39  

    A co chcesz mieć w ramach symulacji? Na mój gust 555 w zupełności wystarcza do tej aplikacji.

    0
  • #5 22 Wrz 2013 13:18
    e11
    Poziom 17  

    Troszkę przedstawiłem to w skrócie. Ale chce, aby na wyświetlaczu wyświetlało mi aktualna prędkość, którą będę zadawał z klawiatury. Ale obsługa wyświetlacza i klawiatury to mniejszy problem. Problem, w jaki sposób wygenerować impulsy na wyjście, aby miernik obrotów odczytał prawidłowe obroty. Np. z klawiatury zadam prędkość 750 obr/min , wyświetlacz pokaże 750 a jak wystawić impulsy na wyjściu, następnie z klawiatury dodam jeden obrót (751) i jak powinien się zmienić przebieg wyjściowy . Tzn. jak się powinien zmienić to ja wiem tylko jak go wygenerować żeby ta cała symulacja zachowywała się liniowo. Wydaje mi się że można by było zrobić tablice ale była by to tablica 2000 elementów czy nie można wprowadzić jakiejś funkcji czy innym sposobem.

    0
  • #6 22 Wrz 2013 13:20
    pbuhne
    Poziom 14  

    a czemu nie zrobisz jedynki i zera symetrycznie? Przecież w realnym układzie jeśli obroty wynoszą 1k rpm to masz okres 60ms, a przy wypełnieniu 50% to jest po 30 ms na 1 i na 0.
    Użyj w tym celu Timera1 w trybie CTC z Toggle na wyjściu. Częstotliwość, a tym samym okres obrotu, regulujesz wartością rejestru OCR1A lub ICR1. Wskazówki masz na str 90 i 91 datasheeta.

    0
  • #7 22 Wrz 2013 13:38
    e11
    Poziom 17  

    Tak właśnie się zastanawiałem, czy nie popełniam błędu, że upieram się przy tym, aby jedynka miała stały czas. Jutro przetestuję z symetrycznym przebiegiem.
    Może w ogóle poszedłem w złym kierunku i mam pomroczność jasną. :cry:

    0
  • #8 22 Wrz 2013 17:52
    emarcus
    Poziom 35  

    e11 napisał:
    Witam serdecznie.
    ............ Chodzi oto, że jest maszyna i sterownik podejmuje decyzje miedzy innymi na podstawie obrotów silnika głównego ............


    Czyli te aktualne obroty musisz w jakiejś formie czytac z maszyny (rodzaj sprzężenia zwrotnego...).
    Jaki sposób, lub/oraz urządzenie przewidziałeś aby tego odczytu dokonac ?
    Jeżeli to urzadzenie wysyła/będzie wysyłac impulsy reprezentujące aktualne obroty silnika, to symulacja takiego układu jest dośc trywialna; -może byc zastąpoine zwykłm 'switchem'.

    e marcus

    0
  • #9 22 Wrz 2013 18:31
    e11
    Poziom 17  

    Nie nie mogą być zastąpione przełącznikiem, ponieważ to ma być przyrząd diagnostyczny, maszyna ma różne-zmienne obroty i w zależności od tych obrotów otwierają się zawory no i na koniec w różnych maszynach mam różne obroty. Dlatego chce zrobić taki troszkę uniwersalny przyrząd mogący symulować różne obroty.

    0
  • #10 22 Wrz 2013 18:47
    dondu
    Moderator Mikrokontrolery Projektowanie

    Takie symulatory, to podstawa do sprawdzania sterowników - idziesz w dobrym kierunku, tylko musisz zastosować timery. Dlatego warto by było, abyś pokazał program, jaki masz aktualnie opracowany, co najmniej w części generującej impulsy.

    0
  • #11 22 Wrz 2013 18:59
    emarcus
    Poziom 35  

    e11 napisał:
    Nie nie mogą być zastąpione przełącznikiem, ponieważ to ma być przyrząd diagnostyczny, maszyna ma różne-zmienne obroty i w zależności od tych obrotów otwierają się zawory no i na koniec w różnych maszynach mam różne obroty. Dlatego chce zrobić taki troszkę uniwersalny przyrząd mogący symulować różne obroty.


    Oczywiście że możesz zastosowac switch w procesie symulacji. Jeżeli masz na myśli stanowisko próbne projektu to możesz zastosowac prowizoryczny impulsator mechaniczny, optyczny, lub magnetyczny (kontaktron lub hallotron albo nawet wykorzystac jeden kanał encodera), którym symulowałbyś obroty silnika.
    Przecież w jakiś sposób bedziesz musiał te obroty czytac z maszyny, nieprawdaż?

    e marcus

    0
  • #12 22 Wrz 2013 19:04
    dondu
    Moderator Mikrokontrolery Projektowanie

    emarcus napisał:
    Przecież w jakiś sposób bedziesz musiał te obroty czytac z maszyny, nieprawdaż?

    Ja rozumiem, że autorowi tematu, chodzi o zadawanie impulsów do sterownika i jego testowanie. Dlatego układ symulujący niczego nie czyta - robi to testowany sterownik.

    0
  • #13 22 Wrz 2013 19:05
    e11
    Poziom 17  

    Dokładnie tak jak piszesz, aby sprawdzić działanie programu nie muszę uruchamiać całej maszyny, którą nie zawsze da się uruchomić. Krańcówki da się symulować przełącznikami, temperaturę rezystancją bądź podgrzewać czujnik ale obroty muszą być obrotami lub odpowiednimi impulsami. Dla tych kolegów , którzy napiszą weź mały silniczek i czujnik indukcyjny od razu odpowiem tak nie zrobię :D
    Program będę mógł dać jutro.
    Dondu - masz racje dlatego na układzie symulującym będzie wyświetlacz pokazujący jakie mam obroty na wyjściu układu

    0
  • #14 23 Wrz 2013 04:11
    wojekkk
    Poziom 17  

    Weź tez pod uwage fakt aby moc ustawiać odpowiedni mnoznik w Twoim programie bo nie zawsze bedzie tak że na 1 obrót przypadnie 1 impuls.

    0
  • #15 23 Wrz 2013 09:04
    Tomasz Gumny
    Poziom 27  

    e11 napisał:
    [...]Przyjąłem też żeby „jedynka” trwała cały czas te 15 ms
    A do czasu „zera” dodawałbym pewna wartość no i tu zaczynają się schody, bo ta wartość nie jest jednak stał a. Na początku do czasu trwania „zera” dodaje 15 mikrosekund i to jakoś się pokrywa, ale później już lipa.
    Zapewne dlatego, że okres (opóźnienie) to odwrotność obrotów (częstotliwości), więc przeliczaj czas półokresu ze wzoru:
    T = (1 / (rpm / 60)) / 2
    lub stablicuj czasy dla założonego zakresu obrotów z rozsądnym krokiem
    i wstawiaj je do funkcji delay.
    Na przykład dla 100, 200, 500, 1000, 2000 obrotów, tablica powinna zawierać:
    czas[] = { 300, 150, 60, 30, 15 }; // w ms

    0
  • #16 25 Wrz 2013 12:46
    e11
    Poziom 17  

    Kawałek kodu :

    Code:
    #include <avr/io.h>
    
    #include <avr/interrupt.h>                  // funkcje obsługujące przerwania
    #include "lcd.h"                        // funkcje obsługujące wyświetlacz LCD
    //
    #define DDR_Out DDRB                     // konfiguracja portu i pinu wyjścia
    #define PORT_Out PORTB
    #define Out PB0

    #define clr_out bit_set(PORT_Out, bit(Out))      // operacje na pin-u wyjścia
    #define set_out bit_clear(PORT_Out, bit(Out)) #define toggle_out bit_toggle(PORT_Out, bit(Out)) // // +--------------------------------------------------------------------...
    // | deklaracja zmiennych globalnych
    // +-----------------------------------------------------------------...
    uint16_t volatile licznik;         // licznik wywołań co 15us
    uint16_t volatile licznik_start   ;   // wartoś startowa licznika = 1000(15ms) + 1000(15ms) + x
    uint16_t volatile x ;            // wartoś 15us, która odpowiada za zmianę prędkości o 1 obr/min
    //
    // prędkość ==> 60000 / (15ms (on) + 15ms (off) + x),  gdzie x=0..2000  x=0 dla 2000 obr/min;  x=2000 dla 1 obr/min // // // +--------------------------------------------------------------------...
    // | funkcja obsługi przerwania Timer0
    // +-----------------------------------------------------------------...
    ISR(TIMER0_OVF_vect)
    {

    //   toggle_out;

          if(licznik) licznik--;                     // jeżeli licznik > 0 to zmniejsz licznik o 1
          if(licznik==(licznik_start-1000)) clr_out;      // jeżeli minie 15ms(1000*15us) to wyłącz wyjście
          if(licznik==0)                           // jeżeli licznik = 0 to :
          {
             licznik=licznik_start+x;               // ustaw wartość licznika na wartość startową
             set_out;                           // załącz wyjście
          }

       TCNT0 = 196;                                 // ustawienie licznika na 196 pozwala wywoływać przerwanie co ~ 15us
    }
    //
    // +--------------------------------------------------------------------...
    // | funkcja konfigurująca Timer0
    // +------------------------------------------------------ -----------...
    void Timer0_init()
    {
       TCCR0 = (1<<CS00);          // prescaler = 1
       TCNT0 = 196;                  // ustawienie licznika na 196 pozwala wywoływać przerwanie co ~ 15us
       TIMSK = (1<<TOIE0);          // załączanie przerwania od przepełnienia timiera "Timer0"
    }
    //
    // +--------------------------------------------------------------------...
    // | główna funkcja programu -=: M A I N :=- // +-----------------------------------------------------------------...
    int main(void)
    {

    0
  • #17 25 Wrz 2013 21:01
    pbuhne
    Poziom 14  

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tu masz błąd, pomimo że pewnie to działa, zapewne chodziło Ci o zapis: TCCR0 |= (1<<CS00).

    Jednak ja wciąż polecam użyć Timera1 i jego trybu CTC, wtedy na wyjściu OC1A. Nie potrzeba wtedy obsługiwać żadnego przerwania, ustawiasz wyjście OC1A w tryb TOGGLE ( rejestr TCCR1A ) i będzie ono zmieniało stan w rytm przepełnień timera. A timer będzi liczył (przez prescaler jaki ustawisz) do wartości jaka sobie ustawisz w OCR1A. Czyli częstotliwość zależy tylko od rejestru OCR1A i prescalera. Najlepsze jest to, że generowanie odbywa się sprzętowo, nie w pętlach czy delay'ach. Strona 91 instrukcji jest tam wzór na częstotliwość.
    A, no i pin PB1 musi być ustawiony jako wyjście.

    0