Forum: Mikrocontroller und Digitale Elektronik "-=" Will nur einmal, aber nicht 3 mal.


von whatsmyname? (Gast)


Lesenswert?

Hallo, ich habe mit folgender Codesequenz ein Problem:
1
          if(pulse_led[i].r_last != 0) pulse_led[i].r_last -= 1;   
2
          if(pulse_led[i].g_last != 0) pulse_led[i].g_last -= 1;
3
          if(pulse_led[i].b_last != 0) pulse_led[i].b_last -= 1;

Wenn r = 0, g = 0 und b > 0 ist, funktioniert das ganze Problemlos.
Wenn jetzt aber r = 0 g > 0 und b = 0 ist will das ganze Nicht mehr ( 
Das ... -= 1; um genauer zu sein).
Das Lustige ist, wenn ich den Code Debugge und die Zeile
1
          if(pulse_led[i].r_last != 0) pulse_led[i].r_last -= 1;
in
1
          if(pulse_led[i].r_last != 0) {
2
             pulse_led[i].r_last -= 1;
3
             serial.printf("%d", pulse_led[i].r_last);
4
          }
ändere, bleibt der Wert von pulse_led... konstant.

Woran könnte das liegen?

MfG

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Hast Du's mal so probiert, also um Compiler-Fehler auszuschließen?
1
if (pulse_led[i].r_last != 0) {
2
    pulse_led[i].r_last = pulse_led[i].r_last - 1;
3
    serial.printf("%d", pulse_led[i].r_last);
4
}

von Ingo (Gast)


Lesenswert?

Welcher Prozessor? Welcher Compiler?
Wie sind die Variablen definiert?
Zeig uns doch mal das ganze Programm.

von whatsmyname? (Gast)


Lesenswert?

Hallo,
ja, hab ich, deshalb hab ich ja auch gefragt. AVR-gcc ist version 4.3.2 
.
Standart in Arduino 1.0.5

von >;->>> (Gast)


Lesenswert?

whatsmyname? schrieb:
> bleibt der Wert von pulse_led... konstant

konstant auf 0 >;->>>

von whatsmyname? (Gast)


Lesenswert?

Das ganze Programm ist ein bisschen zu lang.
Prozessor ist ATMega328p
Der Variablen Typ in dem Fall ist uint8_t, spricht Wertebereich von 0 - 
255.

von Claus M. (energy)


Lesenswert?

Was gebnau funktioniert wann nicht mehr? Die Testausgabe oben ist 
sinnlos, da deiner Aussage nach ja im nicht funktionierenden Fall r==0 
ist.

Ansonsten erzeuten Assembler Code angucken. Welcher Compiler überhaupt, 
welches Zielsystem?

von Claus M. (energy)


Lesenswert?

Zeig mal die Definition von pulse_led

von (prx) A. K. (prx)


Lesenswert?

whatsmyname? schrieb:
> Das ganze Programm ist ein bisschen zu lang.

Dann kürz es (lieber Henry). Alles unnötige raus, aber mit Fehler noch 
drin.

von whatsmyname? (Gast)


Lesenswert?

Das ganze Programm ist ein bisschen zu lang.
Prozessor ist ATMega328p
Der Variablen Typ in dem Fall ist uint8_t, spricht Wertebereich von 0 - 
255.

>;->>> schrieb:
> konstant auf 0 >;->>>

Nein, bspw. auf 127 ;)

Die Definition von pulse_led ist ein Struct:
1
typedef struct {
2
  uint8_t r, g, b;
3
  uint8_t speed; // 0 = slow 1 = normal 2 = fast
4
  uint8_t r_last, g_last, b_last;
5
  bool up;
6
  uint32_t lasttime;
7
} 
8
pulse;

von Ingo (Gast)


Lesenswert?

Hast du Optimierungen beim Übersetzen an,
dann schalt sie doch testweise mal aus...

von Claus M. (energy)


Lesenswert?

whatsmyname? schrieb:
> Die Definition von pulse_led ist ein Struct:

Das ist nicht die ganze Wahrheit, oder warum greift du mit einem Array 
Index darauf zu?

