Arduino serial in thay đổi hành vi của chương trình không mong muốn


10

Tôi đang sử dụng bộ đếm vòng lặp, được khai báo trong tiêu đề:

int loop_counter = 0;

Tôi sử dụng bộ đếm này để kích hoạt một sự kiện thường xuyên. Tôi đã từng sử dụng một modulo cho loại hành vi tương tự này, nhưng tôi đã đơn giản hóa nó để dễ làm việc hơn (nó vẫn dẫn đến hành vi tương tự)

void loop() {
    if(loop_counter > 100) loop_counter = 0;
    else loop_counter++;

    //Serial.println("hey");

    if(loop_counter == 0) {
         //do_something_important();
    }      
}

Tất cả đều tốt và tốt, cho đến khi tôi cố gắng giao tiếp bằng Serialcách bỏ qua //Serial.println("hey"); ( "hey"trong ví dụ này bởi vì, với tôi, hành vi này là vô lý).

Điều này dẫn đến việc loop_counterkhông bao giờ kích hoạt do_something_important();phần mã. Tôi đã cố gắng tuyên bố loop_counternhư volatile, điều đó không thay đổi bất cứ điều gì. Tôi đã thử Serial.printing loop_counter, và tôi cũng nhận được hành vi kỳ quặc (nó sẽ đóng băng vòng lặp). Serial.println("hey");hoạt động theo nghĩa là trong màn hình nối tiếp tôi nhận được rất nhiều "hey", (tức là nhanh chóng hơn 100 "heys", số lần lặp mà phần mã khác sẽ kích hoạt)

Điều gì có thể có thể gây ra việc sử dụng Serial, với dữ liệu không (theo như tôi có thể nói) được buộc để loop_counterngăn chặn hoàn toàn nó hoạt động đúng?

EDIT : Đây là một phần của tệp chính đã đặt ra vấn đề (tốt, đóng góp nhiều nhất cho nó (sử dụng quá nhiều bộ nhớ)):



void display_state() {
  int i,j,index=0;
  short alive[256][2];

 for(i=0;i<num_rows;i++) { 
   for(j=0;j<num_cols;j++) {
     if(led_matrix[i][j]==1) { 
       alive[index][0]=i;
       alive[index][1]=j;
       index++;
     }
   }
 }
 alive[index][0]=NULL; //Null-terminate.
 alive[index][1]=NULL;

 //383 is a great number
 for(int idx=0;idx < index; idx++) {
   display(alive[idx][0],alive[idx][1]);
   delayMicroseconds(283);
 }
}

Đây là "Letters.h":


    #ifndef _MY_LETTERS_H
    #define _MY_LETTERS_H

#define nrows 4
#define ncols 4

#define num_rows 16
#define num_cols 16

#define MAX_WORD_LENGTH 16
#define NUMBER_OF_CHARACTERS 26

#include <stdlib.h>

int loop_count = 0;loop_count = 0 ; ngắn led_matrix [num_rows] [num_cols];ngắn led_matrix [ NUM_ROWS ] [ NUM_COLS ];

const short letter_a [mũi tên] [ncols] = {{0,1,1,0}, ngắn letter_a [ nrows ] [ ncols ] = {{ 0 , 1 , 1 , 0 }, {1,0,0,1},{ 1 , 0 , 0 , 1 }, {1,1,1,1},{ 1 , 1 , 1 , 1 }, {1,0,0,1}};{ 1 , 0 , 0 , 1 }}; const short letter_b [mũi tên] [ncols] = {{1,0,0,0}, {1,1,1,0}, {1,0,1,0}, {1,1,1,0} };const ngắn letter_b [ nrows ] [ ncols ] = {{ 1 , 0 , 0 , 0 }, { 1 , 1 , 1 , 0 }, { 1 , 0 , 1 , 0 }, { 1 , 1 , 1 , 0 } }; const short letter_c [mũi tên] [ncols] = {{0,1,1,1}, {1,0,0,0}, {1,0,0,0}, {0,1,1,1} };const ngắn letter_c [ nrows ] [ ncols ] = {{ 0 , 1 , 1 , 1 }, { 1 , 0 , 0 , 0 }, { 1 , 0 , 0 , 0 }, { 0 , 1 , 1 , 1 } }; const short letter_t [mũi tên] [ncols] = {{1,1,1,1}, {0,1,0,0}, {0,1,0,0}, {0,1,0,0} };const ngắn letter_t [ nrows ] [ ncols ] = {{ 1 , 1 , 1 , 1 }, { 0 , 1 , 0 , 0 }, { 0 , 1 , 0 , 0 }, { 0 , 1 , 0 , 0 } };

