Skocz do zawartości

Arduino + wozek inwalidzki (sterowanie 2 silnikow)


MarcinTe

Pomocna odpowiedź

Czesc,

Robie wozek inwalidzki oparty na 2 silnikach, joystick porusza wozek, przycisk obraca go w miejscu, wszystko dziala.

Problem w tym ze joystick jest maly i silniki bardzo agresywnie reaguja, chcialbym zeby po natychmiastowym wychyleniu do przodu predkosc nie skoczyla od razu do wartosci maksymalnej tylko chwile plynnie do niej dochodzila. Bede wdzieczny za pomoc. Dzieki.

// FINAL Z 1 PRZYCISKIEM ENDER 3

// Button

const int switchPin = 2;
int switchValue;
  
// Motor A
 
int enA = 9;
int in1 = 8;
int in2 = 7;
 
// Motor B
 
int enB = 3;
int in3 = 5;
int in4 = 4;
 
// Joystick Input
 
int joyVert = A0; // Vertical  
int joyHorz = A1; // Horizontal
 
// Motor Speed Values - Start at zero
 
int MotorSpeed1 = 0;
int MotorSpeed2 = 0;

// Joystick Values - Start at 512 (middle position)
 
int joyposVert = 512;
int joyposHorz = 512;  
 
 
void setup()
 
