Używam licznika pętli zadeklarowanego w nagłówku:
int loop_counter = 0;
Używam tego licznika do wywoływania zdarzenia tak często. Kiedyś używałem modulo dla tego samego rodzaju zachowania, ale uprościłem go, aby łatwiej było z nim pracować (nadal powoduje to takie samo zachowanie)
void loop() {
if(loop_counter > 100) loop_counter = 0;
else loop_counter++;
//Serial.println("hey");
if(loop_counter == 0) {
//do_something_important();
}
}
Wszystko jest dobrze i dobrze, dopóki nie spróbuję się komunikować Serial
, odkomentując //Serial.println("hey");
( "hey"
w tym przykładzie, ponieważ dla mnie takie zachowanie jest absurdalne).
Powoduje to, loop_counter
że do_something_important();
sekcja kodu nigdy się nie uruchamia . Próbowałem deklarowania loop_counter
jako volatile
, że nic nie zmieni. Próbowałem Serial.print
ing loop_counter
, a także zachowywałem się dziwnie (spowodowałoby to zawieszenie pętli). Serial.println("hey");
działa w tym sensie, że na monitorze szeregowym dostaję dużo „hej” (tj. szybko dużo więcej niż 100 „hej”, liczba iteracji, przy których powinna zadziałać druga sekcja kodu)
Co może być przyczyną korzystania Serial
z danych, które nie są (o ile wiem) powiązane, aby loop_counter
całkowicie uniemożliwić prawidłowe działanie?
EDYCJA : Oto część głównego pliku, która ostatecznie stanowi problem (cóż, przyczyniając się do niego najwięcej (zużywając zbyt dużo pamięci)):
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);
}
}
Oto „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 ; short led_matrix [ num_rows ] [ num_cols ];
const short letter_a [ nrows ] [ ncols ] = {{ 0 , 1 , 1 , 0 }, { 1 , 0 , 0 , 1 }, { 1 , 1 , 1 , 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_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 } };
typedef struct letter_node { const short * data ; letter_node * next ; 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
Więcej informacji: - Używam Uno (ATMega328)
źródło
loop()
funkcji. Jak mam pomalować swój stos, jeśli jedyna metoda wyjścia, którą mam (Serial.print()
), zawodzi mnie?Odpowiedzi:
Miałem również podobny problem do tego i jestem bardzo pewien, że twój jest również związany z brakiem miejsca na stosie. Spróbuj maksymalnie zmniejszyć kod.
W moim przypadku czasami kod działał, gdy miałem w nim komunikat seryjny, ale wtedy nie działał, gdy go nie miałem. Miałem też przypadek, w którym wysyłanie wiadomości szeregowych powodowałoby nieskończone resetowanie arduino.
Używałem również arduino328. Prawdopodobnie powinieneś zmniejszyć rozmiar tablicy, jeśli masz jakikolwiek do najmniejszego możliwego do zaakceptowania rozmiaru.
źródło
Czy Twój kod inicjuje port szeregowy? Na przykład.
Niezastosowanie się do tego może spowodować awarię przy pierwszym użyciu numeru seryjnego.
źródło
Może kończy Ci się pamięć? Wszystkie łańcuchy drukowane za pomocą Serial.print („coś”) mają miejsce w pamięci SRAM, równej liczbie znaków tego ciągu + 1 dla terminatora \ 0. Można skończyć pamięć, nawet jeśli rozmiar skompilowanego szkicu jest znacznie mniejszy niż pamięć flash Arduino, ponieważ SRAM ma tylko 2048 bajtów dla Atmega328 i 1024 bajtów dla Atmega 168. Miałem podobny problem, który rozwiązałem, skracając wszystkie SMS-y i usuwanie niepotrzebnych komunikatów debugowania.
źródło
display_state()
funkcję, aby nie potrzebowała dodatkowego przydziału. Rzadko wykonuję przetwarzanie wbudowane, chyba w pewnym momencie wszyscy musimy trafić w ścianę pamięci!Nie pokazałeś kodu inicjującego zmienną „loop_counter”. Czy to jest poza procedurą pętli () ?
Czy masz to zadeklarowane w taki sposób, że przylega ono do innego obszaru pamięci, który działa poza swoim zadeklarowanym rozmiarem i trompuje zmienną loop_counter?
źródło
loop()
itp. Czy mówisz, żeSerial.print()
metoda może jakoś go nadpisać?Nie widzę w twoim kodzie, gdzie dzwonisz
loop()
. Nie wygląda również na to, że używaszloop_counter
poza tą funkcją. Czy istnieje powód, dla którego ogłaszasz to globalnie? Zakładam, że to dlatego, że chcesz, aby zachował swoją wartość między rozmowami. Możesz to zrobić za pomocą statycznej zmiennej lokalnej .Powinno to zapewnić, że żadne inne funkcje zewnętrzne nie będą mogły na niego uderzyć. Należy zawsze deklarować zmienne w możliwie najmniejszym zakresie, aby uniknąć niepożądanych zachowań.
Jeśli to nie zadziała, będziesz musiał naprawdę przeanalizować zużycie pamięci. Sprawdź to EE.SE Pytania i odpowiedzi dotyczące różnych przykładowych kodów, aby to zrobić w Arduino.
źródło
setup()
iloop()
są funkcjami, które arduino uruchamia domyślnie,setup()
po pierwsze, poloop()
drugie.loop()
jest zasadniczo podobnymain()
, z wyjątkiem tego, że jest wywoływany wielokrotnie. referencja: arduino.cc/en/Reference/loop Sprawdzę ten link.Serial.print()
. Wygląda na to, że będę musiał wyjść poza normalneprocessing
IDE, jeśli chcę móc korzystać z GDBSerial.print()
działa dobrze, ponieważ drukuje „hej” dużo. Toloop_counter
daje ci problem. Spróbuj usunąćif(loop_counter == 0)
kod, wstawget_free_memory()
kod (pozostawloop_counter
przyrost) i uruchom go. To przynajmniej powie ci, jeśli masz jakieś poważne problemy z przydzielaniem pamięci.Biblioteka szeregowa oprogramowania Arduino używa przerwań. (patrz „softwareSerial.cpp, .h”). Możesz mieć problem polegający na tym, że ISR „wkracza” na główny kod (lub odwrotnie). Spróbuj użyć flag blokady, aby kod czekał na zakończenie operacji drukowania.
źródło
W pewnym momencie miałem wrażenie, że mam ten sam problem. Wtedy rozwiązałem go, dodając opóźnienie (1) przed lub po serial.println. Tak było z Arduino 0022 w systemie Linux. Nie jestem pewien, która to tablica, prawdopodobnie serial Boarduino. Nie mogę tego też odtworzyć.
Obecnie działa dla mnie na pokładzie USB z Arduino 1.01 w systemie Windows:
źródło