Encoder Winkel ?

OP #5172966
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
Gast #5172991
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.
Gast #5172997
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.
OP #5173025
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
}
Gast #5173034
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!?
OP #5173045
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.
Gast #5173047
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.
Gast #5173063
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.
OP #5173100
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
Gast #5173136
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
}
#5173288
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
...

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