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.
Lesezeichen