Zanim...
Zanim...



Polskie Forum FPV

Forum modelarzy i pilotów FPV
Dzisiaj jest niedziela 18 lis 2018, 03:19


Strefa czasowa UTC+1godz.




Nowy temat Odpowiedz w temacie  [ Posty: 10 ] 
Autor Wiadomość
Post: wtorek 14 mar 2017, 13:06 
Offline

Rejestracja: środa 09 mar 2016, 20:45
Posty: 5
Lokalizacja: Gdańsk/Elbląg
Witam wszystkich forumowiczów.

Po dłuższej walce z projektem systemu antykolizyjnego do pojazdów RC doszedłem do momentu w którym jestem zmuszony zwrócić się do osób lepiej znających temat (jestem początkujący w temacie Arduino i mikrokontrolerów dlatego proszę o wyrozumiałość :) ).

W skład projektu wchodzą:
-aparatura FrSky Taranis
-odbiornik FrSky X8R
-arduino nano
-czujnik ir Sharp GP2Y0A710K0F 100-550cm
-auto rc

Zamysłem projektu było stworzenie algorytmu który sczyta sygnały z aparatury - w moim przypadku przeanalizuje sygnał kanału odpowiadającego na przepustnicę auta RC, i w razie konieczności za pomocą danych pochodzących z czujnika, wraz ze zbliżaniem się do przeszkody sukcesywnie zacznie przesterowywać silnik zapobiegając kolizji.

Do czytania wartości sygnałów wykorzystałem sketch arduino autorstwa właściciela następującego bloga:
http://rcarduino.blogspot.com/2012/01/how-to-read-rc-receiver-with.html

Kod:
#define THROTTLE_SIGNAL_IN 0 // INTERRUPT 0 = DIGITAL PIN 2 - use the interrupt number in attachInterrupt
#define THROTTLE_SIGNAL_IN_PIN 2 // INTERRUPT 0 = DIGITAL PIN 2 - use the PIN number in digitalRead

#define NEUTRAL_THROTTLE 1500 // this is the duration in microseconds of neutral throttle on an electric RC Car

volatile int nThrottleIn = NEUTRAL_THROTTLE; // volatile, we set this in the Interrupt and read it in loop so it must be declared volatile
volatile unsigned long ulStartPeriod = 0; // set in the interrupt
volatile boolean bNewThrottleSignal = false; // set in the interrupt and read in the loop
// we could use nThrottleIn = 0 in loop instead of a separate variable, but using bNewThrottleSignal to indicate we have a new signal
// is clearer for this first example

void setup()
{
// tell the Arduino we want the function calcInput to be called whenever INT0 (digital pin 2) changes from HIGH to LOW or LOW to HIGH
// catching these changes will allow us to calculate how long the input pulse is
attachInterrupt(THROTTLE_SIGNAL_IN,calcInput,CHANGE);

Serial.begin(9600);
}

void loop()
{
// if a new throttle signal has been measured, lets print the value to serial, if not our code could carry on with some other processing
if(bNewThrottleSignal)
{

Serial.println(nThrottleIn);

// set this back to false when we have finished
// with nThrottleIn, while true, calcInput will not update
// nThrottleIn
bNewThrottleSignal = false;
}

// other processing ...
}

void calcInput()
{
// if the pin is high, its the start of an interrupt
if(digitalRead(THROTTLE_SIGNAL_IN_PIN) == HIGH)
{
// get the time using micros - when our code gets really busy this will become inaccurate, but for the current application its
// easy to understand and works very well
ulStartPeriod = micros();
}
else
{
// if the pin is low, its the falling edge of the pulse so now we can calculate the pulse duration by subtracting the
// start time ulStartPeriod from the current time returned by micros()
if(ulStartPeriod && (bNewThrottleSignal == false))
{
nThrottleIn = (int)(micros() - ulStartPeriod);
ulStartPeriod = 0;

// tell loop we have a new signal on the throttle channel
// we will not update nThrottleIn until loop sets
// bNewThrottleSignal back to false
bNewThrottleSignal = true;
}
}
}]


