Hallo zusammen,
Der ADC meines ATtiny 13 nimmt die falsche Vref. er sollte Vcc nehmen
nimmt aber die 1,1 V interne Referenz.
hier ist das include File adc.c
kann mir bitte jemand weiterhelfen?
PS. auf dem ATmega 32 läuft der ADC
#include <avr/io.h>
#include <avr/interrupt.h>
//#include <avr/signal.h>
#include "adc.h"
/*!
* Initialisert den AD-Umsetzer.
* @param channel Für jeden Kanal, den man nutzen möchte,
* muss das entsprechende Bit in channel gesetzt sein
* Bit0 = Kanal 0 usw.
*/
void adc_init(char channel){
DDRB &= ~ channel; // Pin als input
PORTB &= ~ channel; // Alle Pullups aus.
}
/*!
* Liest einen analogen Kanal aus
* @param channel Kanal - hex-Wertigkeit des Pins (0x01 f�r PA0; 0x02
f�r PA1, ..)
*/
int adc_read(char channel){
int result = 0x00;
// interne Refernzspannung AVCC, rechts Ausrichtung
ADMUX |= _BV(REFS0) ;//| _BV(REFS1); //|(0<<ADLAR);
//ADMUX = (0<<ADLAR);
ADMUX |= (channel & 0x07); // Und jetzt Kanal waehlen, nur single
ended
ADCSRA= (1<<ADPS2) | (1<<ADPS1)| // prescale faktor= 128 ADC l�uft
(1 <<ADPS0) | // mit 14,7456MHz/ 128 = 115,2kHz
(1 << ADEN)| // ADC an
(1 << ADSC); // Beginne mit der Konvertierung
while ( (ADCSRA & (1<<ADSC)) != 0){} //Warten bis konvertierung
beendet
// Das sollte 25 ADC-Zyklen dauern!
// also 1/4608 s
result= ADCL;
result+=(ADCH <<8); // Ergebnis zusammenbauen
return result;
}
* @param channel Für jeden Kanal, den man nutzen möchte,
6
7
* muss das entsprechende Bit in channel gesetzt sein
8
9
* Bit0 = Kanal 0 usw.
10
11
*/
12
13
voidadc_init(charchannel){
14
15
DDRB&=~channel;// Pin als input
16
17
PORTB&=~channel;// Alle Pullups aus.
18
19
}
totaler Blödsinn, da der Kommentar nicht zur Funktion passt.
Genau wie das hier:
1
//ADMUX = (0<<ADLAR);
Verschieben einer 0 um ADLAR Stellen, ergibt immer noch 0. Damit wird
das ADMUX-Register einfach mal so mit 0 überschrieben.
Dementsprechend auch die Referenzspannung.
Da es aber nur eine Kommentar ist, hat es keine Auswirkung.
Simon Roith schrieb:> Der ADC meines ATtiny 13 nimmt die falsche Vref. er sollte Vcc nehmen> nimmt aber die 1,1 V interne Referenz.
Weil du hier die interne Referenz einstellst:
das include file war schon fertig und die ganzn auskommmentierten sachen
waren auch schon da
ich wollt eig. nur das ganze umschreiben damit der controller die Vcc
als Vref nimmt.
Simon Roith schrieb:> das include file war schon fertig und die ganzn auskommmentierten sachen> waren auch schon da
Dann bereinige das.
Ab und zu mal kurz eine Codestelle auskommentieren ist schon ok.
Aber auf Dauer führt das IMMER zu Verwirrungen.
ok.
und was soll ich jetzt genau ändern damit der Controller die Vcc als
Vref nimmt und nicht die 1,1 volt?
ich blick da nicht mehr durch laut Tutorial stimmt das doch das das
ADMUX bit REFS0 gesetzt wird oder?
ADMUX |= (1<<REFS0);
Simon Roith schrieb:> ich blick da nicht mehr durch laut Tutorial stimmt das doch das das> ADMUX bit REFS0 gesetzt wird oder?
Nicht das Tutorial, das nur ein Beispiel für einen bestimmten Controller
ist, ist maßgebend, sondern das Datenblatt des tatsächlich verwendeten
Controllers. Wenn du Code von einem Controller-Typ zu einem anderen
transferierst, dann musst du schon mal im Datenblatt nachschauen, ob die
jeweiligen Details beim neuen Controller gleich sind. In diesem Fall
(Referenzauswahl bei Mega32 und Tiny13) ist es z.B. nicht gleich.
Simon Roith schrieb:> und was soll ich jetzt genau ändern damit der Controller die Vcc als> Vref nimmt und nicht die 1,1 volt?
Wir sind hier nicht im Kindergarten und binden jedem die Schuhe zu,
insbesondere wenn er hier damit kokettiert, einfach fremden Code
abzuschreiben und sich im Falle von Problemen nicht die Finger damit
schmutzig machen zu wollen, den abgeschriebenen Kram auch zu verstehen.
> ich blick da nicht mehr durch laut Tutorial stimmt das doch das das> ADMUX bit REFS0 gesetzt wird oder?>> ADMUX |= (1<<REFS0);
Diese Anweisung enthält den Fehler. Ich habe ihn beim Blick in das
Datenblatt innerhalb von vielleicht ein bis zwei Sekunden erkannt.
Simon Roith schrieb:> Im Datenblatt steht das ich das bit auf 0 setzen muss> hab ich gemacht und funktioniert wieder ned :(
Mit welcher Anweisung denn?
Simon Roith schrieb:> Im Datenblatt steht das ich das bit auf 0 setzen muss> hab ich gemacht und funktioniert wieder ned :(
WIE hast du das gemacht?
(Oder besser gesagt: Wie glaubst du, dass du das Bit auf 0 gesetzt hast.
Da du aber ganz was anderes geschrieben hast als du dachtest, ist das
Bit immer noch auf 1. Beweis: Der Tiny nimmt immer noch die 1.1V, also
ist das Referenzspannungsbit auf 1)
Das weiß ich auch das das aus dem Datenblatt ist...
ich hab geschrieben
ADMUX &=~ (1<<REFS0);
Das ist doch die richtige anweisung zum löschen eines Bits oder?
Simon Roith schrieb:> Das weiß ich auch das das aus dem Datenblatt ist...>> ich hab geschrieben>> ADMUX &=~ (1<<REFS0);>> Das ist doch die richtige anweisung zum löschen eines Bits oder?
Ja.
Wie sieht der Code rundherum aus.
Bitte: Wenn wir dir helfen sollen Fehler zu finden, dann poste
wenigstens komplette Funktionen. Oft genug sitzt der Fehler nicht dort,
wo du denkst das er sitzt.
Also das ist der code den wir in der Schule bekommen haben für den ADC:
/*
* c't-Bot
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your
* option) any later version.
* This program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307, USA.
*
*/
/*! @file adc.c
* @brief Routinen zum Einlesen der AnalogeingÄnge
* @author Benjamin Benz (bbe@heise.de)
* @date 26.12.05
*/
#include <avr/io.h>
#include <avr/interrupt.h>
//#include <avr/signal.h>
#include "adc.h"
/*!
* Initialisert den AD-Umsetzer.
* @param channel Für jeden Kanal, den man nutzen möchte,
* muss das entsprechende Bit in channel gesetzt sein
* Bit0 = Kanal 0 usw.
*/
void adc_init(char channel){
DDRB &= ~ channel; // Pin als input
PORTB &= ~ channel; // Alle Pullups aus.
}
/*!
* Liest einen analogen Kanal aus
* @param channel Kanal - hex-Wertigkeit des Pins (0x01 f�r PA0; 0x02
f�r PA1, ..)
*/
int adc_read(char channel){
int result = 0x00;
// interne Refernzspannung AVCC, rechts Ausrichtung
ADMUX &=~ (1<<REFS0);
ADMUX |= (channel & 0x07); // Und jetzt Kanal waehlen, nur single
ended
ADCSRA= (1<<ADPS2) | (1<<ADPS1)| // prescale faktor= 128 ADC l�uft
(1 <<ADPS0) | // mit 14,7456MHz/ 128 = 115,2kHz
(1 << ADEN)| // ADC an
(1 << ADSC); // Beginne mit der Konvertierung
while ( (ADCSRA & (1<<ADSC)) != 0){} //Warten bis konvertierung
beendet
// Das sollte 25 ADC-Zyklen dauern!
// also 1/4608 s
result= ADCL;
result+=(ADCH <<8); // Ergebnis zusammenbauen
return result;
}
Ich bin noch Anfänger und kann sowas noch nicht so gut selber schreiben.
Ich versuchs hald auf meine wünsche abzuändern was bisher meistens auch
geklappt had.
ADMUX|=(channel&0x07);// Und jetzt Kanal waehlen, nur single
2
ended
sehe ich jetzt allerdings nichts mehr
(Der Tiny13 hat nur 4 ADC Kanäle. Daher sollte mit 0x03 verundet werden
und nicht mit 0x07. Aber das ist jetzt nicht das Problem.)
Compiliert hat alles richtig?
Beim Brennen ist auch kein Fehler aufgetreten?
Simon Roith schrieb:> ja das Programm hab ich vom Atmega 32 auf den Attiny 13 umgeschrieben
Es geht nicht um das Programm, sondern um die Einstellungen, die für die
Kompilierung verwendet werden!!!
Simon Roith schrieb:> Compiliert wird einwandfrei mit 0 errors und 0 warnings> Programm lässt sich ohne Probleme auf den Flash brennen.
Und noch einmal:
WERDEN DIE KORREKTEN EINSTELLUNGEN FÜR DEN PROZESSORTYP VERWENDET???
Am besten, Du zeigst das GANZE programm und schreibst, was Du erwartest
und was Du stattdessen bekommst.
Das ANDen des Kanals mit 0x7 ist bei einem Tiny13 auch Mist, tut aber
nicht weh, da das überflüssige Bit don't care ist.
@Simon Roith (Gast)
>Also das ist der code den wir in der Schule bekommen haben für den ADC:
Schön, aber hast du dort auch lesen gelernt?
Wenn ja, lies mal was über Netiquette!
MFG
Falk
Simon Roith schrieb:> Also ich hab jetzt>> ADMUX |= (channel & 0x03);>> geändert und es funktioniert :))
Wenn das wirklich die Symptome des Problems verdeckt haben sollte, dann
wurde adc_read() mit einem falschen Parameter aufgerufen...
Folglich ist die Ursache noch nicht behoben; das Problem wird also bald
zurückkehren, vermutlich in wesentlich subtilerer Form. Viel Spaß bei
der Fehlersuche. :-/
in dieser schaltung wird nur 1 kanal ausgelesen. dann passt das schon.
Ich bin ja noch eifrig am lernen in sachen µC und das nächste Projekt
wird dann hoffentlich besser und fehlerfreier werden.
Simon Roith schrieb:> in dieser schaltung wird nur 1 kanal ausgelesen. dann passt das schon.
Nein. Das passt nicht.
Jeder Fehler, der scheinbar verschwindet, ohne das man die Ursache für
das Verschwinden kennt, ist eine potentielle Zeitbombe.
Merke:
Durch Testen kann man immer nur das Vorhandensein von Fehlern
nachweisen, niemals das Fehlen von Fehlern.
Wenn ein Fehler plötzlich nicht mehr auftritt, dann kann das 2 Ursachen
haben:
* der Fehler ist tatsächlich behoben worden
* der Fehler ist versteckt worden (aus irgendeinem Grund)
Hat man einen Fehler behoben, dann kennt man automatisch auch immer die
Ursache des Fehlers. Im Umkehrschluss wird daraus: Kennt man die Ursache
eines Fehlers nicht, verschwindet der Fehler aber trotzdem, dann ist es
sehr wahrscheinlich, dass man den Fehler nur versteckt hat. Der wartet
dann, bis er maximalen Schaden anrichten kann und schlägt dann
erbarmungslos erneut zu.
> Ich bin ja noch eifrig am lernen in sachen µC und das nächste Projekt> wird dann hoffentlich besser und fehlerfreier werden.
Das wird nie passieren, wenn du nicht den Ehrgeiz hast, den Dingen auf
den Grund zu gehen.
In deinem Fall zeigt das Progrmm das gewünschte Verhalten. Das hätte es
vorher auch schon tun müssen, tat es aber laut deiner Aussage nicht. Auf
jeden Fall ist die Änderung von 0x07 zu 0x03 keine Erklärung für das
plötzliche Funktionieren. D.h. du hast eine 'magische Heilung' des
Programms erlebt. Und da programmieren keine Frage des Glaubens sondern
eine Frage der Fakten ist, sollte man rauskriegen, warum dein Programm
nicht funktioniert hat, obwohl es eigentlich hätte funktionieren müssen.
Das kann jetzt ein Handling Fehler sein (falsche Hex-Datei erwischt,
Fehlermeldung vom Compiler nicht gesehen, Nicht neu gebuildet [lach
nicht, alles schon dagewesen], etc ...) oder auch etwas ganz anderes.
Simon Roith schrieb:> Ich hab ja auch ned gesagt das es mir egal ist warum der fehler weg ist.> Ich bin bereits dabei zu suchen. Wenn ich was finde werd ich es hier> posten.
Mit 0x03 funktionionierts.
Geh nochmal zurück auf 0x07. Gehts dann immer noch?
Wenn ja, dann war es irgendein Handlingproblem.
Wenn nein: Wie wird die Funktion aufgerufen?
Was vor allen Dingen das Lesen erschwert, das sind deine vielen
Leerzeilen ohne guten Grund, zusätzliche { }-Blöcke die keiner braucht.
Code der künstlich in die Länge gezogen wird, ist hauptsächlich das:
künstlich in die Länge gezogen. Aber übersichtlicher ist er nicht.
meinst du ich kann die ganzen Klammern weglassen?
Ich habs nur so gemacht wie wirs in der Schule "gelernt" haben...
Da ich es nicht anders kenn hab ichs hald so gemacht.
Bin aba für Verbesserungsvorschläge gerne zu haben.
Karl heinz Buchegger schrieb:> Auf> jeden Fall ist die Änderung von 0x07 zu 0x03 keine Erklärung für das> plötzliche Funktionieren.
Ich habe nebenbei auch mal ins DB geschaut.
Daher von mir noch eine eventuell hilfreiche Erklärung.
REFS0 ist Bit 6 des Registers ADMUX.
Mit
ADMUX &=~ (1<<REFS0);
Wird das Bit gelöscht, also Vcc als Referenz.
Mit
ADMUX |= (channel & 0x07); // Und jetzt Kanal waehlen, nur single
werden nur die Bits 0 bis 2 gesetzt (respektive 0 und 1 bei 0x03).
Es kann also garnicht sein, dass durch 0x07 das REFS0 gesetzt wird (also
interne Referenz) und durch 0x03 nicht.
Der Fehler muss also woanders liegen.
Es ist sogar so, dass der Reset-Wert von ADMUX auf "Vcc Referenz" und
"Kanal 0" steht.
@Simon Roith (Gast)
Wenn Dein Programm trotzdem die interne Referenz nimmt, muss das Bit ja
irgendwo gesetzt werden. Diese Stelle solltest Du ausfindig machen, da
dort sicherlich auch noch mehr umgestellt wird, was Dir später Sorgen
bereiten wird.
erstmal danke an alle die mich unterstützen.
bisher hab ich den Fehler noch nicht gefunden warums plötzlich geht...
kann durch aus sein das ich vergessn hab zu bilden oder so...
bin auf jedn fall weiter auf der suche und in der hoffnung einen Fehler
zu finden.
Btw, bezüglich der Kommentare
Christian H. schrieb:> merker = 1; // merker auf 1 setzen da Anlage ausgeschaltet werden soll.
"merker auf 1 setzen" kannst Du dir sparen, da das ja bereits allgemein
verständlich im Code steht "merker = 1".
Auch müsstest Du nicht schreiben (hast Du ja auch nicht):
"Merker auf 1 setzen, wenn der ADC-Wert kleiner als 716 ist, womit die
Anlage ausgeschaltet werden soll."
Simon Roith schrieb:> meinst du ich kann die ganzen Klammern weglassen?
Nein, es sollen nicht alle Klammern weggelassen werden, sondern nur
Klammern, die überflüssig sind und deren Weglassen keine Fehler
provoziert.
Leerzeilen sind auch nur zwischen semantisch getrennten Bereichen
einzuführen. Die Übersichtlichkeit wird nicht erhöht, wenn nach jeder
Zeile Programmcode eine Leerzeile kommt. Doppelte Leerzeilen haben
innerhalb eines Blockes überhaupt nichts verloren. Ich verwende solche
immer nur, um z.B. Funktionen voneinander abzugrenzen.
Normalerweise sollte zwar vor jeder Funktion ein Kopf mit Erläuterungen
stehen, aber manchmal macht es auch Sinn, einen Kopf für mehrere
Funktionen zu verwenden, WENN diese sehr kurz und einander sehr
ähnlich sind, sich aber nicht sinnvoll zusammenfassen lassen.
Beispiel:
/* Funktionsname: enable_bla, disable_bla */
void enable_bla() {
PORT = 1;
} /* enable_bla() */
void disable_bla() {
PORT = 0;
} /* disable_bla() */
Zudem sollte man auf keinen Fall das Offensichtliche kommentieren, wie
dies geschehen ist:
merker = 0; // merker auf 0 setzen
...
init(); // Aufruf des Unterprogramms init
Simon Roith schrieb:> bisher hab ich den Fehler noch nicht gefunden warums plötzlich geht...
Warum weigerst Du Dich so beharrlich, uns mitzuteilen, ob Du die
Einstellungen für den korrekten Prozessortyp vorgenommen hast?
Du versuchst immer wieder, hiervon abzulenken, indem Du auf 0 Warnungen
oder irgendwelchen C-Programmcode verweist.
wenn du mir erklärst was du mit Einstellungen für den korrekten
Prozessortyp meinst dann sag ich dir was ich gemacht hab.
aba ich kann damit jetzt eig. nur anfangen welchen prozessor typ ich
ausgewählt hab und seine taktfrequenz.
Wo wir gerade so schön dabei sind:
Man kommentiert nur, warum etwas passiert und nicht was. Außer das "was"
ist im Code nicht erkennbar.
Beispielsweise steht die 716 für eine Temperatur, die du bereits
anderweitig in einen ADC-Wert umgerechnet hast.
Kommentar:
"Anlage ausschalten, da Minimaltemperatur von 33°C (= ADC-Wert 716)
unterschritten wurde".
Aber sowas macht man auch nicht, da Konstanten besser in einer eigenen
Header-Datei als #define gesetzt werden.
1
// Minimaltemperatur unter der die Anlage ausgeschaltet wird.
2
// Hier ist der bereits umgerechnete ADC-Wert einzusetzen.
Christian H. schrieb:>> meinst du ich kann die ganzen Klammern weglassen?>> Nicht alle, aber das:{> if (adc_3 < 716)> {> merker = 1; // merker auf 1 setzen da> }> }> kannst Du kürzen in> if (adc_3 < 716) merker = 1; // Anlage soll ausgeschaltet werden
ich würde es so lassen, spätestens wenn man mal ein breakpoint auf
merker=1 setzen will, merkt man das es vorteile hat.
Wenn überhaupt dann so
1
if(adc_3<716)
2
merker=1;
ich bevorzuge sogar
1
if(adc_3<716){
2
merker=1;
3
}
aber alles auf einer Zeile macht man nun wirklich nicht.
Mir ist das hier zu blöd. Das ist doch pure Zeitverschwendung. Statt
endlich einmal eine Aussage zu den Einstellungen zu machen, wird der
Ball an mich zurückgespielt?
Du hast bisher keinerlei Aussagen über die eingesetzte
Entwicklungsumgebung gemacht. Vermutlich handelt es sich um irgendetwas
auf Basis von GCC. Aber mehr dürfen wir ja nicht erfahren, sondern
müssen in die Glaskugel schauen.
Soll ich hier wirklich für die tausend verschiedenen GCC-basierten
Entwicklungsumgebungen die Einstellmöglichkeiten herausfinden? Das kann
ich gerne tun, aber bitte nicht für lau. Gerne erstelle ich ein
entsprechendes Beratungsangebot.
Simon Roith schrieb:> meinst du ich kann die ganzen Klammern weglassen?
Alle nicht.
> Ich habs nur so gemacht wie wirs in der Schule "gelernt" haben...
Schau dir einfach mal deine Kommentare an.
Welche Kommentare sagen genau dasselbe aus, wie das was im Code sowieso
steht.
zb hier
1
merker=0;// merker auf 0 setzen
Im Code steht merker = 0; im Kommentar steht, dass merker auf 0
gesetzt wird. Ist 100% genau dasselbe. Solche Kommentare bringen nichts!
Ein Kommentar soll mir Dinge erzählen, die ich nicht im Code sehe! Zu
bevorzugen ist es allerdings, wenn mir bereits der Code alles erzählt.
Welche Aufgabe hat den merker? Er soll dem Programm anzeigen, dass der
Strom abzuschalten ist, wenn er 1 ist (das also das System
runterzufahren ist). Warum nennst du das dann merker? Nenn es doch
stromAus oder performShutdown oder so. Wenn du dir dann noch
Deifinitionen für TRUE und FALSE reinziehst (oder selber machst), dann
steht im Code
1
performShutdown=FALSE;
2
3
...
4
5
if(adc_3<716)
6
performShutDown=TRUE;
7
8
...
9
10
if(performShutdown==TRUE)
11
{
12
...
13
}
wenn du dir diesen Code durchliest, nur lesen, dann erzählt dir der Code
alles was du wissen musst. Der Code ist sein eigener Kommentar.
1
PORTB|=(1<<PB1);// LED gelb einschalten, BATTERIE SCHWACH
an PB1 ist offenbar eine gelbe Led, die Battery Low signalisiert.
Dann definiere dir doch ein paar Konstanten dafür
1
#define BATTERY_LOW_LED PB1
2
3
...
4
5
PORTB|=1<<BATTERY_LOW_LED;
... und schon wieder ist der Code selbsterklärend geworden.
Wann immer du einen Kommentar schreiben willst, überleg dir zuerst ob
und wie man den Code umarbeiten könnte, so dass es diesen Kommentar
überflüssig macht.
> Da ich es nicht anders kenn hab ichs hald so gemacht.>> Bin aba für Verbesserungsvorschläge gerne zu haben.
Peter schrieb:> Wenn überhaupt dann so> if (adc_3 < 716)> merker = 1;
Das ist ausgeprochen fehlerträchtig. Wie oft kommt es vor, dass man
solch eine Abfrage um eine Kleinigkeit ergänzt, und sei es nur um eine
temporär eingefügte Debug-Ausgabe?
if (adc_3 < 716)
merker = 1;
printf("Merker gesetzt.\n");
> ich bevorzuge sogarif (adc_3 < 716) {> merker = 1;> }
So ist es wesentlich besser.
Man beachte, dass es durchaus auch moderne Sprachen gibt, bei denen die
Einrückungen inhaltliche Bedeutungen haben, z.B. Python. Dort umgeht man
das gesamte Blockklammerproblem nämlich ausschließlich durch
Einrückungen; anfangs ist das gewöhnungsbedürftig, aber man gewöhnt sich
sehr schnell daran. Und anschließend weiß man sogar, dass alle
Einrückungen korrekt sind bzw. dem tatsächlichen Programmfluss
entsprechen.
Simon Roith schrieb:> Ich Arbeite mit AVR - Studio. Programmiert wird der controller über das> PonyProg und der ISP dongle.
Warum nicht gleich so?
Ganz korrekt scheint die Angabe aber nicht zu sein, denn AVR Studio
enthält überhaupt keinen C-Compiler.
Trotzdem wurde noch keine Aussage darüber getroffen, ob im AVR Studio
unter Project->Configuration Options->General->Device der richtige
Prozessortyp ausgewählt wurde, und zwar für jede der möglichen
Konfigurationen.
Diese Einstellungen müssen übrigens nicht die gleichen sein wie im
Connect-Menü für das Programmieren des Controllers!!! Dort kann man
einen ganz anderen Typ auswählen.
Die die jeweils ausgewählten Typen nicht hinreichend kompatibel
zueinander sein sollten, kann es sehr interessante Effekt geben.
Also um im AVR-Studio C schreiben zu können hab ich noch WIN AVR
installiert.
bei Device hab ich den Attiny 13 ausgewählt.
ach ja übrigens stimmt die Frequenz in meinem Quellcode (Kommentierung
am anfang) nicht da steht 14.7456 MHz.
hab ich vergessn zu ändern.
Welche Logik soll hier eigentlich implementiert werden?
Ich denke, das kann man auch einfacher schreiben. Aber dazu muss ich
genau wissen, wie das Zusammenspiel von LEDs und Schalter sein soll.
Sollen die LED auch etwas anzeigen, wenn die Anlage ausgeschaltet ist?
grün leuchtet wenn die batterie über 11,30V hat und der Radio
eingeschaltet ist.
gelb leuchtet wenn sie batterie darunter ist
und rot leuchtet wenn sie 10,50V unterschreitet.
wenn 10,50 unterschreitet wird dann geht grün und gelb aus und rot
leuchtet nur noch.
Ausserdem zieht derhaft ein Relais. Dieses fällt erst ab wenn man einen
Reset durchführt (zündung kurz ausschalten und wieder einschalten).
// Wenn ja, dann Batteriespannung auswerten und anzeigen
85
//
86
if(bit_is_set(PINB,PINB2))
87
{
88
//
89
// Je nach Zustand der Batteriwspannung die richtigen
90
// Led einschalten
91
//
92
if(battery<BATTERY_LEVEL_CRITICAL)
93
{
94
TURN_ON(BATTERY_CRITICAL_LED);
95
TURN_OFF(BATTERY_LOW_LED);
96
TURN_OFF(BATTERY_GOOD_LED);
97
}
98
99
elseif(battery<BATTERY_LEVEL_LOW)
100
{
101
TURN_OFF(BATTERY_CRITICAL_LED);
102
TURN_ON(BATTERY_LOW_LED);
103
TURN_OFF(BATTERY_GOOD_LED);
104
}
105
106
else{
107
TURN_OFF(BATTERY_CRITICAL_LED);
108
TURN_OFF(BATTERY_LOW_LED);
109
TURN_ON(BATTERY_GOOD_LED);
110
}
111
}
112
113
//
114
// Anlage ist ausgeschaltet
115
//
116
else
117
{
118
TURN_OFF(BATTERY_CRITICAL_LED);
119
TURN_OFF(BATTERY_LOW_LED);
120
TURN_OFF(BATTERY_GOOD_LED);
121
}
122
}
123
}
PS: Das Relais ist da jetzt noch nicht berücksichtigt. Das war bei dir
wohl die Varable merker. Nenn sie nicht merker, sondern von mir aus
powerRelais. Ziel ist es wieder, dass Kommentare an den einzelnen
Anweisungen überfüssig werden, weil der Code, wenn man ihn liest
selbsterklärend ist.
der code ist echt spitze danke für das beispiel und deine Bemühung!!!
Beim starten des Motors hab ich gerade festgestellt das kurzzeitig die
spannung auf unter 10,5 V geht.
Wie müsste ich den das jetzt schreiben das wenn die Batteriespannung
länger als 3 sekunden unter 10,50 ist das dann erst das Relais anzieht?
hab einige varianten probiert aba klappt alles nicht.
Simon Roith schrieb:> Wie müsste ich den das jetzt schreiben das wenn die Batteriespannung> länger als 3 sekunden unter 10,50 ist das dann erst das Relais anzieht?
Du brauchst so etwas wie einen Zeitgeber.
Da du keine besonderen Anforderungen hast, könnte man zb so vorgehen.
Mit einem _delay_ms bringt man einen Durchlauf durch die while(1)
Schleife auf eine bekannte Zeitdauer von zb 100ms.
3 Sekunden sind dann 30 Durchläufe durch die while Schleife. D.h. du
lässt dein Relais erst dann anziehen, wenn die Spannung 30 mal
hintereinander im critical Bereich liegt.
Ich denke die Lösung mit dem _delay_ms ist hier vertretbar
* zum einen nimmt es Rücksicht darauf, dass du noch nicht
viel Erfahrung hast
* zum anderen ist dein Programm nicht zeitkritisch. Wenns mal eine
kleine Verzögerung gibt, ist das nicht so schlimm
1
#define F_CPU .... // hier deine Taktfrequenz in Hz eintragen
2
...
3
#include<util/delay.h>
4
...
5
6
intmain()
7
{
8
uint8_tnrBatteryCritical=0;// wie oft war die Batteriespannung im kritischen Bereich
9
10
...
11
12
while(1)
13
{
14
....
15
16
if(battery<BATTERY_LEVEL_CRITICAL)
17
{
18
TURN_ON(BATTERY_CRITICAL_LED);
19
TURN_OFF(BATTERY_LOW_LED);
20
TURN_OFF(BATTERY_GOOD_LED);
21
22
if(nrBatteryCritical<29)
23
nrBatteryCritical++;
24
else
25
{
26
// Relais abschalten, da 3 Sekunden lang critical
27
}
28
}
29
30
elseif(....)
31
{
32
....
33
nrBatteryCritical=0;
34
}
35
36
else
37
{
38
...
39
nrBatteryCritical=0;
40
}
41
}
42
43
_delay_ms(100);
44
}
45
}
Sobald die Spannung kritisch wird, wird der Zähler erhöht (wenn nicht
schon die Grenze erreicht ist). Erholt sich die Spannung, kommt man
irgendwann aus dem kritischen Bereich raus und in den anderen Zweigen
wird der Zähler auf 0 zurückgesetzt. Erholt sich aber die Spannung nicht
mehr, dann wird der Zähler immer weiter erhöht, bis irgendwann die
Grenze erreicht ist und als Folge davon das Relais abschalten.
Fazit: Wird die unterste Schwelle überschritten, so wird das zwar sofort
angezeigt, die Folgeaktion "Relais abfallen lassen" wird aber erst
zeitverzögert ausgeführt.
Tja. Da musst du jetzt durch.
Wenn du das Prinzip verstanden hast, sollte das eigentlich kein Problem
sein rauszufinden, wo was hinmuss. Ich habs ja im Vorschlag ohnehin
angedeutet, indem ich die nicht relevanten Teile mit ... abgekürzt habe.
Den Anfang geb ich gerne vor, aber letzten Endes schreibst DU das
Programm und nicht ich.
ja ich habs mir schon gedacht das da bei den (....) noch was fehlt
desweng gings mitn compilieren auch ned.
Find ich gut von dir das du mir nicht einen fertigen code gibts weil das
ist nicht das ziel.
ich will das ja selber ein bisschen können.
bin in ausbildung zum elektroniker für geräte und systeme da macht ma
leida ned viel mit µC...
Ich find das Thema allerdings sehr intressant und versuch mich auf
eigene weiße weiter zu bilden.
Danke nochmals für die Hilfe :)
Simon Roith schrieb:> hab ihr das Programmieren eigentlich gelernt weil ihr euch so gut> auskennt ober ist das alles Hobbymäßig?
LOL
Die Zeiten als das hobbymässig gemacht wurde sind schon lange vorbei :-)
Seit 25 Jahren verdien ich meine Brötchen damit. (*)
Aber nur damit da jetzt kein falscher Eindruck entsteht: In diesem
Metier hat man nie ausgelernt. Jeden Tag lernt man Neues dazu.
(*) und damals gabs noch kein Internet und ein Forum, in dem man schnell
einmal nachfragen konnte.
gott sei dank gibt es das internet :)
und Profis die sich auskennen.
hab ne andere lösung für mein problem gefunden
werde morgen meinen code hier posten.
nen schönen Abend noch