Arduino Nano- system antykolizyjny do samochodu RC

auta...

Moderatorzy: moderatorzy2014, moderatorzy

remas94
Posty: 5
Rejestracja: środa 09 mar 2016, 20:45
Lokalizacja: Gdańsk/Elbląg

Arduino Nano- system antykolizyjny do samochodu RC

Post autor: remas94 »

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/h ... -with.html

Kod: Zaznacz cały

#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: Zaznacz cały

#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: Zaznacz cały

#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;
}
}
}
Awatar użytkownika
lotpawel
Posty: 918
Rejestracja: wtorek 31 gru 2013, 01:49
Lokalizacja: Ruda Śląska

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: lotpawel »

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".
remas94
Posty: 5
Rejestracja: środa 09 mar 2016, 20:45
Lokalizacja: Gdańsk/Elbląg

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: remas94 »

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 ;/
Awatar użytkownika
lotpawel
Posty: 918
Rejestracja: wtorek 31 gru 2013, 01:49
Lokalizacja: Ruda Śląska

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: lotpawel »

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
madej
Posty: 53
Rejestracja: piątek 18 lis 2016, 17:14
Lokalizacja: Kraków

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: madej »

Na szybko analizując widzę jedną podejrzaną konstrukcję:

Kod: Zaznacz cały

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: Zaznacz cały

// 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.
Awatar użytkownika
miś
Posty: 9242
Rejestracja: niedziela 07 lut 2010, 15:24
Lokalizacja: Bytom

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: miś »

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Ś-----
remas94
Posty: 5
Rejestracja: środa 09 mar 2016, 20:45
Lokalizacja: Gdańsk/Elbląg

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: remas94 »

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ń?

Awatar użytkownika
miś
Posty: 9242
Rejestracja: niedziela 07 lut 2010, 15:24
Lokalizacja: Bytom

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: miś »

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Ś-----
remas94
Posty: 5
Rejestracja: środa 09 mar 2016, 20:45
Lokalizacja: Gdańsk/Elbląg

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: remas94 »

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ć ?
Docent
Posty: 210
Rejestracja: piątek 03 mar 2017, 19:04
Lokalizacja: Bytom

Re: Arduino Nano- system antykolizyjny do samochodu RC

Post autor: Docent »

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
ODPOWIEDZ