Forum: Mikrocontroller und Digitale Elektronik Encoderwert seriell senden


von Elias B. (bouni)


Lesenswert?

Hi zusammen,

Ich versuche schon seit Stunden einen Encoder auszulesen und dessen Wert 
seriell auf ein terminal zu senden.

Meine Hardware:
Encoder mit ??1000?? Incrementen (Habe leider keine Daten zu dem Teil)
STK500 mit Atmega 8515L und internem Oszilator

Hier mein Code:
(Ist zu großen Teilen aus dem Forum)
1
#ifndef F_CPU
2
#define F_CPU 36860000UL            // Interner Quarz  
3
#endif
4
    
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <stdlib.h>
8
9
#define PHASE_A  (PINC & 1<<PINC6)      // PINC.0
10
#define PHASE_B  (PINC & 1<<PINC7)      // PINC.1
11
12
#define BAUD        9600UL       // Baudrate
13
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)   // Baudrate berechen
14
15
              
16
void uart_init(void)        // USART initialisieren
17
{      
18
    UBRRH = (uint8_t) (UBRR_BAUD>>8);          // Baudrate einstellen
19
    UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
20
21
    UCSRB = (1<<RXEN)|(1<<TXEN);    // Aktivieren von Rx und Tx
22
23
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);   // Einstellen 8,n,1
24
}
25
26
int uart_putc(unsigned char c)      
27
{
28
    while (!(UCSRA & (1<<UDRE)))     // warten bis Senden moeglich
29
    {
30
    }
31
    UDR = c;                            // Zeichen senden
32
    return 0;
33
}
34
35
void uart_puts (char *s)        
36
{
37
    while (*s)
38
    {   
39
        uart_putc(*s);
40
        s++;
41
    }
42
}
43
44
volatile int16_t enc_delta;            // -32768 ... 32767
45
46
int main( void )
47
{
48
  char text[7];                                         // itoa Variable
49
  
50
  uart_init();  
51
  
52
  TCCR0 = 1<<CS00;              //ohne Vorteiler
53
  TIMSK = 1<<TOIE0;              //enable timer interrupt
54
  
55
  DDRB = 0xFF;
56
  
57
  sei();
58
59
  while(1)                  // main loop
60
  {
61
  uart_puts( itoa(enc_delta,text,10) );      //In String gewandelte Tahl über UART senden
62
  PORTB = enc_delta;        // PORT B mit LED#s um den Wert paralell visuell zu sehen
63
  }
64
return 0;
65
}
66
67
// Encoder Code von  Peter Dannegger (leicht abgeändert ISR usw.)
68
ISR (TIMER0_OVF_vect)
69
{
70
  static int16_t enc_last = 0x01;
71
  int16_t i = 0;
72
73
  if( PHASE_A )
74
    i = 1;
75
76
  if( PHASE_B )
77
    i ^= 3;                      // convert gray to binary
78
79
  i -= enc_last;                 // difference new - last
80
81
  if( i & 1 )                    // bit 0 = value (1)
82
   {       
83
    enc_last += i;               // store new as next last
84
    enc_delta += (i & 2) - 1;    // bit 1 = direction (+/-)
85
   }
86
}

Ich hab schon alles probiert und weiß nicht mehr weiter :/

Hardware ist i.o. Die LED's zählen schön hoch wie es sein sollte,
das senden von normalen Strings geht auch ohne Probleme.

Ich hab die Vermutung das das senden vom Interrupt unterbrochen wird, 
kann das sein ??

Bin leider kein Held in C, aber ist ja noch kein Meister vom Himmel 
gefallen :)

Bouni

P.S. Danke schon mal im Voraus

von spess53 (Gast)


Lesenswert?

Hi

>Atmega 8515L und internem Oszilator

solltest du schleunigst ändern. Mit dem bekommst du keine stabile 
Verbindung.

#define F_CPU 36860000UL            // Interner Quarz

Habe zwar nur rudimentäre C-Kenntnisse, das passt aber für mich nicht zu 
der anderen Aussage.

MfG Spess

von Elias B. (bouni)


Lesenswert?

Hi,

spess53 wrote:
> #define F_CPU 36860000UL            // Interner Quarz
>
>.... das passt aber für mich nicht zu
> der anderen Aussage.

Also Ich hab keine Probleme mit dem UART!! der tut tadellos, ich kann 
lange Stringssenden ohne das was nicht/oder verkorkst ankommt !!

Daran kanns also nicht liegen!


Trotzdem Danke für die Antwort

von Elias B. (bouni)


Lesenswert?

Um nochmal auf den Oszillator zu kommen:

Ich hab noch n 14,318180 Mhz hier rm liegen, kann ich den einfach auf 
den Steckplatz vom STK500 stecken ??