typedef struct letter_node { cấu trúc letter_node { const ngắn * dữ liệu;const ngắn * dữ liệu ; letter_node * tiếp theo;* tiếp theo ; int x;int x ; int y;int y ; } letter_node;} letter_node ;

letter_node aa = {& letter_a [0] [0], NULL, 1,1};= {& letter_a [ 0 ] [ 0 ], NULL , 1 , 1 }; letter_node bb = {& letter_b [0] [0], NULL, 1,1};= {& letter_b [ 0 ] [ 0 ], NULL , 1 , 1 }; letter_node cc = {& letter_c [0] [0], NULL, 1,1};= {& letter_c [ 0 ] [ 0 ], NULL , 1 , 1 }; letter_node tt = {& letter_t [0] [0], NULL, 1,1};= {& letter_t [ 0 ] [ 0 ], NULL , 1 , 1 };

letter_node letter_map [NUMBER_OF_CHARACTERS];[ NUMBER_OF_CHARACTERS ]; #endif#endif

Một số thông tin khác: - Tôi đang sử dụng Uno (ATMega328)


Kích thước ngăn xếp của bạn là gì? Có một cơ hội mà bạn có thể vẽ ngăn xếp của bạn và xem nếu nó đang bị hỏng. Có phải In nối tiếp sử dụng bị gián đoạn, mã của bạn có được cấp lại không?
Ktc

Bản in nối tiếp không được kích hoạt bởi bất kỳ gián đoạn nào, tôi chỉ sử dụng nó trong loop()chức năng. Tôi nên vẽ ngăn xếp của mình như thế nào nếu phương thức đầu ra duy nhất mà tôi có ( Serial.print()) làm tôi thất bại?
eqzx

2
Để loại bỏ những sai lầm có thể xảy ra và những tác dụng phụ bị hiểu lầm về những thay đổi có vẻ tầm thường, vui lòng thay thế mã trong câu hỏi của bạn bằng một bản sao chính xác, chính xác của một bản phác thảo được cắt giảm đến mức tối thiểu cần thiết để kích hoạt vấn đề . Không phải "đây là chương trình của tôi thất bại nếu tôi .." mà chính xác là chương trình tối thiểu thất bại theo cách này.
Chris Stratton

Câu trả lời:


2

Tôi cũng có một vấn đề tương tự như vậy, và tôi rất chắc chắn rằng bạn cũng không có liên quan đến không gian ngăn xếp. Hãy thử thu nhỏ mã càng nhiều càng tốt.

Trong trường hợp của tôi, mã đôi khi sẽ chạy khi tôi có một tin nhắn nối tiếp trong đó, nhưng sau đó nó dường như không chạy khi tôi không chạy. Tôi cũng có một trường hợp gửi tin nhắn nối tiếp sẽ khiến arduino thiết lập lại vô tận.

Tôi cũng đang sử dụng một arduino328. Có khả năng bạn nên giảm kích thước của mảng nếu bạn có bất kỳ kích thước nhỏ nhất có thể chấp nhận được.


cảm ơn, bạn và Dave Tweed đã nhận nó. Tôi đã cấu trúc lại hàm display_state () để không cần phân bổ thêm đó. Tôi hiếm khi thực hiện xử lý nhúng, tôi cho rằng tất cả chúng ta phải chạm vào tường bộ nhớ tại một số điểm!
eqzx

