mikrocontroller.net

Forum: Compiler & IDEs ATmega 168 wie Kennlinie ablegen


Autor: peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum

Hab schon die suche bemüht leider konnte ich bzgl. lookup tables nix 
beriedigendes finden
Bin gerade dabei ein einfaches Zündungsstuergerät zu programmieren.
Drehzahlerassung und erkennung des ot laufen schon soweit
nun möchte ich im 1. schritt anhand der drehzahl einen zündwinkel 
ausgeben. Sprich eine Kennlinie in der steht bei der und der Drehzahl so 
der und der Zündwinkel ausgegeben werden.
Wie kann ich das am einfachsten in C realisieren? Gibts dann auch 
möglichkeit zischen den stützstellen zu interpolieren??

Danke ür Eure Antworten

Autor: PCler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also wenn Du einen passenden Lookuptable mit Stützstellen schon hast und 
die Funktion dazu, wo liegt dann Dein Problem ?
Oder müssen es Floats sein ?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
peter wrote:
> nun möchte ich im 1. schritt anhand der drehzahl einen zündwinkel
> ausgeben. Sprich eine Kennlinie in der steht bei der und der Drehzahl so
> der und der Zündwinkel ausgegeben werden.

> Gibts dann auch
> möglichkeit zischen den stützstellen zu interpolieren??

Sicher. Ich denke mal lineare Interpolation würde durchaus
ausreichen.

> Wie kann ich das am einfachsten in C realisieren?

Am einfachsten ist es, wenn du den Zündwinkel für Drehzahlen
in einem bestimmten Raster vorgibst. Sagen wir mal für alle
Vielfachen von 500 U/min hast du einen Zündwinkel.

Dann brauchst du noch ein Array, in dem für alle diese Drehzahlen
der zugehörige Zündwinkel abgelegt ist.

uint8_t Winkel[] = {
      80,      /*    0 U/min */
      82,      /*  500       */
      82,      /* 1000       */
      85,      /* 1500       */
      87,      /* 2000       */
      ....
  }

Und dann brauchst du jetzt natürlich noch eine Formel, die
dir, ausgehend von einer bestimmten Drehzahl ausrechnet, an
welcher Stelle im Array der zugehörige Wert zu finden ist.

Könnte zb so aussehen:

   uint16_t Drehzahl;
   uint8_t Index;

   ..... irgendwie kommst du zu deiner Drehzahl

   /* die rechnen wir um in einen Index in die Winkel-Tabelle: */

   Index = Drehzahl / 500;
   einzustellender_Winkel = Winkel[ Index ];

mit dieser einfachen Berechnung kriegst du für Drehzahlen
    0 bis  499    Winkel[0]
  500 bis  999    Winkel[1]
 1000 bis 1499    Winkel[2]
 1500 bis 1999    Winkel[3]
   ....

Wenn dir eine Abstufung von 500 U/min nicht reicht, kannst
du natürlich auch feiner unterteilen.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PCler wrote:
> Also wenn Du einen passenden Lookuptable mit Stützstellen schon hast und
> die Funktion dazu, wo liegt dann Dein Problem ?

An den mangelnden C-Kenntnissen, bzw Fantasie diese
auch einzusetzen :-)
Es ist schon erstaunlich, mit wie wenig Wissen sich viele
an eine Programmieraufgabe heranwagen.

Autor: PCler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger:
An sowas hätt' ich nie im Leben gedacht ;)
BTW sollte Heinz nicht auch mit'm großen "H" anfangen ;)
Ist mir nur gerade beim Kopieren aufgefallen ;)
Dein C-Programm ist OK aber solltest Du nicht "krumme" Werte mit einem 
Modulo o.ä. abfangen ?
Sonst kann's haarig werden mit Index = 2,34568 und int8_t ;)
Oder wird automatisch in int8_t umgewandelt ?

Autor: peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Danke erst mal für die schnellen Antorten


>@Karl heinz Buchegger
>mit dieser einfachen Berechnung kriegst du für Drehzahlen


>   0 bis  499    Winkel[0]
>  500 bis  999    Winkel[1]
> 1000 bis 1499    Winkel[2]
> 1500 bis 1999    Winkel[3]


Das muss ich ja dann mit lauter if oder case abfragen realisieren oder 
gibts da eine elegantere methode?

Sorry für die villeicht banalen fragen aber irgendwie muss man halt 
erfahrungen sammeln :-)


Autor: Marcus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso if oder case?

Karl Heinz hat dir doch schon beschrieben wir das geht! Du ermittelst 
deine Drehzahl, mithilfe einer Ganzzahldivision erhälst du den Index für 
die LUT. Schau noch mal in dem Post von 20:35 Uhr nach.

Marcus

Autor: peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry habs beim 1 mal durchlesen ned gecheckt.


