Ritchie
04.03.2012, 11:33
Hallo Zusammen,
ich arbeite derzeit an einer Routine für die Verbesserung des Ausgabewertes des Gyro ADXRS620 (Breakout Board). Derzeit werden nur die Rohwerte betrachtet. Die errechnete Winkeländerung muss ich auch noch einbauen.
Hierfür verwende ich derzeit das RN COntrolboard und den folgenden Quellcode.
Die Funktion des Programmes ist einfach. Ich gebe den Betrag der Spannungsänderung auf die LED aus, um hier eine visuelle Rückmeldung zur Bewegung zu bekommen.
Trotz gleitenden Mittelwert muss ich feststellen, das Bit 0 nicht verwertet werden kann, da es ständig flackert.
Hat jemand die gleichen Erfahrungen gemacht ? Oder jemand eine Idee, wie man das auch noch aus dem Weg räumt.
Ich habe die Ref.-Spannung mit dem Voltmeter gemessen und hier 4.96Volt gemessen, daher der Mittelpunkt bei 528. Der Gyro gibt hier 2,56 Volt raus. Ungenauigkeiten meines Voltmeter habe ich nicht eingerechnet.
/************************************************** ***********************************************
* INCLUDES *
************************************************** ***********************************************/
# define F_CPU 8000000UL
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <string.h>
#include "uart.h"
/************************************************** ************************************************
* General Settings *
************************************************** ************************************************/
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) // Bit set
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) // Bit clear
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) // Bit check
#define ARRAYSIZEVALUES 40
int ValueArray[ARRAYSIZEVALUES];
int NextArrayIndex=0;
int ZeroValue=0;
/************************************************** ************************************************** ***********
* Init of the array for the floating average calculation *
************************************************** ************************************************** ***********/
void initFilterArray(void)
{
int i;
NextArrayIndex=0;
for(i=0;i< ARRAYSIZEVALUES;i++)
{
ValueArray[i]=512; // set up 2.56 Volt
}
}
/************************************************** ************************************************** ***********
* return the floating calculated average value *
************************************************** ************************************************** ***********/
int getAverageValue(void)
{
int Value=0,i;
for(i=0;i<ARRAYSIZEVALUES;i++)
{
Value += ValueArray[i]; // Add the value for sum
}
Value /= ARRAYSIZEVALUES;
return 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
}
int main(void)
{
int result; // Result of the converting
int Value;
unsigned char Buffer;
int ZeroValue;
int i=0;
Board_init();
initFilterArray();
// Set up the pre Scaler for the Input values
// Prescaler 64 (more is not possible with 8Mhz)
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
// 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=528; // 2.56 using 4,96 Reference Voltage
// Jumper UREF is set
while(1)
{
if (ADCSRA & (1<<ADIF)) // Do we have a new finished measurement of values
{ //
result = ADCW; // Get the value of the measurement
Value = (ZeroValue - result);
ValueArray[NextArrayIndex]= Value; // Store value in the next Position
NextArrayIndex++; // Prepare for the next position
if(NextArrayIndex >= ARRAYSIZEVALUES ) // Are we at the end of position
NextArrayIndex=0;
i++;
if( i > 200)
{
Value = getAverageValue();
Buffer = (unsigned char) abs(Value);
PORTC = ~(Buffer);
i=0;
}
ADMUX = 0; // Select the Channel
ADMUX |= (1<<REFS0); // REFS1 = 0 / REFS0 = 1 -> AREF -> 5 Volt
ADCSRA |= (1<<ADIF); // Clear the IF Flag
ADCSRA |= (1<<ADSC); // Start the measurement
}
}
}
Ich muss diese Routine später noch in den eigentlichen Roboter einbauen und hier noch sehen, ob ich zeitlich mir einen Mittelwert über 40 Messwerte erlauben kann.
Da meine Zielmaschine eine 16Mhz Quarz hat, kann ich mir hier einen Vorzähler von 128 erlauben ?
Meine Zielmaschine muss 8 Analogwerte verarbeiten!
Gruss R.
ich arbeite derzeit an einer Routine für die Verbesserung des Ausgabewertes des Gyro ADXRS620 (Breakout Board). Derzeit werden nur die Rohwerte betrachtet. Die errechnete Winkeländerung muss ich auch noch einbauen.
Hierfür verwende ich derzeit das RN COntrolboard und den folgenden Quellcode.
Die Funktion des Programmes ist einfach. Ich gebe den Betrag der Spannungsänderung auf die LED aus, um hier eine visuelle Rückmeldung zur Bewegung zu bekommen.
Trotz gleitenden Mittelwert muss ich feststellen, das Bit 0 nicht verwertet werden kann, da es ständig flackert.
Hat jemand die gleichen Erfahrungen gemacht ? Oder jemand eine Idee, wie man das auch noch aus dem Weg räumt.
Ich habe die Ref.-Spannung mit dem Voltmeter gemessen und hier 4.96Volt gemessen, daher der Mittelpunkt bei 528. Der Gyro gibt hier 2,56 Volt raus. Ungenauigkeiten meines Voltmeter habe ich nicht eingerechnet.
/************************************************** ***********************************************
* INCLUDES *
************************************************** ***********************************************/
# define F_CPU 8000000UL
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <string.h>
#include "uart.h"
/************************************************** ************************************************
* General Settings *
************************************************** ************************************************/
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) // Bit set
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) // Bit clear
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) // Bit check
#define ARRAYSIZEVALUES 40
int ValueArray[ARRAYSIZEVALUES];
int NextArrayIndex=0;
int ZeroValue=0;
/************************************************** ************************************************** ***********
* Init of the array for the floating average calculation *
************************************************** ************************************************** ***********/
void initFilterArray(void)
{
int i;
NextArrayIndex=0;
for(i=0;i< ARRAYSIZEVALUES;i++)
{
ValueArray[i]=512; // set up 2.56 Volt
}
}
/************************************************** ************************************************** ***********
* return the floating calculated average value *
************************************************** ************************************************** ***********/
int getAverageValue(void)
{
int Value=0,i;
for(i=0;i<ARRAYSIZEVALUES;i++)
{
Value += ValueArray[i]; // Add the value for sum
}
Value /= ARRAYSIZEVALUES;
return 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
}
int main(void)
{
int result; // Result of the converting
int Value;
unsigned char Buffer;
int ZeroValue;
int i=0;
Board_init();
initFilterArray();
// Set up the pre Scaler for the Input values
// Prescaler 64 (more is not possible with 8Mhz)
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
// 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=528; // 2.56 using 4,96 Reference Voltage
// Jumper UREF is set
while(1)
{
if (ADCSRA & (1<<ADIF)) // Do we have a new finished measurement of values
{ //
result = ADCW; // Get the value of the measurement
Value = (ZeroValue - result);
ValueArray[NextArrayIndex]= Value; // Store value in the next Position
NextArrayIndex++; // Prepare for the next position
if(NextArrayIndex >= ARRAYSIZEVALUES ) // Are we at the end of position
NextArrayIndex=0;
i++;
if( i > 200)
{
Value = getAverageValue();
Buffer = (unsigned char) abs(Value);
PORTC = ~(Buffer);
i=0;
}
ADMUX = 0; // Select the Channel
ADMUX |= (1<<REFS0); // REFS1 = 0 / REFS0 = 1 -> AREF -> 5 Volt
ADCSRA |= (1<<ADIF); // Clear the IF Flag
ADCSRA |= (1<<ADSC); // Start the measurement
}
}
}
Ich muss diese Routine später noch in den eigentlichen Roboter einbauen und hier noch sehen, ob ich zeitlich mir einen Mittelwert über 40 Messwerte erlauben kann.
Da meine Zielmaschine eine 16Mhz Quarz hat, kann ich mir hier einen Vorzähler von 128 erlauben ?
Meine Zielmaschine muss 8 Analogwerte verarbeiten!
Gruss R.