Arduino Seri baskı, programın davranışını istenmeyen şekilde değiştirir


10

Bir başlıkta bildirilen bir döngü sayacı kullanıyorum:

int loop_counter = 0;

Bu sayacı sık sık bir olayı tetiklemek için kullanıyorum. Aynı tür davranışlar için bir modulo kullanıyordum, ancak basitleştirdim, böylece çalışmak daha kolay (yine de aynı davranışla sonuçlanıyor)

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

    //Serial.println("hey");

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

Tüm ben ile iletişim deneyin kadar iyi ve güzel Serialuncommenting //Serial.println("hey"); ( "hey"bu örnekte, çünkü bana göre bu davranış saçma).

Bu loop_counterhiçbir zaman do_something_important();kod bölümünü tetiklemez . Ben bildirerek çalıştı loop_counterolarak volatileherhangi bir değişiklik olmadığını,. Denedim Serial.printing loop_counterve ben de (o döngü donduracak) garip davranışları başlamıştı. Serial.println("hey");Seri monitörde bolca "hey", yani kodun diğer bölümünün tetiklemesi gereken yineleme sayısından çok daha fazla 100 "heys" elde ettiğim anlamında çalışır

Düzgün çalışmasını tamamen önlemek için Serialbağlı olmayan (anlayabildiğim kadarıyla) verilerle , kullanımının nedeni ne olabilir loop_counter?

DÜZENLEME : İşte ana dosyanın sorunu ortaya çıkaran kısmı (çok, en çok katkıda bulunan kısım) (çok fazla bellek kullanarak):



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

İşte "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 ; kısa led_matriks [ num_rows ] [ num_cols ];

sabit kısa letter_a [ nrows ] [ ncols ] = {{ 0 , 1 , 1 , 0 }, { 1 , 0 , 0 , 1 }, { 1 , 1 , 1 , 1 }, { 1 , 0 , 0 , 1 } }; sabit kısa mektup_b [ nrows ] [ ncols ] = {{ 1 , 0 , 0 , 0 }, { 1 , 1 , 1 , 0 }, { 1 , 0 , 1 , 0 }, { 1 , 1 , 1 , 0 }}; const kısa letter_c [ nrows ] [ ncols ] = {{ 0 , 1 , 1 , 1 }, { 1 , 0 , 0 , 0 }, { 1 , 0 , 0 , 0 }, { 0 , 1 , 1 , 1 }}; sabit kısa letter_t [ nrows ] [ ncols ] = {{ 1 , 1 , 1 , 1 }, { 0 , 1 , 0 , 0 }, { 0 , 1 , 0 , 0 }, { 0 , 1 , 0 , 0 } };

typedef struct letter_node { const short * verileri ; letter_node * sonraki ; int x ; int y ; } letter_node ;

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

letter_node letter_map [ NUMBER_OF_CHARACTERS ]; #endif

Daha fazla bilgi: - Bir Uno kullanıyorum (ATMega328)


Yığın boyutunuz nedir? Yığını boyamak ve bozuk olup olmadığını görmek için bir şans var mı. Seri Baskı kullanımı kesiliyor mu, kodunuz yeniden girilmiş mi?
Ktc

Seri yazdırma herhangi bir kesinti tarafından tetiklenmez, sadece loop()işlevde kullanıyorum. Sahip olduğum tek çıkış yöntemi ( Serial.print()) beni başarısız ediyorsa yığınımı nasıl boyamalıyım?
eqzx

2
Önemsiz görünen değişikliklerin olası hatalarını ve yanlış anlaşılan yan etkilerini ortadan kaldırmak için, lütfen sorunuzdaki kodu , sorunu tetiklemek için gereken minimum değere indirilmiş bir taslağın gerçek, karakter tam bir kopyasıyla değiştirin . "Bu benim başarısız olduğum program .." değil, tam olarak bu şekilde başarısız olan minimum program.
Chris Stratton

Yanıtlar:


