Làm thế nào để tôi gỡ lỗi một bản phác thảo Arduino?


10

Tôi bắt đầu viết mã cho Arduino gần đây. Và những lỗi trong mã đang giết chết tôi. Vì không có trình gỡ lỗi phần cứng trong Arduino, serial.print () là khu nghỉ mát duy nhất của tôi. Các phương pháp / thực hành bạn thực hiện để gỡ lỗi mã Arduino là gì?


Câu trả lời:


8

Modularity là bạn của bạn. Viết vòng lặp chính của bạn để thực hiện công việc của nó bằng cách gọi các hàm, gọi hàm này, ..., cho đến mức mà các hàm của bạn sẽ đơn giản. Bắt đầu với vòng lặp chính và xuống cấp độ tiếp theo, tạo các hàm còn sơ khai; hoặc trống:

function foo(){
    ;
}

hoặc giả mạo:

function read_temperature(){
    return(95);
}

, điều đó không làm gì ngoài việc trả lại bất cứ thứ gì mà mức gọi cần cho nó để có thể tiếp tục. Khi mức đó hoạt động, di chuyển xuống một mức và bắt đầu điền mã đơn giản tương tự gọi các hàm còn sơ khai. Dần dần bỏ chức năng tại một thời điểm cho đến khi bạn có một ứng dụng hoạt động.

Để gỡ lỗi một hàm trả về giá trị xấu hoặc để tạo một hàm mà không có bất kỳ ảnh hưởng nào từ phần còn lại của ứng dụng, bạn có thể xây dựng giàn giáo - một bản phác thảo đơn giản chỉ cung cấp cho hàm một số giá trị mẫu và trong hàm, in ra các giá trị tham số và một số giá trị trung gian, cho đến khi bạn hiểu rõ hơn về phần nào của hàm bị lỗi. Tôi thậm chí đã thực hiện các chức năng giả mạo nhắc tôi trên thiết bị đầu cuối để có giá trị trả về. (Rõ ràng kỹ thuật này chỉ có thể hoạt động nếu hệ thống có thể chịu được tốc độ tương đối băng của con người chúng ta! Một cách sử dụng khác cho giàn giáo.)

Stubbing hoạt động đặc biệt tốt để hỗ trợ các chức năng giao diện với phần cứng, cho phép bạn bắt đầu đưa ứng dụng lên trước khi bạn phải đi sâu vào các bảng dữ liệu, các vấn đề về thời gian và các chi tiết vụn vặt khác (như, không có các bộ phận!) sự tiến bộ của bạn

Nói về các vấn đề thời gian, việc bật một chân đầu ra tại một điểm cụ thể trong chương trình của bạn, chẳng hạn như nhập và thoát khỏi ISR, cung cấp cho bạn một sóng vuông ở chân Arduino có tần số hoặc chu kỳ nhiệm vụ có thể giúp bạn hiểu rõ hơn về thời gian bên trong của chương trình của bạn. Biểu mẫu cổng I / O trực tiếp, vd

PORTC ^= 0x01;

, sẽ bóp méo thời gian ít hơn so với gọi digitalWrite(). Hữu ích nếu bạn có 'phạm vi tiện dụng hoặc một trong các DMM có khả năng đo tần số và / hoặc chu kỳ nhiệm vụ.

Tương tự, bạn có thể sử dụng chân đầu ra tương tự để xuất giá trị số cho đồng hồ của mình từ bên trong chương trình mà không làm ảnh hưởng đến thời gian quá nhiều hoặc làm phồng mã với các chức năng I / O nối tiếp. Sử dụng các hình thức I / O trực tiếp ở đây, quá.


6

Tôi sử dụng Serial.print () và tôi làm đèn LED nhấp nháy.

Đó là khá nhiều tất cả những gì bạn có thể làm.

Ngoài ra, tôi đảm bảo mã dễ đọc và dễ hiểu. Chia mọi thứ thành các bước đơn giản và tạo chức năng cho từng bước, để bạn có thể xem chuỗi sự kiện chính xác.


5

3 kỹ thuật khác:

  • Xây dựng chức năng của một chương trình bằng cách thử nghiệm chậm ở mỗi giai đoạn, theo cách đó bạn chỉ phải đối mặt với một bộ lỗi nhỏ tại một thời điểm.

  • Xây dựng chương trình xung quanh một trình thông dịch lệnh để bạn có thể làm việc với các phần tại một thời điểm như ở đây .

  • Xung ra vào những thời điểm quan trọng và sử dụng một phạm vi.


3

Các Micro trực quan plugin cho Visual Studio cung cấp Arduino gỡ lỗi . Bao gồm theo dõi và ngắt mã nguồn cũng cho phép các biểu thức và biến được "xem" và / hoặc sửa đổi.

nhập mô tả hình ảnh ở đây


1
Lưu ý rằng điều này được thực hiện thông qua các bản in nối tiếp được tạo tự động được chèn vào mã của bạn.
per1234

Điều đó đúng ngoại trừ các bản in và đọc nối tiếp hoặc wifi được chèn vào một bản sao tạm thời của mã không phải là mã thật! Tất cả đều được giải thích rõ ràng trong các tài liệu visualmicro.com và đối với một số ít có trình gỡ lỗi phần cứng (không thường dùng cho Uno, v.v.), chúng cũng được hỗ trợ. Mỗi phương pháp đều có ưu điểm và nhược điểm riêng.
Visual Micro

Từ Debugger cho Arduino : "Nó không hỗ trợ bước qua mã và nó dựa trên mã ẩn được chèn vào chương trình của bạn trước khi xây dựng để giao tiếp với trình gỡ lỗi."
Peter Mortensen