von whatsmyname? (Gast)


Lesenswert?

Okay, Variable angelegt mit:
1
pulse pulse_led[128];

Das mit den Compiler Optimierungen teste ich jetzt.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Schau doch mal wo "i" beim Aufruf steht ...

von NoName Today (Gast)


Lesenswert?

Du testest in deiner if-Abfrage immer r_last, g_last und
b_last.

Kann es sein, dass die Dinger im Fall von  r = 0 g > 0 und b = 0 nicht 
richtig aktualisiert werden, um !=0 in der If-Bedingung zu sein ???

von >;->>> (Gast)


Lesenswert?

whatsmyname? schrieb:
> Das ganze Programm ist ein bisschen zu lang.

Schon wieder so ein "ich lasse es mir langsam aus der Nase ziehen" 
Beitrag. Am Ende ist es wieder eine übersehene Zuweisung oder anderer 
Fehler des Programmieres.

Also her mit dem vollständigen Code! Und zwar schnelle! :-)))

von whatsmyname? (Gast)


Angehängte Dateien:

Lesenswert?

Da, dann haut euch mal durch :)

von Claus M. (energy)


Lesenswert?

whatsmyname? schrieb:
> pulse pulse_led[128];

Das sind schon 1,5kB RAM. Die Schüssel hat nur 2k, oder? Kann es sein, 
dass du aus dem verfügbaren RAM rausläufst?

von whatsmyname? (Gast)


Lesenswert?

Claus M. schrieb:
> Das sind schon 1,5kB RAM. Die Schüssel hat nur 2k, oder? Kann es sein,
> dass du aus dem verfügbaren RAM rausläufst?

War nur ein bsp ;) wird mit 3 initialisiert

von Werner (Gast)


Lesenswert?

whatsmyname? schrieb:
> War nur ein bsp ;) wird mit 3 initialisiert

Ui, ein Witzbold.
Andere nach Fehler suchen lassen und noch falsche Fährten legen...
Warum kann man das Beispiel nicht gleich so angeben,
wie es echt im Code ist. Kopfschüttel

von Klaus (Gast)


Lesenswert?

Torsten C. schrieb:
> also um Compiler-Fehler auszuschließen?

DAS macht man als allerletztes. Gerade als Anfänger!

von whatsmyname? (Gast)


Lesenswert?

Sorry ;)

von Peter II (Gast)


Lesenswert?

Klaus schrieb:
> Torsten C. schrieb:
>> also um Compiler-Fehler auszuschließen?
> DAS macht man als allerletztes. Gerade als Anfänger!

das ist doch Unsinn, als Anfänger erzeugt mal zu 99.9% den Fehler 
selber. Die Optimierung anzuschalten, führt dann zu fragen warum delay 
nicht stimmt.

von mh (Gast)


Lesenswert?

und lass das dämliche gegrinse...
der fehler liegt bei dir! weder beim compiler, noch beim prozessor, noch 
sonstwo.

von >;->>> (Gast)


Lesenswert?

Wowww, das Programm ist nicht groß sondern strange. ;->

