mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Encoderwert seriell senden


Autor: Elias B. (bouni)
Datum:

Bewertung
0 lesenswert
nicht 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)

#ifndef F_CPU
#define F_CPU 36860000UL            // Interner Quarz  
#endif
    
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#define PHASE_A  (PINC & 1<<PINC6)      // PINC.0
#define PHASE_B  (PINC & 1<<PINC7)      // PINC.1

#define BAUD        9600UL       // Baudrate
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)   // Baudrate berechen

              
void uart_init(void)        // USART initialisieren
{      
    UBRRH = (uint8_t) (UBRR_BAUD>>8);          // Baudrate einstellen
    UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);

    UCSRB = (1<<RXEN)|(1<<TXEN);    // Aktivieren von Rx und Tx

    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);   // Einstellen 8,n,1
}

int uart_putc(unsigned char c)      
{
    while (!(UCSRA & (1<<UDRE)))     // warten bis Senden moeglich
    {
    }
    UDR = c;                            // Zeichen senden
    return 0;
}

void uart_puts (char *s)        
{
    while (*s)
    {   
        uart_putc(*s);
        s++;
    }
}

volatile int16_t enc_delta;            // -32768 ... 32767

int main( void )
{
  char text[7];                                         // itoa Variable
  
  uart_init();  
  
  TCCR0 = 1<<CS00;              //ohne Vorteiler
  TIMSK = 1<<TOIE0;              //enable timer interrupt
  
  DDRB = 0xFF;
  
  sei();

  while(1)                  // main loop
  {
  uart_puts( itoa(enc_delta,text,10) );      //In String gewandelte Tahl über UART senden
  PORTB = enc_delta;        // PORT B mit LED#s um den Wert paralell visuell zu sehen
  }
return 0;
}

// Encoder Code von  Peter Dannegger (leicht abgeändert ISR usw.)
ISR (TIMER0_OVF_vect)
{
  static int16_t enc_last = 0x01;
  int16_t i = 0;

  if( PHASE_A )
    i = 1;

  if( PHASE_B )
    i ^= 3;                      // convert gray to binary

  i -= enc_last;                 // difference new - last

  if( i & 1 )                    // bit 0 = value (1)
   {       
    enc_last += i;               // store new as next last
    enc_delta += (i & 2) - 1;    // bit 1 = direction (+/-)
   }
}


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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Elias B. (bouni)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Elias B. (bouni)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Elias B. (bouni)
Datum:

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

Werd das morgen mal testen.


Danke für die Hilfe :)

Bouni

Autor: Andreas K. (ergoproxy)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Elias B. (bouni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi zusammen,


Habs zum laufen gebracht :D
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define F_CPU       3686400UL                               // internal clock 3.686Mhz

#define BAUD        9600UL                                  // Baudrate
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)                 // Baudrate berechen


#define PHASE_A  (PINC & 1<<PINC6)                          // PINC.6 -> A
#define PHASE_B  (PINC & 1<<PINC7)                          // PINC.7 -> B

volatile uint16_t enc_delta;                                // -32768 ... 32767

void uart_init(void)                                        // USART initialisieren
{
    UBRRH = (uint8_t) (UBRR_BAUD>>8);                       // Baudrate einstellen
    UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
    UCSRB = (1<<RXEN)|(1<<TXEN);                            // Aktivieren von receiver und transmitter
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);               // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
}

int uart_putc(unsigned char c)                              // Einzelnes Zeichen über UART senden
{
    while (!(UCSRA & (1<<UDRE)))                            // Warten bis Senden möglich ist
    {
    }
    UDR = c;                                                // Zeichen senden
    return 0;
}

void uart_puts (char *s)                                    // String über UART senden
{
    while (*s)                                              // Senden bis zum Stringende
    {
        uart_putc(*s);                                      // Einzelnes Zeichen senden
        s++;                                                // Pointer erhöhen
    }
}

int main(void)                                              // MAIN
{
    uart_init();                                            // UART initialisieren
    uart_puts("Encoder Wert");                              // Test String senden

    volatile uint16_t last_enc_delta;                       // Variable für den letzten Encoder Wert

    TCCR0 = 1<<CS00;                                        // Timer ohne Vorteiler
    TIMSK = 1<<TOIE0;                                        // Timer interrupt aktivieren
    
    sei();                                                  // Globale Interrupts aktivieren
    
    while (1)                                               // Für immer
    {
    if(last_enc_delta != enc_delta)                         // Wenn sich der Zähler geändert hat
      {
      char text[7];                            
      itoa(enc_delta,text,10);                              // Zählerwert in String wandeln
      uart_puts(text);                                      // String senden
      uart_putc('\n');                                      // Neue Zeile
      last_enc_delta = enc_delta;                           // Gesendeten Wert als aktuellen eintragen
      }
    }
return 0;                                                   // Wird nie erreicht
}
/* ENCODER CODE von Peter Dannegger */

ISR (TIMER0_OVF_vect)                                       // Timer Interrupt
{
  static int16_t enc_last = 0x01;
  int16_t i = 0;

  if( PHASE_A )
    i = 1;

  if( PHASE_B )
    i ^= 3;                                                 // convert gray to binary

  i -= enc_last;                                            // difference new - last

  if( i & 1 )                                               // bit 0 = value (1)
   {       
    enc_last += i;                                          // store new as next last
    enc_delta += (i & 2) - 1;                               // bit 1 = direction (+/-)
   }
}

@ErgoProxy

War in der Tat n Schreibfehler :)



Bouni

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.