• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Dziwny problem z timerem przy pomiarze prędkości
#1
Temat przeniosłem z działu "Instalacja i rozwiązywanie problemów", gdyż z początku myślałem że nie jest on spowodowany problemem w kodzie. 

A więc tworze autonomicznego robota składającego się z:
- dwóch czujników ultradźwiękowych
- dwóch czujników szczelinowych
- dwóch silników DC
- modułu kart mikro SD


Kod mojego programu:
https://pastebin.com/NgUy9jJu

Problem jest z funkcją timera która służy mi do obliczania prędkości obrotu kół robota
Kod:
void setup() {

Serial.begin(9600);

//Ustawienie timera
Timer1.initialize(1000000); // ustawienie timera na sekunde
//zwieksz counter1 gdy pin predkosciomieza jest na Hig
attachInterrupt(digitalPinToInterrupt (motor_A), ISR_count_A, RISING);
//zwieksz counter2 gdy pin predkosciomieza jest na High
attachInterrupt(digitalPinToInterrupt (motor_B), ISR_count_B, RISING);
}

void ISR_timerone(){
  Timer1.detachInterrupt(); //Stop timera
  
  Serial.print("Motor1 Speed: ");
  float rotation_A = (counter_A / diskslots) * 60.00; //obliczenie obrotow na minute (RPM) dla motor1
  Serial.print(RMPtoCmS(rotation_A));
  Serial.print(" Cm/s - ");
  counter_A = 0;

  Serial.print("Motor2 Speed: ");
  float rotation_B = (counter_B / diskslots) * 60.00; //obliczenie obrotow na minute (RPM) dla motor2
  Serial.print(RMPtoCmS(rotation_B));
  Serial.println(" Cm/s");
  counter_B = 0;

 float srednia_predkosc = (RMPtoCmS(rotation_A) + RMPtoCmS(rotation_B)) /2;

//zapisywanie informacji o prędkości na karcie SD
 myFile = SD.open("DaneMapy.txt", FILE_WRITE);
 if (myFile) {
  Serial.println("Writing to file...");
    myFile.print("Motor1: ");
    myFile.print(RMPtoCmS(rotation_A));
    myFile.print("Motor2: ");
    myFile.print(RMPtoCmS(rotation_B));
    myFile.print(" Średnia prędkość: ");
    myFile.print(srednia_predkosc);
    myFile.close();
    Serial.println("Done.");
   }

 Timer1.attachInterrupt(ISR_timerone);
}
Gdy funkcja jest wywoływana w robocie działa tylko jeden silnik i przy zewnętrznym zasilaniu informacje nie zgrywają się na kartę SD (przy zasilaniu USB informacje się zgrywają).

Natomiast gdy funkcja timera nie jest uruchamiana robot jeździ dobrze.
Zaznaczę również że funkcja timera nie działa nawet gdy nie drukuje w niej informacji do karty SD.
W załączniku schemat (przepraszam że tak mało czytelny ale jestem początkujący), oraz zdjęcia robota.


Załączone pliki Miniatury
           
 
Odpowiedź
#2
W przerwaniu blokujące funkcje print? Nic dziwnego, że uC cały czas siedzi w przerwaniu.
Mam też wątpliwości co do "Timer1.initialize(1000000); " Na pewno argument może być liczbą 32-bit?
 
Odpowiedź
#3
(14-01-2019, 19:21)es2 napisał(a): W przerwaniu blokujące funkcje print? Nic dziwnego, że uC cały czas siedzi w przerwaniu.
Mam też  wątpliwości co do  "Timer1.initialize(1000000); " Na pewno argument może być liczbą 32-bit?
Jak ustawiłem Timer1.initialize na 1000 to wydawało mi się że za szybko sczytywał prędkość.
Czy ustawienie go na 1000 rozwiąże w jakimś stopniu problem?

To jak w inny sposób mógłbym pomierzyć prędkość oraz co sekundę wgrać rzucane informacje na plik? 
Oczywiście nie proszę o gotowe rozwiązanie ale chociaż o jakąś poradę jaką funkcję powinienem użyć.
 
Odpowiedź
#4
Zgaduje więc że problem tkwi w użyciu funkcji Timer1.initialize?
 
Odpowiedź
#5
(14-01-2019, 19:41)johnyNapalm napisał(a): To jak w inny sposób mógłbym pomierzyć prędkość oraz co sekundę wgrać rzucane informacje na plik? 
Tego nie zauważyłem, nie przyszło mi do głowy, że można wpaść na tak nierozsądny pomysł, aby W PRZERWANIU zapisywać dane do pliku!
Samo zapisywanie co sekunda to głupi pomysł a w przerwaniu?
Wiesz ile wykonuje się zapis do pliku?
Wiesz, że zawieszasz program w przerwaniu na koszmarnie długi czas?
Wiesz, że timer systemowy stoi w tym czasie, UART i wszystko co jest na przerwaniach?

Dane, które chcesz zapisywać na DS musisz zapisywać w RAM. Co np minutę lub lepiej kilka, zapisuj te dane na kartę ale W PROGRAMIE GŁÓWNYM!
Oczywiście, w tym czasie, program wisi, jeśli ma być coś robione, to albo na przerwaniach albo użyj RTOS ale AVR i RTOS to zły pomysł.
 
Odpowiedź
#6
Przeczytaj to https://majsterkowo.pl/forum/viewtopic.php?f=38&t=1974 nie jest mojego autorstwa ale biblioteka daje nowe możliwości do sterowania i pracy arduino i "można pominąć przerwania!!!!!!"
 
Odpowiedź
#7
(22-01-2019, 07:26)marwi1 napisał(a): Przeczytaj to https://majsterkowo.pl/forum/viewtopic.php?f=38&t=1974 nie jest mojego autorstwa ale biblioteka daje nowe możliwości do sterowania i pracy arduino i  "można pominąć przerwania!!!!!!"
Wynalazłeś koło na nowo, bo ideę którą zastosowałeś używałem w zeszłym tysiącleciu.
Niestety to rozwiązanie nie przyda się autorowi. Standardowo timeout operacji na karcie SD to 500ms. Co sie stanie, jak wywołanie zapisu spowoduje "zawieszenie" uC na 500ms?
 
Odpowiedź
#8
Problem został rozwiązany za pomocą funkcji millis();.
Co 100ms dane dotyczące jazdy zapisywane są do wewnętrznego bufora. Następnie pętlą sprawdzam czy bufor jest przepełniony. Jeżeli jest to zatrzymuje prace robota i zgrywam dane z bufora na kartę SD.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości