Archiv verlassen und diese Seite im Standarddesign anzeigen : Spannung auslesen
runner02
02.08.2010, 18:11
Hallo Leute,
Habe mich noch einmal intensivst damit beschäftigt, edlich den ADC meiner AVRs bedienen zu können...
Nun habe ich einiges herausgefunden, doch ein paar Fragen habe ich noch.
Hier mal der gesamte Beispielcode (Auszug aus http://www.rn-wissen.de/index.php/ADC_%28Avr%29 )
#include <avr/io.h>
#include <inttypes.h>
uint16_t readADC(uint8_t channel ) {
uint8_t i;
uint16_t result = 0;
// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
// Kanal des Multiplexers waehlen
// Interne Referenzspannung verwenden (also 2,56 V)
ADMUX = channel | (1<<REFS1) | (1<<REFS0);
// Den ADC initialisieren und einen sog. Dummyreadout machen
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));
// Jetzt 3x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<3; i++) {
// Eine Wandlung
ADCSRA |= (1<<ADSC);
// Auf Ergebnis warten...
while(ADCSRA & (1<<ADSC));
result += ADCW;
}
// ADC wieder deaktivieren
ADCSRA &= ~(1<<ADEN);
result /= 3;
return result;
}
int main(void) {
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an Pin 0,
// also ADC0. In result steht das Ergebnis.
return 0;
}
Der 'Kanal des Multiplexers' heißt in diesem Fall PortB1 oder auch ADC1 ??
Die interne Referenz ist 2,56 V. Dazu muss ich noch einen Kondensator (mit 15pF ?) an AREF schalten?
Wohin gibt die Funktion die Variable 'result' eigentlich zurück?
Hier... Im letzten Absatz, für was ist der gut?? Da ruft man einfach eine neue Funktion auf, die das Ergebnis ausliest? Wieso heißt das result = read ADC(0)? Wieso fragt man nicht direkt die Variable ab? Oder fragt man hier den AD-Converter, welchen Wert er als letzten draufhatte?? Und das return 0 heißt, er springt wieder zum Anfang zurück und misst wieder die Spannung (Endlosschleife?)??
Ist dies eine Funktion? Die Schreibweise sieht so aus...
Was heißt hier das Channel?
Auf jeden Fall Danke im Vorraus!!
BurningWave
02.08.2010, 19:19
Fangen wir mal von hinten an: channel ist eine Variable des Typs uint8_t, die der Funktion (ja das ist eine Funktion) beim Aufrufen als Parameter übergeben wird. Statt uint8_t könnte man auch char als Typ nehmen (hat beides 8 Bit). Im letzten Absatz in der Hauptfunktion (main()), die ja beim Starten des Programms ausgeführt wird, wird eine Variable des Typs uint16_t (16 Bit) erzeugt, die result heißt. In ihr wird der Wert, den die Funktion readADC (die oben definiert ist) zurück gibt, gespeichert. Das zurückgeben geschieht mit "return result" (result ist der digitalisierte Analogwert). Das return 0 in main() tut nichts weiter, als das Programm zu beenden, also eine 0 aus main() zurück zu geben.
Hier: http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC steht die Beschaltung von AREF
channel ist an dieser Stelle der Parameter der Funktion readADC. Hier musst du nichts verändern. Beim Funktionsaufruf musste du nur eine Zahl, angeben, also nichts mit PORTB oder so. Duch diesen Befehl werden die entsprechenden MUXx Bits im ADMUX Register gesetzt (näheres siehe Link).
Ich hoffe das bringt dich weiter.
mfg
runner02
03.08.2010, 10:03
Das heißt, zuerst ruft der Chip die Funktion Main auf (eigentlich klar), und dort steht uint16_t result = readADC(0); . Das heißt, er springt nach oben und benutzt den Quellcode zum Auslesen?
channel ist eine Variable des Typs uint8_t, die der Funktion (ja das ist eine Funktion) beim Aufrufen als Parameter übergeben wird.
Könnte ich sie statdessen auch x oder xyz nennen?
Beim Funktionsaufruf musste du nur eine Zahl, angeben, also nichts mit PORTB oder so. also result, die gibt er sich selber, oder? Oder ist hier das void bzw. 0 gemeint?
Danke soweit mal,
das hat mir schon einiges geholfen... =D>
Er ruft die Funktion auf und benutzt den Code der dort steht um den ADC auszulesen.
Du kannst einer Variable sogut wie jeden Namen geben so lange der sich an den C-Standard hält. (Schau im Wiki nach, da steht drin was für namen alles erlaubt sind, bin mir grad nicht mehr ganz sicher)
Wie meinst du das mit ?:
also result, die gibt er sich selber, oder? Oder ist hier das void bzw. 0 gemeint?
Also der Variable Result wird in der Funktion ein Wert zugewiesen, und dieser zurückgegeben--> return result;
runner02
03.08.2010, 14:48
Habe das ganze mal in mein Programm geschrieben,
Dabei hat sich mir schnell noch eine Frage aufgedrängt:
das Resultat ist vom Typ uint16_t Also integer mit 16 Zeichen.
Nun, Ich habe dann geschrieben
uint16_t spannung;
spannung=result*3.125
Dann müsste die Spannung in Millivolt ausgegeben werden. Allerdings wird der Compiler aufschreien, da - sofern ich mich richtig erinnere, keine FLießkommawerte erlaubt sind... Sollte ich char oder float nehmen? Oder uchar16_t ?
@shedepe: Hat sich erledigt, trotzdem Danke für dein Bemühen
(readADC ist die Funktion, wenn man sie aufruft gibt man readADC(0) ein, dann muss man an ADC0 anlegen)
uint16_t ist ein integer mit 16bit nicht mit 16 Zeichen.
Schau dir Festkomma-arithmetik an. Floats sind auf Atmegas ziemlich speicher und rechenintensiv.
BurningWave
03.08.2010, 19:07
uint16_t spannung;
spannung=result*3.125
Dann müsste die Spannung in Millivolt ausgegeben werden.
Nein, so einfach ist das nicht: result beinhaltet einen 10 Bit Wert. Wobei 0b0 das niedrigste Ergebnis ist, das der ADC liefern kann und 0b1111111111 (=1024) das Höchste (es würde deinen 3,125V enstprechen). Du kannst es so umrechnen:
float fErgebnis = (float)(result) / 1024.0f * 3.125f;
runner02
03.08.2010, 20:05
(es würde deinen 3,125V enstprechen)
Ich glaube da hast du mich unterschätzt. Meine Versorgungsspannung ist 3,2V, daher entspricht ein erfassbarer Schritt exact 3,125mV (3,2/1024)...
;) Also könnte ich
float spannung = result * 3.125; nehmen (?)
Hey ich habe noch ein riesen Problem: Ich habe versucht, den Code auf meinen Chip zu spielen. Allerdings tauchen unzählige Fehler auf... Er kennt alle Ausdrücke nicht wie ADMUX, ADCSAR, ADEN,... 'not found on the scope'
aber, wie es in dem Beispiel link stand, habe ich #include <inttypes.h> dazugeschrieben, trotzdem kennt er die Befehle nicht...
BurningWave
03.08.2010, 20:57
OK, ich habe dann deinen Rechenweg oben nicht ganz verstanden, das stimmt dann natürlich.
Also inttypes.h definiert nur die verschiedenen int-Varianten (uint8_t, uint16_t,...), in der Datei avr/io.h werden alle Register usw. definiert. Hast du in den Projekteinstellungen den richtigen Typ des µCs angegeben? Es kann auch sein, dass die Register deines µCs anders heißen, dazu solltest du in dem Datenblatt deines Controllers nachschauen.
Hast du dir schon mal ein anständiges AVR-GCC Tutorial durchgelesen und auch durchgearbeitet? Wäre vllt. besser bevor du noch weitere tausende fragen wegen Kleinigkeiten stellst ?!
So mal als anhaltspunkte:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
http://www.rn-wissen.de/index.php/Avr-gcc
http://www.rn-wissen.de/index.php/C-Tutorial
mfg shedepe
runner02
04.08.2010, 08:41
Hast du dir schon mal ein anständiges AVR-GCC Tutorial durchgelesen und auch durchgearbeitet? Wäre vllt. besser bevor du noch weitere tausende fragen wegen Kleinigkeiten stellst ?!
Ja natürlich. Aber es tauchen immer wieder ungereimtheiten auf, die mir dann erst im Nachhinein (also nachdem sie mir jemand erklärt hat) klar sind.
runner02
04.08.2010, 13:26
Ich habe nun im Datasheet nachgesehen, die Befehle stimmen alle...
(http://www.atmel.com/dyn/resources/prod_documents/doc2535.pdf Seite 81)
Wieso kennt er nun immer nicht ADEN, ADMUX und co?
Ich glaube man muss mit include noch was einbinden, sonst kennt er es nicht... (Oder sollte gar mein Programm zu lange sein? glaube ich kaum)
Kompilierst du auch für den richtigen Controller ?
runner02
04.08.2010, 21:37
Kompilierst du auch für den richtigen Controller ?
Da bin ich mir relativ sicher, habe seit dem letzten Programm (Blinklicht, das funktionierte) nichts mehr an den Einstellungen verändert, nutze noch den selben Chip.
BurningWave
04.08.2010, 21:46
Ich nehme an, du benutzt AVR Studio? Wenn ja, muss man die Einstellungen für jedes Projekt vornehmen. Öffne die Projekteinstellungen und überprüfe den eingestellten Controllertyp unter Device.
runner02
05.08.2010, 14:04
Ich benutze my AVR workpad Plus...
Gestern hatte ich leider keine Zeit mehr, heute habe ich nachgesehen:
Es war der Chip eingestellt, das war kein Problem... Aber unter // Prozessor hatte ich geschrieben 'Attiny 13 od Attiny 26' und das mochte er nicht (obwohl es im Kommentar war)
Nun ließ er es zu. Die Errorliste wurde plötzlich ganz klein, doch etwas stimmt noch nicht...
''Hinweis: Es wird die im Quelltext angegebene Sprache verwendet: C
Hinweis: Es wird die im Quelltext angegebene Einstellung des Prozessors verwendet: Attiny13
compilieren ...
Spannungsmesser.cc In function 'uint16_t readADC(uint8_t)':
Spannungsmesser.cc:29 29: error: 'REFS1' was not declared in this scope
''
ich bin scheinbar schon ganz knapp dran...
Ich bin mir nich ganz sicher (Bin das Datenblatt nur ganz kurz durch) Aber gibt es beim Attine überheipt ein REFS1 ? musst du noch mal im Datenblatt nachschaun bei ADC- Registerüberblcik
runner02
05.08.2010, 16:11
Also ich habe mit Str+F (Suchfunktion) REFS1 schon gefunden...
Ich weiß nicht, irgendwie sollte der schon gehen... Was ist, wenn ich es einfach mal weglasse(?)
BurningWave
05.08.2010, 19:06
Der ATTiny13 hat nur ein REFS0, aber kein REFS1.
Die genaue Bedeutung wird auf Seite 91 im Datenblatt ( http://www.atmel.com/dyn/resources/prod_documents/doc2535.pdf ) erklärt. Ich würde REFS0 an deiner Stelle aber nicht setzen, da der µC, wenn das Bit gesetzt ist, als Referenzspannung des ADC eine interne Referenzspannung benutzt, wenn es nicht gesetzt ist, benutzt er Vcc als Referenz.
runner02
06.08.2010, 09:53
Ah, danke.
Das heißt jetzt müsste es gehen??
Das wäre ja echt mega!
D.h. ich setze (werder REFS0) noch REFS1 ... Probiere ich gleich mal aus
Schau halt im Datenblatt nach, was es bedeutet REFS0 zusetzen (oder auch nicht zusetzen). Datenblatt lesen ist nich alzu schwierig, wenn man sich erst mal rangetraut hat. Die wahl der Referenzspannung hängt davon ab wie stabil dein VCC ist, welchen Spannungsbereich du messen willst usw.
Aber ja sollte funzen wenn du keins der beiden bits setzt
runner02
06.08.2010, 18:49
Zum Uploaden auf den Chip klappt es endlich!!
aber irgendwas (Wackelkontakt) muss noch in meiner Schaltung sein, denn es läuft nicht...
Ich habe es einprogramiert, dass sobald die Spannung zwei Werte erreichen sollte jewils eine Led blinken soll, wenn nicht leuchten beide. Nun leuchtet aber nix...
BurningWave
06.08.2010, 18:57
Dann zeig uns mal deinen Code.
Um Hardwarefehler auszuschließen kannst du mal ein Programm schreiben, das die LEDs einfach einschält. Wenn sie nicht leuchten, weißt du, dass irgendwas an deiner Schaltung nicht stimmt.
Hast du die LEDs auch schon mal einzeln. Also unabhängig vom ADC-Messwert getestet ?
Poste vllt auch noch einmal das gesamte Programm.
PS. Wenn du eine möglichkeit hast die Daten (z.B. auf ein Display oder an den PC) auszugeben. Sende doch die ADC-Messwerte erst einmal an den PC
runner02
07.08.2010, 12:24
//----------------------------------------------------------------------
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <inttypes.h>
//----------------------------------------------------------------------
uint16_t readADC(uint8_t channel)
{
// Funktion 1 zum Auslesen der Spannung
uint8_t i; // Variablen definieren (Zählervariable i + Resultat)
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
// wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 (Tabelle Datasheet)
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
int main (void) // Hauptprogramm, startet bei Power ON und Reset
{
float spannung; //Definiere Variable
DDRB=0b00001111;
while (true)
{
uint16_t result = readADC(0); // ruft die ADC Funktion auf an Pin0 =ADC0
return 0;
spannung=0.003086*result;
waitMs(400);
if (1.5<spannung<1.7)
{
PORTB=PORTB|(1<<PB1);
waitMs(600);
PORTB=PORTB&(~(1<<PB1));
}
if ((spannung>1)&(spannung<1.1))
{
PORTB=PORTB|(1<<PB2);
waitMs(600);
PORTB=PORTB&(~(1<<PB2));
}
else
{
PORTB=PORTB|(1<<PB1)|(1<<PB2);
waitMs(600);
PORTB=PORTB&(~(1<<PB1))&(~(1<<PB2));
}
}
}
_____
So, das wäre der Code
Dazu wäre noch zu sagen: ich nehme einen Spannungsteiler aus 2 oder 3
330Ohm Widerständen bei einer Spannung von 3,16V -> Daher wird bei 2 Widerständen rund 1,6 V in der Mitte abfallen
Nimm größere Widerstände. Sonst fließt da ja ein nennenswerter Strom den du in Wärme umwandelst.
also in deiner endlosschleife.
while(true)
{
return 0; //Sollte nicht drin vorkommen. Da geht er aus deiner Schleife raus weil er die MainFunktion als beendet sieht.
}
Und dir fehlt auch noch eine Konvertierung in float. Sonst geht die Zeile:
spannung=0.003086*result;
nicht.
BurningWave
07.08.2010, 15:05
Bitte benutze Code-Tags und rücke deinen Code richtig ein, sonst hat niemand Lust den Code zu lesen!
Also wie schon gesagt: return 0; gehört vor die letzte geschweifte Klammer, die main() schließt, da return aus der aktuellen Funktion zurückspringt und in diesem Fall das Programm beendet.
Außer dem ist "if (1.5<spannung<1.7)" Unsinn, da solche Vergleiche nicht das bewirken, was du willst, es müsste "if((spannung > 1.5) && (spannung < 1.7))" heißen, genauso wie hier: "if ((spannung>1)&(spannung<1.1))" statt & schreibt man && wenn man den logischen Operator meint.
PORTB=PORTB|(1<<PB1); schreibt man besser PORTB |= (1 << PB1); und PORTB=PORTB&(~(1<<PB2)); sollte besser PORTB &= ~(1 << PB2); lauten. Beide Schreibweisen funktionieren, jedoch ist letzteres besser, da es kürzer und übersichtlicher ist.
Was hängt jetzt genau an deiner ADC-Pin? Ich würde am besten ein Poti dranhängen (ca. 10 - 100k), dessen Schleifer am µC hängt und die beiden anderen Kontakte jeweils an Vcc bzw. GND.
EDIT: 500. Beitrag :P
runner02
09.08.2010, 09:56
Was hängt jetzt genau an deiner ADC-Pin? Ich würde am besten ein Poti dranhängen (ca. 10 - 100k), dessen Schleifer am µC hängt und die beiden anderen Kontakte jeweils an Vcc bzw. GND.
Also vorerst habe ich mal zwei 330 Ohm angehängt und n der Mitte die Spannung angezapft...
Dh. ich muss result erst in eine float umwandeln?
BurningWave
09.08.2010, 13:29
Also vorerst habe ich mal zwei 330 Ohm angehängt und n der Mitte die Spannung angezapft...
Nimm ein Poti, wie ich es gesagt habe, das ist besser.
Dh. ich muss result erst in eine float umwandeln?
Nicht unbedingt, ist aber schöner, also (float)(result)
Hast du die anderen Fehler behoben und das mit den LEDs ausprobiert? Wenn ja, funktioniert es?
runner02
09.08.2010, 19:04
Hast du die anderen Fehler behoben und das mit den LEDs ausprobiert? Wenn ja, funktioniert es?Leider noch nicht.
Ich habe mir vor kurzem ein neues Steckraster-Board gekauft und da hatte ich noch gewisse Anfangsprobleme. Sobald ich aber einen Schritt weiter bin, poste ich dies natürlich gleich ;)
runner02
10.08.2010, 12:03
So, das Board geht erst mal, waren nur kleine Verbindungsdenkfehler mit fataler Wirkung ;)
Naja, also den Code hab ich auch gerade ausgebessert und lade ihn jetzt auf den Chip.
Fehlercode scheint auf:
""
brennen ...
benutze: mySmartUSB MK2 an com3 mit ATtiny13
USB-Treiber installiert, aktiv (V 5.4.24.0), Port: com3
Prozessor: ATtiny13
schreibe 2968 Bytes in Flash-Memory ...
Fehler: beim Überprüfen der geschriebenen Daten.
Erste Abweichung bei Byte 0 , "0x09" != "0x01"
""
Dann poste ich noch mal den korrigierten Code:
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <inttypes.h>
//----------------------------------------------------------------------
uint16_t readADC(uint8_t channel)
{
// Funktion 1 zum Auslesen der Spannung
uint8_t i; // Variablen definieren (Zählervariable i + Resultat)
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
// wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 (Tabelle Datasheet)
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
int main (void) // Hauptprogramm, startet bei Power ON und Reset
{
float spannung; //Definiere Variable
DDRB=0b00001111;
while (true)
{
uint16_t result = readADC(0); // ruft die ADC Funktion auf an Pin0 =ADC0
(float) (result);
spannung=0.003086*result;
waitMs(400);
if ((spannung > 1.5) && (spannung < 1.7))
{
PORTB=PORTB|(1<<PB1);
waitMs(600);
PORTB=PORTB&(~(1<<PB1));
}
if ((spannung>1)&& (spannung<1.1))
{
PORTB=PORTB|(1<<PB2);
waitMs(600);
PORTB=PORTB&(~(1<<PB2));
}
else
{
PORTB=PORTB|(1<<PB1)|(1<<PB2);
waitMs(600);
PORTB=PORTB&(~(1<<PB1))&(~(1<<PB2));
}
}
return 0;
}
Beide Schreibweisen funktionieren, jedoch ist letzteres besser, da es kürzer und übersichtlicher ist. Naja, der Verständlichkeit gegenüber Anfängern halber bevorzuge ich a=a|... statt a|=a denn zu Anfang konnte ich mir |= nicht erklären und fand es auch nirgendwo im Internet... als ich las, das ist das selbe wie =...|... war alles sofort klar!
BurningWave
10.08.2010, 12:18
So, das Board geht erst mal, waren nur kleine Verbindungsdenkfehler mit fataler Wirkung
Heißt das, dass das mit den LEDs funktioniert, und dass der µC auf jeden Fall läuft?
Es gibt 3 Möglichkeiten, warum du den Fehler bekommst:
1. Der µC ist defekt (verfused?)
2. Es gibt Verbindungsprobleme.
3. Der µC läuft nicht (evtl. zu niedrige Spannung, falscher Quarz,...)
Könnte der µC durch deinen Verbindungsfehler kaputt gegangen sein?
Edit:
Noch ein Fehler:
Das muss so heißen: spannung=0.003086*(float) (result);
runner02
10.08.2010, 12:23
Heißt das, dass das mit den LEDs funktioniert, und dass der µC auf jeden Fall läuft?
Nein. ich habe mir einen baugleichen ATtiny13 damals gekauft, und der hat ein Blinkprogramm drauf.
Das heißt also lediglich, dass die Kontakte nun passen.
Der Computer hat ja nen Error ausgegeben, dh. der Chip wird nicht funzen...
Edit: den (float) (result) habe ich jetzt geändert. Trotzdem Fehlermeldung.
BurningWave
10.08.2010, 12:26
Funktioniert das Blinkprogramm? Hast du ein Indiz, dass der µC läuft?
Wenn nein, überprüfe deine Schaltung und Verbindung, poste am besetn den Schaltplan. Tausche dann den µC aus und überprüfe, ob der µC erkannt wird.
runner02
10.08.2010, 12:30
Naja, ich nehme sehr stark an, dass der Chip läuft. Denn ich habe ihn (leider) schon ein paar mal (3-4 mal) falsch beschalten, und er ging immer noch. Spätestens das Programm neu draufbrennen und geht wieder. Nun passiert aber der Fehler beim neu draufbrennen also muss der Fehler im Code sein...
Tausche dann den µC aus und überprüfe, ob der µC erkannt wird. Wer soll ihn erkennen?
Ich habe dazu die altbewährte Minimalbesschaltung, um es einfacher zu gestalten. Also VCC auf Plus, GND auf -, PB0 und PB2 über 330 Ohm zu LED nach Ground.
BurningWave
10.08.2010, 12:42
Wenn sich der Chip nicht brennen lässt, liegt der Fehler auf jeden Fall NICHT im Code, da es eine andere Sache ist, ob der Code funktioniert oder, ob der µC funktioniert.
Dein Computer, genauer dein Programmer soll den Chip erkennen ;)
Wenn deine Schaltung schon einmal funktioniert hat und es plötzlich nicht mehr funktioniert, liegt es sicher am µC (also defekt), es sei denn, du hast irgendwas verändert oder deine SChaltung hat einen Wackelkontakt, Poste eben mal den Schaltplan.
Programmierst du den µC per ISP (also direkt in deiner Schaltung) oder mit dem myMultiProg von myAVR?
Wer soll ihn erkennen?
Ich habe dazu die altbewährte Minimalbesschaltung, um es einfacher zu gestalten. Also VCC auf Plus, GND auf -, PB0 und PB2 über 330 Ohm zu LED nach Ground.
Der Reset Pin sollte mit ~ 10k auf VCC gelegt werden, sonst kann
es passieren das der µC nicht läuft/anläuft. An dein Programm selber
wird es kaum liegen das Dein Programmer den µC nicht findet/erkennt!
Entweder hast Du noch Hardwahre Fehler oder der µC ist hinnüber. :-)
Gruß Richard
runner02
11.08.2010, 20:55
Wenn sich der Chip nicht brennen lässt, liegt der Fehler auf jeden Fall NICHT im Code, da es eine andere Sache ist, ob der Code funktioniert oder, ob der µC funktioniert.
Ich spiele mal den alten Blinkcode auf den Chip, wenn der dann geht (was ich vermute) ist noch ein Fehler im Code drinnen....
An dein Programm selber
wird es kaum liegen das Dein Programmer den µC nicht findet/erkennt!
Ich habe ja schon mehrere Programme draufgebrannt, und gegangen ist alles immer. Dass er ihn erkennen sollte wusste ich nicht, klingt aber logisch...
Wie gesagt, geklappt hats bisher trotzdem.
BurningWave
11.08.2010, 21:15
Ich spiele mal den alten Blinkcode auf den Chip, wenn der dann geht (was ich vermute) ist noch ein Fehler im Code drinnen....
Wird nicht gehen, wetten?
Es ist dem Chip und dem Programieradapter TOGALEGAL was Du
ins Flasch schreibst, ein Programm oder "hallo". Wenn da keine oder
eine fehlerhafte Verbindung vorliegt, klappt das nicht. Wenn der Chip
defeckt oder dessen Fuses nicht richtig gesetzt sind klappt das auch
nicht und Du kannst auch x mal Glück haben wenn falsch verdrahtet
wurde bei x+1 ist er dann halt hin.
Gruß Richard
runner02
12.08.2010, 15:21
Ok, hab mal das alte Blinkprogramm auf den Chip gespielt und ratet mal...
Es ging ohne Probleme zum draufspielen! Keinerlei Fehlermeldungen.
Naja, schon mal die halbe Miete dachte ich mir und schließe ihn an meine Platine an... Und... Sie blinkt mit dem Code, den sie Blinken sollte.
Also ist der Fehler 100 %ig im Code!!
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <inttypes.h>
//----------------------------------------------------------------------
uint16_t readADC(uint8_t channel)
{
// Funktion 1 zum Auslesen der Spannung
uint8_t i; // Variablen definieren (Zählervariable i + Resultat)
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
// wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 (Tabelle Datasheet)
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
int main (void) // Hauptprogramm, startet bei Power ON und Reset
{
float spannung; //Definiere Variable
DDRB=0b00001111;
while (true)
{
uint16_t result = readADC(0); // ruft die ADC Funktion auf an Pin0 =ADC0
(float) (result);
spannung=0.003086*(float) (result);
waitMs(400);
if ((spannung > 1.5) && (spannung < 1.7))
{
PORTB=PORTB|(1<<PB1);
waitMs(600);
PORTB=PORTB&(~(1<<PB1));
}
if ((spannung>1)&& (spannung<1.1))
{
PORTB=PORTB|(1<<PB2);
waitMs(600);
PORTB=PORTB&(~(1<<PB2));
}
else
{
PORTB=PORTB|(1<<PB1)|(1<<PB2);
waitMs(600);
PORTB=PORTB&(~(1<<PB1))&(~(1<<PB2));
}
}
return 0;
}
BurningWave
12.08.2010, 19:48
Auch wenn du es nicht glaubst, Programmerfehler entstehen nicht durch fehlerhaften Code. Wenn du es unbedingt testen musst, dann erstelle eine neue Datei, schreibe irgendeinen Mist rein und speicher die Datei unter .hex und versuche sie zu brennen, es wird funktionieren, wenn der Programmer den µC erkennt und die Verdrahtung stimmt. In diesem Fall funktioniert es einfach mit jeder Datei.
Vielleicht hat deine Schaltung einen Wackelkontakt oder so (du willst sie ja nicht posten)?! Du sagtest, dass du den µC nach dem Programmieren in deine Platine gesteckt hast, heißt das, dass du das eine Mal ISP benutzt und das andere Mal den Programmer direkt?
runner02
14.08.2010, 15:32
Vielleicht hat deine Schaltung einen Wackelkontakt oder so (du willst sie ja nicht posten)?
Sry falls das blöd rübergekommen ist, aber ich habe keine Ahnung mit welchem Programm ich Schaltungen zeichnen kann...
Nur, wie gesagt, Minimalbeschaltung... Ich kann probieren sie in Paint zu zeichnen und dann hier irgendwie raufzustellen...
So ein Fehler mit 0x0F =! 0x00 hatte ich schon mal bei nem Blinkprogramm, dann hab e ich die Klammern geändert und aus int main (void) main () gemacht und es ging. Der Fehler schien nicht mehr auf...
Darum bin ich von einem Codefehler überzeugt...
BurningWave
14.08.2010, 15:44
So ein Fehler mit 0x0F =! 0x00 hatte ich schon mal bei nem Blinkprogramm, dann hab e ich die Klammern geändert und aus int main (void) main () gemacht und es ging. Der Fehler schien nicht mehr auf...
Darum bin ich von einem Codefehler überzeugt...
Und ich bin mir sicher, dass es Zufall war, es klingt ganz nach Wackelkontakt (o. ä.). int main (void) ist durchaus erlaubt (und wenn es ein Fehler wäre, würde der Compiler meckern). Ich denke, dass du einfach das eine Mal pech hattest und nach dem du das verbessert hast, hattest du Glück oder so.
Du kannst Schaltpläne mit Eagle ( www.cadsoft.de ) erstellen oder einfach von Hand zeichnen und als Bild hochladen. Wie programmierst du den µC jetzt genau? Welcher Programmer? Welche Software? Wie sieht die Verbindung aus? ISP?
runner02
15.08.2010, 16:56
Und ich bin mir sicher, dass es Zufall war, es klingt ganz nach Wackelkontakt
Du meinst, in der Programmer-Platine??
Wie programmierst du den µC jetzt genau?
Also auf jeden Fall über USB. Es heißt myAVR Workpad und war bei der Platine mitgeliefert.
http://www.myavr.de/
mySmartUSB MK2
myMultiProg MK2 USB
Das eine wird auf das andere gelötet, Software liegt bei.
BurningWave
15.08.2010, 21:21
OK, das mySmartUSB MK2 und das myMultiProg habe ich auch - und noch nie Probleme damit gehabt. Ein Wackelkontakt könnte nur in sofern vorliegen, dass die 2 Platinen nicht sauber miteinander verbunden sind oder der µC nicht richtig in der Fassung steckt.
Ich würde dir empfehlen, mal einen anderen Programmer und Compilerzu benutzen, vielleicht funktioniert es dann. Ich benutze AVR Studio mit dem WinAVR Plugin (für avr-gcc) und als Programmer das mitgelieferte AVR Prog (unter dem Tools-Menü zu finden). Sollte das Programmieren mit AVR Prog fehlschlagen, dass ist der µC höchstwahrscheinlich defekt.
runner02
17.08.2010, 15:09
Hey, ich habe das Programm soweit vereinfacht wie nur irgendwie möglich.
Alles Unnötige rausgestrichen, wie die Anzeige der Daten.
Zuerst hatte ich die ganze main-Funktion rausgeschmissen, mit dieser fängt er aber an, drum gabs gleich einen Error.
Jetzt misst er nur mehr die Spannung mittels der Mainfunktion.
Und: Es klappte endlich zum draufbrennen!!!!!!!!!!
Der Code sieht vorerst so aus:
uint16_t readADC(uint8_t channel)
{
// Funktion 1 zum Auslesen der Spannung
uint8_t i; // Variablen definieren (Zählervariable i + Resultat)
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
// wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 (Tabelle Datasheet)
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
main () // Hauptprogramm, startet bei Power ON und Reset
{
float spannung; //Definiere Variable
DDRB=0b00001111;
while (true)
{
uint16_t result = readADC(0); // ruft die ADC Funktion auf an Pin0 =ADC0
}
return 0;
}
Nun hätte ich gerne, dass er die Spannung konvertiert und anzeigt. Das sollte doch mittels Bit-Verschiebung gehen, oder?
Ich meine zB. 1,65 Grad: für die 1 Volt blinkt Led1 1 mal, für die sechs Volt Led2 6mal, etc.
Edit: Wenn ich ''spannung=0.003086*(float) (result);'' dazugebe, streikt das Programm wieder...
runner02
23.08.2010, 09:44
So, hier habe ich die Schaltung
das mit dem Attachment hinzufügen klappt irgendwie nicht, liegt das an meinem PC??
''spannung=0.003086*(float) (result);'' ist also der Fehler in meinem Program. Ich habe es auch schon ohne (float) versucht... Nichts geht irgendwie...
BurningWave
23.08.2010, 10:10
spannung=0.003086*(float) (result); diese Zeile ist definitiv richtig und wenn du das Programm nicht brennen kannst, wenn es diese Zeile beinhaltet, dann funktioniert entweder dein Compiler nicht oder es ist irgendwas an der Hardware defekt.
Mache es, wie ich gesagt habe und benutze AVR Studio mit WinAVR-Plugin.
runner02
23.08.2010, 15:45
Ok, habe mir das AVR Studio schon runtergeladen, werde es dann mal mit dem probieren.
Ich habe noch mal probiert, die Schaltung hochzuladen, jetzt schrieb er 'ungültiges Format' (ist in Paint geszeichnet...)
runner02
25.08.2010, 18:50
So, das Programm verlangt ein hexafile. Kann ich da zb. einfach die datei 'blinker.cc' vom workpad rüberziehen?
Dann fragte er noch ob flash oder eeprom...
Übrigends: Habe vorher das Programm leicht modifiziert, und die Messbereiche in drittel gegliedert. Nun muss die gemessene Spannung bei 2 gleichen Widerständen im mittleren Drittel sein, logisch. (Also zw. 1024/3 und 1024*2/3) Dann sollte das Programm zweimal blinken und das tat es auch.
Also müsste der Chip korrekt messen.
BurningWave
25.08.2010, 19:43
Das Hex-File, das AVR-Prog verlangt musst du mit AVR Studio erstellen. Dein C Quelltext wird zu so einer Datei compiliert. Brennen natürlich in den Flash-Speicher.
Übrigends: Habe vorher das Programm leicht modifiziert, und die Messbereiche in drittel gegliedert. Nun muss die gemessene Spannung bei 2 gleichen Widerständen im mittleren Drittel sein, logisch. (Also zw. 1024/3 und 1024*2/3) Dann sollte das Programm zweimal blinken und das tat es auch.
Also müsste der Chip korrekt messen.
Was willst du damit sagen? Funktioniert es jetzt?
runner02
26.08.2010, 13:29
Was willst du damit sagen? Funktioniert es jetzt?
Die Messung funktioniert.
Ich bekomme einen ADC-Wert (rund 1024/2) raus, den ich mit 0,00308V multiplizieren müsste, um die gemessene Spannung zu bekommen...
Allerdings klappt das gar nicht.
Denn:
Sobald ich ''spannung=0.003086*(float) (result);'' dazugebe, streikt das Programm wieder...
es geht auch nicht einfach '' spannung=result;'' (nachher wollte ich dann spannung noch *0,003 machen) <- nicht einmal das geht...
BurningWave
26.08.2010, 20:50
Sehr seltsam...
Probiere jetzt einmal, ob es mit AVR Studio geht. Es müsste eigentlich gehen, ich hatte zumindest damit noch nie solche Probleme. Alternativ kannst du dir einen Workaround einfallen lassen, was ich aber nicht für die perfekte Lösung halte.
runner02
27.08.2010, 16:44
Da hat sich ein weiteres Problem ergeben: Das AVR Workpad kann nur in .cc bzw. .asmb speichern, nicht in .hex...
Dann kann ich mit dem AVR Prog nicht laden... Also lade ich mir mal das AVR Studio runter.
Habe wieder versucht, das Programm zum Laufen zu bringen, und ich bin einem Fehler auf die Schliche gekommen...
Also: Ich schreibe
uint16_t result;
double spannung;
result=result+1;
Das geht. Wenn ich aber stattdessen
uint16_t result;
double spannung;
spannung=spannung+1
schreibe, gehts nicht mehr. Übrigends mit float statt double auch nicht...
BurningWave
27.08.2010, 17:04
Das müsste auf jeden Fall gehen...
Wie ist es mit spannung=spannung+1.0f und
spannung++ ?
(Das f bei 1.0f bedeutet, dass es sich um eine konstante Fließkomazahl handelt.)
runner02
31.08.2010, 09:40
Ok, habe mir das AVR Studio probiert, irgendwie ziemlich kompliziert... Zuerst schreibt er ihm fehlt die USB Software, und es ist auf das STK500 eingestellt... Und wie man in .hex umwandelt, muss ich auch erst noch finden...
Wie ist es mit spannung=spannung+1.0f und
spannung++ ?
Nicht einmal das nimmt er an...
Ist das ein Fehler vom Workpad?
Oder muss ich noch " #include Fließkommaberechnungen/c " dazuschreiben ?? ????
Eigentlich nervt das ziemlich, denn jetzt kann ich zwar den ADC-Wert korrekt auslesen (ein Wunder!!) und habe das schwerste somit hinter mir und halbwegs verstanden... Und dann Scheitert es an simplen mathematischen berechnungen... in der 'Hilfe' findet sich leider auch nichts dazu...
BurningWave
31.08.2010, 11:40
Ja das wird ein Fehler von Workpad sein, auch wenn es sehr seltsam ist, dass ein Compiler solche Fehler macht...
Zu AVR Studio:
Als erstes muss du den USB Treiber vom mySmartUSB installieren, falls du das noch nicht gemacht hast. Download hier: http://shop.myavr.de/index.php?sp=download.sp.php&suchwort=dl46 Danach solltest du AVR Studio installieren und zuletzt das WinAVR gcc Plugin (das ist der C Compiler von AVR Studio). Download hier: http://winavr.sourceforge.net/download.html
Jetzt kannst du neue gcc-Projekte erstellen und über die Schaltfläche Compilieren erzeugt er dir eine .hex-Datei. Über das Menü Tools gelangst du zum AVR Prog, das deinen Programmer dann erkennen sollte. Wichtig: Du darfst nicht versuchen den integrierten STK Programmer zu benutzen.
runner02
05.09.2010, 14:41
Wenn ich auf compile drücke, schreibt er alles gut gelaufen, aber es kommt keine Datei raus...
Gibt es eigentlich eine Deutsche Version davon?
Habe das Workpad übrigends deinstalliert und wieder rauf installiert. Kein Effekt...
BurningWave
05.09.2010, 19:29
Die .hex-Datei müsste im Unterordner Default liegen. Wenn sie nicht erstellt wird, musst du wohl noch unter Project -> Configuration Options Create Hex File auswählen. Hier solltest du auch noch den verwendeten µC und die Taktfrequenz angeben.
Und nein, es gibt keine deutsche Version.
runner02
28.10.2010, 15:34
OK,
Bin auf etwas gekommen:
Bei meinen Schleifenprogrammen ging ja weder die for- noch die while- Schleife.
Durch Zufall kam ih gestern drauf, das ich vergessen hatte, mittels DDRB die PINs als Ausgänge zu deklarieren!! Ein Fehler, der mich nun schon Wochen geplagt und zurückgeworfen hat...
Nun gehen simple schleifen wie:
int i;
int hunderterstelle=5; // z.B. 5
DDRB=0b00001111; //Wichtig!!!!!!
main()
{
for(i=0;i<hunderterstelle;i++)
{
PORTB=PORTB|(1<<PB1);
waitMs(100);
PORTB=PORTB&(~(1<<PB1));
waitMs(100);
}
}
Und auch in der Schaltung gehts hervorragend.
Wenn ich aber die Schleife unten an mein ADC-Auswerteprogramm hänge, dann passiert in der Schaltung genau nie etwas.
Ich hatte mir gedacht, dass ich im Programm was falsch mache, aber nun, nachdem die Schleife geht, passiert immer noch nix...
Daher habe ich geschrieben if (spannung==0) {...}
und siehe da, die LEDs mit diesem 'Morsecode' leuchten auf!!
Früher hatte ich jedoch, wie bereits hier beschrieben, die Messbereiche des ADCs gedrittelt, und das funktionierte auch prima. Nur halt, dass er 1) keine Spannung direkt rechnen konnte, 2) Dass es nur 3 Codes geben konnte, statt mit einer Schleife der hunderterstelle entsprechend zu blinken.
Also halt: viel Strom, mittel oder wenig, das konnte er sagen.
Also, nun zeigt der ADC offensichtlich immer 0, egal ob ich auf + , - oder auf gar nichts lege.
Da ich den ADC mit der selben Batterie des ATtiny versorge, kann das nicht sein, es sollten rund etwas unter 1,5V (oder 1500mV, Programm teilt durch 100 -> also 15 mal blinken) rauskommen
BurningWave
28.10.2010, 15:44
Poste mal das komplette Programm.
runner02
30.10.2010, 13:34
Dieses Programm war das, was ich eigentlich machen wollte
//----------------------------------------------------------------------
// Titel : Spannung messen AVR-C
//----------------------------------------------------------------------
// Funktion : Misst Spannung
// Schaltung : erstmals Minimalbeschaltung
//----------------------------------------------------------------------
// Prozessor : Attiny13
// Takt : 3.6864 MHz
// Sprache : C
// Datum : 03.08.2010
// Version : 1
// Autor :
//----------------------------------------------------------------------
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <inttypes.h>
//----------------------------------------------------------------------
uint16_t readADC(uint8_t channel)
{
// Funktion 1 zum Auslesen der Spannung
uint8_t i; // Variablen definieren (Zählervariable i + Resultat)
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
// wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 (Tabelle Datasheet)
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
main () // Hauptprogramm, startet bei Power ON und Reset
{
int spannung; //Definiere Ganzzahl-Variable Spannung
int einer,zehner, hunderter, startwert, mittelwert, endwert;
int i=0;
int j =0;
int k =0;
while (true)
{
uint16_t result = readADC(0); // ruft die ADC Funktion auf an Pin0 =ADC0
spannung = result*3086;
spannung = spannung/1000;
startwert=spannung/10;
hunderter=startwert/100;
mittelwert=startwert-100*hunderter;
zehner=mittelwert/10;
endwert=mittelwert-10*zehner;
einer=endwert;
for (i=0;i<(einer);i++)
{
DDRB=0b00001111;
PORTB=PORTB|(1<<PB0);
waitMs(50);
PORTB=PORTB&(~(1<<PB0));
waitMs(50);
}
for (j=0;j<(zehner);j++)
{
DDRB=0b00001111;
PORTB=PORTB|(1<<PB1);
waitMs(50);
PORTB=PORTB&(~(1<<PB1));
waitMs(50);
}
for (k=0;k<(hunderter);k++)
{
DDRB=0b00001111;
PORTB=PORTB|(1<<PB2);
waitMs(50);
PORTB=PORTB&(~(1<<PB2));
waitMs(50);
}
waitMs(1100);
}
return 0;
}
//----------------------------------------------------------------------
Als das nicht ging (besser gesagt nichts passierte), schrieb ich zahlreiche Testprogrammen, wie z.b. dass er nur die Hunderterstelle ausgeben sollte, sonst das gleiche wwie oben. Als das auch nicht ging, sollte er hunderter und Zehner schreiben (Wie gesagt, ich rechne in mV, das durch 10-> 125 (1-2-5) dh. 1,25V)
if (spannung==0) // Problem: spannung = laut adc immer 0
{
PORTB=PORTB|(1<<PB1)|(1<<PB2);
waitMs(330);
PORTB=PORTB&(~(1<<PB1));
waitMs(80);
PORTB=PORTB|(1<<PB2);
waitMs(80);
PORTB=PORTB&(~(1<<PB2));
waitMs(80);
}
Das dazugefügt führt immer dazu, dass das Passiert, also muss ADC immer gleich null sein...
Auch das hier
//----------------------------------------------------------------------
// Titel : Spannung messen AVR-C
//----------------------------------------------------------------------
// Funktion : Misst Spannung
// Schaltung : erstmals Minimalbeschaltung
//----------------------------------------------------------------------
// Prozessor : Attiny13
// Takt : 3.6864 MHz
// Sprache : C
// Datum : 03.08.2010
// Version : 1
// Autor :
//----------------------------------------------------------------------
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <inttypes.h>
//----------------------------------------------------------------------
uint16_t readADC(uint8_t channel)
{
// Funktion 1 zum Auslesen der Spannung
uint8_t i; // Variablen definieren (Zählervariable i + Resultat)
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
// wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 (Tabelle Datasheet)
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
main () // Hauptprogramm, startet bei Power ON und Reset
{
int spannung; //Definiere Ganzzahl-Variable Spannung
int einer,zehner, hunderter, startwert, mittelwert, endwert=0;
int i=0;
DDRB=0b00001111;
while (true)
{
uint16_t result = readADC(0); // ruft die ADC Funktion auf an Pin0 =ADC0
spannung = result*3086;
spannung = spannung/100000; // zB. 15 = 1500mV
PORTB=PORTB|(1<<PB1); //kurzer LED - Test
waitMs(10);
PORTB=PORTB&(~(1<<PB1));
waitMs(100);
if (spannung==0) // Problem: spannung = laut adc immer 0
{
PORTB=PORTB|(1<<PB1)|(1<<PB2);
waitMs(330);
PORTB=PORTB&(~(1<<PB1));
waitMs(80);
PORTB=PORTB|(1<<PB2);
waitMs(80);
PORTB=PORTB&(~(1<<PB2));
waitMs(80);
}
if ((spannung>0)&(spannung<=15))
{
PORTB=PORTB|(1<<PB1);
waitMs(100);
PORTB=PORTB&(~(1<<PB1));
waitMs(100);
}
if ((spannung>15)&(spannung<40))
{
PORTB=PORTB|(1<<PB2);
waitMs(100);
PORTB=PORTB&(~(1<<PB2));
waitMs(100);
}
if (spannung>40)
{
PORTB=PORTB|(1<<PB1);
waitMs(100);
PORTB=PORTB&(~(1<<PB1));
waitMs(100);
PORTB=PORTB|(1<<PB2);
waitMs(100);
PORTB=PORTB&(~(1<<PB2));
waitMs(100);
}
waitMs(1100);
}
return 0;
}
//----------------------------------------------------------------------
zeigt immer 0 an.
runner02
04.11.2010, 12:00
So, jetzt habe ich den Code (der nicht geht) so umgeschrieben, dass er nicht mehr die Spannung ausrechnet, sondern den ADC Wert ausgibt.
wieder mit for-Schleife.
Dieses mal habe ich vier Widerstände, und siehe da:
Vor dem Ersten zeigt er 1020 an (Einerstelle nicht ausgegeben), beim 2ten 760, beim 3tten 510 und dann kommt das Problem: Danach zeigt er nichts an, obwohl ja noch ein Wiederstand dahinter ist.
Also: er MÜSSTE 256 anzeigen, tut er aber einfach nicht!!! Wieso gibt es sowas????
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.