2

Ben de buna benzer bir sorun vardı ve seninki de yığın alanı ile ilgili olduğundan eminim. Kodu olabildiğince daraltmayı deneyin.

Benim durumumda bazen içinde seri bir mesaj varken kodu çalışacaktı, ama sonra yapmadım gibi görünmüyor. Seri mesajlar göndermenin arduino'nun sonsuza kadar sıfırlanmasına neden olacağı bir durum da vardı.

Ayrıca bir arduino328 kullanıyordum. Muhtemelen kabul edilebilir en küçük boyuta sahipseniz dizinizin boyutunu küçültmelisiniz.


teşekkür ederim, sen ve Dave Tweed anladınız. Bu ekstra tahsise ihtiyaç duymadan display_state () işlevini yeniden düzenledim. Nadiren gömülü işleme yapıyorum, sanırım hepimiz bir noktada hafıza duvarına çarpmak zorundayız!
eqzx

Merhaba, bende benzer bir durum var. Dizi boyutunu 128'den 96'ya değiştiriyorum ve programım iyi çalışıyor. Ama bu sorun gerçekten hata ayıklamak için iz dışında olduğunu düşünüyorum, çünkü benim dizi boyutu beyan yığın boyutu daha küçüktür. Bu tür bir sorunla başa çıkmak için nerede bilgi bulabileceğimi biliyor musunuz?
Lion Lai

4

Kodunuz seri bağlantı noktasını başlatıyor mu? Örneğin.

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

Bunun yapılmaması, serinin ilk kullanımında çökmeye neden olabilir.


Evet, bende var.
eqzx

3

Belki hafızanız bitiyor? Serial.print ("bir şey") ile yazdırdığınız tüm dizeler, \ 0 sonlandırıcısı için bu dizenin karakter sayısına + 1 eşit olan SRAM'de yer alır. Çiziminizin derlenmiş boyutu Arduino flash bellekten çok daha küçük olsa bile bellek tükenebilir, çünkü SRAM Atmega328 için sadece 2048 bayt ve Atmega 168 için 1024 bayttır. metinler ve gereksiz hata ayıklama iletileri kaldırma.


Hmm. Başlığımda bildirilen çok boyutlu birkaç dizim var, belki sorun budur? SRAM'da mı depolanıyorlar?
eqzx

1
@ nrhine1: Bu durumda, muhtemelen sadece sorunun olduğunu düşündüğünüz bölümleri değil, tüm çiziminizi bize göstermelisiniz .
Dave Tweed

@DaveTweed Evet, yapacak.
eqzx

1
Üstbilgi dosyanızda, yalnızca orada bildirmek yerine çok fazla depolama alanı tanımladığınızı fark ediyorum (ayrımı anlamadıysanız bu sayfaya bakın ). Bu bir C programında alışılmadık bir durumdur; Arduino'daki normal uygulama bu mu? Bu yapıların birden çok kopyasıyla sonuçlanıyor olabilirsiniz. Ayrıca, 1024 bayttan fazla yığın alanı gerektiren display_state () öğesindeki "canlı" dizi gibi çok büyük otomatik değişkenler de tanımlayabilirsiniz. Eminim sadece hafızanız bitiyor.
Dave Tweed

@DaveTweed teşekkür ederim, sen ve Reza anladın. display_state()Bu ekstra tahsise ihtiyaç duymadan işlevi yeniden düzenledim . Nadiren gömülü işleme yapıyorum, sanırım hepimiz bir noktada hafıza duvarına çarpmak zorundayız!
eqzx

1

"Loop_counter" değişkenini başlatan kodu göstermediniz. Bu loop () rutininin dışında mı ?

Bunu, bildirilen boyutunun dışında çalışan başka bir bellek depolama alanına bitişik ve döngü_sayısı değişkeni üzerinde sıkışan bir şekilde bildirmiş olabilir misiniz?