Do pomiarów wykorzystałem bibliotekę Sharp.IR:
Kod:
#include <SharpIR.h>

/* Instances */
SharpIR sharp(A0,100500);

/* Setup function */
void setup() {
pinMode( A0, INPUT);

Serial.begin(9600);
}

/* Infinite loop */
void loop() {
/* Check for obstacles */
int dist=sharp.distance();
Serial.println(dist);

/* Avoid reading before the new distance is sampled */
delay( 500 );
}


Wykorzystanie powyższego kodu mierzenia odległości bez użycia przerwań, bezpośrednio w kodzie sczytywania wartości sygnałów (kod umieszczam na końcu postu), nie dało oczekiwanych efektów. Mimo stabilności odczytu sygnału (sprawdzane wielokrotnie za pomocą monitora portu szeregowego) auto wielokrotnie doznaje nieoczekiwanych przyśpieszeń- tak jakby dostawało od aparatury wartość odpowiadającą maksymalnemu przyśpieszeniu (niezgodnemu ze "strymowanym" sygnałem z nadajnika). Drugim problemem jest zbyt wolny czas reakcji algorytmu- domniemam że wina leży w wykorzystaniu odpowiedniego opóźnienia wymaganego do poprawnego działania czujnika.

Bardzo proszę o pomoc jak rozwiązać powyżej przedstawione problemy oraz o wszelakie wskazówki.

Użyty kod podczas testów:
Kod:
#include<Servo.h>
#include <SharpIR.h>

#define THROTTLE_SIGNAL_IN 0 // INTERRUPT 0 = DIGITAL PIN 2 - use the interrupt number in attachInterrupt
#define THROTTLE_SIGNAL_IN_PIN 2 // INTERRUPT 0 = DIGITAL PIN 2 - use the PIN number in digitalRead
#define NEUTRAL_THROTTLE 1500 // this is the duration in microseconds of neutral throttle on an electric RC Car

volatile int nThrottleIn = NEUTRAL_THROTTLE; // volatile, we set this in the Interrupt and read it in loop so it must be declared volatile
volatile unsigned long ulStartPeriod = 0; // set in the interrupt
volatile boolean bNewThrottleSignal = false; // set in the interrupt and read in the loop
// we could use nThrottleIn = 0 in loop instead of a separate variable, but using bNewThrottleSignal to indicate we have a new signal
// is clearer for this first example

Servo myservo;
SharpIR sharp(A0,100500);

void setup()
{
// tell the Arduino we want the function calcInput to be called whenever INT0 (digital pin 2) changes from HIGH to LOW or LOW to HIGH
// catching these changes will allow us to calculate how long the input pulse is
attachInterrupt(THROTTLE_SIGNAL_IN,calcInput,CHANGE);

pinMode(10, OUTPUT);
pinMode(A0, INPUT);
myservo.attach(10);

Serial.begin(9600);
}

void loop()
{
// if a new throttle signal has been measured, lets print the value to serial, if not our code could carry on with some other processing
if(bNewThrottleSignal)
{

Serial.println(nThrottleIn);
myservo.writeMicroseconds(nThrottleIn);

// set this back to false when we have finished
// with nThrottleIn, while true, calcInput will not update
// nThrottleIn
bNewThrottleSignal = false;
}

// other processing ...

int dist = sharp.distance();
Serial.println(dist);

if (dist>=110 && dist<=130){
myservo.writeMicroseconds(NEUTRAL_THROTTLE);
Serial.println(dist);
}



}

void calcInput()
{
// if the pin is high, its the start of an interrupt
if(digitalRead(THROTTLE_SIGNAL_IN_PIN) == HIGH)
{
// get the time using micros - when our code gets really busy this will become inaccurate, but for the current application its
// easy to understand and works very well
ulStartPeriod = micros();
}
else
{
// if the pin is low, its the falling edge of the pulse so now we can calculate the pulse duration by subtracting the
// start time ulStartPeriod from the current time returned by micros()
if(ulStartPeriod && (bNewThrottleSignal == false))
{
nThrottleIn = (int)(micros() - ulStartPeriod);
ulStartPeriod = 0;

// tell loop we have a new signal on the throttle channel
// we will not update nThrottleIn until loop sets
// bNewThrottleSignal back to false
bNewThrottleSignal = true;
}
}
}


