Skocz do zawartości

ps19

Użytkownicy
  • Zawartość

    598
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    13

ps19 zajął 1. miejsce w rankingu.
Data osiągnięcia: 5 lutego 2018.

Treści użytkownika ps19 zdobyły tego dnia najwięcej polubień!

O ps19

  • Urodziny 19.03.1996

Informacje

  • Płeć
    Mężczyzna
  • Lokalizacja
    Opole
  • Programuję w
    C/C++/C#/Java/Matlab
  • Zawód
    Technik Elektronik/Student AiR
  • Moje zainteresowania:
    Robotyka,Programowanie,Fotografia

Ostatnio na profilu byli

1 733 wyświetleń profilu

Osiągnięcia użytkownika ps19

Innowator

Innowator (10/19)

  • Za 25 postów
  • Za 5 postów
  • Za 100 postów
  • Ulubieniec czytelników
  • Lokalna gwiazda

Odznaki

66

Reputacja

  1. Kinematyka prosta i odwrotna te pojęcia powinieneś szukać 😉
  2. Cześć, Mam taki mały problem z odpaleniem sterowania wektorowego (FOC) z modulacją przestrzenną wektora (SVM). Problem polega na tym, że silnik zamiast kręcić się stoi w miejscu, jak próbuję go ręcznie ruszyć to pomiędzy cewkami jest wyczuwalny luz natomiast w miejscu cewek próbuje trzymać pozycję. Raczej nie liczę na sprawdzenie kodu, ale podpowiedź co może powodować takie zachowanie. FOC: void focAlgorithm(motorParamsTypedef *mot) { __disable_irq(); static float32_t pSinVal, pCosVal; arm_sin_cos_f32(mot->enc.elecAngleDegrees_f32, &pSinVal, &pCosVal); arm_clarke_f32(mot->current.n_f32[PHASE_A], mot->current.n_f32[PHASE_B], &mot->current.alpha_f32, &mot->current.beta_f32); arm_park_f32(mot->current.alpha_f32, mot->current.beta_f32, &mot->current.IdMagnFlux_f32, &mot->current.IqRotaryTorque_f32, pSinVal, pCosVal); mot->current.targetIqRotaryTorque_f32 = mot->pidAngVel.PIDout; //PI working in SysTick handler below PIDIdMagnFluxFunc(&mot->pidId, &mot->current, mot->current.targetIdMagnFlux_f32); PIDIqRotaryTorqueFunc(&mot->pidIq, &mot->current, mot->current.targetIqRotaryTorque_f32); arm_inv_park_f32(mot->pidId.PIDout, mot->pidIq.PIDout, &mot->current.alphaPostInvPark_f32, &mot->current.betaPostInvPark_f32, pSinVal, pCosVal); arm_inv_clarke_f32(mot->current.alphaPostInvPark_f32, mot->current.betaPostInvPark_f32, &mot->current.aPostInvClarke_f32, &mot->current.bPostInvClarke_f32); svmAlgorithm(mot); __enable_irq(); } SVM: void svmAlgorithm(motorParamsTypedef *mot) { float32_t Uout = 0, angle = 0; angle = mot->enc.elecAngleRadians_f32 + M_PI; //angle = atan2f(mot->current.betaPostInvPark, mot->current.alphaPostInvPark); //sq -> a^2 arm_sqrt_f32(sq(mot->current.alphaPostInvPark_f32) + sq(mot->current.alphaPostInvPark_f32), &Uout); float32_t t1 = M_SQRT3_2*arm_sin_f32(M_PI_3 - angle)*Uout; float32_t t2 = M_SQRT3_2*arm_sin_f32(angle)*Uout; float32_t t0 = 1.0F - (t1 + t2); if(angle >= 0 && angle < DEG2RAD_60) //sector 1 { mot->svm.a_f32 = t1 + t2 + (t0/2); mot->svm.b_f32 = t2 + (t0/2); mot->svm.c_f32 = (t0/2); } else if(angle >= DEG2RAD_60 && angle < DEG2RAD_120) //sector 2 { mot->svm.a_f32 = t1 + (t0/2); mot->svm.b_f32 = t1 + t2 + (t0/2); mot->svm.c_f32 = (t0/2); } else if(angle >= DEG2RAD_120 && angle < DEG2RAD_180) //sector 3 { mot->svm.a_f32 = (t0/2); mot->svm.b_f32 = t1 + t2 + (t0/2); mot->svm.c_f32 = t2 + (t0/2); } else if(angle >= DEG2RAD_180 && angle < DEG2RAD_240) //sector 4 { mot->svm.a_f32 = (t0/2); mot->svm.b_f32 = t1 + (t0/2); mot->svm.c_f32 = t1 + t2 + (t0/2); } else if(angle >= DEG2RAD_240 && angle < DEG2RAD_300) //sector 5 { mot->svm.a_f32 = t2 + (t0/2); mot->svm.b_f32 = (t0/2); mot->svm.c_f32 = t1 + t2 + (t0/2); } else if(angle >= DEG2RAD_300 && angle <= DEG2RAD_360) //sector 6 { mot->svm.a_f32 = t1 + t2 + (t0/2); mot->svm.b_f32 = (t0/2); mot->svm.c_f32 = t1 + (t0/2); } else { mot->svm.a_f32 = 0; mot->svm.b_f32 = 0; mot->svm.c_f32 = 0; angle = 0; } mot->timMot->CCR1 = mot->svm.a_f32; mot->timMot->CCR2 = mot->svm.b_f32; mot->timMot->CCR3 = mot->svm.c_f32; } FOCInit: void focInit(motorParamsTypedef *mot) { float32_t Ts = 1.0F/TIM_PWM_FREQUENCY; float32_t Td = Ts; float32_t Ti = Ts; myAdc.adcFilterSteps_u16 = 10; myAdc.adcCalibSteps_u16 = 1000; myAdc.adcCalibFlag_enum = CALIB_START; mot->motorMaxVoltage_f32 = 1; mot->current.targetIdMagnFlux_f32 = 0; mot->svm.ts_f32 = Ts; mot->targetAngularVelocity_f32 = 10000; //PID1 mot->pidAngVel.kp = 0.01; mot->pidAngVel.ki = 0.1; mot->pidAngVel.kd = 0; mot->pidAngVel.Ts = 0.001; mot->pidAngVel.Td = mot->pidAngVel.Ts; mot->pidAngVel.Ti = mot->pidAngVel.Ts; mot->pidAngVel.PIDoutMax = MOTOR_MAX_ANG_VEL_RAD; mot->pidAngVel.PIDoutMin = -MOTOR_MAX_ANG_VEL_RAD; mot->pidAngVel.errorTolerance = 0.01; //PID2 mot->pidId.kp = computeKp(13); mot->pidId.ki = computeKi(13, 1); mot->pidId.kd = 0; mot->pidId.Ts = Ts; mot->pidId.Td = Td; mot->pidId.Ti = Ti; mot->pidId.PIDoutMax = MOTOR_MAX_CURRENT; mot->pidId.PIDoutMin = -MOTOR_MAX_CURRENT; mot->pidId.errorTolerance = 0.01; //PID3 mot->pidIq.kp = computeKp(13); mot->pidIq.ki = computeKi(13, 1); mot->pidIq.kd = 0; mot->pidIq.Ts = Ts; mot->pidIq.Td = Td; mot->pidIq.Ti = Ti; mot->pidIq.PIDoutMax = MOTOR_MAX_CURRENT; mot->pidIq.PIDoutMin = -MOTOR_MAX_CURRENT; mot->pidIq.errorTolerance = 0.01; } Inne: void PIDIdMagnFluxFunc(PidTypedef *pid, MotorCurrentTypedef *motI, float32_t targetIdMagnFlux) { pid->valPres = motI->IdMagnFlux_f32; pid->valTarget = targetIdMagnFlux; PIDController(pid); } void PIDIqRotaryTorqueFunc(PidTypedef *pid, MotorCurrentTypedef *motI, float32_t targetIqRotaryTorque) { pid->valPres = motI->IqRotaryTorque_f32; pid->valTarget = targetIqRotaryTorque; PIDController(pid); } void PIDMotorAngularVelocity(PidTypedef *pid, encoderTypedef *enc, float32_t targetAngularVelocity) { pid->valPres = enc->angleRadiansSpeed_f32; pid->valTarget = targetAngularVelocity; PIDController(pid); } float32_t computeAB(float32_t VBusDC) { //https://www.st.com/resource/en/user_manual/cd00298474-stm32f-pmsm-singledual-foc-sdk-v43-stmicroelectronics.pdf //page 38 return (VBusDC*SHUNT_RES_VAL*SHUNT_AMPLIFICATION)*UC_REF_VOLTAGE; } float32_t computeKp(float32_t VBusDC) { return MOTOR_LS_H*(MOTOR_MAX_ANG_VEL_RAD/computeAB(VBusDC))*PID_KP_DIV; } float32_t computeKi(float32_t VBusDC, float32_t T) { return ((MOTOR_RS_OHM*MOTOR_MAX_ANG_VEL_RAD*PID_KI_DIV)/computeAB(VBusDC))*T; } void SysTick_Handler(void) { encoderAngularSpeedRead(&motorLeftStruct.enc); encoderAngularSpeedRead(&motorRightStruct.enc); motorLeftStruct.targetAngularVelocity_f32=50; PIDMotorAngularVelocity(&motorLeftStruct.pidAngVel, &motorLeftStruct.enc, motorLeftStruct.targetAngularVelocity_f32); PIDMotorAngularVelocity(&motorRightStruct.pidAngVel, &motorRightStruct.enc, motorRightStruct.targetAngularVelocity_f32); }
  3. Witam Próbuję zaimplementować algorytm podążania robota mobilnego 2-kołowego po trajektorii zadanej z góry wzorem na podstawie znalezionych materiałów. materiały: https://www.researchgate.net/publication/225543929_Control_of_Wheeled_Mobile_Robots_An_Experimental_Overview (strona 16 - Nonlinear Control Design) https://kcir.pwr.edu.pl/~mucha/Pracki/Rafal_Cyminski_praca_magisterska.pdf (strona 38) Problem polega na tym, że robot albo jedzie tylko część trajektorii albo ruch wynikowy nie przypomina ani trochę trajektorii wynikowej. void lissajousInit(lissajousTypedef *liss,trajectoryTypedef *traj, sampsonTypedef *samp) { traj->ts = 0.01F; robotMove1.ts = traj->ts; liss->amplitudeX_f32 = 0.5F; liss->amplitudeY_f32 = 0.6F; liss->paramA_u8 = 1.0F; liss->paramB_u8 = 2.0F; liss->paramDelta_f32 = M_PI/2; samp->Kp_f32 = 0.526; samp->Kd_f32 = 0.00263; traj->translationDesigned_f32 = integrateTrapz(0, M_TWOPI, 1000.0F, lissajousTrajectoryVelocitySpecial); } void lissajousTrajectoryGenarate(lissajousTypedef *liss,trajectoryTypedef *traj, sampsonTypedef *samp, robotMoveTypedef *robMov) { if(robMov->translationMeters <= traj->translationDesigned_f32) { traj->time_f32 += traj->ts;//M_PI_DIV; traj->trajRunning_u8 = 1; lissajousTrajectoryPath(traj, liss); calcAngleRadians(traj); trajectoryVelocity(traj); trajectoryAcceleration(traj); samp->angleNow_f32 = robMov->robotAngleDiff; samp->angleErr_f32 = (traj->angleRadiansDiff_f32- robMov->robotAngleDiff); samp->xErr_f32 = (traj->px_f32 - robMov->x); samp->yErr_f32 = (traj->py_f32 - robMov->y); samp->progrVelDesigned_f32 = traj->vxy_f32; samp->angVelDesigned_f32 = ((traj->ay_f32*traj->vx_f32) - (traj->ax_f32*traj->vy_f32))/traj->vxy_f32; sampsonAlgorithm(samp); } else { traj->trajRunning_u8 = 0; //robMov->translationMeters = traj->translationDesigned_f32; } } void lissajousTrajectoryPath(trajectoryTypedef *traj, lissajousTypedef *liss) { traj->pxPrev_f32 = traj->px_f32; traj->pyPrev_f32 = traj->py_f32; traj->px_f32 = liss->amplitudeX_f32*arm_sin_f32(liss->paramA_u8*traj->time_f32 + liss->paramDelta_f32); traj->py_f32 = liss->amplitudeY_f32*arm_sin_f32(liss->paramB_u8*traj->time_f32); } void trajectoryVelocity(trajectoryTypedef *traj) { if(lisTraj.amplitudeX_f32 > 0) { traj->vx_f32 = lisTraj.amplitudeX_f32*lisTraj.paramA_u8*cosf(lisTraj.paramA_u8*traj->ts + lisTraj.paramDelta_f32); traj->vy_f32 = lisTraj.amplitudeY_f32*lisTraj.paramB_u8*cosf(lisTraj.paramB_u8*traj->ts); } else { //for anothor purpose traj->vxPrev_f32 = traj->vx_f32; traj->vyPrev_f32 = traj->vy_f32; traj->vx_f32 = (traj->pxPrev_f32 - traj->px_f32)/traj->ts; traj->vy_f32 = (traj->pyPrev_f32 - traj->py_f32)/traj->ts; if(traj->velocityDesigned_f32) { if(traj->vx_f32 != 0) traj->vx_f32 = (traj->velocityDesigned_f32/traj->vx_f32)*traj->vx_f32; if(traj->vy_f32 != 0) traj->vy_f32 = (traj->velocityDesigned_f32/traj->vy_f32)*traj->vy_f32; } } float32_t sumOfSqares = (traj->vx_f32*traj->vx_f32) + (traj->vy_f32*traj->vy_f32); traj->vxy_f32 = sqrtf(sumOfSqares); } void trajectoryAcceleration(trajectoryTypedef *traj) { if(lisTraj.amplitudeX_f32 > 0) { traj->ax_f32 = -lisTraj.amplitudeX_f32*lisTraj.paramA_u8*lisTraj.paramA_u8*sinf(lisTraj.paramA_u8*traj->ts + lisTraj.paramDelta_f32); traj->ay_f32 = -lisTraj.amplitudeY_f32*lisTraj.paramB_u8*lisTraj.paramB_u8*sinf(lisTraj.paramB_u8*traj->ts); } else { //for anothor purpose traj->ax_f32 = (traj->vxPrev_f32 - traj->vx_f32)/traj->ts; traj->ay_f32 = (traj->vyPrev_f32 - traj->vy_f32)/traj->ts; } float32_t sumOfSqares = (traj->ax_f32*traj->ax_f32) + (traj->ay_f32*traj->ay_f32); traj->axy_f32 = sqrtf(sumOfSqares); } void calcAngleRadians(trajectoryTypedef *traj) { traj->angleRadiansPrev_f32 = traj->angleRadians_f32; traj->angleRadians_f32 = atan2f(traj->py_f32, traj->px_f32); traj->angleRadiansDiff_f32 = traj->angleRadians_f32 - traj->angleRadiansPrev_f32; } float deg2rad(float num) { return num * (M_PI / M_PI_DEG); } float rad2deg(float num) { return num * (M_PI_DEG / M_PI); } static float32_t lissajousTrajectoryVelocitySpecial(float32_t mytime) { static float32_t vxySpecial; trajectory1.vx_f32 = lisTraj.amplitudeX_f32*lisTraj.paramA_u8*cosf((lisTraj.paramA_u8*mytime) + lisTraj.paramDelta_f32); trajectory1.vy_f32 = lisTraj.amplitudeY_f32*lisTraj.paramB_u8*cosf(lisTraj.paramB_u8*mytime); float32_t sumOfSqares = (trajectory1.vx_f32*trajectory1.vx_f32) + (trajectory1.vy_f32*trajectory1.vy_f32); vxySpecial = sqrtf(sumOfSqares); return vxySpecial; } float32_t integrateTrapz(float32_t xp, float32_t xk, uint16_t N, float32_t(*f)(float32_t)) { float32_t dx = 0, s = 0; s = 0; dx = (xk - xp) / N; for (int i = 1; i < N; i++) { s += (*f)(xp + i * dx); } s = (s + ((*f)(xp) + (*f)(xk)) / 2) * dx; return s; } Algorytm omawiany w wyżej wymienionych publikacjach: void sampsonAlgorithm(sampsonTypedef *alg) { alg->xTrackErr_f32 = cosf(alg->angleNow_f32)*alg->xErr_f32 + sinf(alg->angleNow_f32)*alg->yErr_f32; alg->yTrackErr_f32 = -sinf(alg->angleNow_f32)*alg->xErr_f32 + cosf(alg->angleNow_f32)*alg->yErr_f32; if(alg->angleErr_f32 == 0) alg->angleErr_f32 = FLT_MIN; //very small number - 0 casued NaN (Not a Number) alg->progrVelRef_f32 = alg->Kp_f32*alg->xTrackErr_f32 + alg->progrVelDesigned_f32*cosf(alg->angleErr_f32); alg->angVelRef_f32 = alg->angVelDesigned_f32 + (alg->Kd_f32*alg->angleErr_f32) + (alg->progrVelDesigned_f32*alg->yTrackErr_f32*(sinf(alg->angleErr_f32)/alg->angleErr_f32)); alg->velLeftWheel_f32 = alg->progrVelRef_f32 - (ROBOT_LENGHT/2)*alg->angVelRef_f32; alg->velRightWheel_f32 = alg->progrVelRef_f32 + (ROBOT_LENGHT/2)*alg->angVelRef_f32; alg->velLeftWheelTicks_f32 = (convertMetersToTicks(alg->velLeftWheel_f32)/100.0F); alg->velRightWheelTicks_f32 = (convertMetersToTicks(alg->velRightWheel_f32)/100.0F); } Obliczanie pozycji robota: void calculateRobotKinematics(encoderTypedef *encLeft, encoderTypedef *encRight, robotMoveTypedef *robMov) { robMov->translationMeters = (encLeft->distanceMeters_f32 + encRight->distanceMeters_f32)/2; robMov->translationMetersDiff = (encLeft->distanceMetersDiff_f32 + encRight->distanceMetersDiff_f32)/2; MPU6050_Read_Gyro(&hi2c3, &MPU6050); if(fabsf(MPU6050.Gz) < 0.1F) //high-pass filter [deg] { MPU6050.Gz = 0.0F; } robMov->rotationRadians += deg2rad(MPU6050.Gz)*robMov->ts; // (encRight->distanceMeters - encLeft->distanceMeters)/ROBOT_LENGHT; robMov->rotationRadiansDiff = robMov->rotationRadians - robMov->rotationRadiansPrev; //może *ts ??? robMov->robotAngleDiff = robMov->robotAngle - robMov->robotAnglePrev; //może *ts ??? robMov->x = robMov->translationMeters*cosf(robMov->rotationRadians); robMov->y = robMov->translationMeters*sinf(robMov->rotationRadians); robMov->robotAngle = atan2f(robMov->y, robMov->x); robMov->rotationRadiansPrev = robMov->rotationRadians; robMov->robotAnglePrev = robMov->robotAngle; } Wywołanie całości (co 10ms --> f = 100Hz): if(START_PILOT_VIENNA || START_PILOT_JSUMO) { lissajousTrajectoryGenarate(&lisTraj,&trajectory1, &sampsonData, &robotMove1); PIDwheelVelocity(&pidLeftWheel, &encoderLeft, sampsonData.velLeftWheelTicks_f32); PIDwheelVelocity(&pidRightWheel, &encoderRight, sampsonData.velRightWheelTicks_f32); if(trajectory1.trajRunning_u8) { MotorSpeed(pidLeftWheel.PWMout, pidRightWheel.PWMout); } else { MotorSpeed(0,0); } } else { MotorSpeed(0,0); }
  4. Płytki nowe, oryginalnie zapakowane, kupione do projektu na który nie miałem ostatecznie czasu. - Nucleo-32 STM32L412 (2sztuki) - 45zł/szt https://allegrolokalnie.pl/oferta/zestaw-rozwojowy-edukacyjny-nucleo-32-stm32l412 - Nucleo-144 STM32F439 (2 sztuki) - 120zl/szt https://allegrolokalnie.pl/oferta/zestaw-rozwojowy-edukacyjny-nucleo-144-stm32f439 - Raspberry Pi 3 model A+ (2 sztuki) - 105zł/szt https://allegrolokalnie.pl/oferta/raspberry-pi-3-model-a - Raspberry Pi 3 model B+ (3 sztuki)- 165zł/szt https://allegrolokalnie.pl/oferta/raspberry-pi-3-model-b-5zj Ceny do małej negocjacji. Wysyłka - paczkomat 12 zł lub kurier 15 zł/za pobraniem 20zł
  5. Takie złącze, możesz dać 6 pinowe bez problemu (SWO nie jest potrzebne). Nie musi to być raster 2,54 mm są też 2 mm - z jednej strony normalne goldpiny 2,54 mm na tasiemce a z drugiej goldpiny na 2mm. Można dać też 1x6 wg pinologii z Nucleo. Przykłady: https://botland.com.pl/pl/80-przewody-i-zlacza-idc https://botland.com.pl/pl/przewody-i-zlacza-idc/1246-przewod-idc-6-pin-zensko-zenski-30-cm.html
  6. Wyprowadzasz złącze np. samo SWD na goldpinach i tyle, igly są drogie i nie wygodne jak programujesz coś dużą ilość razy w czasie testów. Na Nucleo odpinasz zworki i masz je jako programator a linie są wyprowadzone właśnie na goldpinach. Tak samo robisz na swoim PCB i problem z głowy. Ja mam zamiast goldpinów gniazdo IDC wyprowadzone zgodnie ze standardem SWD.
  7. na początku dodałbym jeszcze ustawianie stanu wysokiego w Setup`ie i pinMode zmienia tryb pracy pinu a nie digitalWrite, a domyślnie piny są wejściami w AVRach także nic dziwnego że nie działa. Void setup () { pinMode(7,OUTPUT); pinMode(8,OUTPUT); digitalWrite(8,HIGH); digitalWrite(7,HIGH); } i cały program: Void setup () { pinMode(7,OUTPUT); pinMode(8,OUTPUT); digitalWrite(8,HIGH); digitalWrite(7,HIGH); } void loop() { digitalWrite(8,LOW); delay(50000); digitalWrite(8,HIGH); delay(300); digitalWrite(7,LOW); delay(50000); digitalWrite(7,HIGH); delay(300); }
  8. Tutaj jest napisane, druga sprawa to może arduino nie wyrabia prądowo - zapalenie diody to jedno, a wyzwolenie cewki przekaźnika to inna sprawa. Polecam używanie słownika w przeglądarce w przypadku dysleksji czy po prostu robieniem błędów - prawym mszy na podkreślone na czerwono słowo i pojawią się poprawne propozycje.
  9. Dokladnie to błędu szukaj w krzemie STMa - ta magistrala w tych procesorach tak ma, ale pod HALem jakoś to działa. Pokaż kod i sprawdź stany rejestru SR od I2C - jak rozwiniesz SFR to masz tam rózne flagi BUSY, ACK itp. W Attolicu, CubeIDE i innych Eclipso podobnych masz okienko SFR w debugu - podgląd rejestrów (Jak nie ma w to poszukaj w View gdzieś). Przed włączeniem I2C możesz spróbować zresetować magistralę I2C - tak procedura jest opisana w Erracie procka. I2Cx->CR1 |= I2C_CR1_SWRST; //Software reset 1 I2Cx->CR1 &= ~ I2C_CR1_SWRST; //Software reset 0 zamiast I2Cx wstawiasz IC21 albo I2C2 itd zależnie którego używasz. Handlery są w pliku stm32fxxxx_it.c (gdzie x to numer rodziny itp), ale jakbyś był w Handlerze to by Ci tam debug wskakiwał po wciśnięciu pauzy. Najważniejsze to kod - dla programisty ważniejsze niż opis słowny, bez tego to możemy wróżyć tutaj przez rok.
  10. Wskazówka nr 1 Standard Peripheral Library (SPL) jest już od kilku lat nierozwijana i niewspierana przez ST, zainteresuj się biblioteką HAL. Co do kodu przerwanie od przycisku nie ma sensu, musiałbyś blokować zmianę stanu diody jakimś timerem w przerwaniu od EXTI bo to się może wykonuje ale na tyle szybko że nie zauważasz. Zmiana priorytetów przerwań na początku nauki - nie polecam. Przy priorytetach domyślnych i tak wykona Ci się to bardzo szybko przy tak prostym programie. Zamiast tego: nvic.NVIC_IRQChannel = EXTI0_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 0x00; nvic.NVIC_IRQChannelSubPriority = 0x00; nvic.NVIC_IRQChannelCmd = ENABLE; Lepiej użyć: NVIC_EnableIRQ(EXTI0_IRQn); Nie musisz wtedy ustalać priorytetów przerwań i pisać 4 linii kodu.
  11. Sprawdź konfigurację pinu BOOT STMa
  12. Masz 3 człony obrotowe a w wyniku wyszedł ci jeden to chyba coś nie tak 😉 Masz rotację po X i 2 po Z 1.Przesunięcie po Z o d1, 2. obrót po X po theta1, 3. obrót po Z po theta2, 4. przesuniecie po X o a2/l2 5. obrót po Z po theta3, 6. przesuniecie po X o a3/l3. Powinno ci wyjść: x = cos(th1)*(l2*cos(th2) + l3*cos(th2+th3)) x = sin(th1)*(l2*cos(th2) + l3*cos(th2+th3)) z = d1 + (l2*sin(th2) + l3*sin(th2+th3)) Tutaj masz dla 6 osiowego ale to wystarczy opuścić ostatnie macierze A45 i A56 https://www.researchgate.net/publication/310389891_Kinematics_Analysis_and_Modeling_of_6_Degree_of_Freedom_Robotic_Arm_from_DFROBOT_on_Labview
  13. To nie problem biblioteki jak napisałem - nowa biblioteka nie zapobiegnie użyci zlej funkcji/metody podczas pisania programu. Równie dobrze mogłem zaproponować pisanie na rejestrach w w C czy nawet asemblerze, ale nie o to chodzi. OFFTOP: Wyklikiwanie konfiguracji w Cube niekoniecznie uczy programowania mikroprocesorów bardziej pomaga zacząć nie do końca wiedząc jak działa procesor, ale nie chce wszczynać dyskusji o wyższości bibliotek czy rejestrów bo sam korzystam czasami różnie od potrzeb z różnych kombinacji HAL lub rejestry czy HAL + rejestry.
  14. Od czego jest pin PA5 ? Problem masz raczej w przerwaniu od TIM2 skoro ono działa z f = 4 kHz a PWM ma 12 kHz i na wykresie masz co 3 (okres ?) szpilkę w dół (12/4) Chyba korzystasz z kursu dotyczącego biblioteki SPL już nie rozwijanej, ale to nie problem 😉 https://forbot.pl/blog/kurs-stm32-f1-hal-liczniki-timery-w-praktyce-pwm-id24334
  15. ps19

    Mobilność pojazdu gąsienicowego

    https://pdfs.semanticscholar.org/4e98/09960be9ec7f1ad8fadf61dad8cb1c8818d0.pdf http://www.par.pl/2012/PAR_10_2012_Pyka_74_78.pdf https://we.po.opole.pl/dmdocuments/autoreferat_pyka.pdf http://web.mit.edu/jlramos/www/Arquivos/ReportDifferentialDrive.pdf Z książek - Modelowanie i sterowanie mobilnych robotów kołowych - Giergiel,Hendzel, Żylski (PWN) - Robot Dynamics and Control - Mark W. Spong - Robotics: Modelling, Planning and Control (Springer) - https://www.academia.edu/11985316/Introduction_to_Mobile_Robot_Control
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.