|
Fórum » ARM - Miértek hogyanok
Mit értesz azon, hogy akad a léptetőmotor?
Egyáltalán nem megy, vagy csak lelassul a léptetés, amikor az USART dolgozik?
Az interruptok időtartamát nézted már? Csak egy tipp, de ha az USART kiszolgálása sokáig tart, a következő motor léptetésnek szerintem várakoznia kell, amíg az USART interrupt service be nem fejeződik, még akkor is, ha a Timernek magasabb a prioritása.
Nem találtam erről leírást (szóval bocs, ha tévedek), de az NVIC szerintem alapban tiltja a Global interruptot addig, amíg egy interrupt service-ben van.
Rossz az egész USART1_IRQHandler szervezése!
Nem szabad kivárni, amíg elmegy 1 egész sor: uart_karakterlanc_kuldes(uart_rx_adat); ???
És addig nem csinálni semmi mást!
Tessék karakterenként kezelni, Vétel: megjött 1 karakter kapsz megszakítást: eltárolod, kilépsz …
Adás: Elment 1 karakter kapsz megszakítás, küldöd a következőt, kilépsz …
És a két INT akció között bőven van időd egyéb feladatra!
A léptetőmotor léptetéséhez jelsorozatra van szükség, step jelre. Mint egy signal generátor. Ennek a jelsorozatnak csúszik el az időzítése.
Az NVIC nem pont arra való hogy ha benne vagyok egy alacsonyabb prioritású ISR-ben akkor azt megszakítja és a magasabb prioritású ISR indítja el? Tehát lényegében itt is az van hogy az ISR-ben a lehető legkevesebb időt kell eltölteni amelyet úgy tudok elképzelni hogy egy flag-et billentek be ha megvan az egész visszaküldendő adat és a főszálból kell figyelnem ezt a flag-et amely immár onnan fogja visszaküldeni az egész karakterláncot. Ekkor viszont nem értem hogy mi értelme is van az NVIC-nek és a prioritás megadási lehetőségeknek? Ugye amíg a főprogram küldi az adatot addig a timer ISR szabadon tud megszakításokat generálni és léptetni a motort.
Én viszont úgy értelmeztem, hogy a torlódó megszakítások végrehajtási sorrendjét tudod beállítani.
De ezt kevés debugolással könnyen le ellenőrizheted.
Ezért is nem értettem hogy egy Arduino-n futó GRBL controller a 8 bites AVR-ek 16Mhz sebességével hogyan is képes visszaküldeni a szerszámpozíciót (uart kommunikáció) léptetőmotor vezérlés közben. Hát így. Köszönöm
Az AVR-nél bevan vésve a HW-be az INT sorrend, nem tudod SW-báől újra szervezni!
Sziasztok!
Egy olyan problémába futottam amely teljesen keresztbe tett nekem. Szinte teljesen lámának érzem magam, vagy egy BUG-ról van szó.
uart-on adatot fogadok, ezzel egy flaget állítok be amely elindít 3 timert/countert (TIM2-3-4). Ez az interpolátorom 3 tengelyének a lépésidőzítője. Mind 3 timer ISR-jében a timerek saját magukat képesek leállítani, közben a fóprogramban figyelem a 3 timert és a flag-et. A 3 timer leáll, debuggolásnál látom hogy már nem fut az ISR egyiknél sem, viszont a timer/counter engedélyező bitet olvasva azt látom hogy a 3-ból 2 timer nem kapcsolt ki. Ez hogy lehet? Így beakad a programom.
Ez a main függvényben van, a főprogram:
while(1)
{
if(uart_adat_feldolgozasi_kerelem)
{
if( strstr(uart_rx_adat, "$") )
{
cnc_parancs_olvasas_es_vegrehajtas(uart_rx_adat);
}
else
{
if(cnc_allapot == KESZENLET)
{
cnc_gkod_olvasas(uart_rx_adat);
}
else
{
cnc_valasz = HIBA_GEP_FOGLALT;
}
}
UART_RX_ADAT_TORLES;
uart_adat_feldolgozasi_kerelem = HAMIS;
}
t1 = READ_BIT(TIM2->CR1, TIM_CR1_CEN);
t2 = READ_BIT(TIM3->CR1, TIM_CR1_CEN);
t3 = READ_BIT(TIM4->CR1, TIM_CR1_CEN);
//if( !READ_BIT(TIM2->CR1, TIM_CR1_CEN) && !READ_BIT(TIM3->CR1, TIM_CR1_CEN) && !READ_BIT(TIM4->CR1, TIM_CR1_CEN) && cnc_allapot != KESZENLET)
if( !t1 && !t2 && !t3 && (cnc_allapot != KESZENLET))
{
cnc_valasz = GKOD_OK;
cnc_allapot = KESZENLET;
}
if(cnc_valasz != SEMMI)
{
switch (cnc_valasz)
{
case PARANCS_OK:
uart_karakterlanc_kuldes("PARANCS_OK");
break;
case HIBA_ISMERETLEN_PARANCS:
uart_karakterlanc_kuldes("HIBA_ISMERETLEN_PARANCS");
break;
case GKOD_OK:
uart_karakterlanc_kuldes("GKOD_OK");
break;
case HIBA_ISMERETLEN_GKOD:
uart_karakterlanc_kuldes("HIBA_ISMERETLEN_GKOD");
break;
case HIBA_GEP_FOGLALT:
uart_karakterlanc_kuldes("HIBA_GEP_FOGLALT");
break;
case HIBA_VEGALLAS:
uart_karakterlanc_kuldes("HIBA_VEGALLAS");
break;
}
// cnc_x_szerszampozicio = uj_cnc_x_szerszampozicio;
// cnc_y_szerszampozicio = uj_cnc_y_szerszampozicio;
// cnc_z_szerszampozicio = uj_cnc_z_szerszampozicio;
cnc_valasz = SEMMI;
cnc_szerszampoziciok_kuldese();
uart_karakterlanc_vege();
}
vegallaskapcsolok_es_erinto_allapot_kuldes();
// if(cnc_allapot != KESZENLET)
// {
// cnc_szerszampoziciok_kuldese();
// uart_karakterlanc_vege();
// }
}
t1-3 változók a timerek állapota, és ezeket a biteket hiába olvasom azt adják vissza hogy a timerek futnak. Miért?
Timer-ek initializálása:
void cnc_initializalas(void)
{
double buffer_szorzo;
TIM_TimeBaseInitTypeDef timerInitStructure;
NVIC_InitTypeDef nvicStructure;
cnc_felbontas = ((MENETEMELKEDES / (360.0 / LEPTETOMOTOR_LEPESSZOGE)) / MIKROLEPES_MOD);
cnc_lepes_per_mm = 1.0 / cnc_felbontas;
mikrolepes_initializalasa();
//felbontás szorzó/osztó keresése kerekítéshez
buffer_szorzo = 10;
while(1)
{
if(((unsigned long)(cnc_felbontas * buffer_szorzo)) == ((double)(cnc_felbontas * buffer_szorzo)))
{
szorzo_oszto_kerekiteshez = buffer_szorzo;
break;
}
else
{
buffer_szorzo *= 10;
}
}
//Timer 2,3,4
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
timerInitStructure.TIM_Prescaler = 42 - 1;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = (65536 / (200 / 30.52)) - 1;
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &timerInitStructure);
TIM_TimeBaseInit(TIM3, &timerInitStructure);
TIM_TimeBaseInit(TIM4, &timerInitStructure);
elotolas_beallitas_x(ALAP_SEBESSEG_MMPP);
elotolas_beallitas_y(ALAP_SEBESSEG_MMPP);
elotolas_beallitas_z(ALAP_SEBESSEG_MMPP);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
nvicStructure.NVIC_IRQChannelSubPriority = 0;
nvicStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvicStructure);
nvicStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_Init(&nvicStructure);
nvicStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_Init(&nvicStructure);
TIM_Cmd(TIM2, DISABLE);
TIM_Cmd(TIM3, DISABLE);
TIM_Cmd(TIM4, DISABLE);
}
Timerek ISR és frekvenciabeállító metódusai:
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
if(uj_cnc_x_szerszampozicio > (cnc_x_szerszampozicio + (cnc_felbontas / 2)))
{
x_plusz();
}
else if(uj_cnc_x_szerszampozicio < (cnc_x_szerszampozicio - (cnc_felbontas / 2)))
{
x_minusz();
}
else
{
TIM_Cmd(TIM2, DISABLE);
cnc_x_szerszampozicio = uj_cnc_x_szerszampozicio;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
if(uj_cnc_y_szerszampozicio > (cnc_y_szerszampozicio + (cnc_felbontas / 2)))
{
y_plusz();
}
else if(uj_cnc_y_szerszampozicio < (cnc_y_szerszampozicio - (cnc_felbontas / 2)))
{
y_minusz();
}
else
{
TIM_Cmd(TIM3, DISABLE);
cnc_y_szerszampozicio = uj_cnc_y_szerszampozicio;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
if(uj_cnc_z_szerszampozicio > (cnc_z_szerszampozicio + (cnc_felbontas / 2)))
{
z_plusz();
}
else if(uj_cnc_z_szerszampozicio < (cnc_z_szerszampozicio - (cnc_felbontas / 2)))
{
z_minusz();
}
else
{
TIM_Cmd(TIM4, DISABLE);
cnc_z_szerszampozicio = uj_cnc_z_szerszampozicio;
}
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
void elotolas_beallitas_x(double mmpp)
{
TIM2->ARR = (65536 / (((mmpp / 60) * cnc_lepes_per_mm) / 30.52)) - 1;
//TIM2->ARR = ((((1000000.0*60.0) / mmpp) / cnc_lepes_per_mm));
}
void elotolas_beallitas_y(double mmpp)
{
TIM3->ARR = (65536 / (((mmpp / 60) * cnc_lepes_per_mm) / 30.52)) - 1;
//TIM2->ARR = ((((1000000.0*60.0) / mmpp) / cnc_lepes_per_mm));
}
void elotolas_beallitas_z(double mmpp)
{
TIM4->ARR = (65536 / (((mmpp / 60) * cnc_lepes_per_mm) / 30.52)) - 1;
//TIM2->ARR = ((((1000000.0*60.0) / mmpp) / cnc_lepes_per_mm));
}
Itt indítom el a 3 timert:
void cnc_gyorsmenet_inditasa(void)
{
double x_tavolsag, y_tavolsag, z_tavolsag, tavolsag;
cnc_allapot = G0;
//tengelyek sebességszámolása
x_tavolsag = abszolut_ertek(kerekites_long_double(uj_cnc_x_szerszampozicio - cnc_x_szerszampozicio));
y_tavolsag = abszolut_ertek(kerekites_long_double(uj_cnc_y_szerszampozicio - cnc_y_szerszampozicio));
z_tavolsag = abszolut_ertek(kerekites_long_double(uj_cnc_z_szerszampozicio - cnc_z_szerszampozicio));
tavolsag = kerekites_long_double(sqrt( pow(x_tavolsag,2.0) + pow(y_tavolsag,2.0) + pow(z_tavolsag,2.0))); //(tér)vektor hossza
elotolas_beallitas_x( (x_tavolsag / tavolsag) * ALAP_SEBESSEG_MMPP);
elotolas_beallitas_y( (y_tavolsag / tavolsag) * ALAP_SEBESSEG_MMPP);
elotolas_beallitas_z( (z_tavolsag / tavolsag) * ALAP_SEBESSEG_MMPP);
TIM2->CNT = 0;
TIM3->CNT = 0;
TIM4->CNT = 0;
TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
Ugye egy control regiszter kapcsolok be a főprogramból és olvasom. A kikapcsolás pedig saját maga ISR-jéből történik. Úgy tudom ha egy globális változót használok ISR-en belül akkor annak típusa mindig volatile de egy control regisztert nem tudok volatile-re beállítani.
Létezik hogy ezért nem működik megfelelően a kódom? Nálatok hogyan van a fordító beállítva? Az is lehet hogy csak egy optimalizációs beállítás vagy ilyesmi van elállítva nálam. A hozzászólás módosítva: Jún 2, 2015
Én sehol nem látom, hogy ezekben a if vizsgálatokban levő értékeket, menetközben változtatnád?
if(uj_cnc_x_szerszampozicio > (cnc_x_szerszampozicio + (cnc_felbontas / 2)))
{
x_plusz(); // Ezt sem látom???
}
else if(uj_cnc_x_szerszampozicio < (cnc_x_szerszampozicio - (cnc_felbontas / 2)))
{
x_minusz();// Ez mit tesz? Ezt sem látom???
}
else
// Mikor teljesül: if(uj_cnc_x_szerszampozicio == (cnc_x_szerszampozicio - (cnc_felbontas / 2)))
{ // Ide, hogyan kerülünk be?
TIM_Cmd(TIM2, DISABLE);
cnc_x_szerszampozicio = uj_cnc_x_szerszampozicio;
}
Mikor fut így bele az else ágba? A hozzászólás módosítva: Jún 3, 2015
Igazad van, igen azok a függvények olvassák az aktuális végálláskapcsolót és a gép felbontásával növelik vagy csökkentik a cnc pozícióváltozókat.
unsigned char x_plusz(void)
{
if(!X_PLUSZ_VEGALLAS_ALLAPOT)
{
X_EGY_LEPES_PLUSZBA;
cnc_x_szerszampozicio = kerekites_long_double(cnc_x_szerszampozicio + cnc_felbontas);
}
else
{
return HIBA_VEGALLAS;
}
return 0;
}
unsigned char x_minusz(void)
{
if(!X_MINUSZ_VEGALLAS_ALLAPOT)
{
X_EGY_LEPES_MINUSZBA;
cnc_x_szerszampozicio = kerekites_long_double(cnc_x_szerszampozicio - cnc_felbontas);
}
else
{
return HIBA_VEGALLAS;
}
return 0;
}
unsigned char y_plusz(void)
{
if(!Y_PLUSZ_VEGALLAS_ALLAPOT)
{
Y_EGY_LEPES_PLUSZBA;
cnc_y_szerszampozicio = kerekites_long_double(cnc_y_szerszampozicio + cnc_felbontas);
}
else
{
return HIBA_VEGALLAS;
}
return 0;
}
unsigned char y_minusz(void)
{
if(!Y_MINUSZ_VEGALLAS_ALLAPOT)
{
Y_EGY_LEPES_MINUSZBA;
cnc_y_szerszampozicio = kerekites_long_double(cnc_y_szerszampozicio - cnc_felbontas);
}
else
{
return HIBA_VEGALLAS;
}
return 0;
}
unsigned char z_plusz(void)
{
if(!Z_PLUSZ_VEGALLAS_ALLAPOT)
{
Z_EGY_LEPES_PLUSZBA;
cnc_z_szerszampozicio = kerekites_long_double(cnc_z_szerszampozicio + cnc_felbontas);
}
else
{
return HIBA_VEGALLAS;
}
return 0;
}
unsigned char z_minusz(void)
{
if(!Z_MINUSZ_VEGALLAS_ALLAPOT)
{
Z_EGY_LEPES_MINUSZBA;
cnc_z_szerszampozicio = kerekites_long_double(cnc_z_szerszampozicio - cnc_felbontas);
}
else
{
return HIBA_VEGALLAS;
}
return 0;
}
Viszont tegnap éjjel rájöttem a bibire, most más problémán tornázok.
A tegnapi hiba akkor jött elő mikor valamelyik tengellyel nem mentem semerre így a megteendő távolság nulla volt. Így az autoreload regiszterbe is nullát írt, ezért nem következett be az aktuális timer ISR-je sem. Ezt orvosoltam a timerek indításnál:
if(x_tavolsag > cnc_felbontas){ TIM_Cmd(TIM2, ENABLE); }
if(y_tavolsag > cnc_felbontas){ TIM_Cmd(TIM3, ENABLE); }
if(z_tavolsag > cnc_felbontas){ TIM_Cmd(TIM4, ENABLE); }
Így jó lett.
Azóta megírtam hozzá a gyorsítás lassítás algoritmusokat, de ha valamelyik tengellyel kevesebbet kell lépni mint a megadott gyorsítási/lassítási távolság akkor az a tengely ugye nem éri el a G0 gyorsmenet max sebességét mert a gyorsítás_eddig és lassítás_innen változók összecsúsznak.
pl:
x tengellyel mennem kell 10mm-ert. A gyorsítási és lassítási távolságom 1mm. Ekkor:
gyorsítás_eddig = aktuális_pozíció + gyorsítás_lassítás_távolság = 1mm
lassítás_innen = (aktuális_pozíció + x_távolság) - gyorsítás_lassítás_távolság = 9mm
Ekkor 0-1mmig gyorsít, 9-10mm-ig lassít.
Ha mind 3 tengellyel többet lépek mint a gyorsítási lassítási távolság akkor hibátlan, ha valamelyikkel kevesebbet akkor elcsúszik az a tengely a többitől amelyik kevesebb utat tesz meg.
Indítás:
void cnc_gyorsmenet_inditasa(void)
{
double x_tavolsag, y_tavolsag, z_tavolsag, tavolsag;
long double igenyelt_x_sebesseg_mmpp, igenyelt_y_sebesseg_mmpp, igenyelt_z_sebesseg_mmpp;
long double sebesseg_kulonbseg_x, sebesseg_kulonbseg_y, sebesseg_kulonbseg_z;
//tengelyek sebességszámolása
x_tavolsag = abszolut_ertek(kerekites_long_double(uj_cnc_x_szerszampozicio - cnc_x_szerszampozicio));
y_tavolsag = abszolut_ertek(kerekites_long_double(uj_cnc_y_szerszampozicio - cnc_y_szerszampozicio));
z_tavolsag = abszolut_ertek(kerekites_long_double(uj_cnc_z_szerszampozicio - cnc_z_szerszampozicio));
tavolsag = kerekites_long_double(sqrt( pow(x_tavolsag,2.0) + pow(y_tavolsag,2.0) + pow(z_tavolsag,2.0))); //(tér)vektor hossza
aktualis_x_sebesseg_mmpp = (x_tavolsag / tavolsag) * ALAP_SEBESSEG_MMPP;
aktualis_y_sebesseg_mmpp = (y_tavolsag / tavolsag) * ALAP_SEBESSEG_MMPP;
aktualis_z_sebesseg_mmpp = (z_tavolsag / tavolsag) * ALAP_SEBESSEG_MMPP;
igenyelt_x_sebesseg_mmpp = (x_tavolsag / tavolsag) * MAX_SEBESSEG_MMPP;
igenyelt_y_sebesseg_mmpp = (y_tavolsag / tavolsag) * MAX_SEBESSEG_MMPP;
igenyelt_z_sebesseg_mmpp = (z_tavolsag / tavolsag) * MAX_SEBESSEG_MMPP;
sebesseg_kulonbseg_x = igenyelt_x_sebesseg_mmpp - aktualis_x_sebesseg_mmpp;
sebesseg_kulonbseg_y = igenyelt_y_sebesseg_mmpp - aktualis_y_sebesseg_mmpp;
sebesseg_kulonbseg_z = igenyelt_z_sebesseg_mmpp - aktualis_z_sebesseg_mmpp;
sebesseg_egyseg_x = sebesseg_kulonbseg_x / (GYORSITAS_LASSITAS_TAVOLSAG_MM / cnc_felbontas);
sebesseg_egyseg_y = sebesseg_kulonbseg_y / (GYORSITAS_LASSITAS_TAVOLSAG_MM / cnc_felbontas);
sebesseg_egyseg_z = sebesseg_kulonbseg_z / (GYORSITAS_LASSITAS_TAVOLSAG_MM / cnc_felbontas);
// if(((x_tavolsag > 0) && (x_tavolsag < (GYORSITAS_LASSITAS_TAVOLSAG_MM * 2))) || ((y_tavolsag > 0) && (y_tavolsag < (GYORSITAS_LASSITAS_TAVOLSAG_MM * 2))) || ((z_tavolsag > 0) && (z_tavolsag < (GYORSITAS_LASSITAS_TAVOLSAG_MM * 2))))
// {
// sebesseg_egyseg_x = 0;
// sebesseg_egyseg_y = 0;
// sebesseg_egyseg_z = 0;
// }
elotolas_beallitas_x(aktualis_x_sebesseg_mmpp);
elotolas_beallitas_y(aktualis_y_sebesseg_mmpp);
elotolas_beallitas_z(aktualis_z_sebesseg_mmpp);
if(uj_cnc_x_szerszampozicio > cnc_x_szerszampozicio)
{
x_gyorsitas_eddig = cnc_x_szerszampozicio + GYORSITAS_LASSITAS_TAVOLSAG_MM;
x_lassitas_innen = uj_cnc_x_szerszampozicio - GYORSITAS_LASSITAS_TAVOLSAG_MM;
}
else if(uj_cnc_x_szerszampozicio < cnc_x_szerszampozicio)
{
x_gyorsitas_eddig = cnc_x_szerszampozicio - GYORSITAS_LASSITAS_TAVOLSAG_MM;
x_lassitas_innen = uj_cnc_x_szerszampozicio + GYORSITAS_LASSITAS_TAVOLSAG_MM;
}
if(uj_cnc_y_szerszampozicio > cnc_y_szerszampozicio)
{
y_gyorsitas_eddig = cnc_y_szerszampozicio + GYORSITAS_LASSITAS_TAVOLSAG_MM;
y_lassitas_innen = uj_cnc_y_szerszampozicio - GYORSITAS_LASSITAS_TAVOLSAG_MM;
}
else if(uj_cnc_y_szerszampozicio < cnc_y_szerszampozicio)
{
y_gyorsitas_eddig = cnc_y_szerszampozicio - GYORSITAS_LASSITAS_TAVOLSAG_MM;
y_lassitas_innen = uj_cnc_y_szerszampozicio + GYORSITAS_LASSITAS_TAVOLSAG_MM;
}
if(uj_cnc_z_szerszampozicio > cnc_z_szerszampozicio)
{
z_gyorsitas_eddig = cnc_z_szerszampozicio + GYORSITAS_LASSITAS_TAVOLSAG_MM;
z_lassitas_innen = uj_cnc_z_szerszampozicio - GYORSITAS_LASSITAS_TAVOLSAG_MM;
}
else if(uj_cnc_z_szerszampozicio < cnc_z_szerszampozicio)
{
z_gyorsitas_eddig = cnc_z_szerszampozicio - GYORSITAS_LASSITAS_TAVOLSAG_MM;
z_lassitas_innen = uj_cnc_z_szerszampozicio + GYORSITAS_LASSITAS_TAVOLSAG_MM;
}
TIM2->CNT = 0;
TIM3->CNT = 0;
TIM4->CNT = 0;
if(x_tavolsag > cnc_felbontas){ TIM_Cmd(TIM2, ENABLE); }
if(y_tavolsag > cnc_felbontas){ TIM_Cmd(TIM3, ENABLE); }
if(z_tavolsag > cnc_felbontas){ TIM_Cmd(TIM4, ENABLE); }
cnc_allapot = G0;
}
ISR:
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
//gyorsítás lassítás
if(uj_cnc_x_szerszampozicio > cnc_x_szerszampozicio)
{
if(cnc_x_szerszampozicio < x_gyorsitas_eddig)
{
aktualis_x_sebesseg_mmpp += sebesseg_egyseg_x;
}
if(cnc_x_szerszampozicio > x_lassitas_innen)
{
aktualis_x_sebesseg_mmpp -= sebesseg_egyseg_x;
}
}
else if(uj_cnc_x_szerszampozicio < cnc_x_szerszampozicio)
{
if(cnc_x_szerszampozicio > x_gyorsitas_eddig)
{
aktualis_x_sebesseg_mmpp += sebesseg_egyseg_x;
}
if(cnc_x_szerszampozicio < x_lassitas_innen)
{
aktualis_x_sebesseg_mmpp -= sebesseg_egyseg_x;
}
}
elotolas_beallitas_x(aktualis_x_sebesseg_mmpp);
//léptetés
if(uj_cnc_x_szerszampozicio > (cnc_x_szerszampozicio + (cnc_felbontas / 2)))
{
x_plusz();
}
else if(uj_cnc_x_szerszampozicio < (cnc_x_szerszampozicio - (cnc_felbontas / 2)))
{
x_minusz();
}
else
{
TIM_Cmd(TIM2, DISABLE);
cnc_x_szerszampozicio = uj_cnc_x_szerszampozicio;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
//gyorsítás lassítás
if(uj_cnc_y_szerszampozicio > cnc_y_szerszampozicio)
{
if(cnc_y_szerszampozicio < y_gyorsitas_eddig)
{
aktualis_y_sebesseg_mmpp += sebesseg_egyseg_y;
elotolas_beallitas_y(aktualis_y_sebesseg_mmpp);
}
if(cnc_y_szerszampozicio > y_lassitas_innen)
{
aktualis_y_sebesseg_mmpp -= sebesseg_egyseg_y;
elotolas_beallitas_y(aktualis_y_sebesseg_mmpp);
}
}
else if(uj_cnc_y_szerszampozicio < cnc_y_szerszampozicio)
{
if(cnc_y_szerszampozicio > y_gyorsitas_eddig)
{
aktualis_y_sebesseg_mmpp += sebesseg_egyseg_y;
elotolas_beallitas_y(aktualis_y_sebesseg_mmpp);
}
if(cnc_y_szerszampozicio < y_lassitas_innen)
{
aktualis_y_sebesseg_mmpp -= sebesseg_egyseg_y;
elotolas_beallitas_y(aktualis_y_sebesseg_mmpp);
}
}
//léptetés
if(uj_cnc_y_szerszampozicio > (cnc_y_szerszampozicio + (cnc_felbontas / 2)))
{
y_plusz();
}
else if(uj_cnc_y_szerszampozicio < (cnc_y_szerszampozicio - (cnc_felbontas / 2)))
{
y_minusz();
}
else
{
TIM_Cmd(TIM3, DISABLE);
cnc_y_szerszampozicio = uj_cnc_y_szerszampozicio;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
//gyorsítás lassítás
if(uj_cnc_z_szerszampozicio > cnc_z_szerszampozicio)
{
if(cnc_z_szerszampozicio < z_gyorsitas_eddig)
{
aktualis_z_sebesseg_mmpp += sebesseg_egyseg_z;
elotolas_beallitas_z(aktualis_z_sebesseg_mmpp);
}
if(cnc_z_szerszampozicio > z_lassitas_innen)
{
aktualis_z_sebesseg_mmpp -= sebesseg_egyseg_z;
elotolas_beallitas_z(aktualis_z_sebesseg_mmpp);
}
}
else if(uj_cnc_z_szerszampozicio < cnc_z_szerszampozicio)
{
if(cnc_z_szerszampozicio > z_gyorsitas_eddig)
{
aktualis_z_sebesseg_mmpp += sebesseg_egyseg_z;
elotolas_beallitas_z(aktualis_z_sebesseg_mmpp);
}
if(cnc_z_szerszampozicio < z_lassitas_innen)
{
aktualis_z_sebesseg_mmpp -= sebesseg_egyseg_z;
elotolas_beallitas_z(aktualis_z_sebesseg_mmpp);
}
}
//léptetés
if(uj_cnc_z_szerszampozicio > (cnc_z_szerszampozicio + (cnc_felbontas / 2)))
{
z_plusz();
}
else if(uj_cnc_z_szerszampozicio < (cnc_z_szerszampozicio - (cnc_felbontas / 2)))
{
z_minusz();
}
else
{
TIM_Cmd(TIM4, DISABLE);
cnc_z_szerszampozicio = uj_cnc_z_szerszampozicio;
}
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
Azt gondoltam hogy így 3 timerrel jobb lesz mint egyel, viszont így meg nem tudom megakadályozni a 3 timer elcsúszását.
Vissza kell írnom egy timerre, egy megszakítással és egyenes arányossággal számolni a pozíciókat és ezzel lépkedni.
Szia! Bocsánat, hogy belekontárkodom, de szerintem a tengelyenkénti Timer-eknek csak üresjárásban van értelme, ott meg elméletileg nem számít az út "torzulása". Miért nem használsz csak 1db STEP timert? A legnagyobb aktuális sebességet úgy is a "leglassabb" tengely határozza meg. Még egy apró szakmai kérdésem lenne: azt hogyan oldod meg, hogy az előtolás sebessége állandó legyen? (gondolok itt arra, hogy egy 0,0=>0,100 egyenesnél a 0,0=>100,100 vonal 1.4-el nagyobb út).
Ezt jó hogy eszembe juttatod. Egyenlőre úgy megy a dolog hogy a 3 tengely közül veszem a legnagyobb táv abszulútértékét és elosztom a felbontással. Ekkor kijon hogy hány lépés is kell az adott sorhoz. Ez egy számláló maximuma. Ebből a maximumból számolok mind 3 tengelynek lépési egységet amelyet majd a timer isrben beszorzok az isr lefutás számlálóval és hozzáadom az induló pozícióhoz. Ekkor kapok 3 számolt pozícióértéket. Megnézem pluszba és minuszba is mind 3 tengelyen hogy nagyobb-e az eltérés mint a gép felbontása és ha igen akkor lépek vele amerre kell egyet. Tehát nálam most lényegében a legnagyobb távolságot megtévő tengelynek van állandó sebessége és a másik kettő vagy egy tengelyé hozzáadódik.
Szia! Szorzol? O.k. biztos van rá idő (nekem AVR-en nem volt, főleg nem lebegőpontossal). Azt hittem Bresenham a vonalhúzód. (ha jól értem, most az egyenes általános egyenletét használod, meredekséget számolva) Bresenham-nál tudsz olyat csinálni (ha fontos az állandó előtolás), hogy a Step-timer értékét szorzod 1.4-el, ha 2 tengely lép, 1.7-el ha mindhárom. A gyorsítás/lassítás meg adja magát, a leghosszabb tengelyre számolva (mert ugye a többi csak is lassabb lehet, max. ugyan annyi).
Igen 168Mhz-ből csak telik rá egy kis idő de, inkább beillesztem a kódom, egy kód többet mond ezer szónál
Interpolátor indítás előkészítés:
void cnc_G0_inditasa(void)
{
long double x_tavolsag = kerekites_long_double(uj_cnc_x_szerszampozicio - cnc_x_szerszampozicio);
long double y_tavolsag = kerekites_long_double(uj_cnc_y_szerszampozicio - cnc_y_szerszampozicio);
long double z_tavolsag = kerekites_long_double(uj_cnc_z_szerszampozicio - cnc_z_szerszampozicio);
long double legnagyobb_tavolsag = abszolut_ertek(x_tavolsag);
if(abszolut_ertek(y_tavolsag) > legnagyobb_tavolsag) { legnagyobb_tavolsag = abszolut_ertek(y_tavolsag); }
if(abszolut_ertek(z_tavolsag) > legnagyobb_tavolsag) { legnagyobb_tavolsag = abszolut_ertek(z_tavolsag); }
interpolator_lepes_igeny = legnagyobb_tavolsag / cnc_felbontas;
intepolator_lepes_szamlalo = 0;
interpolator_x_indulo_pozicio = cnc_x_szerszampozicio;
interpolator_y_indulo_pozicio = cnc_y_szerszampozicio;
interpolator_z_indulo_pozicio = cnc_z_szerszampozicio;
interpolator_x_lepes_egyseg = x_tavolsag / interpolator_lepes_igeny;
interpolator_y_lepes_egyseg = y_tavolsag / interpolator_lepes_igeny;
interpolator_z_lepes_egyseg = z_tavolsag / interpolator_lepes_igeny;
//gyorsítás/lassítás
interpolator_aktualis_sebesseg_mmpp = ALAP_SEBESSEG_MMPP;
elotolas_beallitas(interpolator_aktualis_sebesseg_mmpp);
interpolator_elotolas_kulonbseg = MAX_SEBESSEG_MMPP - ALAP_SEBESSEG_MMPP;
interpolator_elotolas_egyseg = interpolator_elotolas_kulonbseg / (GYORSITAS_LASSITAS_TAVOLSAG_MM / cnc_felbontas);
interpolator_gyorsitas_eddig_lepes = GYORSITAS_LASSITAS_TAVOLSAG_MM / cnc_felbontas;
interpolator_lassitas_innen_lepes = interpolator_lepes_igeny - (GYORSITAS_LASSITAS_TAVOLSAG_MM / cnc_felbontas);
TIM2->CNT = 0;
cnc_allapot = G0;
TIM_Cmd(TIM2, ENABLE);
}
ISR:
void linearis_interpolator_ISR()
{
//gyorsítás lassítás
if(intepolator_lepes_szamlalo < interpolator_gyorsitas_eddig_lepes)
{
interpolator_aktualis_sebesseg_mmpp += interpolator_elotolas_egyseg;
elotolas_beallitas(interpolator_aktualis_sebesseg_mmpp);
}
if(intepolator_lepes_szamlalo > interpolator_lassitas_innen_lepes)
{
interpolator_aktualis_sebesseg_mmpp -= interpolator_elotolas_egyseg;
elotolas_beallitas(interpolator_aktualis_sebesseg_mmpp);
}
interpolator_szamolt_x_pozicio = kerekites_long_double(interpolator_x_indulo_pozicio + (interpolator_x_lepes_egyseg * intepolator_lepes_szamlalo));
interpolator_szamolt_y_pozicio = kerekites_long_double(interpolator_y_indulo_pozicio + (interpolator_y_lepes_egyseg * intepolator_lepes_szamlalo));
interpolator_szamolt_z_pozicio = kerekites_long_double(interpolator_z_indulo_pozicio + (interpolator_z_lepes_egyseg * intepolator_lepes_szamlalo));
//x léptetés
if(interpolator_szamolt_x_pozicio >= kerekites_long_double(cnc_x_szerszampozicio + cnc_felbontas))
{
x_plusz();
}
if(interpolator_szamolt_x_pozicio <= kerekites_long_double(cnc_x_szerszampozicio - cnc_felbontas))
{
x_minusz();
}
//y léptetés
if(interpolator_szamolt_y_pozicio >= kerekites_long_double(cnc_y_szerszampozicio + cnc_felbontas))
{
y_plusz();
}
if(interpolator_szamolt_y_pozicio <= kerekites_long_double(cnc_y_szerszampozicio - cnc_felbontas))
{
y_minusz();
}
//z léptetés
if(interpolator_szamolt_z_pozicio >= kerekites_long_double(cnc_z_szerszampozicio + cnc_felbontas))
{
z_plusz();
}
if(interpolator_szamolt_z_pozicio <= kerekites_long_double(cnc_z_szerszampozicio - cnc_felbontas))
{
z_minusz();
}
//interpolator
if(intepolator_lepes_szamlalo < interpolator_lepes_igeny)
{
intepolator_lepes_szamlalo++;
}
else
{
TIM_Cmd(TIM2, DISABLE);
cnc_valasz = GKOD_OK;
cnc_allapot = KESZENLET;
}
}
void elotolas_beallitas(double mmpp)
{
TIM2->ARR = (65536 / (((mmpp / 60) * cnc_lepes_per_mm) / 30.52)) - 1;
}
Ezt a Bresenham vonalhúzást áttanulmányozom a nagyobb sebesség érdekében és megpróbálom implementálni.
Hát igen, az erőmű... Én igaz, hogy 16MHz/AVR-re és csak 2D-t csináltam, de 5000step/sec-el tudtam menni (úgy, hogy HPGL volt a bejárat, az fordult 2-felé, ha karakter volt a kérés, akkor lebontotta vektorkra, átszaladt egy transzformációs mátrixon, hogy lehessen csűrni-csavarni-hajlítani a karakterképeket és ment a stepper pufferbe, mindeközben tapicsos grafikus LCD-n, ha kellett szimulálta a rajzolatot vagy menüzött). Szóval nem kötelező ezt használni, ha bírja a cucc és nagyon mással nem kell foglalkoznia (igazából grafikailag duplázható az algoritmus sebessége, de az most Neked nem jó). Ha nem boldogulsz, papíron csináld meg mondjuk a 0,0=>17,3 vonalat (direkt ilyen elvetemült számok), azonnal megérted a működését.
Idézet: „Szorzol? O.k. biztos van rá idő” 1 orajel a 32x32 bit.
Most nálam 420mm/perc a biztonságos sebesség, mármint amelyik tengelyen (Z) a marómotor súlya van. (a többi megy gyosabban is) 3db NEMA17 léptetőmocival, DRV2588 meghajtókkal. M6 menetes szár 2db kotyogásmentesre ellenfeszített anyával minden tengelyen. 8-as mikrolépésben. 1mm menetemelkedés. Most a G0 11200 lépés/sec-re van korlátozva és nem a CPU sebesség szab határt hanem a táp 12V-ja. Ha ettől jobban gyorsítok akkor annyira lecsökken a léptetőmotorok áramfelvétele (ugye a forgatónyomatékkal együtt) hogy kap egy kis terhelés és már meg is állt. Nincs visszacsatolás, útmérő. Így inkább lassabban menjen de ne tévedjen, pontosan (lépésvesztés).
Közben rájöttem hogy annyit nem nyerek rajta hogy megérje átírni az interpolátorom. Szóval maradt A hozzászólás módosítva: Jún 5, 2015
Ezt én is tudom, ..
Többi üzenetem kitöröltem, nem akarok hitvitát a 32-bit aritmetika / egész között.
Jó, most nincs kiélezve a feladat, de a töltögetést/komparálást is számold már hozzá...mindegy, kiszálltam, csak segíteni akartam...
ja, hát vast azt nem ismertetted eddig, ha ennyi elég, akkor elég... már bocs, de 12V táp...az nagyon keskeny. Én anno 24V /20A-el is szenvedtem, most meg előfordul 70V/350A csúcsban. Szerintem, ha jót akarsz, növeld a tápfeszt.
Bevégeztem...JAni
Tisztelt Wbt!
Nehogy megsértődj már!
Hasznosak voltak a hszek nem szabad törölni! Kérjük vissza!
Most kezd érdekes lenni a téma, jól jönnek a tapasztalt hozzáértők!
Szerintem, majd ahogy szaporodnak a feladatok, és kezd kifulladni a proceszor idő, rájön, hogy spórolni kel az erőforrásosokkal!
Én pl. eddig azt hitem, hogy szervomotort akarunk vezérelni!
Ha viszont léptetőmotor, akkor mért nem lépésszámlálással mérjük az út hosszát?
Tisztelt killbill!
Honnan veted az 1 szorzás 1 órajel adatot?
Itt pl. nem találok erre utalást, 3.6 Multiply and divide instructions :
STM32F4 Series Cortex®-M4 programming manual
Ha hozzá kalkuláljuk a regiszterek feltöltését is?
Examples
MUL R10, R2, R5 ; multiply, R10 = R2 x R5
MLA R10, R2, R1, R5 ; multiply with accumulate, R10 = (R2 x R1) + R5
MULS R0, R2, R2 ; multiply with flag update, R0 = R2 x R2
MULLT R2, R3, R2 ; conditionally multiply, R2 = R3 x R2
MLS R4, R5, R6, R7 ; multiply with subtract, R4 = R7 - (R5 x R6)
Az emlekeimbol vettem. Es meg az is lehet, hogy 2 orajel. De a szorzas, az szorzas es nem regiszter toltogetes. Igazabol csak azert irtam, mert mar megszoktuk, hogy a szorzas az nagyon draga muvelet, de ARM-en (mondjuk M3-mon) nem dragabb, mint egy osszeadas.
Bocsi!
A kérdésem lényege a forrás lett volna, ahol az utasításokhoz szükséges órajelekre található utalás!
Idézet: „Szorzol? O.k. biztos van rá idő (nekem AVR-en nem volt,” AVR vs. ARM. En csak ehhez szoltam hozza.
Köszönöm! 
Idézet: „Ha viszont léptetőmotor, akkor mért nem lépésszámlálással mérjük az út hosszát?” Peldaul azert, mert ha egy lepes kiesik, nincs informaciod rola.
„Peldaul azert, mert ha egy lepes kiesik, nincs informaciod rola.” ???
Ezt most abszolúte nem értem!
Miért, ha nincsen visszajelzésed, bármilyen módszerrel lesz valami infód a ténylegesen megtett
útról?
A jobbak épen ezért használnak szervomotort, és enkodert! A hozzászólás módosítva: Jún 6, 2015
A 12V-os meghajtás szerintem is édes kevés lesz!
Kellene legalább a duplája. És tengelyenként megoldani a PWM-es leszabályozását álló helyzetben, csak kisebb tartó fessz kel.
Különben túlmelegszenek a motorok. A hozzászólás módosítva: Jún 6, 2015
|
|