Skocz do zawartości

[C] Linefollower sterowanie bluetooth


Pomocna odpowiedź

Witam, mam problem z sterowaniem robota za pomocą bluetooth. Robot startuje gdy wyśle "1" ale się nie zatrzymuje gdy wyśle "0". Prosiłbym o wytłumaczenie jak to powinno wyglądać, ewentualnie jakieś tematy gdzie mógłbym zaczerpnąć trochę informacji.

int main(void)
{
init();
USART_Init();


while(1)
{	
	//jazda ^=1;
	if(petla && jazda)
	{
		petla = 0;
		petla_LF();
	}

}
} 
ISR(TIMER0_COMP_vect)			// obsługa przerwania od Timera 0
{
petla = 1;
}

ISR(USART_RXC_vect)
{
  switch(UDR)
  {
   case 0x30: 
    jazda = 0;
   break;

   case 0x31: 
   jazda = 1;
   break;

  }

}

Plik usart.c

#include "usart.h"

#include <avr/io.h>

//FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
//FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ);

static FILE uart_io = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

void USART_Init()
{
uint16_t baudrate = 103; //103 -> 9600 at 16MHz
USART_InitAtBaud(baudrate);
}

void USART_InitAtBaud( uint16_t baud )
{
/* Set baud rate */
UBRRH = (unsigned char) ( baud >> 8 );
UBRRL = (unsigned char) baud;
/* Enable receiver and transmitter */
UCSRB = ( 1 << RXEN ) | ( 1 << TXEN );
/* Set frame format: 8data, 1stop bit */
UCSRC = ( 1 << URSEL ) /*|(1<<USBS)*/ | ( 1 << UCSZ1 ) | ( 1 << UCSZ0 );
UCSRB |= (1<<RXCIE);
stdout = &uart_io;
stdin  = &uart_io;	
}

void USART_Flush( void )
{
uint8_t dummy;
while ( UCSRA & ( 1 << RXC ) )
{
	dummy = UDR;
}
}

uint8_t USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & ( 1 << RXC )) )
;
/* Get and return received data from buffer */
return UDR;
}

void USART_Transmit( uint8_t data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & ( 1 << UDRE )) )
;
/* Put data into buffer, sends the data */
UDR = data;
}

void uart_putchar(char c, FILE *stream) {
if (c == '\n') {
	USART_Transmit('\r');
}
USART_Transmit(c);
}

char uart_getchar(FILE *stream) {
return USART_Receive();
} 
Link to post
Share on other sites

Niepotrzebnie blokujesz główną pętlę programu gdy jazda jest = 0. Po porostu nie ma kto wyłączyć silników.

Zrób tak, by wykonanie wnętrza pętli było uzależnione tylko od flagi czasu, a stan zmiennej petla właśnie przekazuj jako parametr do funkcji pętla_LF():

petla_LF(jazda);

Wtedy to ta funkcja będzie podejmowała decyzje co robić: jechać czy zahamować napędy. Co więcej, może przechowywać własny stan i wiedząc (zapamiętując) co miała zrobić lub co zrobiła poprzednio może inteligentnie reagować na zmiany parametru przez "rozumienie", że jest to początek jazdy (bo poprzednio "jazda" była 0 a teraz jest 1) lub jej koniec (gdy odwrotnie). Bazując na stałym timingu możesz zrobić tam automat np. płynnie rozpędzający i hamujący silniki lub piszczący lub błyskający czymś przy starcie lub stopie.

Link to post
Share on other sites

marek1707, O to ci chodziło? jeżeli tak to nie działa.

int main(void)
{
init();
USART_Init();


while(1)
{	

	if(petla)
	{
		petla = 0;
		petla_LF(jazda);
	}

}
} 
ISR(TIMER0_COMP_vect)			// obsługa przerwania od Timera 0
{
petla = 1;
}

ISR(USART_RXC_vect)
{
  switch(UDR)
  {
   case 0x30: 
   jazda = 0;
   break;

   case 0x31: 
   jazda = 1;
   break;

  }

}
Link to post
Share on other sites