Đúng rồi. Nó tránh sự cần thiết của người dùng để thêm các bản in nối tiếp, cho phép cập nhật các vars có tên trong khi cpu chạy, hiển thị biểu đồ và chân kỹ thuật số, v.v ... Nó khác với trình gỡ lỗi phần cứng nhưng nhanh và dễ dàng và có các lợi ích khác. Đây là tất cả tài liệu tốt trên visualmicro.com vì vậy xin vui lòng đọc. Nếu bạn hỗ trợ gdb hoặc bạn sử dụng atmel studio, tất nhiên sẽ có các tùy chọn gỡ lỗi khác. Tất cả phụ thuộc vào chuyên môn của bạn và phần cứng bạn có. Nếu bạn có Arduino chính hãng, trong studio Atmel, bạn có thể kết hợp arduino với gỡ lỗi hoặc sim.
Visual Micro

2

Đi từ các công cụ xa xỉ như ARM hoặc các nền tảng khác (AVR, PIC với các công cụ phong nha) Tôi đồng ý rằng các phương tiện gỡ lỗi Arduino quá hạn chế. Nhưng nó là một công cụ khởi động với mục nhập thấp.

Serial.print () là bạn của bạn. Đối với dự án cụ thể của tôi (đại học), tôi đã không có bất kỳ đèn LED nào được đính kèm, vì vậy đó là serial.print (). Nếu tôi muốn kiểm tra xem mã có chạy đúng qua các câu lệnh hay không, tôi thường đặt Serial.print ("A"); , sau đó đi đến B, C, v.v. hoặc một cái gì đó thông qua phần tôi đang gỡ lỗi. Tôi so sánh các chữ cái gỡ lỗi với những gì tôi mong đợi nó nên làm.

Ngoài ra, không có điểm dừng hoặc bước mã. Arduino không gì khác hơn là một bo mạch với chip atmega AVR, môi trường phát triển bootloader + và hàng tấn thư viện phần mềm. Thật không may, làm việc với bộ tải khởi động sẽ hạn chế khả năng sửa lỗi.


0

Để sử dụng serial.printkiểm soát nhiều hơn, bạn có thể xác định biến boolean toàn cầu để bật và tắt gỡ lỗi. Bất kỳ dòng nào serial.printsẽ được gói trong một ifcâu lệnh sẽ chỉ được thực thi nếu cờ gỡ lỗi được BẬT. Bằng cách này, bạn có thể để các dòng gỡ lỗi trong mã ngay cả khi bạn hoàn thành, nhưng hãy đảm bảo đặt cờ gỡ lỗi thành TẮT sau.


0

Tốt hơn so với serial.print trực tiếp, sử dụng macro. Thí dụ:

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

Sử dụng nó như thế này:

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

    ...

    traceln1("<-doIt");
}

Bạn có thể có các cấp độ dấu vết khác nhau (#ifdef TRACE2 ...)với nhiều chi tiết hơn.

Và bạn có thể sử dụng macro "F" , (trace1(F("param1"));). Macro "F" ngăn chặn chuỗi sẽ sử dụng số lượng SRAM cực kỳ hạn chế.


0

Đèn LED nhấp nháy, in mọi thứ trên cổng nối tiếp, viết và gỡ lỗi các phần mã nhỏ tại một thời điểm, đôi khi chỉ một vài dòng.

Có những lúc bạn có thể mô đun hóa. Ví dụ, nếu trong C, bạn có thể phát triển và kiểm tra chức năng tính toán, ví dụ như không chạm vào phần cứng trên máy tính chủ, bộ xử lý khác, bọc chức năng bằng một băng ghế thử nghiệm để cung cấp cho đầu vào và kiểm tra đầu ra, v.v.

Một cách tương tự khác có thể là sử dụng một trình giả lập tập lệnh nếu bạn có quyền truy cập vào một (nếu không, đó là một dự án rất giáo dục và bổ ích, sau khi bạn đã thực hiện một vài trong số chúng, bạn có thể thực hiện một trong hai hoặc hai ngày cuối tuần). Thậm chí tốt hơn nếu ai đó có bản sao Verilog hoặc VHDL của bộ xử lý ( ví dụ OpenCores ), bạn có thể thử GHDL, Verilator hoặc Icarus Verilog . Nó có thể đủ gần để bao gồm các thiết bị ngoại vi mà bạn quan tâm và bạn có thể nhận được mức độ tín hiệu ở những gì đang diễn ra bên trong.

Cấp nó có lẽ không phải là một bản sao hoàn hảo, nhưng nó có thể là đủ tốt. Verilator giúp thực sự dễ dàng tạo các thiết bị ngoại vi trong C / C ++ để bạn có thể mô phỏng bất cứ thứ gì bạn có thiết bị AVR của mình được nối.

Đầu ra UART và đèn LED nhấp nháy và / hoặc nhấp nháy dòng GPIO và sử dụng máy hiện sóng hoặc vôn kế. Chìa khóa để không phát điên là viết và gỡ lỗi các phần nhỏ của mã. Tôi tốt hơn là viết 10 dòng cùng một lúc và thực hiện 100 bài kiểm tra hơn 1000 dòng và cố gắng gỡ lỗi tất cả trong một lần. Đặc biệt là khi bạn tìm ra hầu hết các bảng dữ liệu và hướng dẫn tham khảo cho lập trình viên cho phần cứng không phải lúc nào cũng đúng. Một số hack luôn được yêu cầu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.