Forum: Mikrocontroller und Digitale Elektronik Encoder Winkel ?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Michael H. (h_m)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte mit einem Encoder 250 Teilungen der nach dem Auswerten 1000 
Zählimpulse hat mir den Winkel Seriell auf meinem Hterm anzeigen lassen.

dazu muß ich 1000/360= 2.777 Grad Pro Schritt Rechnen richtig ?

jetzt habe ich aber bei der Ausgabe ein Problem, das der Wert überhaupt 
nicht stimmt.

das mit Sicherheit an meiner Schreibweise für die Ausgabe liegt. Da hab 
ich natürlich schon verschiedene Varianten ausprobiert, aber aktuell 
habe ich es so, da wird mir nur ein ? \r\n angezeigt
1
  printf("\r\n %f", enc_delta/1000*2.77   );
1
volatile float  enc_delta;


Wie kann ich das richtig ausgeben das ich mir den winkel von 0-360 Grad 
ausgeben kann ?

kann mir das Bitte jemand zeigen, ich habe auch ein Buch wo das mit den 
Ausgabeformaten steht, mit % i, d, f, c usw. aber Irgenwie steig ich da 
gerade nicht durch.


Grüsse Huber

von Barrex (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Du hast den Dreisatz einfach nur falsch angewendet.

Überlege Dir, ob dein zu berechnender Winkel zu 360 oder 1000 gehört!
Überlege Dir, ob Dein enc_delta zu 360 oder 1000 gehört!

Wenn Dir das klar ist, erstelle die passende Verhältnisgleichung.

von Barrex (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Im übrigen hilft es bei der Erstellung von Gleichungen die 
physikalischen Einheiten mitzuführen. Kommt die richtige einheit raus, 
ist die Wahrscheinlichleit hoch das die Gleichung stimmt. Passt die 
Einheit des Ergebnisses nicht, stimmt die Gleichung nicht.

von Michael H. (h_m)


Bewertung
0 lesenswert
nicht lesenswert
also dasmit der berechnug bekomme ich dann schon hin, mein Problem ist 
die richtige Ausgabe.

ich dachte, wenn ich mit komma Zahelen rechne, dann muss ich die 
Variable in float benennen und bei der Ausgabe auch auf float achten 
"%f" da kommt nur ein ? raus und %d kommt nur irgendwas mit +30000 und - 
30000 am terminal



1
 #define F_CPU 16000000UL
2
 #define BAUD  9600UL
3
 
4
 #include <util/delay.h>
5
 #include <string.h>
6
 #include <stdlib.h>
7
 #include <stdio.h>
8
 #include <ctype.h>
9
 #include <avr/io.h>
10
 #include <avr/interrupt.h>
11
 #include "serial2.h"
12
 
13
 FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); // Wandelt putchar und getchar in printf um
14
15
// target: ATmega328
16
//------------------------------------------------------------------------
17
18
 #define XTAL        16e6             // 16MHz
19
20
#define PHASE_A     (PINB & 1<<PB0)
21
#define PHASE_B     (PINB & 1<<PB1)
22
23
#define LEDS_DDR    DDRC
24
#define LEDS        PORTC           // LEDs against VCC
25
26
27
volatile float  enc_delta;         // Variable Zählimpuls
28
static int8_t last;
29
30
31
void encode_init( void )
32
{
33
  int8_t new;
34
35
  new = 0;
36
  if( PHASE_A ) new = 3;
37
  if( PHASE_B ) new ^= 1;       // convert gray to binary
38
  last = new;                   // power on state
39
  enc_delta = 0;
40
  TCCR1B = (1<<WGM12) | (1<<CS10) ;   // CTC, prescaler 1
41
  OCR1A = (uint8_t)(XTAL/ 1.0 * 1e-4 - 0.5);   // 1ms
42
  TIMSK1 |= 1<<OCIE1A;
43
}
44
45
46
ISR( TIMER1_COMPA_vect )            // 1ms for manual movement
47
{
48
  int8_t new, diff;
49
50
  new = 0;
51
  if( PHASE_A ) new = 3;
52
  if( PHASE_B ) new ^= 1;          // convert gray to binary
53
  diff = last - new;               // difference last - new
54
  if( diff & 1 ) {                 // bit 0 = value (1)
55
    last = new;                    // store new as next last
56
    enc_delta += (diff & 2) - 1;   // bit 1 = direction (+/-)
57
  }
58
}
59
60
61
int8_t encode_read1( void )         // read single step encoders
62
{
63
  int8_t val;
64
65
  cli();
66
  val = enc_delta;
67
  enc_delta = 0;
68
  sei();
69
  return val;                   // counts since last call
70
}
71
72
73
74
75
int main( void )
76
{
77
   uart_init(F_CPU, BAUD);
78
   stdout = stdin = &mystdout;
79
   
80
   
81
  int32_t val = 0;
82
83
  LEDS_DDR = 0xFF;
84
  encode_init();
85
  sei();
86
  
87
       while (1)
88
       {
89
        
90
         printf("\r\n %d", enc_delta*0.36   );
91
         //_delay_ms(10);
92
        
93
       }
94
      
95
96
  for(;;)
97
  {
98
    val += encode_read1();          // read a single step encoder
99
    LEDS = val;
100
  }
101
    
102
  
103
}

von Hauke Haien (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Michael H. schrieb:
> also dasmit der berechnug bekomme ich dann schon hin, mein Problem ist
> die richtige Ausgabe.

Das sieht hier aber ganz anders aus.
Der Encoder gibt dir 1000 Inkremente / 360°.
Ein Inkrement entspricht demnach einem Tausendstel von 
dreihundertsechzig grad.
Klingelts!?

von Michael H. (h_m)


Bewertung
0 lesenswert
nicht lesenswert
Hauke Haien schrieb:
> Michael H. schrieb:
>> also dasmit der berechnug bekomme ich dann schon hin, mein Problem ist
>> die richtige Ausgabe.
>
> Das sieht hier aber ganz anders aus.
> Der Encoder gibt dir 1000 Inkremente / 360°.
> Ein Inkrement entspricht demnach einem Tausendstel von
> dreihundertsechzig grad.
> Klingelts!?
1
printf("\r\n %d", enc_delta*0.36   );
1
printf("\r\n %i", enc_delta*0.36   );
1
printf("\r\n %f", enc_delta*0.36   );
1
printf("\r\n %c", enc_delta*0.36   );
1
printf("\r\n %o", enc_delta*0.36   );
1
printf("\r\n %s", enc_delta*0.36   );

1000*0.36= 360

aber ich bekomme ja das richtige Ausgabeformat nicht hin, das es mir den 
Wert richtig im Terminal anzeigt, egal was ich von oben genannten 
probiere bekomme ich irgend etwas auf dem Terminal angezeigt aber keine 
komma Zahl.

von Barrex (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ausgabe float variable:

float value = 0.0;
printf("value = %f\n",value);

Das stimmmt schon so. Allerdings ist die Frage ob die Verwendung von %f 
im printf in den AVR Bibliotheken überhaupt realisiert ist. Denn die 
Verwendung von float kostet ziemlich viel Ressourcen. Das muss dir aber 
ein AVR Experte beantworten.

In der Regel ist es besser rein mit Integer-Variablen zu arbeiten, 
sprich also mit Festkomma Zahlen. und dafür dann eine eigene 
Ausgabefunktion zu schreiben.

von Barrex (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Es kann sogar sein, dass Du solche ausgabe Funktionen wie printf() 
sowieso allein implementieren musst. Eventuell sind sie zwar bekannt, 
und könnten verwendet werden aber die eigentliche Implementation fehlt 
ganz.

Denn bezogen auf den eigentlichen Mikrocontroller IC ist ja ohne 
konkrete Anwendung und Schaltung ja erstmal nicht klar, wo solche 
Ausgaben überhaupt erfolgen sollen.

Aber wie oben geschrieben, das ist ein Thema für einen AVR Experten der 
den Compiler genau kennt.

von Michael H. (h_m)


Bewertung
0 lesenswert
nicht lesenswert
hier ist mal meine Serial.h dateies muss doch möglich sein den wert 
ausgeben zu können.

weil oben gennnant integer (Ganzzahl) mit festkomma Zahlen. Ich will 
nicht float unbedingt hernehmen, aber ich dachte float ist di einzige 
Bezeichnung mit der ich kommastellen darstellen kann

1
/ * serial2.h*/
2
3
4
#ifdef UCSR0A
5
6
//Initialisiert UART gegebener Oszillatorfrequenz und Baudrate
7
void uart_init(long Oszi, long Baud)
8
{ 
9
  if ((Oszi / 16L / Baud - 1) > 30)
10
  {    
11
    UBRR0L = (unsigned char)(Oszi /16L / Baud - 1);
12
    UBRR0H = (unsigned char)((Oszi / 16L / Baud - 1) >> 8);
13
    UCSR0A = 0; 
14
  }
15
  else
16
  {
17
    //Falls Teilerwert zu klein => Rundungsfehler
18
    //Daher doppelte Rate waehlen  
19
    UBRR0L = (unsigned char)(Oszi / 8L / Baud - 1);
20
    UBRR0H = (unsigned char)((Oszi / 8L / Baud - 1) >> 8);
21
    UCSR0A = (1 << U2X0);
22
  }
23
   
24
  UCSR0B = UCSR0B | (1 << TXEN0) | (1 << RXEN0);
25
  UCSR0C = UCSR0C | (1 << UMSEL01) | (1 << UCSZ01) | 
26
          (1 << UCSZ00);  
27
}
28
    
29
//Sendet 1 Byte an UART 
30
int uart_putchar(char data, FILE* stream) 
31
{ 
32
  while (!(UCSR0A & (1 << UDRE0)));
33
  UDR0 = (char)data;
34
  return 0;
35
} 
36
37
//Empfaengt 1 Byte vom UART
38
static int uart_getchar(FILE *STREAM) 
39
{ 
40
  while (!(UCSR0A & (1 << RXC0))); 
41
  return (UDR0); 
42
} 
43
 
44
#else
45
46
//Initialisiert UART gegebner Oszillatorfrequenz und Baudrate
47
void uart_init(long Oszi, long Baud) 
48
{ 
49
  if ((Oszi / 16L / Baud - 1) > 30)
50
  {
51
    UBRRL = (unsigned char)(Oszi / 16L / Baud - 1);
52
    UBRRH = (unsigned char)((Oszi / 16L / Baud - 1) >> 8);
53
    UCSRA = 0x00;  
54
  }
55
  else
56
  {
57
    //Falls Teilerwert zu klein => Rundungsfehler
58
    //Daher doppelte Rate waehlen
59
    UBRRL = (unsigned char)(Oszi / 8L / Baud - 1);
60
    UBRRH = (unsigned char)((Oszi /8L / Baud - 1) >> 8);
61
    UCSRA = (1 << U2X);
62
  }
63
  
64
  UCSRB = UCSRB | (1 << TXEN) | (1 << RXEN); //RX TX Enable
65
  //Bit Mode
66
  CSRC =  UCSRC | (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
67
}
68
    
69
//Sendet 1 Byte an UART
70
int uart_putchar(char data, FILE* stream)
71
{
72
  while (!(UCSRA & (1 << UDRE)));
73
  UDR = (char)data;
74
  return 0;
75
}   
76
77
//Empfaengt 1 Byte vom UART
78
int uart_getchar(FILE* stream) 
79
{ 
80
  while (!(UCSRA & (1 << RXC))); 
81
  return (UDR); 
82
}
83
 
84
#endif

von Yalu X. (yalu) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
Michael H. schrieb:
> "%f" da kommt nur ein ? raus

Dann musst du das hier lesen und befolgen:

  http://nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

1
Since the full implementation of all the mentioned features becomes
2
fairly large, three different flavours of vfprintf() can be selected
3
using linker options.
4
...

von Frickelfritze (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Bevor das hier zur float-Orgie ausartet:

#include<stdio.h>
1
int main() 
2
{
3
   unsigned int hundertselgrad = 18234;
4
   while (1)
5
   {
6
    printf("Winkel ist  %u.%02u Grad\r\n", hundertselgrad/100, hundertselgrad%100);
7
    //delay_ms(1000);
8
    hundertselgrad += 456;
9
   }
10
   
11
}

von Michael H. (h_m)


Bewertung
0 lesenswert
nicht lesenswert
Frickelfritze schrieb:
> int main()
> {
>    unsigned int hundertselgrad = 18234;
>    while (1)
>    {
>     printf("Winkel ist  %u.%02u Grad\r\n", hundertselgrad/100,
> hundertselgrad%100);
>     //delay_ms(1000);
>     hundertselgrad += 456;
>    }

Danke, das ist ein Traum. unter welchen Schlagwort kann ich denn das 
noch im Netz finden. alles aber das steht nicht in meinem Buch

von Barrex (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Festkommazahlen ist das Stichwort. :-)

von M. K. (sylaina)


Bewertung
0 lesenswert
nicht lesenswert
Michael H. schrieb:
> aber ich bekomme ja das richtige Ausgabeformat nicht hin, das es mir den
> Wert richtig im Terminal anzeigt, egal was ich von oben genannten
> probiere bekomme ich irgend etwas auf dem Terminal angezeigt aber keine
> komma Zahl.

Das liegt wahrscheinlich an die printf-Geschichte, da muss man was am 
Linker oder so einstellen damit printf auch %f kann. Ich umgehe das nur 
immer mit folgendem Code weshalb ich da nicht genau sagen kann was da im 
Busch ist.
1
...
2
float myFloat = 3.1415;
3
char myValueToSend[7];
4
...
5
dtostrf(myFloat,  // Variable die zum String gewandelt werden soll
6
        6,        // Gesamtzahl der Stellen incl. Komma
7
        4,        // Zahl der Nachkommastellen
8
        myValueToSend); // String-Variable, in die die Wandlung soll
9
printf("Winkel ist ");
10
printf(myValueToSend);
11
printf(" Grad\r\n);
12
...

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.