> Index = Drehzahl / 500;


Was würd jezt aber passieren wenn Drehzahl zb 700 ist, Index währ ja 
dann 1,4 also würde ja abgerundet. Wie kann ich dann zwischen 2 
stüzstellen interpolieren??

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PCler wrote:
> Sonst kann's haarig werden mit Index = 2,34568 und int8_t ;)
> Oder wird automatisch in int8_t umgewandelt ?

Da ist alles Ganzzahl. 1350 / 500 ergibt 2


Autor: PCler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das meinte ich mit "krumme" Werte ;)
Ich bin gemein ich weiß ;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
peter wrote:
> Sorry habs beim 1 mal durchlesen ned gecheckt.
>
>
>> Index = Drehzahl / 500;
>
>
> Was würd jezt aber passieren wenn Drehzahl zb 700 ist, Index währ ja
> dann 1,4 also würde ja abgerundet. Wie kann ich dann zwischen 2
> stüzstellen interpolieren??

indem du zwischen dem Wert kleiner (diesen Index kriegst du
aus der Division) und dem Wert grösser (das ist dann Index + 1)
interpolierst.

Also: gemessene Drehzahl 1300
  Index = 1300 / 500 -> 2

  Wert[2] -> 82
  Wert[3] -> 85

Und jetzt wird zwischen den beiden Interpoliert.

  2 * 500 -> 1000

  1300 - 1000 -> 300

  ( 85 - 82 ) * 300 / 500 -> 1.8   als Ganzzahl 1

  82 + 1 -> 83


Die Mathe dazu jetzt herzuleiten ist mir ehrlich zu mühselig
auch wenns trivial ist.


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PCler wrote:
> Das meinte ich mit "krumme" Werte ;)
> Ich bin gemein ich weiß ;)

Nicht wirklich :-)
Die Interpolation ist trivial.

Ich würds aber trotzdem nicht so machen:
Ein Motormanagement sollte wohl so schnell wie
möcglich auf veränderte Drehzahlen reagieren.
Wenn 500 U/min Auflösung nicht reichen, dann geh
ich halt runter auf 100 oder 50. Die Tabelle im Excel
aufstellen, geht wohl schneller als wenn der µC sich
da durch Divisionen durchquälen muss.

Autor: PCler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger:
Bist Du Dir wirklich sicher das uint8_t var = 1300 / 500 ZWEI ergeben ?
Weil da kommt ja eigentlich 2,6 heraus ??
Sorry aber in "normalem" C kracht das ziemlich !
Außer Du nimmst uint8_t var = (uint8_t) 1300 / 500 ...
Oder steh' ich gerade auf'm Schlauch ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Bist Du Dir wirklich sicher das uint8_t var = 1300 / 500 ZWEI ergeben ?

Ja, ich bin mir absolut sicher

> Weil da kommt ja eigentlich 2,6 heraus ??

Nicht wirklich.
1300 ist ein int. 500 ist ein int. Also wird die Division
als int-Division ausgeführt. Und das ergibt nun mal 2.

> Sorry aber in "normalem" C kracht das ziemlich !

Äh. Nein. So sind die C-Regeln. Das ist schon seit
Zeiten von K&R so (also seit den 60-er Jahren).

> Außer Du nimmst uint8_t var = (uint8_t) 1300 / 500 ...

Das ändert überhaupt nichts. Ist nach wie vor eine int Division.


Ah. OK
Ich hätte vielleicht dazu schreiben sollen, dass Zahlen
ohne einen Kommapunkt bei mir immer int sind. Wenn ich
eine Kommazahl haben will schreibe ich immer einen Dezimalpunkt:

   1300.0 / 500.0

ist daher was anderes als

   1300 / 500


Klärt das das Missverständniss auf?

Autor: PCler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@All:
Sorry, hab's gerade selbst nachgesehen:
http://www.csee.usf.edu/~eschrich/cis4930/faq/intd...
Also Karl-Heinz hat recht ;)
Ich muß wohl irgendwie was verwechselt haben ;)
Wobei es ja heißt das iterative Sprachen immer ineinander übersetzt 
werden können ...
Aber wie heißt es So schön:
C:
Shoot urself in the foot.
PENG

Pascal:
The compiler wont let u shoot urself in the foot.

Sorry,
PCler

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> C
> Pascal

Aaaah. Jetzt weiss ich woher der Wind weht :-)

In Pascal ist das anders. Stimmt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>
>   ( 85 - 82 ) * 300 / 500 -> 1.8   als Ganzzahl 1
>
>   82 + 1 -> 83
>

Wenn du die 1.8 gerundet haben möchtest, dann musst
du noch eine Rundungskorrektur anbringen.

 ( ( 85 - 82 ) * 300 + 250 ) / 500


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.