PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Drehzahlmessung, Display kann nur bis ca 620rpm anzeigen



Teslafan
01.04.2012, 16:35
Servus ihr lieben,

Sitz grad an meiner Drehzahlmessung, Drehzahlregelung. Hab das Problem das auf meinem Display nur eine Umdrehungsdrehzahl von 0 bis 620 rpm dargestellt werden kann. Bei allem was drüber geht werden -Zahlen angezeigt und wenn es dann arg schneller wird steht nur noch 0 dar. Woran kann das liegen? Schon mal jemand so nen Fehler gehabt? Datenausgabe über Diplay erfolgt via String.

Gruß Andi

oberallgeier
01.04.2012, 16:51
... Problem das auf meinem Display nur eine Umdrehungsdrehzahl von 0 bis 620 rpm ...Na ohne Code, Schaltplan, Bild oder genauer Beschreibung ist das eher ein Aprilscherz. Kann es sein, dass Du den String jedes Mal ausgibst, wenn eine Messung fertig ist? Und bei hohen Drehzahlen kommen die Messwerte möglicherweise schon, bevor der String fertig ausgegeben ist . . .

Aber - besser gehts nicht, weil meine Kristallkugel - - -

Teslafan
01.04.2012, 17:45
Sorry lag vorhin als ich das gepostet hab mit dem Tablet im Grünen,hatte da den Code nicht zur Hand.

Hier mal der Code:



//*****Grundeinstellungen

//defines:
#define F_CPU 16000000

//includes:
#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include "lcd-routines.h"

#include <stdlib.h>


char Buffer[20];

int counter = 0;

unsigned short countert0 = 0;

long rpm = 0;




//3***Interrupt Service Routine - Interrupt Eingang INT0****************************************
ISR (INT0_vect)
{
counter++;
}

ISR (TIMER0_COMP_vect)
{

countert0++;

if (countert0 == 100)
{

cli();

countert0 = 0;

rpm = (counter * 60) / 50;

counter = 0;

lcd_clear();

lcd_setcursor( 0, 1 );


itoa( rpm, Buffer, 10 );

lcd_string( Buffer );

sei();
}

}

//main programm:
int main (void)
{

//1***pwm init********************************************** ************************************
TCCR1B |= (1<<CS12); //Prescaler 256

TCCR1A |= (1<<WGM10); //Fast PWM Mode
TCCR1B |= (1<<WGM12);

TCCR1A |= (1<<COM1A1) | (1<<COM1B1) ;

OCR1A = 0; //PWM Start-Wert

DDRD |= (1<< PD5); //PWM aktivieren


//2***Switch init********************************************** *********************************
DDRA = 0b00000000; //Setze Port A auf Eingang

PORTA = 0b00000000; //Deaktiviere alle internen Pull-Ups an Port A

//3***Interrupt INT0 init********************************************** *************************
GICR |= (1<<INT0); //Aktivieren des INT0 Interrupt Eingangs

MCUCR |= (1<<ISC01) | (1<<ISC00); //Löst aus bei Wechsel von "low" nach "high"

//4***Interrupt TIMER0 init********************************************** ***********************
TCNT0 = 0; //Anfangszählerstand = 0

TCCR0 = (1<<CS02) | (1<<CS00); //Prescaler von 1024 auswählen
/* CPU-Takt = 16.000.000Hz Prescaler = 1024
Zeit bis overflow = CPU-Takt/Prescaler = 16.000.000HZ / 1024 = 15.625Hz
*/

OCR0 = 50; //Zähler zählt bis 156
/* Zeit bis overflow = 15625Hz Zählwert = 156
Zeit bis Interrupt = 15625Hz / 156 = 100,16Hz ~ 100Hz
1s / 100 = 0,01s = 10ms
*/

TIMSK |= (1<<OCIE0); //Interrupt aktivieren

//5**LCD init********************************************** *************************************

lcd_init();

//***main******************************************* ********************************************


//Test
while(1)
{

sei();

if ( PINA & (1<<PINA0) )
{
OCR1A = 75;
}
else
{OCR1A = 17;

// lcd_clear();
}






}


}





Gruß Andi

Hubert.G
01.04.2012, 18:20
Wenn negative Zahlen angezeigt werden, dann hast du eine Variabel nicht als unsigned deklariert. Nehme mal an es ist counter.
Für die Anzeige würde ich dann auch utoa nehmen.

Teslafan
01.04.2012, 20:11
Vielen dank für die schnelle Hilfe, werds gleich mal ausprobieren :)

Besserwessi
01.04.2012, 21:20
Das Problem liegt in der Zeile mit
RPM = (counter*60) / 50

dabei wird counter *60 als integer (als 15 Bit + Vorzeichen ) ausgerechnet, und das geht früh schief.

Etwas besser wäre es da RPM = (counter*6) / 5 zu schreiben. Da hat man einen Faktor 10 mehr Platz nach oben. Wenn man dann noch counter als unsigned wählt, hat man nochmal den doppelten Platz. Ober wenn die rechenzeit nicht so kritisch ist kann man auch statt der 6 einen 6L oder 6UL schreiben, dann geht die Rechnung mit 32 Bits.

Es geht hier mit den Datentypen etwas sehr durcheinander - da ist alles mit dabei, was dem Compiler nicht so entgegen kommt.

Das CLI() und SEI() in der ISR ist auch keine gute Idee. Das kann jenachdem was GCC an Optimierungen macht ggf. auch noch schief gehen. In der ISR sind weitere Interrupts sowieso gesperrt. Die LCD-Befehle in der ISR sind nicht optimal. Da wäre ggf. zu überlegen Interrupts in der ISR freizugeben (per SEi()) - das ist aber auch nicht ohne Probleme. Eine sichere aber langsamere Alternative ist es nach der Ausgabe noch mal den Timer und die Interupt Falgs zurück zu setzen, also erst dann die nächste Messung zu starten.