Forum: Mikrocontroller und Digitale Elektronik Servo Einstellung und Anzeige in Grad


von Ein Neuling (Gast)


Lesenswert?

Hallo
Habe gerade einen Servotester mit Timer programmiert:
1
void timer_init()
2
  {            // Timer 1 16 Bit konfigurieren
3
  TCCR1B = (1<<WGM11)|(1<<CS11);//|(1<<CS10);  // CTC Modus, Prescaler 8
4
  TIMSK1|=(1<<OCIE1A)|(1<<OCIE1B);      // Interrupt erlauben
5
  OCR1A=3999;    // Timer 1 Register A
6
  OCR1B=1220;    // Timer 1 Register B  Mittelstellung
7
  }
8
9
// Impuls starten 
10
ISR(TIMER1_COMPA_vect)
11
  {
12
  PORTA &=~(1<<PINA1);
13
  }
14
  
15
  // Impuls stoppen
16
ISR(TIMER1_COMPB_vect)
17
  {
18
    PORTA |=(1<<PINA1);
19
  }
20
21
if ( !(PINA & (1<<PINA7)) )
22
      {        
23
      if(OCR1B < 3999);
24
        {
25
        OCR1B = OCR1B + 10;
26
        }
27
      if(OCR1B>=2870)
28
        {
29
        OCR1B = 2870;
30
        }     
31
      _delay_ms(1);
32
      }  
33
34
if ( !(PINA & (1<<PINA3)) )
35
      {        
36
      lcd_printlc(3,1,"Ta 1 - dreht links ");  
37
      PORTC |= (1<<PINC5);
38
      PORTC &= ~(1<<PINC6);
39
      if(OCR1B > 80);
40
        {
41
        OCR1B = OCR1B - 10;
42
        }
43
      }  
44
45
 itoa(OCR1B,wert,10);        // Berechne wert von OCR1B
46
     lcd_printlc(4,1,"OCR1B=");  
47
     lcd_printlc(4,7,"             ");  
48
     lcd_printlc(4,8,wert);        // Anzeige wert 
49
     _delay_ms(30);
Läuft mit Timer 1 16 Bit CTC Prescaler 8 auf 20ms. Mit den beiden Tasten 
kann ich links oder rechts drehen. Funktioniert super. Mit itoa wird 
OCR1B angezeigt. Die Begrenzung nach oben funktioniert auch, wird aber 
noch verbessert.
Das Problem ist itoa. Als Wert für OCR1B kann doch eigentlich nur ein 
positiver Wert angezeigt werden. Bekomme aber Werte von -400 bis +2870.
Möchte auch den Wert in Grad von 0 bis 180° anzeigen lassen. Positver 
Winkel von -410?
Wie kann ich am besten in Grad umrechnen? Hat jemand eine Idee dazu?
LG P.

: Verschoben durch Moderator
von FOp (Gast)


Lesenswert?

Dein itoa scheint den Eingabewert als 16-bittig, vorzeichenbehaftet 
anzusehen. Pech.

Vielleicht gibt es ja auch ein ltoa. Dann nimm das.

Wenn nicht musst Du das ganz schwere Geschütz snprintf auffahren oder 
selber was stricken.

Sollte der Zusammenhang zwischen Tastverhältnis und Winkel linear sein, 
hilft entweder die Funktion map() beim Arduino oder das Kapitel "lineare 
Gleichungen" im Mathebuch.

Aber auch dabei immer darauf achten, dass alle Variablen genügend Platz 
bieten.

von Oliver S. (oliverso)


Lesenswert?

Ein Neuling schrieb:
> Das Problem ist itoa. Als Wert für OCR1B kann doch eigentlich nur ein
> positiver Wert angezeigt werden.

Das unterscheidet das i vom u. Also nimm auch utoa.

Oliver

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ein Neuling schrieb:
> Läuft mit Timer 1 16 Bit CTC Prescaler 8 auf 20ms.
Bei mir läuft dieser Code nirgends. Du kannst einfach genaus die 
Sourcedatei anhängen, die den Fehler zeigt und dann noch sagen, auf 
welcher Plattform mit welchem compiler du das Problem beobachtest (ich 
weiß schon: man könnte sich das auch erraten, aber ich bin da grade zu 
faul dazu...).

> Als Wert für OCR1B kann doch eigentlich nur ein positiver Wert angezeigt
> werden. Als Wert für OCR1B kann doch eigentlich nur ein positiver Wert
> angezeigt werden.
Warum? Wo soll der gezeigte Code OCR1B nach unten begrenzen?

