Autor |
Atmega Fahrradtacho Suche nach: atmega (406) |
|
|
|
|
BID = 701087
Truddel Gelegenheitsposter
Beiträge: 54
|
|
Hallo Leute,
hat jemand von euch schonmal mit einem Atmega Prozessor und einem Reed Kontakt einen einfach Tacho mit der erstmal einzigsten Funktion, nähmlich die aktuelle Geschwindigkeit anzuzeigen, programmiert?
Ich würde sowas gerne machen weiß aber leider nicht wie ich anfagen muss.
Hoffe ihr könnt mir helfen.
Lg Basti
Ps: Das ganze soll am besten in C passieren. |
|
BID = 701095
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
|
Na, ganz einfach. Du musst bloß die Frequenz der Gebersignale bestimmen - dazu reicht ein Timer des µCs aus.
Fertigen Kode habe ich nicht, sollte es aber im I-Net geben.
_________________
|
|
BID = 701127
Racingsascha Schreibmaschine
Beiträge: 2247 Wohnort: Gundelsheim
|
In Software passiert folgendes:
-Messung der Zeit zwischen zwei Impulsen vom Reed-Kontakt
-Die Berechnung k/Messwert, wobei k vom Radumfang und dem Messwert bei einer bestimmten Geschwindigkeit abhängt. Man wählt k so, dass zb. bei 27km/h als Ergebnis 27 oder 270 herauskommt.
-Das Ergebnis passend für die Anzeige umwandeln und anzeigen.
Performancemäßig ist das alles sehr gut machbar. In meinem Tacho wird eine Radumdrehung mit 32 Impulsen aufgelöst. Mit einem 16Bit Capturemodul kann ich bei bis zu 70km/h 0,1km/h auflösen, und die Divison k/Messwert (24Bit/16Bit) könnte der PIC selbst bei 70km/h etwa 12x durchführen, bis der nächste Impuls kommt
_________________
Fnord ist die Quelle aller Nullbits in deinem Computer.
Fnord ist die Angst, die Erleichterung, und ist die Angst.
Fnord schläft nie.
|
BID = 701134
Truddel Gelegenheitsposter
Beiträge: 54
|
Ich habe jetzt mal etwas geschrieben weiß aber nicht wie ich weiter machen soll. Bin ich damit auf dem richtigen Weg?
Code : |
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
DDRB = 0xff; //Alle Pins Port B Ausgang
DDRB &= ~( 1 << DDB0 ); //Pin0 Eingang Rest Normal
TCCR0 = (1<<CS01); //Prescaler 8
TIMSK |= (1<<TOIE0);
while (1)
{
if ( DDRB & (1<<DDB0) ) //Wenn Reed ist zu
{
sei();
}
}
} |
|
|
BID = 701149
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Überhaupt nicht.
_________________
|
BID = 701189
Truddel Gelegenheitsposter
Beiträge: 54
|
Wieso nicht?
|
BID = 701197
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Weil das Programm in Zusammenhang mit der Aufgabenstellung nicht ansatzweise Sinn ergibt.
_________________
|
BID = 701229
Nukeman Schriftsteller
Beiträge: 754 Wohnort: bei Kleve
|
-Die Aufgabenstellung kommt noch ganz gut ohne Interrupts aus.
-Wenn man sie schon freigibt, sollte eine entsprechende Interrupt-Routine auch vorhanden sein.
- Die Abfrage "Reed zu" ist sehr wahrscheinlich falschrum
- warum zum Geier sollen die Interrupts (in einer Schleife ) erst enabled werden, wenn das Ereignis zutrifft und ausserdem ins Leere läuft.
- ob die Timer-Konfiguration hinhaut, hab ich angesichts der vorherigen Fehler nicht mehr gecheckt.
-> zurück auf Start! Da war kaum die Intention eines sinnvollen Vorschlags zu erkennen.
Gruß
Stefan
|
BID = 701315
Truddel Gelegenheitsposter
Beiträge: 54
|
Ich habe bei Mikrocontroller.net einen Code gefunden. Darf ich den hier posten um euch zu fragen ob der gehen würde?
|
BID = 701329
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Ja, dann aber bitte mit Link zum Urheber oder zum entsprechenden Thread.
Hochladen wäre übertrieben, besser wäre hier reinzuschreiben (spart Zeit).
_________________
|
BID = 701330
Truddel Gelegenheitsposter
Beiträge: 54
|
Okay hier der Code:
Er gibt nur die Drehzahl aus was aber leicht in km/h umzurechnen wäre.
Code : |
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
// beim Aufruf des C Compilers gab.
#ifndef F_CPU
#define F_CPU 4000000
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd-routines.h"
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die waehrend
// der Messung passiert sind
volatile unsigned int StartTime = 0; // ICR-Wert bei 1.High-Flanke speichern
volatile unsigned int EndTime = 0; // ICR-Wert bei 2.High-Flanke speichern
volatile unsigned char ProgrammDurchlauf; // Job Flag
char lcdCounterString[8];
char lcdDrehzahlString[8];
double Erg = 0.0;
double drehzahl = 0.0;
// LCD Position an der das Ergebnis der Frequenzmessung ausgegeben wird
#define LCD_LINE1 0x00 // ist diese definition notwendig?? schadet aber auch nicht..
ISR( TIMER1_CAPT_vect )
{
static unsigned char ErsteFlanke = TRUE;
if( ProgrammDurchlauf == TRUE) // Das Display wurde mit den Ergebnissen der vorhergehenden
return; // Messung noch nicht upgedated. Die naechste Messung
// verz?gern, bis die Start und EndTime Variablen wieder
// gefahrlos beschrieben werden koennen
// Bei der ersten Flanke beginnt die Messung, es wird der momentane
// Timer beim Input Capture als Startwert gesichert
if( ErsteFlanke == TRUE )
{
StartTime = ICR1; // Startzeit= ICR 1
NrOverflows = 0;
ErsteFlanke = FALSE; // Die naechste Flanke ist das Ende der Messung
}
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
else
{
EndTime = ICR1; // Stopzeit für die Messung= ICR1
ProgrammDurchlauf = TRUE; // Eine vollst?ndige Messung. Sie kann ausgewertet werden
ErsteFlanke = TRUE; // Bei der naechsten Flanke beginnt der naechste Messzyklus
}
}
ISR( TIMER1_OVF_vect )
{
NrOverflows++;
}
void init_interrupt(void) // Interrups klar machen
{
TCCR1B = (1<<ICES1) | (1<<CS10); // Input Capture steigende Flanke an ICT-Pin(PB0), kein PreScale
TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture + Overflow
sei(); //Interrups freigeben
}
void Drehzahl_berechnen(void)
{
//---------------------------------------------------------------------------------------------
//Berechnung der Drehzahl des Motors
//---------------------------------------------------------------------------------------------
// Die Zeitdauer zwischen den Flanken bestimmen
// Da EndTime und StartTime unsigned sind, braucht nicht
// darauf Ruecksicht genommen werden, dass EndTime auch
// kleiner als StartTime sein kann. Es kommt trotzdem
// das richtige Ergebnis raus.
// Allerdings muss die Anzahl der Overflows in der Messperiode
// beruecksichtigt werden
// Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
// beiden gemessenen Flanken berechnet ...65536=16bit
Erg = (NrOverflows * 65536) + EndTime - StartTime;
// ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
Erg = F_CPU / Erg; // f = 1 / t
//aus der Frequenz berechnet sich die Drehzahl
drehzahl = Erg * 20; // Drehzahl berechnen aus der Frequenz
//f*(20sec also 60sec/3Pulse pro Umdrehung)= U/min
}
void Messwerte_ausgeben(void)
{
//Drehzahl auf dem Display ausgeben
itoa( drehzahl, lcdDrehzahlString, 10 ); // Das Ergebnis fuer die Anzeige aufbereiten
// Messergebnisse auf dem Displayausgeben
lcd_clear();
set_cursor( 0,1 ); // Gehe zu Pos. XY
lcd_string(lcdDrehzahlString); // Datenwert
lcd_string(" U/min"); // Ausgabe Maske
// Das wars: Display ist wieder up to date
// die naechste Messung kann starten
}
int main()
{
lcd_init(); //lcd initialisieren
init_interrupt(); //Interrups klar machen
while(1) //diese Schleife soll das Programm immer wiederholen.
{
if( ProgrammDurchlauf == TRUE) // liegt ein vollständiger Durchlauf vor?
{
Drehzahl_berechnen();
Messwerte_ausgeben();
ProgrammDurchlauf = FALSE;
}
}
}
|
|
Der Link zu dem Topic ist hier
Die Funktion Messwerte ausgeben müsste ich dann noch an das dann benutzte LCD anpassen. Genauso wie ich es nur mit einem Magneten verwenden würde.
|
BID = 702036
Truddel Gelegenheitsposter
Beiträge: 54
|
Da das Programm ja für einen Atmega8 programmiert wurde muss ich ja die High Flanke für den Atmega32 ändern.
Hier ist die Definition für den Mega8:
Code : |
TCCR1B = (1<<ICES1) | (1<<CS10); |
|
Wie muss ich das schreiben, dass es mit dem Mega32 funktioniert? Ich würde den Pin PB0 verwenden. Kann mir jemand helfen?
|
BID = 703699
Truddel Gelegenheitsposter
Beiträge: 54
|
Kann mir hier noch jemand weiterhelfen oder eher nicht?
|
BID = 703737
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Hab grad wenig Zeit, schau mal im Datenblatt nach
Da stehen so unwichtige Dinge drin
Edit: Datenblatt, Seite 108:
_________________
Außerdem empfiehlt sich natürlich die Lektüre der Seiten 91 ff.
[ Diese Nachricht wurde geändert von: DonComi am 25 Jul 2010 20:49 ]
|
BID = 703904
Truddel Gelegenheitsposter
Beiträge: 54
|
Ah ok Danke.
Also kann ich diese Funktion nicht an jedem Pin ausführen oder?
Nur an PD6.
|