Temperaturdarstellung mit RGB-LED und Atmega8

  • Hallo


    Für ein Schulprojekt muss ich mit einem Mikrokontroller (myAVR, also Atmega 8) arbeiten. Ich habe mir überlegt, dass ich mit einem Sensor (welcher am besten? NTC? PTC?) die Temperatur messe und diese dann über eine RGB-LED (3fach Rebel) darstellen. Als KSQ verwende ich einfach eine ganz einfache LM317-KSQ, die LEDs auf 50mA um die Hitzeentwicklung gering zu halten (Kühlung vorhanden). Der Mikrokontroller wird in C programmiert.


    Hier meine Fragen:
    1. Welchen Sensor nehme ich am besten? Wie ist es am einfachsten in Sachen Schaltung und Programmierung?
    2. Wie setze ich die Temperatur am besten in einen Farbwert (also R, G und B) um? Gibt es da altbekannte Algorithmen um einen einzelnen Wert in drei Werte quasi aufzuteilen?
    3. Hat der Atmega8 drei Hardware-PWM-Ausgänge oder muss ich es über Software-PWM realisieren? (soweit wie ich das erkennen konnte hat der 2x8bit und 1x16bit?)


    Gruß,
    Andy

  • Ich halte zwar ne RGB Rebel Anordnung für Overkill aber na gut.
    Die KSQ könntest du in dem Strombereich durch die instructable KSQ noch günstiger und effizienter hinkriegen.


    Welchen Sensor du nehmen sollst würde ich von der Aufgabenstellung, dem Fach und der Schule abhängig machen. Wenn es was informationstechnisches ist eher nen digitaler Sensor, wenn der Schwerpunkt eher bei der Elektrotechnik ist wahrscheinlich eher ein analoger Sensor.


    2. Z.B. If then else


    3. Datenblatt :!: :!: :!:

  • Hallo,


    zu 2: würde ich mit einer HSV zu RGB-Umrechnung machen; (H)ue über die Temperatur, S(aturation) auf max und (V)alue auch auf max ergibt das gesamte Spektrum von Rot über Gelb, Grün, Blau bis Lila. Siehe auch Wiki-Artikel zu HSV.


    zu 3: Ist einfach mit einer Soft-PWM zu machen, bei 3 Kanälen kannst Du eine beliebige Methode nehmen, die Rechenleistung vom Mega8 reicht in jedem Fall aus.


    Schöne Grüße,
    Martin

  • Hallo zusammen,


    danke schon mal für eure Antworten.


    Habe es jetzt so umgesetzt, dass ich den HSV-Farbraum benutze und diesen dann in RGB umrechne. Die Temperatur hole ich mir jetzt über einen LM75 per TWI, denn für das verwendete myAVR-Board gibt es eine Erweiterungsplatine dafür. Damit bin ich aber noch nicht fertig, derzeit gebe ich noch Temperaturen von Hand ein (was vorerst reicht).


    Hier mein C-Code:


    Ich berechne ja jetzt in jedem Durchlauf die Werte neu. Ist natürlich nicht so schön und führt dazu, dass die LED stark flackert.


    Wenn ich die Variablen global mache, wie kann ich z.B. eine Funktion alle x Takte/ms aufrufen? Dass die Temperatur nicht in jedem Durchlauf geholt wird und in RGB-Werte umgesetzt wird?


    Gruß,
    Andy

  • Hallo,


    zu Deiner Frage: regelmäßige Aufrufe von Funktionen macht man bei Mikrocontrollern mit einer Interrupt-Routine, die von einem der eingebauten Zeitgebern (Tmer) ausgelöst wird. Zum Einlesen eignet sich das AVR Tutorial von Mikrocontroller.net.


    Zu Deinem Code: Leider muss man sich bei 8-Bit Mikrocontrollern etwas mehr Gedanken machen, was die Datentypen können und was nicht, als bei einem ausgewachsenen PC. So wird Deine HSV-Berechnung so leider nicht funktionieren: Du setzt H auf Temp*6, S und V auf 1. In H ist also in dem Beispiel 78.


    hi setzt Du auf H / 60, also auf 1 (da hi ein uint_8 ist, wird der Komma-Anteil einfach abgeschnitten). f setzt Du auf H/60 (also 1, da der komplette Ausdruck in Integer gerechnet wird) - hi (=1), also auf 1-1 = 0. Das ändert sich für <10°C auf hi=0 und f=0, für 20°C-30°C auf hi=2 und f=0, für 30°C-40°C auf hi=3 und f=0 u.s.w. f ist also immer 0. Damit ist aber p = 0, q = V (=1) und t=0 (und zwar unabhängig von der Temperatur).


    Damit wird in Abhängigkeit der Temperatur Rot (<10°C und >50°C), Grün(10°C-30°C) oder Blau (30°C-50°C) ganz schwach leuchten. Schwach deswegen, da V=1 und damit R, G, B entweder 1 oder 0. Damit werden aber die entsprechenden LEDs bei i=0 (bzw. 255) eingeschaltet und im übernächsten Durchlauf (der sehr schnell sein kann) wieder ausgeschaltet.


    Damit hast Du hier zwei Hauptprobleme: Dadurch, dass die Berechnungen in uint_8 (bzw. int16) durchgeführt werden, bekommst Du nicht den Fabmix, den Du haben willst, und es leuchtet kaum (bei double-Berechnung wäre der Wertebereich von p,q,t zwischen 0 und 1). Du solltest hier die Variablen als Fixkomma-Variale mit Skalierung verwenden - also die Berechnung z.b. in int16 durchführen (dabei allerdings die Berechnung von f durch den Modulo-Operator durchführen), H in Abhängigkeit von dem gewünschten Temperaturbereich skalieren, so dass es zwischen 0 und 240 liegt (dann aber auch nicht durch 60, sondern durch 40 teilen) und S und V auf 255 setzen - H ist also im Vergleich zum Wikipedia-Artikel mit 2/3, S und V mit 255 multipliziert. Da f dann weiterhin zwischen 0 und 1 liegen würde, muss es entsprechend skaliert werden (geschieht, indem man einfach f= H % 40 statt f=H/40-hi rechnet - dies entspricht einer Multiplikation mit 40). Zuletzt noch die p,q,t-Berechnungen passend skalieren, indem die erste 1 durch eine 255 ersetzt wird und dafür der Gesamtausdruck durch 255 geteilt wird.


    Jetzt gibt es nur noch zwei Sachen: erstens müssen die Produkte von f durch 40 geteilt werden (da f ja mit 40 skaliert worden ist) - allerdings muss im Ausdruck (1-f) dafü auch die 1 durch eine 40 ersetzt werden. Zum Anderen ergibt sich ein Genauigkeitsverlust bei q und t, da zwei relativ kleine Zahlen voneinander abgezogen werden. Dies kann man dadurch verbessern, dass man das Teilen durch 40 erst nach der Subtraktion durchführt - dann muss allerdings die Konstante auch passend skaliert werden.


    Es ergibt sich somit für die Berechnung von p,q und t folgendes:


    hi = H / 40
    f = h % 40


    p = (V * (255-S)/255
    q = (V* ( ( (255*40) - (S*f))/40)) / 255
    t = (V *( ( (255*40) - (S*(40-f)))/40))/255


    p, q und t liegen damit im Bereich zwischen 0 und 255 und damit in dem Bereich, den Du erwartest. Du musst nur noch dafür sorgen, dass Dein H im Bereich zwischen 0 und 240 liegt.


    Neben dem Einlesen derTemperatur-Werte und Berechnen der RGB-Größen in einem Interrupt, solltest Du Dir überlegen, ob Du nicht auch die PWM in einen Timer-Interrupt ausagern möchtest. Das reduziert dann die Rechenlast erheblich. Auch würde sonst der Temperatur-Task die PWM stören, und die LED würde unregelmäßig flackern.


    Und um noch einen möglichen Stolperstein im Vorraus aus dem Weg zu räumen: Globale Variablen, die in Interrupt-Routinen verwendet werden, müssen als volatile gekennzeichnet sein, damit der Compiler weiss, dass diese Variable jederzeit geändert werden kann (sonst können eventuell Optimierungen dazu führen, dass die Variable nicht so verwendet wird, wie du es erwarten würdest.


    Ansonsten noch viel Spass mit der Schulaufgabe - falls Du meine Erklärung zu Festkommazahlen-Arithmetik nicht verstanden haben solltest, könnte Dir auch hier eventuell die Wikipedia weiterhelfen.


    Schöne Grüße,
    Martin

  • Nur falls es interessiert: Neni hat hier mal eine HSV -> RGB Umrechnung vorgestellt, die ohne Fest- oder Fließkommaarithmetik auskommt durch entsprechendes Skalieren der Wertebereiche (Hue geht hier von 0 - 1529)...


    dabei werden nur Bytes und Words verwendet und kommen auch nur Divisionen durch 256 vor, die man ganz leistungssparend machen kann, indem man vom Ergebnis der vorherigen Rechnung (ein Word) nur das High-Byte nimmt...


    ist dort zwar in Bascom, ließe sich aber auch leicht auf C umschreiben, falls es in Betracht kommt.

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Hallo,


    da es eine Schulaufgabe war, wollte ich es ihm nicht zu leicht machen ;) - auf Fragen des Lehrers kann man nur antworten, wenn man das Prinzip verstanden hat, und das fällt mir am leichtesten, wenn ich etwas selbst entwickele. Das Beispiel von Neni benutz übrigens auch Festkommaarithmetik, auch wenn es nicht so genannt wird (S,V,R,G,B sind ufix( 8 )mit 2^8 skalierung, H ist ufix(16) mit 'ner Skalierung von 4.24). Programmtechnisch ist die Division durch 256 sicherlich einfacher als durch 255, allerdings bekommt man damit niemals die maximale Helligkeit (da 255*255 / 256 = 254). Ich habe deswegen bewusst die 255 gewählt; aus dem gleichen Grund habe ich nicht den vollen Bereich von 255 für H vorgeschlagen, da die Beschränkung auf 240 (also eine Skalierung von 2/3) eine schöne Skalierung der 60°-Sektoren erlaubt (bei der Ausnutzung des Wertebereiches eines Bytes müsste an sich mit 42,5 gerechnet werden. Benutzt man dann die 42, so geht wieder Genauigkeit verloren).


    Ich gebe aber gerne zu, dass dies eher akademische Probleme sind, die in der Realität nicht sichtbar sind. Den Lehrer könnten sie aber interessieren...


    Deutlich wichtiger was die Sichtbarkeit angeht ist sicherlich, die PWM nicht ungetaktet im Hauptprogramm ablaufen zu lassen, damit eine unterschiedliche Arbeitsbelastung des Mikrocontrollers nicht zum flackern führt (z.B. beim Einlesen der Temperaturen).


    Schöne Grüße,
    Martin

  • Hi


    (Hier war vorher eine andere Frage, aber die ist so peinlich, die musste ich löschen :D )


    Habe jetzt die PWM im 8bit-Timer. Wo soll ich denn nun die Berechnung hinpacken? So wie ich das beim 16bit-Timer verstanden habe, kann der keine Interrupts auslösen?


    Die Berechnung also in die Main und mit _delay_ms(); bremsen?


    Gruß,
    Andy

  • (S,V,R,G,B sind ufix( 8 )mit 2^8 skalierung, H ist ufix(16) mit 'ner Skalierung von 4.24).

    Ja, da erzählst Du mir Sachen, mit sowas kenne ich mich nicht aus! :D - ich mache Assembler, und da gibt's für mich halt nur "ganze Zahlen" bzw. beim "teilen" fällt halt dann was weg etc. ... ;)


    Programmtechnisch ist die Division durch 256 sicherlich einfacher als durch 255, allerdings bekommt man damit niemals die maximale Helligkeit (da 255*255 / 256 = 254).

    ja das stimmt, aber den Unterschied zwischen 254 und 255 sieht nun wirklich kein Mensch... ;)


    da es eine Schulaufgabe war, wollte ich es ihm nicht zu leicht machen ;)

    ah, sorry, das hatte ich tatsächlich einfach übersehen...

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Zitat

    Das Beispiel von Neni benutz übrigens auch Festkommaarithmetik, auch wenn es nicht so genannt wird


    Ja, natürlich ist es im Prinzip Fixkommaarithmetik, da ja mit einem bestimmten Faktor vormultipliziert wird, allerdings mit dem kleinen Unterschied, dass nicht auf Rundungen geachtet wird (intentionell).


    Zitat

    Programmtechnisch ist die Division durch 256 sicherlich einfacher als durch 255, allerdings bekommt man damit niemals die maximale Helligkeit (da 255*255 / 256 = 254)


    Naja, das stimmt für diesen Fall, aber nicht für meine Umrechenfunktionen ;) . Überall wo das Produkt aus Saturation und Hue_Teilwert (0-255) ins Spiel kommt, wird dieses eben erst von 65280 (255 * 256) abgezogen und dann durch 256 geteilt, also eben (255 * 256 - Hue_Teilwert * Saturation) / 256. Man kann's nun durchspielen, wenn man den Hue_Teilwert und die Saturation von 0 bis 255 variert, wobei man feststellen wird, dass der resultierende Wertebereich ebenfalls genau 0 - 255 und nicht 0 - 254 (oder 1 - 255) ist. Das liegt eben daran, dass bei der Division (bzw. Rechtsschieben oder High-Byte) nur der ganzzahlige Anteil ungerundet übrig bleibt.
    Bei der Skalierung für die Helligkeit (V) wird dann etwas anderes gemacht: ((V_Wert + 1) * Farb_Wert) / 256. Da wirkt sich der 'Vorteil' der fehlenden Rundung auch wieder positiv aus.


    Alle diese Optimierungen sind natürlich für einfache 8-Bit µCs wie den AVR gedacht, wo eben eine 'echte' Division sehr kostenintesiv (benötigte Takte) ist, insbesondere auch für die MEGA-AVRs, welche zwar eine HW-Multiplikation aber keine HW-Division anbieten. Bei einem 32-Bit ARM Cortex M (HW-Multiplikation und - Division) z.Bsp. würden solche Verenkungen wenig bringen.


    Gruss
    Neni


    PS: Hier übrigens nochmal zusammengefasst die ganzen HSVnachRGB-Umrechenfunktionen für versch. PWM-Bittiefen (vielleicht sollte man daraus mal einen Sticky oder sowas machen):

  • Habe jetzt die PWM im 8bit-Timer. Wo soll ich denn nun die Berechnung hinpacken? So wie ich das beim 16bit-Timer verstanden habe, kann der keine Interrupts auslösen?


    Auch der 16-Bit-Timer kann Interrupts auslösen, beim ATMega8 muss man dafür z.B. Bit 2 (TOIE1) in Register TIMSK setzen, um bei einem Overflow einen Interrupt zu erzeugen.



    Die Berechnung also in die Main und mit _delay_ms(); bremsen?


    Wenn Dein Mikroconroller nichts anderes machen soll, ist das die einfachste Variante - wenn beide Aufgaben in verschiedenen Interrupts ausgeführt werden, muss man sich Gedanken darüber machen, dass der ATMega von Haus aus keine Interrupt-Priorisierung kennt, was ohne Gegenmaßnahmen dann gelegentlich zu (leichtem) Flackern führen würde, wenn an sich die PWM-Routine 'dran wäre, der Prozessor jedoch gerade im Temperatur-Interrupt steckt. Und das Du prinzipiell mit Timern und Interrupts umgehen kannst, hast Du dann ja schon mit der PWM-Routine gezeigt.


    @Neni:
    Respekt für die Berücksichtigung der Besonderheiten beim Teilen durch 256, ich muss zugeben, dass ich mir die Konstanten nicht so genau angesehen hatte - bei verschiedenen anderen Routinen, die man im Netz finden kann, sind sie nicht berücksichtigt worden, was ich dann fälschlich auf Deine Routine übertragen habe. Was ich so direkt allerdings nicht aus Deinem C-Code ablesen kann ist, was Du unter "Light-Emission-normalized" verstehst?


    Schöne Grüße,
    Martin

  • Was ich so direkt allerdings nicht aus Deinem C-Code ablesen kann ist, was Du unter "Light-Emission-normalized" verstehst?


    Eventuell die Anpassung an das menschliche Auge? Nur eine wage Vermutung ;)


    Danke für eure Antworten und ganz besonders an Neni für die Umrechnung. Hat mir sehr geholfen bzw. Arbeit abgenommen :) Projektabgabe ist morgen, allerspätestens nächste Woche Montag :)

  • bei "normalized" bleibt die Strahlungsleistung insgesamt gleich - bei der oberen Version ist z.B. gelb aus 100% rot und 100% grün gemischt, also heller als rot oder grün alleine - bei "normalized" ist dann gelb aus 50% rot und 50% grün gemischt, also genauso hell...


    fährt man praktisch den Hue ab, dann schwankt die Helligkeit bei der ersten Variante (gelb, cyan und magenta sind heller), bei der "normalized"-Variante bleibt sie gleich


    wegen dem Timer: Du machst ja SW-PWM, rufst also regelmäßig ne ISR auf - diese kannst Du ja auch gleich für weitere zeitbasierte Vorgänge benutzen, z.B. in der Timer-ISR ne Variable runterzählen, immer wenn die 0 ist, ein Flag setzen für "Zeitsegment abgelaufen" - in der Hauptschleife schaust Du dann, ob dieses Flag gesetzt ist, wenn ja, löscht Du es wieder, holst den Wert vom Sensor, "rechnest die Farbe aus" und schreibst sie in den PWM-Buffer...


    Neni: ich glaube, ich mache mal nen "Sammelthread SW-Schnipsel" oder sowas, und hefte den bei "LED Schaltungen..." fest, da kommt dann Deine Umrechnungsroutine mit rein...

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Genau, die Light Emission Normalized Versionen halten die Lichtemission bei fixem Brightness-Wert konstant. d.h. es gibt weniger bis kein 'Helligkeitspumpen' beim Rainbow-Fading und auch Saturation-Fading nach Weiss, was vor allem bei RGB-Mood-Beleuchtungen häufig einen homogeneren Eindruck macht. Ausserdem wird der maximale, mittlere LED-Stromverbrauch auf etwa ein Drittel reduziert. Man kann dann eine entsprechend weniger leistungsfähige Stromversorgung einplanen, wenn die PWM-Frequenz hoch genug gewählt und eine ausreichend gute Pufferung der LED-Versorgung mit low ESR Elkos vorgesehen wird.


    Die Normalized-Varianten eignen sich hingegen nicht für Video-Wände etc., da der Dynamik-Umfang deutlich verringert ist, was einer realitätsnahen Bilddarstellung entgegen wirkt.


    Gruss
    Neni

  • So langsam weiß ich echt nicht mehr weiter, wie ich diese schei* Temperatur auslesen soll :cursing:


    Status bisher: PWM über 8bit Timer, Temp über 16bit Timer, Hauptschleife macht nichts.


    Habe versucht, mir eine Hardware-TWI-Implementation zu programmieren, jetzt sehe ich aber, dass dieser myTWI Temperatursensor (von myAVR) nicht an PC4 (SDA) und PC5 (SCL) sondern PC3 und PC4 hängt... WER DENKT SICH SO EINE SCHEI**E AUS? X( :cursing:


    Jetzt gibt es ja noch Interruptgesteuerte I2C-Implementationen, u.a. die von Peter Fleury ( http://jump.to/fleury ). Allerdings habe ich da absolut keine Peilung, wie ich das Ding benutzen muss, ob ich das erst bauen muss (oder wofür ist das Makefile?), wenn ja wie? Zudem müsste ich dann ja einen Timer wieder frei machen, oder nicht? Aber gut, das ist ja dank Pesis Vorschlag dazu (in Hauptschleife auslagern) nicht allzu dramatisch.


    Hier mein bisheriger Code:
    http://pastebin.com/xeKrgmg1 (Pastebin wegen Syntax-Highlighting)

  • Hallo,


    wegen dem Timer: Du machst ja SW-PWM, rufst also regelmäßig ne ISR auf - diese kannst Du ja auch gleich für weitere zeitbasierte Vorgänge benutzen, z.B. in der Timer-ISR ne Variable runterzählen, immer wenn die 0 ist, ein Flag setzen für "Zeitsegment abgelaufen" - in der Hauptschleife schaust Du dann, ob dieses Flag gesetzt ist, wenn ja, löscht Du es wieder, holst den Wert vom Sensor, "rechnest die Farbe aus" und schreibst sie in den PWM-Buffer...


    wobei in diesem Fall (da nur ein Task abzuarbeiten ist) der einzige Unterschied zur Methode mit dem Delay im Hauptprogramm ist, dass sich im Fall des Delay die zeitlichen Variationen bei der Abarbeitung des PWM aufaddieren (also der Temperatursensor, wenn er denn 1 mal pro Sekunde gelesen werden soll, erst nach 1000.5 oder 999.5 oder so Sekunden zum 1000en mal ausgelesen wird), während bei der Interrupt-Methode die Absolutzeiten eingehalten werden. Die zeitlichen Variationen zwischen zwei Temperatur-Messungen sind die gleichen, genauso der Stromverbrauch oder die thermische Belastung.


    Interessant wird damit das Auslösen der Messung im Interrupt für mich erst dann, wenn das Messen nebenläufig ist (also noch andere Aufgaben wie Kommunikation o.ä. durchgeführt werden), oder aber der Prozessor zum Stromsparen schlafen geschickt wird (was bei einer PWM allerdings nur begrenzt sinnvoll ist, da erstens der Prozessor sehr häufig aufwacht, zweitens 6 zusätzliche Takte zum Aufwachen braucht und drittens die Einsparung "nur" rund 70% entspricht).


    Der Einfachheit halber würde ich in diesem Projekt jedoch darauf verzichten und bei der Delay-Methode bleiben (zumal es hier nicht wirklich darauf ankommt, ob nach 1 Sekunde oder 1.01 Sekunde die Temperatur gemessen wird). Ist aber sicher auch persönlicher Geschmack...


    Ebenso persönlicher Geschmack, wenn ich mir Nenis Code ansehe: ich sichere entweder jeden Eingangswert ab (die While-Schleifen für Hue), oder ich verlasse mich darauf, dass die definierten Wertebereiche bei allen Variablen eingehalten werden; ich würde nur dann ausschließlich den Hue-Wert bei der 8-Bit-PWM absichern, wenn sat und bri als uint_8 definiert wären (was durchaus funktionieren sollte).


    Ach ja: nicht vergessen, das Programm ordentlich zu kommentieren. Dabei mehr Wert darauf legen, zu beschreiben, wie es gemacht wird, nicht was gemacht wird - also nicht schreiben: setze Blue_val auf 255 - Saturation, das kann man nämlich direkt aus dem Code lesen, sondern etwa: Mische der Farbe in Abhängigkeit der Saturation Weiss bei, indem der Blauanteil umgekehrt proportional zur Saturation erhöht wird.


    Diese Art der Kommentierung dauert deutlich länger als die "wörtliche", zeigt aber einerseits (natürlich nur, wenn die Kommentare richtig sind :D ) dass Du verstanden hast, was Du machst, andererseits helfen sie Dir dann auch, in 2 Jahren noch verstehen zu können, warum Du das genau so programmiert hast. Ich gebe aber gerne zu, dass ich hier auch gerne schlampe - mit den entsprechenden negativen Folgen :( Und der Code von Neni enthält schon einige "Tricks", die nicht direkt offensichtlich sind, wenn man nur die Wikipedia-Formeln kennt (Wertebereich Hue, um jede Farbe des entsprechenden RGB-Farbraums mit HSV darstellen zu können, Wahl der Konstanten, um durch 256 und nicht 255 teilen zu können, Auslagern der Multiplikation des V-Wertes an den Schluss um Speicherplatz zu sparen und Erhöhen des V-Wertes um 1 um durch 256 teilen zu können, eventuell auch noch weitere).



    NACHTRAG: Während ich schreibe, seid ihr schon weiter :D zum Thema i2c / TWI: Der Vorteil dieses Busses ist, dass das Timing vollkommen egal ist, deswegen lässt er sich auch recht einfach in Software ohne Interrupt abbilden (ist allerdings schon etwas aufwändiger, ein Beispiel für die Megas findest Du ebenfalls bei Mikrocontroller.net ; hier musst Du nur einfach die Funktionen Deinem Programm hinzufügen). Dann würde ich die Kommunikationsroutinen jedoch auf alle Fälle nicht im Interrupt laufen lassen (also entweder wie bei Pesi über Timer getriggert im Hauptprogramm, oder einfach mit Delay im Hauptprogramm). Ach ja, falls Du fremden Code verwendest, bei dem offensichtlich ist, dass er in der Dir zur Verfügung stehenden Zeit nicht von Dir entwickelt worden sein kann, solltest Du das im Kommentar darstellen; bei anderem "geborgten" Code ist es höflich (aber eventuell nicht der Note förderlich - Kommentiere ihn aber zumindest zusätzlich, so dass er nicht direkt bei einer Google-Suche "herausspringt" ^^ ) Falls Neni als Urheber genannt werden möchte, wird er es Dir sicherlich mitteilen...


    Schöne Grüße,
    Martin

  • Hi


    Wenn ich die von dir verlinkte Bibliothek verwenden möchte, kommt das...



    Ich habe die Bibliothek aber eingebunden (die Dateien aus der RAR befinden sich im Unterordner i2c):

    Code
    #include "./i2c/i2c_software_master.h"


    Warum kennt der das denn jetzt nicht?


    Gruß,
    Andy


    P.S.: Benutze myAVR Workpad PLUS (Demo)

  • Hallo,


    Bibliotheken in C bestehen in der Regel aus 2 Teilen: einmal der Deklarationsteil in der Header (.h)-Datei, der nicht unbedingt notwendig ist, aber beim Compilieren Warnungen vermeidet bzw. auch Fehler verhindert (wenn eine Funktion z.B. uint_8-Werte erwartet oder zurückgibt, dann kann je nach Compiler das Aufrufen ohne dass die Funktion deklariert ist daneben gehen (weil Integerwerte ohne zusätzliche Information immer als int übergeben werden, und das ist beim AVR normalerweise int_16). Dieser wird mit dem #include eingebunden


    Der zweite Teil besteht aus der Definition, also den eigentlichen Routinen, die in ".c"-Dateien abgelegt sind. Diese können entweder als Bibliothek eingebunden werden (dann werden die ".c"-Dateien vorcompiliert und zu einer Bibliothek zusammengefasst, die dann mit der Linkeroption -l hinzugefügt wird, wobei der Linker dann nur die Routinen auswählt, die wirklich benötigt werden), oder aber die Dateien werden mitcompiliert und dann mitgelinkt (dann werden alle Routinen eingebunden). Dies geschieht dann beim Linker. Da ich gerade nicht an die Dokumentation zu myAVR herankomme (die Webseite hat anscheinend aktuell Probleme beim Download der Dokumentation) und Dir deswegen gerade nicht die Compiler- und Linker-Optionen sagen kann, würde ich Dir empfehlen, den Inhalt der i2c_software_master.c einfach vor Deine eigene Routinen in Dein C-Programm zu kopieren (oder mit #include nach der ".h"-Datei einzubinden, auch wenn das an sich verpöhnt ist).


    Schöne Grüße,
    Martin