"-=" Will nur einmal, aber nicht 3 mal.

Gast #3213811
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
Gast #3213848
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;
Gast #3213864
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 ???
Gast #3213921
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.
Gast #3213991
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.
#3214309
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$
Gast #3214346
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.
Gast #3214363
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.
#3214380
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren