Hallo Zusammen,

hier jetzt das kleine Testprogram mit Winkelanzeige via LED Anzeige in der Version 1.

Das Programm zeigt jetzt den Winkel in Grad an ( Nun ja, nur bis 255 Grad korrekt.)

Ich muss noch sehen, wie stark der Schleppfehler wird.

- Programm für RN Control mit 16Mhz

Code:
/*************************************************************************************************
 * INCLUDES                                                                                      *
 *************************************************************************************************/

# define F_CPU 16000000UL

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <math.h>

#include "uart.h"

/**************************************************************************************************
 *         Generel setting                                                               *
 **************************************************************************************************/

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))             // Bit Set
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))         // Bit reset
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))             // Bit Check


#define        ARRAYSIZEVALUES                40
int            ValueArray[ARRAYSIZEVALUES];
int            NextArrayIndex=0;
int            ZeroValue=0;
float        Angle=0;

volatile    unsigned    int            m_Status;
volatile                char        m_TimerCounter=0;        // Time value 0...100 * 10ms-> 1 sec.


/***************************************************************************************************************
 *  Init of the array for the floating average calculation                                                    *
 ***************************************************************************************************************/
void        initFilterArray(void)
{
int        i;

    NextArrayIndex=0;
    for(i=0;i< ARRAYSIZEVALUES;i++)
        {
        ValueArray[i]=ZeroValue;                        // set up 2.56 Volt
        }
}

/***************************************************************************************************************
 *            return the floating calculated average value                                                    *
 ***************************************************************************************************************/

int            getAverageValue(void)
{
long        Value=0,i;

    for(i=0;i<ARRAYSIZEVALUES;i++)
        {
        Value += ValueArray[i];                    // Add the value for sum
        }

    Value /= 4; 

    return    (int) Value;
}
/***************************************************************************************************************
 *  Init of the Board                                                                             *
 ***************************************************************************************************************/
void Board_init(void)
{
        
 /* Ports initialisieren */
   DDRA = 0x00;                                                    // Port A: All as Analoh Input
   DDRC = 0xFF;                                                    // Port C: Bit 0... 5, 6 and 7 as Output

   PORTA = 0x0;                                                    // Port A: without Pull-Up
   PORTC = 0xFF;                                                // Port C: with Pull ups for the LED

                                                                // set up the timer 0
    TCCR0 = (1<<CS02) | (1<<CS00);                                // Pre-saler of 1024    
                                                                // Set up the interrupt for timer 0, overflow
    TIMSK |= (1<<TOIE0);                                        // Activate the Interrupt "overflow"
}


int main(void)
{
int                Value,LastDiff=0,Diff;
float            AngleChangeInDegree,AngleChangeInRad;
float            AngleChangeInMinutes;
unsigned char    Buffer;

    cli ();                                                // Clear any interrupt
    Board_init();
    PORTC = 0xff;                                        // Clear the Port 
    sei();
    // Set up the pre Scaler for the Input values
    // Prescaler 128
    ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);     
    
    // We are starting with channel zero
    ADMUX = 0;
    ADMUX |= (1<<REFS0);                                // REFS1 = 0 / REFS0 = 1 -> AREF -> 5 Volt
    ADCSRA |= (1<<ADSC);                                // Start the measurement

    ZeroValue=5285;                                        // 2.56 using 4,96 Reference Voltage ( + 5 -> rounding)
    initFilterArray();

    while(1)
    {
    if (ADCSRA & (1<<ADIF))                                // Do we have a new finished measurement of values    
        {                                                // 
        ValueArray[NextArrayIndex]=  ADCW;                // Store value in the next Position
        NextArrayIndex = (NextArrayIndex + 1) % ARRAYSIZEVALUES;
        ADMUX = 0;                                        // Select the Channel
        ADCSRA |= (1<<ADIF);                            // Clear the IF Flag
        ADCSRA |= (1<<ADSC);                            // Start the measurement
        }
        
    if((m_Status & 1))                                    // Do we have to control the motor speed
        {
        m_Status=0;                                        // Clear the request of the calculation
        Value = getAverageValue();                        // get the difference value
        Diff = ZeroValue - Value;                        // get the difference of the change
        if( Diff > 20 || Diff < -20 )                    // do we have a real change 
            {                                            // ->  +-300° (5,23598775rad)  -> per second
                                                        // ->  +-30°  (0,523598775rad) per 100ms
                                                        // ->  +-180 angular minute  per 10ms
            AngleChangeInMinutes=((float)((Diff+LastDiff) / 20 ) * 0.3515625);
            AngleChangeInDegree    = AngleChangeInMinutes / 60.0;
            AngleChangeInRad    = (AngleChangeInDegree * M_PI) / 180.0;
            Angle += (AngleChangeInDegree);

            if( Angle < 0.0 )                            // Limit Range (only 8 bits)
                Angle=360.0;
            if( Angle > 360.0 )
                Angle=0.0;
                
            LastDiff=Diff;
            }
        else
            LastDiff=0;                                    // No difference found
        
        Buffer = (unsigned char) Angle;                    // Convert Angle to the LED format
        PORTC = ~(Buffer);                                // Output inverted         
        }
    }
}

SIGNAL (SIG_OVERFLOW0)                                     // Interrupt Overflow Timer T0
{
    m_TimerCounter++;
    SETBIT(m_Status,0);                                    // Calculate the angle speed            
    TCNT0 = 99;                                            // restart the time again
}

Hier sind mit Sicherheit noch Rundsfehler (Aufaddieren der Fehler) enthalten. Bin für Ideen offen.

Gruss R.