Mfg Bouni

von spess53 (Gast)


Lesenswert?

Hi

>kann ich den einfach auf den Steckplatz vom STK500 stecken ??

Ja. Und die Jumper umstecken. Jumperbelegung steht auf der Unterseite 
des STK.

>uart_puts( itoa(enc_delta,text,10) );

Bist du sicher, das itoa einen string als Funktionsergebnis zurück gibt? 
Ich würde 'uart_puts' eher 'text' übergeben.

MfG Spess

von Elias B. (bouni)


Lesenswert?

du meinst also:
1
...
2
 while(1)                  // main loop
3
  {
4
  itoa(enc_delta,text,10);
5
  uart_puts(text);      //In String gewandelte Tahl über UART senden
6
  PORTB = enc_delta;        // PORT B mit LED#s um den Wert paralell visuell zu sehen
7
  }
8
...

Werd das morgen mal testen.


Danke für die Hilfe :)

Bouni

von Andreas K. (ergoproxy)


Lesenswert?

Hab mal ne Frage wird die #define F_CPU 36860000UL nicht in Hertz 
angegeben ? Wären das dann nicht 36.860.000 Hz also 38,86 MHz ? Oder 
Spinn ich grade n bischen ?

Gruß ErgoProxy

von Elias B. (bouni)


Lesenswert?

Hi zusammen,


Habs zum laufen gebracht :D
1
#include <avr/io.h>
2
#include <inttypes.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
6
#define F_CPU       3686400UL                               // internal clock 3.686Mhz
7
8
#define BAUD        9600UL                                  // Baudrate
9
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)                 // Baudrate berechen
10
11
12
#define PHASE_A  (PINC & 1<<PINC6)                          // PINC.6 -> A
13
#define PHASE_B  (PINC & 1<<PINC7)                          // PINC.7 -> B
14
15
volatile uint16_t enc_delta;                                // -32768 ... 32767
16
17
void uart_init(void)                                        // USART initialisieren
18
{
19
    UBRRH = (uint8_t) (UBRR_BAUD>>8);                       // Baudrate einstellen
20
    UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
21
    UCSRB = (1<<RXEN)|(1<<TXEN);                            // Aktivieren von receiver und transmitter
22
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);               // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
23
}
24
25
int uart_putc(unsigned char c)                              // Einzelnes Zeichen über UART senden
26
{
27
    while (!(UCSRA & (1<<UDRE)))                            // Warten bis Senden möglich ist
28
    {
29
    }
30
    UDR = c;                                                // Zeichen senden
31
    return 0;
32
}
33
34
void uart_puts (char *s)                                    // String über UART senden
35
{
36
    while (*s)                                              // Senden bis zum Stringende
37
    {
38
        uart_putc(*s);                                      // Einzelnes Zeichen senden
39
        s++;                                                // Pointer erhöhen
40
    }
41
}
42
43
int main(void)                                              // MAIN
44
{
45
    uart_init();                                            // UART initialisieren
46
    uart_puts("Encoder Wert");                              // Test String senden
47
48
    volatile uint16_t last_enc_delta;                       // Variable für den letzten Encoder Wert
49
50
    TCCR0 = 1<<CS00;                                        // Timer ohne Vorteiler
51
    TIMSK = 1<<TOIE0;                                        // Timer interrupt aktivieren
52
    
53
    sei();                                                  // Globale Interrupts aktivieren
54
    
55
    while (1)                                               // Für immer
56
    {
57
    if(last_enc_delta != enc_delta)                         // Wenn sich der Zähler geändert hat
58
      {
59
      char text[7];                            
60
      itoa(enc_delta,text,10);                              // Zählerwert in String wandeln
61
      uart_puts(text);                                      // String senden
62
      uart_putc('\n');                                      // Neue Zeile
63
      last_enc_delta = enc_delta;                           // Gesendeten Wert als aktuellen eintragen
64
      }
65
    }
66
return 0;                                                   // Wird nie erreicht
67
}
68
/* ENCODER CODE von Peter Dannegger */
69
70
ISR (TIMER0_OVF_vect)                                       // Timer Interrupt
71
{
72
  static int16_t enc_last = 0x01;
73
  int16_t i = 0;
74
75
  if( PHASE_A )
76
    i = 1;
77
78
  if( PHASE_B )
79
    i ^= 3;                                                 // convert gray to binary
80
81
  i -= enc_last;                                            // difference new - last
82
83
  if( i & 1 )                                               // bit 0 = value (1)
84
   {       
85
    enc_last += i;                                          // store new as next last
86
    enc_delta += (i & 2) - 1;                               // bit 1 = direction (+/-)
87
   }
88
}

@ErgoProxy

War in der Tat n Schreibfehler :)



Bouni

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.