{

   Serial.begin(9600);
   
//button
   
 pinMode(switchPin, INPUT_PULLUP);
  
  // Set all the motor control pins to outputs
 
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
   
  // Start with motors disabled and direction forward
  
  // Motor A
  
  digitalWrite(enA, LOW);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  
  // Motor B
  
  digitalWrite(enB, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  
}
 
void loop() {

// button state

   switchValue = digitalRead(switchPin);

 if (switchValue==1) {

  // Read the Joystick X and Y positions
 
  joyposVert = analogRead(joyVert); 
  joyposHorz = analogRead(joyHorz);
 
  // Determine if this is a forward or backward motion
  // Do this by reading the Verticle Value
  // Apply results to MotorSpeed and to Direction
 
  if (joyposVert < 460)
  {
    // This is Backward
 
    // Set Motor A backward
 
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
 
    // Set Motor B backward
 
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
 
    //Determine Motor Speeds
 
    // As we are going backwards we need to reverse readings
 
    joyposVert = joyposVert - 460; // This produces a negative number
    joyposVert = joyposVert * -1;  // Make the number positive
 
   MotorSpeed1 = map(joyposVert, 0, 460, 0, 255);
   MotorSpeed2 = map(joyposVert, 0, 460, 0, 255);

 
  }
  else if (joyposVert > 564)
  {
    // This is Forward
 
    // Set Motor A forward
 
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
 
    // Set Motor B forward
 
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
 
    //Determine Motor Speeds
 
   MotorSpeed1 = map(joyposVert, 564, 1023, 0, 255);
   MotorSpeed2 = map(joyposVert, 564, 1023, 0, 255); 

 
  }
  else
  {
    // This is Stopped
 
    MotorSpeed1 = 0;
    MotorSpeed2 = 0; 
 
  }
  
  // Now do the steering
  // The Horizontal position will "weigh" the motor speed
  // Values for each motor


 
  if (joyposHorz < 460)
  {
    // Move Left
 
    // As we are going left we need to reverse readings
 
    joyposHorz = joyposHorz - 460; // This produces a negative number
    joyposHorz = joyposHorz * -1;  // Make the number positive
 
    // Map the number to a value of 255 maximum
 
   joyposHorz = map(joyposHorz, 0, 460, 0, 255);

    
 
    MotorSpeed1 = MotorSpeed1 - joyposHorz;
    MotorSpeed2 = MotorSpeed2 + joyposHorz;
 
    // Don't exceed range of 0-255 for motor speeds
 
    if (MotorSpeed1 < 0)MotorSpeed1 = 0;
   if (MotorSpeed2 > 255)MotorSpeed2 = 255;

 
  }
  else if (joyposHorz > 564)
  {
    // Move Right
 
    // Map the number to a value of 255 maximum
 
   joyposHorz = map(joyposHorz, 564, 1023, 0, 255);

   
        
 
    MotorSpeed1 = MotorSpeed1 + joyposHorz;
    MotorSpeed2 = MotorSpeed2 - joyposHorz;
 
    // Don't exceed range of 0-255 for motor speeds
 
   if (MotorSpeed1 > 255)MotorSpeed1 = 255;
    
    if (MotorSpeed2 < 0)MotorSpeed2 = 0;      
 
  }
 
 
  // Adjust to prevent "buzzing" at very low speed
 
if (MotorSpeed1 < 10)MotorSpeed1 = 0;
 if (MotorSpeed2 < 10)MotorSpeed2 = 0;

 }
else if (switchValue==0) {

 
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  MotorSpeed1=150;
  // Motor B
  
 
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
MotorSpeed2=150;
}
 
  // Set the motor speeds
 
  analogWrite(enA, MotorSpeed1);
  analogWrite(enB, MotorSpeed2);

   
Serial.print("X: ");
  Serial.print(MotorSpeed1);
   Serial.print(" Y: ");
  Serial.print(MotorSpeed2);
  Serial.print(" Button: ");
  Serial.println(switchValue);
  
 
}

 

Link do komentarza
Share on other sites

To może dodaj zmienną, w której będziesz trzymać docelową prędkość danego silnika, osobną od aktualnej jego prędkości, i w każdym obrocie pętli, jeśli docelowa prędkość jest większa od aktualnej, to zwiększaj aktualną o jakąś ograniczoną od góry wartość, a jak jest mniejsza, to zmniejszaj, analogicznie.

Link do komentarza
Share on other sites

15 godzin temu, MarcinTe napisał:

chcialbym zeby po natychmiastowym wychyleniu do przodu predkosc nie skoczyla od razu do wartosci maksymalnej tylko chwile plynnie do niej dochodzila.

Prędkość zwiększaj w przerwaniu od timera.

Jak chcesz zrobić rampę to mam gdzieś kod źródłowy.

Edytowano przez InspektorGadzet
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

30 minut temu, MarcinTe napisał:

Nie wiem o co chodzi z ta rampa ale i tak poprosze o ten kod

Nie wiesz a chcesz? Mam odczucie, że kod się nie przyda. Jest w dużym projekcie, wyciąłem istotne fragmenty, jak potrzebne coś jeszcze to napisz co konkretnie.

void Przesow( uint8_t stan )
{
  if ( stan ) {
		AktualnaMoc = 1;
		fazaRozpedu = ROZBIEG;
		KrokPrzyrostukMocy = (float)Cfg.silnik / Cfg.tRozpedzania;						// przyrost mocy na 1ms = (Vmax-Vmin / 500ms)
		uint8_t mocMin = 30;																									// Procentowa moc, do ktorej zwalniamy
		if( mocMin > Cfg.silnik ) mocMin = Cfg.silnik;
		KrokZmniejszaniaMocy = (float)(Cfg.silnik-mocMin) / Cfg.lHamowania;		// spadek predkosci w % na 0,1mm (Pmax-Pmin) / DYSTANS mm
		UstawMoc( AktualnaMoc );
    HAL_TIM_Base_Start_IT( &htim4 );// Start przerwan od timera
    TimEnkoder = DEF_TIMENKODER; FL_tstEnkoder = true;   // Wlaczenie kontroli enkodera
  }
  else {
    HAL_TIM_Base_Stop_IT( &htim4 );  // Stop timera
		HAL_GPIO_WritePin( STEP_GPIO_Port, STEP_Pin, GPIO_PIN_RESET );	// STEP (PWM) Konczymy zawsze poziomem niskim
    FL_koniecPrzesowu = true;
    FL_tstEnkoder = false;           // Wylaczenie kontroli enkodera
		FL_Enkoder = false;
//		hamulec( 0 );	// TimHamucec==1 zalatwia sprawe
  }
}


void TIM4_IRQHandler(void)
{
  /* USER CODE BEGIN TIM4_IRQn 0 */
	HAL_GPIO_TogglePin( STEP_GPIO_Port, STEP_Pin );

  /* USER CODE END TIM4_IRQn 0 */
  HAL_TIM_IRQHandler(&htim4);
  /* USER CODE BEGIN TIM4_IRQn 1 */

  /* USER CODE END TIM4_IRQn 1 */
}


//------------------------------------------------------------
char volatile FL_wykrytoZnacznik = false;
//------------------------------------------------------------
void wykrytyZnacznik()		// Zadzialala fotokomorka. Wykryte przez EXTI lub 1ms
{
	if( FL_wykrytoZnacznik ) return; 				// Jesli znacznik byl juz wykryty wyjdz

	FL_wykrytoZnacznik = true;
//	Przesow( false );											// Natychmiastowe zatrzymanie

	fazaRozpedu = HAMOWANIE;								// soft-stop
	TimSoftStop = CZAS_ZATRZYMANIA_Z_FOTO;
}


//------------------------------------------------------------
void ZwalnianieFoto()		// Wywolywane w przerwaniu 1ms
{
	if( (!TimSoftStop && FL_wykrytoZnacznik && Cfg.TrybPracy==1) ||
			(!TimSoftStop && FL_wykrytoZnacznik && Cfg.TrybPracy==2) )
			{
			TimSoftStop = 0xFFFF;
			Przesow( false );
			}
}


void PracaSilnika1ms()			// Wywolywane co 1ms w przerwaniu
{
int static volatile dobieg=0;


	switch( fazaRozpedu )
	{
		case ROZBIEG:
			if( AktualnaMoc <= (float)Cfg.silnik  )					// Jesli moc mniejsza od minimalnej
			{
			AktualnaMoc += KrokPrzyrostukMocy;
			UstawMoc( AktualnaMoc );
			}
			else{
				fazaRozpedu = BIEG;
      __NOP();
			}
			break;
		case BIEG:
			if( lenZmierzone/1000 > Cfg.len-Cfg.lHamowania ){		// Jesli zblizamy sie do konca materialu
				fazaRozpedu = HAMOWANIE;
				hamulec( Cfg.tHamulec );												// INFO: hamulec zwalniany przez "Przesow(" INFO: przez TimHamulec
			__asm{ NOP };
			}
			break;
		case HAMOWANIE:
				if( AktualnaMoc > 1 )	{
				AktualnaMoc -= KrokPrzyrostukMocy;
				UstawMoc( AktualnaMoc );
				}
			break;
	}
}

 

Link do komentarza
Share on other sites

8 godzin temu, MarcinTe napisał:

faktycznie niewiele z tego rozumiem

Spodziewałem się tego. Nawet nie zauważyłeś, że kod jest dla STM32 i używa HAL.

Możesz pokazać fotografie jak rozwiązałeś napęd i jak zabezpieczyłeś sterownik przez wpływami atmosferycznymi? W wózku to chyba IP 67 musi być? Zgadza się?

Link do komentarza
Share on other sites

1 godzinę temu, MarcinTe napisał:

odpuszcze to przedsiewziecie, widze ze mnie zdecydowanie przerasta.

Jest powiedzenie (przysłowie?) "Mierz siły na zamiary".

Jesteś początkujący, co widać po problemie, który masz a wybrałeś sobie ambitne, jak na swoje możliwości zadanie. Zacznij od czegoś prostszego, może samochód zdalnie sterowany? Dzięki temu zapoznasz się z problemami jakie występują przy sterowaniu silników.

Link do komentarza
Share on other sites

Moc obliczeniowa Arduino spokojnie wystarczy do sterowania wózkiem. Znam bardziej skomplikowane projekty ,(sterowanie głosem) oparte na RPi.

Tu jednak najważniejsze jest bezpieczeństwo. Pomyśl, co się stanie jeśli jakiś drucik wsadzony w gniazdo w Arduino uzna za stosowne wysunąć się np. w trakcie wjazdu na krawężnik...

 

Link do komentarza
Share on other sites

1 godzinę temu, ethanak napisał:

Moc obliczeniowa Arduino spokojnie wystarczy do sterowania wózkiem

Pod warunkiem, że użyje się sprzętu a nie, jak to mówią (piszą) "machanie pinem" a w tym kodzie tak prawdopodobnie jest. Autor nie dołączył kodu bibliotek, ale one dają możliwość generowania sygnału na dowolnym pinie. To oznacza, że nie korzystają ze sprzętu, a to oznacza, że są ułomne.

 

Edytowano przez InspektorGadzet
Link do komentarza
Share on other sites

19 minut temu, ethanak napisał:

Możesz jakoś rozwinąć owo niewątpliwie twórcze stwierdzenie? Szczególnie interesujące jest tu owo "niekorzystanie ze sprzętu"...

Nie analizuję każdej biblioteki Arduino (używam  ARM, głównie STM32 często LPC od NXP), bo te co analizowałem (jest ich dziesiątki tysięcy), używają millis, programowych SPI, I2C, UART. Jakiej użył autor tego wątku? Nie wiadomo? Przykładowo pod nazwą  "onewire" są biblioteki akceptowalne i nieakceptowalne. Takich, które używają rozwiązań zalecanych przez producenta (Dallas, teraz Dallas-Maxim) nie widziałem. Nie oznacza to, że takich nie ma, ale na forach widzę tylko "machanie pinem".

Analizowałem biblioteki graficzne U8 (coś tam dalej w nazwie). Tragedia! Moja kostka wyświetlałaby obrazek poi kilku sekundach! Co gorsza, byłoby widać jego rysowanie! Próbowałem te biblioteki z 320x240 SPI. Szkoda pisać, to trzeba zobaczyć. Wczytanie i wyświetlenie BMP to 2,5 sekundy. Dopiero na ARM, do LCD DMA, do karty SDIO (4-bit), daje zadowalające efekty.

 

Edytowano przez InspektorGadzet
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.