Na górę
 Wyświetl profil  
 
Post: wtorek 14 mar 2017, 13:19 
Offline
Awatar użytkownika

Rejestracja: wtorek 31 gru 2013, 01:49
Posty: 885
Lokalizacja: Ruda Śląska
podłącz sonar do arduino i napisz sketch, który wyświetli w konsoli odległość podawaną przez czujnik, zobaczysz że czasami mimo stałej odległości od przeszkody czujnik się gubi i pokazuje jakieś "kwiatki", i tu leży problem.
Najlepiej bylo by czytać odległość od przeszkody kilku/kilkunastukrotnie i uśredniać wynik, odrzucać "szpile" które są nieprawdziwe. Taki "filtr".


Na górę
 Wyświetl profil  
 
Post: wtorek 14 mar 2017, 13:39 
Offline

Rejestracja: środa 09 mar 2016, 20:45
Posty: 5
Lokalizacja: Gdańsk/Elbląg
O ile się nie mylę biblioteka SharpIR działa dokonując 25 pomiarów-próbek i zwraca ich medianę. Co gorsze, niestabilne zachowanie dotyczy także kodu który nie uwzględnia w ogóle czujnika- auto potrafi odbierać przesterowania nawet podczas gdy nie dotykam aparatury ;/


Na górę
 Wyświetl profil  
 
Post: wtorek 14 mar 2017, 13:46 
Offline
Awatar użytkownika

Rejestracja: wtorek 31 gru 2013, 01:49
Posty: 885
Lokalizacja: Ruda Śląska
czyli "czytasz" pwm z odbiornika i "wypluwasz" je następnym pinem w arduino?
Rozbij w takim razie projekt na mniejsze etapy i sprawdz jak zachowuje się auto, gdzie będzie arduino po między odbiornikiem a esc, które bedzie tylko przekazywało sygnał 1 do 1


Na górę
 Wyświetl profil  
 
Post: wtorek 14 mar 2017, 15:54 
Offline

Rejestracja: piątek 18 lis 2016, 17:14
Posty: 52
Lokalizacja: Kraków
Na szybko analizując widzę jedną podejrzaną konstrukcję:

Kod:
myservo.writeMicroseconds(nThrottleIn);   //ustawiasz prędkość silnika tym co dostałeś z aparatury
//..
int dist = sharp.distance();                        //odczytujesz dystans, funkcją, która nie wiadomo ile trwa.
//..

if (dist>=110 && dist<=130){
myservo.writeMicroseconds(NEUTRAL_THROTTLE);    //drugi raz zapisujesz prędkość silnika, o ile dystans jest w granicach.
Serial.println(dist);
}


Czyli jeśli funkcja sharp.distance() trwa odpowiednio długo, informacja do silnika może zostać wysłana na podstawie tego co wysyłasz z aparatury, zanim ją nadpiszesz na podstawie pomiaru odległości.
Lepiej pominąć pierwsze ustawienie prędkości i zapisać to w ten sposób:

Kod:
// to wyrzucamy myservo.writeMicroseconds(nThrottleIn);   //ustawiasz prędkość silnika tym co dostałeś z aparatury
//..
int dist = sharp.distance();                        //odczytujesz dystans, funkcją, która nie wiadomo ile trwa.
//..

if (dist>=110 && dist<=130){
myservo.writeMicroseconds(NEUTRAL_THROTTLE);    //drugi raz zapisujesz prędkość silnika, o ile dystans jest w granicach.
Serial.println(dist);
}
else
{
myservo.writeMicroseconds(nThrottleIn);
}


Oczywiście to też nie jest dobre (jak się zawiesi na odczycie odległości, to samochód nie będzie reagował), najlepiej zrobić to wszystko na przerwaniach.