Xin chào, tôi có tình huống tương tự. Tôi thay đổi kích thước của mảng từ 128 thành 96 và chương trình của tôi hoạt động tốt. Nhưng tôi nghĩ vấn đề này thực sự không phù hợp để gỡ lỗi, bởi vì kích thước của mảng của tôi nhỏ hơn kích thước ngăn xếp khai báo. Bạn có biết nơi tôi có thể tìm thấy thông tin để giải quyết vấn đề này không?
Sư tử Lai

4

Mã của bạn có khởi tạo cổng nối tiếp không? Ví dụ.

void setup()
{
    Serial.begin(9600);
}

Không làm điều này có thể dẫn đến một sự cố khi sử dụng nối tiếp lần đầu tiên.


Vâng, tôi có điều đó.
eqzx

3

Có lẽ bạn đang hết bộ nhớ? Tất cả các chuỗi bạn in bằng Serial.print ("một cái gì đó") diễn ra trong SRAM, bằng với số ký tự của chuỗi đó + 1 cho dấu kết thúc \ 0. Có thể hết bộ nhớ ngay cả khi kích thước được biên dịch của bạn nhỏ hơn nhiều so với bộ nhớ flash Arduino, vì SRAM chỉ có 2048 byte cho Atmega328 và 1024 byte cho Atmega 168. Tôi đã gặp một vấn đề tương tự, tôi đã giải quyết bằng cách rút ngắn tất cả văn bản và loại bỏ các thông báo gỡ lỗi không cần thiết.


Hừm. Tôi có một số mảng đa chiều được khai báo trong tiêu đề của mình, có lẽ đó là vấn đề? Chúng được lưu trữ trong SRAM?
eqzx

1
@ nrhine1: Trong trường hợp đó, có lẽ bạn nên cho chúng tôi xem toàn bộ bản phác thảo của bạn, không chỉ những phần mà bạn nghĩ vấn đề nằm ở đó.
Dave Tweed

@DaveTweed Có, sẽ làm.
eqzx

1
Tôi nhận thấy bạn đang xác định rất nhiều dung lượng lưu trữ trong tệp tiêu đề của mình, thay vì chỉ khai báo nó ở đó (nếu bạn không hiểu sự khác biệt hãy xem trang này ). Điều này sẽ là bất thường trong một chương trình C; Có phải đó là cách làm thông thường trên Arduino? Bạn có thể kết thúc với nhiều bản sao của các cấu trúc này. Ngoài ra, bạn đang xác định một số biến tự động rất lớn, chẳng hạn như mảng "còn sống" trong display_state (), cần hơn 1024 byte không gian ngăn xếp. Tôi khá chắc chắn rằng bạn chỉ đơn giản là hết bộ nhớ.
Dave Tweed

@DaveTweed cảm ơn bạn, bạn và Reza đã nhận nó. Tôi đã cấu trúc lại display_state()hàm để không cần phân bổ thêm đó. Tôi hiếm khi thực hiện xử lý nhúng, tôi cho rằng tất cả chúng ta phải chạm vào tường bộ nhớ tại một số điểm!
eqzx

1

Bạn chưa hiển thị mã khởi tạo biến "loop_corer". Có phải đó là bên ngoài thường trình loop () ?

Bạn có thể đã khai báo theo cách mà nó liền kề với một vùng lưu trữ bộ nhớ khác đang hoạt động bên ngoài kích thước được khai báo của nó và tromping trên biến loop_corer không?


Tôi đã thử khai báo nó theo nhiều cách khác nhau, ở nhiều nơi khác nhau. Trong tiêu đề, ngay phía trên loop(), v.v. Bạn đang nói rằng Serial.print()phương thức có thể ghi đè lên bằng cách nào đó?
eqzx

Điều tôi muốn nói bởi bình luận trước đó là tôi gần như tích cực rằng tôi đã cô lập hành vi 'xấu' với sự tồn tại của Serial.print (). Khi nó không ở đó, mọi thứ hoạt động tốt.
eqzx

@ nrbine1 - Dường như với tôi rằng biến toàn cục "loop_corer" của bạn đang được sử dụng bởi phương thức Serial.print () như tôi đã đề xuất trong câu trả lời của mình. Trong câu trả lời của posipiet, bạn đã được hỏi liệu đối tượng Nối tiếp đã được khởi tạo đúng chưa. Nếu điều đó chưa được thực hiện, nó có thể giải thích "tromping" trên bộ đếm của bạn khi nó nối tiếp.print () cố gắng sử dụng bộ đệm chưa được phân bổ và thiết lập đúng.
Michael Karas