> Bekomme aber Werte von -400 bis +2870. ...
> Positver Winkel von -410?
Wie kommst du da auf -410, wenn nur Werte von -400 bis ... angezeigt 
werden?


BTW: das ist schon irgendwie planlos:
1
      if(OCR1B < 3999);
2
        {
3
        OCR1B = OCR1B + 10;
4
        }
5
6
      if(OCR1B>=2870)
7
        {
8
        OCR1B = 2870;
9
        }


Ein Neuling schrieb:
> Werte von -400 bis +2870.
> Möchte auch den Wert in Grad von 0 bis 180° anzeigen lassen.
Stichwort "lineare Interpolation": wenn ein wert von -400 einem Winkel 
von 0° entspricht und +2870 einem Winkel von 180°, welcher Winkel 
entspricht dann einem wert von 1190?

Ein Tipp: es wird einfacher, wenn du erst mal die Baustelle mit den -400 
aufräumst.

: Bearbeitet durch Moderator
von Ein Neuling (Gast)


Lesenswert?

Lothar M. schrieb:
> Ein Tipp: es wird einfacher, wenn du erst mal die Baustelle mit den -400
> aufräumst.
Das ist mir absolut klar.
Arbeite mit C am Atmega 128, AVR Studio 7

Lothar M. schrieb:
> Stichwort "lineare Interpolation": wenn ein wert von -400 einem Winkel
> von 0° entspricht und +2870 einem Winkel von 180°, welcher Winkel
> entspricht dann einem wert von 1190?

OCR1B beginnt ja mit 0, damit ist -400 falsch

Lothar M. schrieb:
> BTW: das ist schon irgendwie planlos:

Das soll noch vereinfacht werden, steht auch drin, muss erst die -400 
loswerden

von FOp (Gast)


Lesenswert?

Na -400 ist in eigentlich 65136. Man muss nur die Bits auch so 
interpretieren wie es der Timer macht.

von Ein Neuling (Gast)


Lesenswert?

FOp schrieb:
> Na -400 ist in eigentlich 65136. Man muss nur die Bits auch so
> interpretieren wie es der Timer macht.

Stimmt. Wenn ich utoa verwende erscheint zwar kein - mehr, aber dafür 
655516 und kleiner.
Wie kann das sein wenn OCR1B max 0 sein kann. Bei 0 hat der Servo aber 
sein Ende noch nicht erreicht, erst bei 65026?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ein Neuling schrieb:
> OCR1B beginnt ja mit 0, damit ist -400 falsch
Mag sein, dass du das so empfindest. Trotzdem steht da offenbar -400 
(oder -410) drin. Wie kommt es also dazu? Wer außer dir manipuliert da 
im OCR1B herum?

Ein Neuling schrieb:
> Wie kann das sein wenn OCR1B max 0 sein kann.
Ich denke, du willst, dass es "minimal 0" sein können. Aber wie gesagt: 
du hast das nirgends begrenzt.

> Wie kann das sein
Stichwort: Zweierkomplement.
Du beginnst bei 0 (0x0000) und ziehst 10 (0x000A) ab, dann kommen 
unsigned 65526 (0xFFF6) heraus. Das machst du dann noch weitere 39 
mal...

: Bearbeitet durch Moderator
von FOp (Gast)


Lesenswert?

Ich habe nochmal über den Code geschaut. In der Tat sollte unter 
normalen Umständen der Wert von 80 bis 2870 sein. Und das passt alles in 
vorzeichenbehaftete 16 Bit.

OCR1BH und OCR1BL sind im Datenblatt auch als R/W gekennzeichnet, also 
sollte man den Wert auch zurück lesen können, wenn man die richtige 
Reihenfolge einhält. Die sollte aber der C-Compiler kennen und beachten.

Womit Du allerdings was über den Haufen schiessen kannst, ist in einem 
Interrupt auf OCR1xx, ICR1x oder TCNT1x zuzugreifen. Wenn ich mal davon 
ausgehe, dass der Code, den Du hier ausserhalb jeglicher Funktion 
gepostet hast, Teil des Hauptprogramms ist.

Wann kommen den die negativen Zahlen ? Unterhalb von 80, oberhalb von 
2870 oder immer mal irgendwo anders mittendrin ?

von Uwe K. (ukhl)


Lesenswert?

Versuche mal die Register OCR1B (es sind zwei) vor dem utoa() Aufruf in 
einer Variable zu schreiben.
1
uint16_t ctc = 0;
2
ctc = OCR1B;
3
utoa(ctc,wert,10);        // Berechne wert von OCR1B

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.