Bunu birçok farklı şekilde, birçok farklı yerde beyan etmeyi denedim. Başlıkta, hemen yukarıda loop(), vb. Serial.print()Yöntemin bir şekilde üzerine yazıyor olabileceğini mi söylüyorsunuz ?
eqzx

Önceki yorumdan kastettiğim, 'kötü' davranışı Serial.print () varlığına izole ettiğimden neredeyse olumlu olduğum. Orada olmadığında işler iyi gider.
eqzx

@ nrbine1 - Bana öyle geliyor ki genel değişken değişkeni "loop_counter" cevabımda önerdiğim gibi Serial.print () yöntemi ile adım atıyor. Tarafından cevap olarak posipiet Seri nesne düzgün başlatıldı eğer istendi. Bu yapılmadıysa, Serial.print () düzgün bir şekilde tahsis edilmemiş ve kurulmamış bir arabellek kullanmaya çalıştığından, sayacınızdaki "sıkıştırma" yı açıklayabilir.
Michael Karas

Tüm kaynağımı ekledim.
eqzx

1

Kodunuzu nerede aradığınızı göremiyorum loop(). Ayrıca loop_counterbu işlevin dışında kullandığınız gibi görünmüyor . Küresel ilan etmenizin bir nedeni var mı? Bunun, aramalar arasındaki değerini korumasını istediğiniz için varsayıyorum. Bunu bunun yerine statik bir yerel değişkenle yapabilirsiniz .

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

Bu, başka hiçbir harici fonksiyonun üzerine basamayacağından emin olmalıdır. İstenmeyen davranışlardan kaçınmak için değişkenlerinizi daima mümkün olan en küçük kapsamda beyan etmelisiniz.

Bu işe yaramazsa, bellek kullanımınızı gerçekten analiz etmeniz gerekir. Kontrol bu EE.SE Q & A bir Arduino içinde yapmanız çeşitli örnek kod için.


Zaten statik hale getirmeyi denedim. Yardım etmedi. Bu farklı bir yinelemedir. setup()ve loop()arduino'nun varsayılan olarak setup()birinci, loop()ikinci olarak çalıştırdığı işlevlerdir . arka arkaya çağrılması dışında loop()esasen gibidir main(). reference: arduino.cc/tr/Reference/loop Bu bağlantıyı kontrol edeceğim.
eqzx

yine, diğer yorumlarda da belirttiğim gibi, hata ayıklayamıyorum Serial.print(). processingGDB kullanabilmek istiyorsam normal IDE'nin dışında kalmam gerekecek gibi görünüyor
eqzx 25:12

@ nrhine1 Serial.print()Çok fazla "hey" yazdırdığı için iyi çalıştığını söylediniz . Bu loop_countersize bir sorun veriyor. if(loop_counter == 0)Kodu kaldırmayı ve kodu girmeyi get_free_memory()( loop_counterartışı bırak ) ve çalıştırmayı deneyin . Bu, en azından bellek ayırma işleminizle ilgili büyük sorunlarınız olup olmadığını söyleyecektir .
embedded.kyle

1

Arduino yazılım seri kitaplığı kesmeler kullanır. (bkz. "softwareSerial.cpp, .h"). ISR'nin ana koda "adım attığı" (veya tersi) konusunda bir sorununuz olabilir. Yazdırma işlemleri tamamlandığında kodun beklemesi için kilitleme bayraklarını kullanmayı deneyin.


0

Bir süre önce bir noktada aynı problemin olduğu izlenimine kapıldım. O zamanlar, önünde veya seri.println'den sonra bir gecikme (1) ekleyerek çözdüm. Bu Linux'ta Arduino 0022 ile oldu. Hangi kurulu olduğunu emin değilim, muhtemelen bir Boarduino seri. Ya da çoğaltamaz.

Şu anda, Windows'ta Arduino 1.01 ile bir boarduino USB'de çalışıyor:

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

Önerin için teşekkürler. Maalesef sorunu çözmedi.
eqzx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.