Niestety nie widzę całego Twojego kodu i też nie jestem jasnowidzem. Prosisz o pomoc więc wysilaj się na szersze opisy, bo nikt nie naprawi samochodu z opisem usterki "nie działa". Miałeś zmienić pętlę - zrobiłeś i funkcję petla_LF(), tak by korzystała z nowego argumentu. Jeżeli dostanie zerowy ma wyłączać silniki a gdy >0 jechać jak dawniej. To proste jak drut, ale jeśli piszesz kod to zawsze możesz wsadzić jakiegoś babola którego ja nie widzę i nie przewidzę.

Masz już ideę - o to chyba prosiłeś. Jeśli ją rozumiesz, napisz poprawny program realizujący ją i go uruchom usuwając po kolei błędy. W końcu to Ty tu jesteś programistą. Jeśli nie rozumiesz co masz zrobić, zadawaj lepsze pytania.

Link to post
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

Wiem, że na forach nie lubią leniów, starałem się coś zrobić żeby to działało. Siedziałem nad tym na prawdę parę godzin i cały czas bez sukcesu. Prosiłem o radę jak to ma wyglądać - dostałem ją ale wciąż nie mogę sobie z tym poradzić. Po prostu na tą chwile chciałbym żeby robot zatrzymywał się i startował na moją komendę wysyłaną przez bluetooth. Gdyby ktoś mógłby zerknąć w kod i wskazać, ewentualnie poprawić błąd byłbym na prawdę wdzięczny. Dziękuje marek1707, za udzieloną pomoc.

main.c:

#include "io_cfg.h"
#include "init.h"
#include "linefollower.h"
#include "usart.h"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


int main(void)
{
init();
USART_Init();

while(1)
{	
	if(petla)
	{
		petla = 0;
		petla_LF(jazda);
	}

}
} 
ISR(TIMER0_COMP_vect)		
{
petla = 1;
}

ISR(USART_RXC_vect)
{
  switch(UDR)
  {
   case 0x30: 
   jazda = 0;
   break;

   case 0x31: 
   jazda = 1;
   break;

  }

}

linefollower.c

#include <avr/io.h>
#include <stdlib.h>
#include "io_cfg.h"
#include "linefollower.h"


volatile int jazda = 0, petla = 0;

.
. nie znaczący kod
.

void petla_LF()
{
czytaj_adc();
diody();
blad = licz_blad();
int regulacja = PD();
PWM(V_zad + regulacja, V_zad - regulacja);
}

linefollower.h

#ifndef LINEFOLLOWER_H
#define LINEFOLLOWER_H

void PWM(int lewy, int prawy);
void czytaj_adc();
void diody();
int licz_blad(); 
int PD();
void petla_LF();


extern volatile int jazda, petla;

#endif 

Link to post
Share on other sites

Nie dziękuj, moja pomoc poszła na marne 😐

Przecież jeśli do funkcji przekazujesz argument "jazda", to ona sama automagicznie z niego nie skorzysta, nie naprawi się sama i nie wyłączy silników gdy będziesz tego chciał. Musisz coś w niej zmienić, nieprawdaż?

Teraz masz tak, że w jednym miejscu wołasz:

petla_LF(jazda);

a w innym deklarujesz:

void petla_LF();

a potem w definicji funkcji:

void petla_LF() 
{ 
blablabla
}

To nie zadziała, bo funkcja "nie wie" jak i do czego ma otrzymany argument użyć.

Gdybyś w pliku .h zapowiedział:

void petla_LF(int komenda_dla_silnikow);

a potem w definicji funkcji zrobił coś z tym sensownego, np:

void petla_LF(int komenda_dla_silnikow) 
{
  if (komenda_dla_silników > 0)
  {
     tu jest obsługa normalnej jazdy, np. poprzednie blablabla
  }
  else
  {
     tu bezwarunkowo zatrzymujesz silniki
  }
}

to wtedy miałoby to jakąś szansę. Kapujesz?

  • Lubię! 1
Link to post
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.