Dir geht es um die Funktion led_pulse():
1
      switch (pulse_led[i].speed) {
2
      ...
3
      default:
4
        break;
auch bei default sollte wait gesetzt werden oder eine Fehlerroutine 
angesprungen werden.

Setze deine Ausgabe
1
serial.printf("%d", pulse_led[i].r_last);
2
serial.printf("%d", pulse_led[i].g_last);
3
serial.printf("%d", pulse_led[i].b_last);
an das Ende der for Schleife.

von Leo C. (rapid)


Lesenswert?

volatile!

leo@cb:/tmp/sketch_jun22a$ grep led_pulse *
handle_threads.ino:    led_pulse();
led_funcs.ino:void led_pulse() {
leo@cb:/tmp/sketch_jun22a$ grep handle_timer1_interrupt *
handle_threads.ino:void handle_timer1_interrupt() {
sketch_jun22a.ino:  Timer1.attachInterrupt(handle_timer1_interrupt);
leo@cb:/tmp/sketch_jun22a$

von amateur (Gast)


Lesenswert?

@ThatsYourName

Ich habe wirklich keine Lust mich in Dein System und Deinen Code 
einzuarbeiten, aber Du zeigst da 3 Zeilen, die praktisch unabhängig von 
einander sind.
In diesem Falle gilt: Geht eine, gehen alle.

Wenn nicht gerade Deine Indizes (i) ausflippen, oder Du an anderer 
Stelle zu großzügig mit dem Speicher umgegangen bist, müsste das Ganz 
auch gehen.

Gibt Dein Compiler am Ende nicht eine Speicherbelegung aus?

Wenn das alles in Ordnung ist, liegt der Fehler an anderer Stelle.

von Vlad T. (vlad_tepesch)


Lesenswert?

Leo C. schrieb:
> volatile!

das war mein erster Gedanke, als ich das Codesnippet gelesen habe.

klingt nach einem typischen volatile-vergessen-Fehler.

von Peter II (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> klingt nach einem typischen volatile-vergessen-Fehler.

glaube ich nicht. Bei diesen 3 Zeilen ist es egal on der wert in einem 
Register zwischengespeichert wird oder nicht. Nach dem -=1 muss der Wert 
um ein kleiner sein. Wenn er jetzt ein volatile verwendet dann kann eine 
ISR den wert wieder um eins erhöhen. Ohne volatile kann das aber nicht 
passieren.

von Karl H. (kbuchegg)


Lesenswert?

Ist es auch nicht.
Das ganze wird aus einem Interrupt heraus aufgerufen.

Allerdings ist die ganze Interrupt Logik mit mehreren Tasks und 
gleichzeitigm UART Handling etwas 'verquert' und die UART Auswert ist 
komplett hinüber, so dass ich nicht ausschliessen möchte, dass er sich 
mit dem UART Handling die Variablenwerte zerschiesst.

Da ist wieder mal die Annahme, dass wenn man in der UART einen read() 
aufruft, dann kommt da irgendwie alles was die Gegenstelle schickt in 
einem Rutsch daher.
Pustekuchen
1
void update_serial() {
2
  uart_rec="";
3
  while(uart.available()) {
4
    uart_rec += (char)uart.read();
5
  }
6
}
7
8
void evaluate_serial_input() {
9
10
  String tmpstring0 = "";
11
  uint8_t cnum = 0;
12
13
  if(uart_rec != "") {
14
    // Detect ',' in received string
15
    for(int i = 0; i < uart_rec.length(); i++) {
16
      char 
17
      if(  ',') cnum++;
18
    }
19
20
  ....

eben das leidige Problem, dass Anfänger erst mal lernen müssen, was 
eigentlich ein Protokoll ist und wozu es dient, bzw. wie man sowas 
auswertet, das es unabdingbar ist, dass man mit der Gegenstelle eine 
End-Of-Message Kennung vereinbart, die dann auch ausgewertet werden muss 
und erst dann gilt eine Message als komplett übertragen, so dass man 
nicht 'noch nicht übertragene' Daten als gültig ansieht und mit denen 
arbeitet etc. etc.


Edit: Ich bin mir recht sicher, dass das eigentliche Problem irgendwo in 
diesem Bereich passiert. Den ganzen UART/Protokoll Teil müsste man neu 
machen. Das ist alles nicht tragfähig - und warum der UART Teil da in 
der Timer-Interrupt-Task-Scheduling Sache mit drinn hängen muss, ist mir 
auch nicht klar. Da würde ich erst mal ansetzen. Es gibt keinen Grund, 
warum der UART Teil da so verquert in die Timer-Interrupt Logik mit 
reingenommen werden muss. Die UART Abfrage bzw. Auswertung kann 
wunderbar in der Hauptschleife loop() bleiben. Aber als allererstes muss 
da mal ein die Übertragung steuerndes Protokoll mit einer Form der 
Message-Endekennung her.

von zebra (Gast)


Lesenswert?

Arduinos sind Teufelswerk. Es gibt Gründe, weshalb manch ein 
Arduino-Kind zu faul ist, einen Atmega8 aufm Steckbrett 
zusammenzustecken.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.