Arduino Serial 인쇄가 프로그램의 동작을 바람직하지 않게 변경


10

헤더에 선언 된 루프 카운터를 사용하고 있습니다.

int loop_counter = 0;

이 카운터를 사용하여 매번 이벤트를 트리거합니다. 나는 같은 유형의 행동에 대해 모듈로를 사용했지만, 작업하기가 더 쉬워졌습니다 (여전히 동일한 행동을 초래합니다)

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

    //Serial.println("hey");

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

Serial주석 처리를 제거하여 의사 소통을 시도 할 때까지 //Serial.println("hey"); ( "hey"이 예제에서는이 동작이 터무니 없기 때문에) 모두 훌륭 합니다.

이로 인해 코드 섹션이 loop_counter트리거되지 않습니다 do_something_important();. 나는 선언하는 시도 loop_countervolatile아무것도 변경하지 않았다. 나는 Serial.printing을 시도했고 loop_counter이상한 행동을하고 있었다 (루프를 동결시킬 것이다). Serial.println("hey");직렬 모니터에서 많은 "hey"(즉, 100 개 이상의 "heys", 다른 코드 섹션이 트리거해야하는 반복 횟수)를 얻는다는 의미에서 작동합니다.

(내가 알 수있는 Serial한) 데이터가 loop_counter제대로 작동하지 않도록 완전히 묶이지 않은 데이터를 사용하여을 사용하는 원인은 무엇입니까 ?

편집 : 다음은 문제를 일으키는 메인 파일의 일부입니다 (잘 사용하여 메모리를 많이 사용함).



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);
 }
}

"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_counter = 0;loop_counter = 0 ; 짧은 led_matrix [num_rows] [num_cols];짧은 led_ 행렬 [ num_rows ] [ num_cols ];