Na górę
 Wyświetl profil  
 
Post: wtorek 14 mar 2017, 17:20 
Offline
Awatar użytkownika

Rejestracja: niedziela 07 lut 2010, 15:24
Posty: 9168
Lokalizacja: Bytom
A czytałeś TO: http://rcarduino.blogspot.com/2012/11/h ... stlib.html
Tam jest opisany problem glitchów przy jednoczesnym odczycie i wysyłaniu sygnału PWM.
Może zastosowanie RCArduinoFastLib i zmiana procedury odczytu na "Updated ISR" pomoże ?

_________________
Pzdr. -----MIŚ-----


Na górę
 Wyświetl profil  
 
Post: wtorek 14 mar 2017, 19:31 
Offline

Rejestracja: środa 09 mar 2016, 20:45
Posty: 5
Lokalizacja: Gdańsk/Elbląg
miś pisze:
A czytałeś TO: http://rcarduino.blogspot.com/2012/11/h ... stlib.html
Tam jest opisany problem glitchów przy jednoczesnym odczycie i wysyłaniu sygnału PWM.
Może zastosowanie RCArduinoFastLib i zmiana procedury odczytu na "Updated ISR" pomoże ?


Po szybkim załadowaniu sketchu w 3 na 4 próbach problem nie ustąpił. W tej jednej próbie sterowanie przebiegało bez zakłóceń aż do momentu gdy dotknąłem wyłącznik zasilania- przesterowanie na oko wyniosło wartość powyżej maksymalnej wartości jaką może nadać aparatura (trym w granicach 1300-1700um). Jaka jest szansa że powyższe błędy wynikają ze złego/słabej jakości połączeń?



Na górę
 Wyświetl profil  
 
Post: środa 15 mar 2017, 02:09 
Offline
Awatar użytkownika

Rejestracja: niedziela 07 lut 2010, 15:24
Posty: 9168
Lokalizacja: Bytom
Debug, debug, debug... horror programisty. Sypiesz tam danymi poprzez uart, więc loguj i wyciągaj wnioski (tylko zwiększyłbym prędkość tego uarta do 57600 aby samo wysyłanie debugu nie blokowało zbytnio reszty).
Powodzenia.

_________________
Pzdr. -----MIŚ-----


Na górę
 Wyświetl profil  
 
Post: sobota 25 mar 2017, 12:49 
Offline

Rejestracja: środa 09 mar 2016, 20:45
Posty: 5
Lokalizacja: Gdańsk/Elbląg
Pewna mądra głowa zasugerowała że problem niestabilności może wynikać z nieuziemionego wejścia przez co sygnał nadchodzący z odbiornika "pływa". Ile w tym prawdy i jak się poprawnie za to zabrać/ gdzie o tym doczytać ?


Na górę
 Wyświetl profil  
 
Post: sobota 25 mar 2017, 13:03 
Offline

Rejestracja: piątek 03 mar 2017, 19:04
Posty: 204
Lokalizacja: Bytom
Nie bardzo rozumiem. Podłączyłeś sygnał PWM wychodzący z odbiornika bez masy? W jaki sposób masz podłączony odbiornik do zasilania / z czego go zasilasz?

_________________
Pozdrawiam Krzysiek
---------------------------------------------------------------
QAV-250, Martian II, GEPRC-AX215, QAV-R 220, ARMATTAN CHAMELEON, T-Rex 500
Zapraszam na bloga


Na górę
 Wyświetl profil  
 
Wyświetl posty nie starsze niż:  Sortuj wg  
Nowy temat Odpowiedz w temacie  [ Posty: 10 ] 

Strefa czasowa UTC+1godz.


Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość


Nie możesz tworzyć nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Przejdź do:  
cron
Technologię dostarcza phpBB® Forum Software © phpBB Group

Strona korzysta z plików cookie w celu realizacji usług zgodnie z . Polityką prywatności
Możesz określić warunki przechowywania lub dostępu do cookie w Twojej przeglądarce lub konfiguracji usługi.