Tôi đã thêm tất cả các nguồn của mình.
eqzx

1

Tôi không thấy trong mã của bạn nơi bạn đang gọi loop(). Nó cũng không giống như bạn đang sử dụng loop_counterbên ngoài chức năng đó. Có một lý do bạn tuyên bố nó toàn cầu? Tôi cho rằng đó là vì bạn muốn nó giữ giá trị của nó ở giữa các cuộc gọi. Bạn có thể làm điều này với một biến cục bộ tĩnh thay thế.

void loop() {
    static int loop_counter = 0;

    if(loop_counter > 100)
    {
        loop_counter = 0;
    }
    else
    {
        loop_counter++;
    }

    Serial.println("hey");

    if(loop_counter == 0)
    {
         //do_something_important();
    }      
}

Điều đó sẽ đảm bảo rằng không có chức năng bên ngoài nào có thể dẫm lên nó. Bạn phải luôn luôn khai báo các biến của mình trong phạm vi nhỏ nhất có thể để tránh hành vi không mong muốn.

Nếu điều đó không hiệu quả, bạn sẽ cần thực sự phân tích việc sử dụng bộ nhớ của mình. Kiểm tra EE.SE Q & A này để biết nhiều mã mẫu khác nhau để thực hiện điều này trong Arduino.


Tôi đã thử làm cho nó tĩnh. Nó không giúp được gì. Đây là một lần lặp khác nhau. setup()loop()là các chức năng mà arduino chạy theo mặc định, setup()thứ nhất, loop()thứ hai. loop()về cơ bản là như thế main(), ngoại trừ nó được gọi nhiều lần. tham khảo: arduino.cc/en/Reference/loop Tôi sẽ kiểm tra liên kết đó.
eqzx

một lần nữa, như tôi đã đề cập trong các bình luận khác, tôi không thể gỡ lỗi Serial.print(). Có vẻ như tôi sẽ phải ở ngoài processingIDE bình thường nếu tôi muốn có thể sử dụng GDB
eqzx

@ nrhine1 Bạn nói rằng nó hoạt Serial.print()động tốt ở chỗ nó đã in ra "hey" rất nhiều. Đó loop_counterlà cho bạn một vấn đề. Hãy thử loại bỏ if(loop_counter == 0)mã và nhập get_free_memory()mã (để lại số loop_countergia) và chạy nó. Điều này ít nhất sẽ cho bạn biết nếu bạn có bất kỳ vấn đề lớn nào với việc phân bổ bộ nhớ của bạn.
embed.kyle

1

Thư viện nối tiếp phần mềm Arduino sử dụng các ngắt. (xem "phần mềmSerial.cpp, .h"). Bạn có thể gặp sự cố khi ISR ​​"bước" vào mã chính (hoặc ngược lại). Hãy thử sử dụng các cờ khóa liên động để mã chờ trong khi các thao tác in hoàn tất.


0

Tại một thời điểm trước đây tôi đã có ấn tượng là có cùng một vấn đề. Trước đó, tôi đã giải quyết nó bằng cách thêm một độ trễ (1) ở phía trước hoặc sau serial.println. Đó là với Arduino 0022 trên Linux. Không chắc chắn đó là bảng nào, có lẽ là một sê-ri Boarduino. Không thể tái tạo nó.

Hiện tại, nó hoạt động với tôi trên USB boarduino với Arduino 1.01 trên Windows:

int loop_counter = 0;
int led = 13;

void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);}

void loop() {
    if(loop_counter > 100) {
      loop_counter = 0;
    }
    else {
      loop_counter++;
    }

    Serial.println(loop_counter);

    if(loop_counter == 0) {
      Serial.println("hey hey orange, hey hey!");
    }      
}

Cám ơn vì sự gợi ý. Thật không may, nó không giải quyết được vấn đề.
eqzx
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.