Forum: Compiler & IDEs Frage zu Rechnungen


von ed (Gast)


Lesenswert?

Hallo!

In meinem Code lese ich AD-Wandler aus:
1
joystickx = round(ADC_Read(3)/10.45+1);//AD-Wandler 3 lesen
2
joysticky = round(ADC_Read(2)/10.45+1);//AD-Wandler 2 lesen

Die Funktion zum Runden ist hier:
1
int round (float x)
2
{
3
  if(x>0) return (int)(x + 0.5);
4
5
  return (int)(x - 0.5);
6
}

Durch einen Timer gesteuert wird jede ms folgende Funktion aufgerufen:
1
{
2
  if (m1==0) { PORTB = 0b00000011; _delay_us(1); }
3
  m1++;
4
  m2=(joysticky*joystickx);
5
  if (m1>m2) {PORTB = 0b00000111; m1=0;}
6
}

Am PORTB hängt eine Schrittmotorsteuerung. Mit den beiden Analogreglern 
kann nun die Geschwindigkeit des Motors gesteuert werden. Das Problem 
ist aber: Wenn man ganz langsam die Regler bewegt, dann gibt es immer 
wieder Punkte, an welchen der Motor nur Zuckt und Vibriert.
Ich schaue mir den Wert m2 auf einem Display an, dieser ist hier ok. 
Wenn ich einen m2 Wert manuell setze bei welchem der Moto gezuckelt hat 
dann klappt es. Es muss also irgendwas mit den Variablen nicht stimmen. 
Bleibt evtl. bei der Division irgendein Rest der auf dem Display nicht 
angezeigt wird, jedoch den m2-Wert zerschießt?

Ich hoffe ihr könnt mir einen Ansatz geben :)

von Karl H. (kbuchegg)


Lesenswert?

ed schrieb:


Wenn dein Interrupt genau in den Zeitraum kommt, in dem
hier
> joystickx = round(ADC_Read(3)/10.45+1);//AD-Wandler 3 lesen

die Zuweisung an die Variable erfolgt, kann es passieren, dass die 
Interrupt Routine auf inkonsistente Daten zugreift, wenn joystickx etwas 
größeres als ein uint8_t ist. In diesem Fall darfst du joystickx nur 
dann beschreiben, wenn die Interrupts abgeschaltet sind.

   tmp = round(ADC_Read(3)/10.45+1);//AD-Wandler 3 lesen;
   cli();
   joystickx = tmp;
   sei();

   tmp = round(ADC_Read(2)/10.45+1);//AD-Wandler 2 lesen
   cli();
   joysticky = tmp;
   sei();

von ed (Gast)


Lesenswert?

Danke für die schnelle Antwort.

Die Wandler werden aber auf einem anderen Controller gelesen. Dieser 
gibt die Daten dann via TWI an den Controller weiter welcher den Timer 
und die Motorbefehle verarbeitet.
Ich habe nun ein Testprogramm laufen, welches im Sekundentakt die 
Ausgangswerte der Regler um einen Wert vergrößert.
Ich kann das selbe Phänomen beobachten.
Wenn ich den Motor im Halbschrittbetrieb habe, dann sind die Probleme 
auch noch vorhanden.

von Karl H. (kbuchegg)


Lesenswert?

ed schrieb:
> Danke für die schnelle Antwort.
>
> Die Wandler werden aber auf einem anderen Controller gelesen. Dieser
> gibt die Daten dann via TWI an den Controller weiter welcher den Timer
> und die Motorbefehle verarbeitet.

D.h. dein ADC läuft gar nicht auf dem selben Controller?

Sauber. Wozu erzählst du das dann? INteressiert keinen. Wichtig ist wo 
der Motor-Steuerungscontroller seine Werte herkriegt. Und wenn das per 
berittenem Boten ist, dann ist das eben berittener Bote. D.h. mich 
interessiert der Stall in dem der Bote sein Pferd abstellt und wie die 
Botschaft im SChloss weiterverteilt wird. Wo der Bote herkommt, welche 
Prinzessin ihn geschickt hat, ist mir hingegen wieder sowas von egal, 
solange die Botschaft den richtigen Inhalt hat.


In der Funktion
1
Durch einen Timer gesteuert wird jede ms folgende Funktion aufgerufen:
2
{
3
  if (m1==0) { PORTB = 0b00000011; _delay_us(1); }
4
  m1++;
5
  m2=(joysticky*joystickx);
6
  if (m1>m2) {PORTB = 0b00000111; m1=0;}
7
}

greifst offenbar in einem Interrupt auf joysticky bzw. joystickx zu.

Und wenn die 2 Byte Variablen sind (int, uint16_t, int16_t) oder noch 
größer, dann muss das Beschreiben dieser Variablen (wo auch immer das 
passiert) unter Interruptsperre erfolgen.

> Ich habe nun ein Testprogramm laufen, welches im Sekundentakt die
> Ausgangswerte der Regler um einen Wert vergrößert.
> Ich kann das selbe Phänomen beobachten.
> Wenn ich den Motor im Halbschrittbetrieb habe, dann sind die Probleme
> auch noch vorhanden.

Schön.

Ich mag nicht mehr.
In unvollständigem Code, mit unvollständiger Beschreibung, ohne Ahnung 
vom Gesamtsystem dubiose Fehler suchen bzw. erraten ... sorry. Heut hab 
ich einfach den Nerv nicht mehr dafür. Meine Kristallkugel bleibt für 
heute dunkel.

von Werner (Gast)


Lesenswert?

Wenn es dir letztendlich sowieso darum geht, einen Int-Wert von deinem 
Joy-Stick zu bekommen und es nicht nur um Beschäftigungstherapie für den 
Prozessor in der ISR geht, könntest du die ganze Floatingpointarthmetik 
rausschmeißen.
Hast du geprüft, ob die Prozessorzeit, die du in der ISR verbringst, 
nicht länger als das Intervall zwischen den Timer-Interupts ist?

Was soll überhaupt das Delay in der ISR? Die Rechenzeit für die 
Float-Rechnerei, die im übrigen in der ISR überhaupt nichts zu suchen 
hat, sorgt schon für genug ziemlich undefinierte Verzögerung.

von Bronco (Gast)


Lesenswert?

ed schrieb:
> Das Problem
> ist aber: Wenn man ganz langsam die Regler bewegt, dann gibt es immer
> wieder Punkte, an welchen der Motor nur Zuckt und Vibriert.

Du könntest die berechneten Werte (über UART o.ä.) mitloggen. Dann 
siehst Du genau, was gemessen und berechnet wird.
Display wird nicht viel helfen, es sei denn, Du kannst 1000 Werte pro 
Sekunde ablesen.

Wichtig: wer mißt mißt Mist! Eine Aussage kannst Du nur machen, wenn Du 
Dir sicher bist, daß Du alle Meß-/Rechenwerte mitgeloggt hast. Ein 
Zeitstempel kann nicht schaden.

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.