const short letter_a [nrows] [ncols] = {{0,1,1,0}, 짧은 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 [nrows] [ncols] = {{1,0,0,0}, {1,1,1,0}, {1,0,1,0}, {1,1,1,0} };const short letter_b [ nrows ] [ ncols ] = {{ 1 , 0 , 0 , 0 }, { 1 , 1 , 1 , 0 }, { 1 , 0 , 1 , 0 }, { 1 , 1 , 1 , 0 } }; const short letter_c [nrows] [ncols] = {{0,1,1,1}, {1,0,0,0}, {1,0,0,0}, {0,1,1,1} };const short letter_c [ nrows ] [ ncols ] = {{ 0 , 1 , 1 , 1 }, { 1 , 0 , 0 , 0 }, { 1 , 0 , 0 , 0 }, { 0 , 1 , 1 , 1 } }; const short letter_t [nrows] [ncols] = {{1,1,1,1}, {0,1,0,0}, {0,1,0,0}, {0,1,0,0} };const short letter_t [ nrows ] [ ncols ] = {{ 1 , 1 , 1 , 1 }, { 0 , 1 , 0 , 0 }, { 0 , 1 , 0 , 0 }, { 0 , 1 , 0 , 0 } };

typedef struct letter_node { struct letter_node { const short * data;const short * data ; letter_node * 다음;* 다음 ; 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

추가 정보 :-Uno (ATMega328)를 사용하고 있습니다.


스택 크기는 무엇입니까? 스택을 칠하고 손상되었는지 확인할 수있는 기회가 있습니까? Serial Print는 인터럽트를 사용합니까? 코드 재진입입니까?
Ktc

직렬 인쇄는 인터럽트에 의해 트리거되지 않으며 loop()기능 에서만 사용합니다 . 내가 가지고있는 유일한 출력 방법 ( Serial.print())이 실패 하면 어떻게 스택을 페인트해야 합니까?
eqzx

2
사소한 변경으로 인해 발생할 수있는 실수를 없애고 부작용을 잘못 이해하려면 문제의 코드를 문자 그대로 정확한 스케치 사본으로 바꾸어 문제를 유발하는 데 필요한 최소한으로 줄이십시오 . "이 프로그램은 실패하면 실패합니다."가 아니라 정확하게 실패하는 최소 프로그램입니다.
Chris Stratton

답변:


2

나는 이것과 비슷한 문제가 있었고, 당신도 스택 공간과 관련이 없다는 것을 확신합니다. 코드를 최대한 줄이십시오.

필자의 경우 직렬 메시지가있을 때 코드가 실행되는 경우가 있지만 그렇지 않은 경우 실행되지 않는 것처럼 보입니다. 직렬 메시지를 보내면 arduino가 끝없이 재설정되는 경우도 있습니다.

나는 또한 arduino328을 사용하고있었습니다. 허용 가능한 가장 작은 크기가있는 경우 배열 크기를 줄여야합니다.


감사합니다. 당신과 데이브 트위드가 그것을 얻었습니다. 추가 할당이 필요하지 않도록 display_state () 함수를 리팩터링했습니다. 나는 임베디드 프로세싱을 거의하지 않는다. 우리 모두가 어느 시점에서 메모리 벽에 부딪쳐 야한다고 생각한다!
eqzx

안녕하세요, 비슷한 상황이 있습니다. 배열의 크기를 128에서 96으로 변경하면 프로그램이 정상적으로 작동합니다. 그러나 내 배열의 크기가 선언 스택 크기보다 작기 때문에이 문제는 실제로 디버그하기에 부족하다고 생각합니다. 이런 종류의 문제를 해결할 정보를 어디서 찾을 수 있는지 알고 있습니까?
사자 라이

4

코드가 직렬 포트를 초기화합니까? 예 :

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

이렇게하지 않으면 시리얼을 처음 사용할 때 충돌이 발생할 수 있습니다.


그렇습니다.
eqzx

3

메모리가 부족할 수 있습니다. Serial.print ( "something")으로 인쇄하는 모든 문자열은 SRAM에서 발생하며 해당 문자열의 문자 수 + \ 0 종결 자에 대해 1입니다. SRAM이 Atmega328의 경우 2048 바이트이고 Atmega 168의 경우 1024 바이트이기 때문에 스케치의 컴파일 된 크기가 Arduino 플래시 메모리보다 훨씬 작은 경우에도 메모리가 부족할 수 있습니다. 비슷한 문제가있었습니다. 텍스트 및 불필요한 디버그 메시지 제거


흠. 헤더에 여러 다차원 배열이 선언되어 있는데, 이것이 문제입니까? 그들은 SRAM에 저장되어 있습니까?
eqzx

1
@ nrhine1 :이 경우, 당신은 아마 우리에게 전체 스케치뿐 아니라 부분 표시해야합니다 당신은 문제가 거짓말을 생각합니다.
Dave Tweed

@DaveTweed 그렇습니다.
eqzx

1
헤더 파일에 단순히 저장하지 않고 많은 저장 공간을 정의하고 있음을 알았습니다 (차별을 이해하지 못하면 이 페이지 참조 ). 이것은 C 프로그램에서는 드문 일입니다. Arduino의 일반적인 관행입니까? 이러한 구조의 여러 사본으로 끝날 수 있습니다. 또한 1024 바이트 이상의 스택 공간이 필요한 display_state ()의 "alive"배열과 같은 매우 큰 자동 변수를 정의하고 있습니다. 나는 당신이 단순히 메모리가 부족하다고 확신합니다.
Dave Tweed

@DaveTweed는 당신과 Reza가 감사합니다. display_state()추가 할당이 필요하지 않도록 함수를 리팩터링했습니다 . 나는 임베디드 프로세싱을 거의하지 않는다. 우리 모두가 어느 시점에서 메모리 벽에 부딪쳐 야한다고 생각한다!
eqzx

1

변수 "loop_counter"를 초기화하는 코드를 표시하지 않았습니다. loop () 루틴 외부에 있습니까?

선언 된 크기를 벗어나 작동하는 다른 메모리 저장 영역에 인접하고 loop_counter 변수에서이 트롬 핑되는 방식으로 선언 했습니까?


여러 곳에서 다양한 방법으로 선언하려고 시도했습니다. 헤더, 바로 위 loop()등에서 Serial.print()메서드가 어떻게 든 덮어 쓸 수 있다고 말하고 있습니까?
eqzx

이전 의견에서 의미 한 바는 '나쁜'동작을 Serial.print ()의 존재와 격리 시켰다는 것입니다. 그것이 없으면 일이 잘 작동합니다.
eqzx

@ nrbine1-전역 변수 변수 "loop_counter"가 내 대답에서 제안한 Serial.print () 메서드에 의해 강화되고있는 것 같습니다. posipiet 의 답변 에서 Serial 객체가 올바르게 초기화되었는지 묻습니다. 그렇게하지 않으면 Serial.print ()가 올바르게 할당 및 설정되지 않은 버퍼를 사용하려고 시도 할 때 카운터의 "트롬 핑"을 설명 할 수 있습니다.
Michael Karas

내 소스를 모두 추가했습니다.
eqzx

1

코드에서 전화하는 곳을 볼 수 없습니다 loop(). 또한 loop_counter그 기능 밖에서 사용하는 것처럼 보이지 않습니다 . 당신이 그것을 세계적으로 선언하는 이유가 있습니까? 통화간에 가치를 유지하기를 원하기 때문이라고 가정합니다. 대신 정적 로컬 변수를 사용 하여이 작업을 수행 할 수 있습니다.

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();
    }      
}

다른 외부 기능이 밟 히지 않도록해야합니다. 원치 않는 동작을 피하려면 가능한 한 가장 작은 범위에서 변수를 선언해야합니다.

그래도 문제가 해결되지 않으면 메모리 사용량을 실제로 분석해야합니다. Arduino 내에서이를 수행하기위한 다양한 샘플 코드는 이 EE.SE Q & A 를 확인하십시오 .


나는 그것을 정적으로 만들려고 노력했다. 도움이되지 않았습니다. 이것은 다른 반복입니다. setup()그리고 loop(), 기본적으로 실행을 아두 이노 함수입니다 setup(), 첫 loop()번째는. 반복적으로 호출된다는 점을 제외하고 loop()는 본질적 main()으로입니다. 참조 : arduino.cc/en/Reference/loop 해당 링크를 확인하겠습니다.
eqzx

다른 의견에서 언급했듯이 다시 디버깅 할 수 없습니다 Serial.print(). 나는 정상적인 외부로해야합니다 마치 processing내가 GDB를 사용할 수 있도록하기 위해서는 IDE
eqzx

@ nrhine1 Serial.print()"hey"를 많이 출력한다는 점에서 잘 작동한다고했습니다. 그것은 loop_counter당신에게 문제를주는 것입니다. if(loop_counter == 0)코드를 제거하고 코드를 넣고 get_free_memory()( loop_counter증분을 남겨둔 후 ) 실행하십시오. 이것은 적어도 메모리 할당에 중대한 문제 가 있는지 알려줍니다 .
embedded.kyle

1

Arduino 소프트웨어 시리얼 라이브러리는 인터럽트를 사용합니다. ( "softwareSerial.cpp, .h"참조) ISR이 주 코드에서 "스테핑 (stepping)"하는 문제가있을 수 있습니다 (또는 그 반대). 인쇄 작업이 완료되는 동안 코드가 대기하도록 인터 락 플래그를 사용해보십시오.


0

어느 시점에서 나는 같은 문제가 있다는 인상을 받았습니다. 당시에는 serial.println 앞이나 뒤에 지연 (1)을 추가하여 문제를 해결했습니다. Linux에서 Arduino 0022를 사용했습니다. 어떤 보드인지 확실하지 않은지, 아마도 Boarduino 시리얼 일 것입니다. 캔트도 재현.

현재 Windows의 Arduino 1.01이있는 boarduino USB에서 작동합니다.

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!");
    }      
}

제안 해 주셔서 감사합니다. 불행히도 문제를 해결하지 못했습니다.
eqzx
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.