Jak debugować szkic Arduino?

10

Ostatnio zacząłem kodować dla Arduino. A te błędy w kodzie mnie zabijają. Ponieważ w Arduino nie ma debugera sprzętowego, serial.print () jest moją jedyną możliwością. Jakie metody / praktyki wdrażasz w celu debugowania kodu Arduino?

0xakhil
źródło
spójrz na boisko.arduino.cc/Main/DevelopmentTools dla IDE i narzędzi do
debuggowania

Odpowiedzi:

8

Modułowość to twój przyjaciel. Napisz swoją główną pętlę, aby zrobić to, wywołując funkcje, które wywołują funkcje ..., aż do poziomu, na którym twoje funkcje będą proste. Rozpocznij od głównej pętli i następnego poziomu w dół, wykonaj funkcje kodów pośredniczących; albo pusty:

function foo(){
    ;
}

lub fałszywy:

function read_temperature(){
    return(95);
}

, które zwracają tylko tyle, ile potrzebuje poziom wywołania, aby mógł kontynuować. Kiedy ten poziom działa, zejdź niżej i zacznij wypełniać prosty kod, który również wywołuje funkcje kodu pośredniczącego. Stopniowo odpakowuj funkcję na raz, aż będziesz mieć działającą aplikację.

Aby debugować funkcję, która zwraca złą wartość lub utworzyć ją bez żadnego wpływu ze strony pozostałej aplikacji, możesz zbudować rusztowanie - prosty szkic, który po prostu podaje funkcji kilka przykładowych wartości, aw ramach funkcji wydrukuj wartości parametrów i niektóre wartości pośrednie, dopóki nie uzyskasz wglądu w to, która część funkcji zawiedzie. Stworzyłem nawet fałszywe funkcje, które zachęcają terminal do zwrócenia wartości. (Oczywiście ta technika może działać tylko wtedy, gdy system może tolerować względnie lodowcową prędkość nas ludzi! Kolejne zastosowanie do rusztowań).

Stubbing działa szczególnie dobrze, zastępując funkcje interfejsu ze sprzętem, umożliwiając rozpoczęcie uruchamiania aplikacji, zanim będziesz musiał zagłębić się w arkusze danych, problemy z timerem i inne drobiazgi (takie jak brak części!), Które w przeciwnym razie mogą zostać zawieszone Twój postęp.

Mówiąc o problemach z timingiem, przełączanie pinów wyjściowych w określonym punkcie programu, takich jak wejście i wyjście z ISR, daje ci kwadratową falę na pinie Arduino, którego częstotliwość lub cykl pracy może dać ci wgląd w wewnętrzny timing twojego programu. Bezpośredni formularz port-I / O, np.

PORTC ^= 0x01;

, zniekształci czas mniej niż dzwonienie digitalWrite(). Przydatne, jeśli masz pod ręką lunetę lub jeden z multimetrów cyfrowych z możliwością pomiaru częstotliwości i / lub cyklu pracy.

Podobnie, można użyć analogowego styku wyjściowego, aby wyprowadzić wartość liczbową do miernika z wnętrza programu, nie zakłócając zbytnio taktowania ani nie nadużywając kodu za pomocą szeregowych funkcji we / wy. Skorzystaj również z bezpośrednich formularzy We / Wy.

JRobert
źródło
6

Używam Serial.print () i sprawiam, że diody LED migają.

To prawie wszystko, co możesz zrobić.

Ponadto dbam o to, aby kod był czytelny i łatwy do zrozumienia. Podziel rzeczy na proste kroki i utwórz funkcje dla każdego kroku, aby zobaczyć dokładną sekwencję zdarzeń.

Majenko
źródło
5

3 inne techniki:

  • Zbuduj funkcjonalność programu, powoli testując na każdym etapie, w ten sposób konfrontujesz tylko niewielki zestaw błędów na raz.

  • Zbuduj program wokół interpretera poleceń, aby móc pracować z sekcjami naraz, tak jak tutaj .

  • Impulsuj w znacznych momentach i użyj lunety.

russ_hensel
źródło
3

Wizualna Micro plugin do Visual Studio zapewnia Arduino Debug . Obejmuje śledzenie i łamanie kodu źródłowego, pozwala także na „obserwację” i / lub modyfikację wyrażeń i zmiennych.

wprowadź opis zdjęcia tutaj

Visual Micro
źródło
1
Zauważ, że odbywa się to za pomocą automatycznie generowanych wydruków seryjnych wstawianych do kodu.
per1234
To prawda, z wyjątkiem wydruków seryjnych lub Wi-Fi oraz odczytów umieszczonych w tymczasowej kopii kodu, a nie prawdziwego kodu! Wszystko zostało wyjaśnione w dokumentacji visualmicro.com, a dla tych kilku, którzy mają sprzętowe debuggery (zwykle nie dla Uno itp.), Są również obsługiwane. Każda metoda ma swoje zalety i wady.
Visual Micro
Z Debuggera dla Arduino : „Nie wspierało przechodzenia przez kod i było oparte na ukrytym kodzie wstawionym do twojego programu przed kompilacją w celu komunikacji z debuggerem”.
Peter Mortensen
Zgadza się. Pozwala to uniknąć konieczności dodawania przez użytkowników wydruków seryjnych, umożliwia aktualizację nazwanych zmiennych podczas uruchamiania procesora, wyświetlania wykresów i cyfrowych pinów itp. Różni się od sprzętowego debugera, ale jest szybki i łatwy i ma inne zalety. Wszystko to jest dobrze udokumentowane na visualmicro.com, więc proszę przeczytać. Jeśli planujesz obsługuje gdb lub używasz atmel studio, istnieją oczywiście inne opcje debugowania. Wszystko zależy od Twojej wiedzy i posiadanego sprzętu. Jeśli masz oryginalne Arduino, w studio Atmel możesz arduino połączyć z debugowaniem atm lub simem.
Visual Micro
2

Wychodząc z luksusowych narzędzi takich jak ARM lub inne platformy (AVR, PIC z przyzwoitymi narzędziami) Zgadzam się, że możliwości debugowania Arduino są zbyt ograniczone. Ale to narzędzie startowe z niskim wejściem.

Serial.print () to twój przyjaciel. Do mojego konkretnego projektu (uczelni) nie miałem podłączonych żadnych diod LED, więc jest to Serial.print (). Jeśli chcę sprawdzić, czy kod działa poprawnie w instrukcjach, zwykle umieszczam Serial.print („A”); , następnie przechodzę do B, C itp. lub czegoś innego w sekcji Debuguję. Porównuję litery debugowania z tym, czego oczekuję.

Poza tym nie ma punktów przerwania ani stopniowania kodu. Arduino to nic innego jak płytka z chipem atmega AVR, bootloaderem + środowiskiem programistycznym i mnóstwem bibliotek oprogramowania. Niestety praca z programem ładującym ogranicza możliwości debugowania.

Hans
źródło
0

Aby użyć serial.printbardziej kontrolowanego, możesz zdefiniować globalną zmienną logiczną, która będzie włączać i wyłączać debugowanie. Wszelkie wiersze serial.printzostaną zawinięte w ifinstrukcji, która zostanie wykonana tylko wtedy, gdy flaga debugowania jest WŁĄCZONA. W ten sposób możesz zostawić wiersze debugowania w kodzie, nawet gdy skończysz, ale pamiętaj, aby później ustawić flagę debugowania na WYŁ.

gadatliwy
źródło
0

Lepiej niż bezpośrednio serial.print, używaj makr. Przykład:

#ifdef TRACE1
#define trace1(s) serial.print(s)
#define traceln1(s) serial.println(s)
#else
#define trace1(s)
#define traceln1(s)
#endif

Użyj tego w ten sposób:

function doIt(param1, param2) {
    trace1("->doIt("); trace1("param1: "); trace1(param1); trace1(" param2: "); trace1(param2); traceln1(")");

    ...

    traceln1("<-doIt");
}

Możesz mieć różne poziomy śledzenia (#ifdef TRACE2 ...)z większą ilością szczegółów.

I można użyć „F” makra (trace1(F("param1"));). Makro „F” zapobiega używaniu przez łańcuch bardzo ograniczonej ilości SRAM.

Mangar
źródło
0

Migaj diody LED, drukuj rzeczy na porcie szeregowym oraz pisz i debuguj małe sekcje kodu na raz, czasem tylko kilka linii.

Są chwile, w których możesz modularyzować. Jeśli na przykład w C można opracować i przetestować funkcję obliczeniową, która na przykład nie dotyka sprzętu na komputerze-hoście, innym procesorze, należy owinąć funkcję stanowiskiem testowym, aby podać dane wejściowe i sprawdzić dane wyjściowe itp.

Innym podobnym sposobem może być użycie symulatora zestawu instrukcji, jeśli masz dostęp do jednego (jeśli nie, jest to bardzo edukacyjny i satysfakcjonujący projekt, po wykonaniu kilku z nich możesz wybić jeden w weekend lub dwa). Nawet lepiej, jeśli ktoś ma klon procesora Verilog lub VHDL ( na przykład OpenCores ), możesz wypróbować GHDL, Verilator lub Icarus Verilog . Może być wystarczająco blisko, aby uwzględnić urządzenia peryferyjne, które Cię interesują, i możesz uzyskać wgląd w poziom sygnału w tym, co dzieje się w środku.

To prawda, że ​​prawdopodobnie nie jest to idealny klon, ale może być wystarczająco dobry. Verilator sprawia, że ​​tworzenie peryferiów w C / C ++ jest naprawdę bardzo łatwe, dzięki czemu można symulować wszystko, do czego podłączone jest urządzenie AVR.

Wyjście UART i migające diody LED i / lub migające linie GPIO oraz za pomocą oscyloskopu lub woltomierza. Kluczem do szaleństwa jest pisanie i debugowanie małych fragmentów kodu. Lepiej jest pisać 10 linii na raz i wykonywać 100 testów niż 1000 linii i próbować debugować je wszystkie za jednym razem. Zwłaszcza gdy dowiesz się, że większość kart danych i podręczników programistów nie zawsze jest poprawna. Zawsze wymagane jest hakowanie.

old_timer
źródło