Moin Moin,
ich bastel seit geraumer Zeit (3-4 Wochen) mit einem ATMega32 auf einem
STK-500 herum. Zum programmieren benutze ich das AVR Studio 4.
Soviel dazu... nun zu meinem Problem:
Der unten angehängte Code soll im Grunde genommen nur die Spannung, den
Strom, die Leistung und den Widerstand mit Hilfe des integrierten ADC
angeben.
Leider misst er derzeit völlig falsch (teilweise totaler Daten-quatsch),
und ich weiß auch nicht mehr woran es liegen kann. Obwohl ich, mit genau
diesem Code, vor ein paar Tagen noch wunderbar die vier Sachen (mit
leichten Einschränkungen) messen konnte.
Zur Schaltung: Ich habe einen Poti mit max. 25k und einen Widerstand mit
4.7k in Reihe geschaltet. An Pin A1 vom µC messe ich die Gesamtspannung
und am Pin A4 den Spannungsabfall über dem Widerstand. Mit hilfe des
Widerstandes berechne ich den Strom.
Evtl. sieht ja jemand einen Fehler, der mir entgangen ist. Oder ich
mache grundlegend etwas verkehrt.
Das ist mein erstes Projekt in dieser Richtung, deswegen sollten dem
einen oder anderem bestimmte Zeilen im Code aus dem Forum hier bekannt
sein. Sollte irgendwas völlig schief gelaufen oder der Beitrag nicht
direkt verständlich sein, dann bitte fragen und nicht auf mich rumholzen
:)
Lieben Gruß
Mike
EDIT:
Spannung, Strom und Leistung habe ich wieder hinbekommen.
Fehler: Eins der Kabel hatte sich ein wenig selbstständig gemacht...
Jedoch nach wie vor berechnet er den Widerstand verkehrt.
Wenn du die Messwerte in Verdacht hast, dann lass dir die Werte vom ADC
mal direkt (ohne Umrechnung) ausgeben.
1 | while(loop1==1)
| 2 | {
| 3 | wert = 0.004887585*analogwert; // 5/1023=0.00488...
| 4 | spannung = wert * 100;
| 5 | itoa( spannung, wert3, 10 );
| 6 | if(spannung >= 100){
| 7 | UDR = wert3[0];
| 8 | UDR = ',';
|
Heeee! Du kannst doch nicht einfach Bytes ins UDR stopfen wie du lustig
bist!
Warum machst du dir nicht einfach erst mal ein paar UART
Basisfunktionen.
* Eine Funktion, die ein einzelnes Zeichen ausgibt
* Darauf aufbauend eine Funktion, die einen String ausgibt
* Darauf wiederrum aufbauend eine Funktion, die einen Fixpoint-Wert
ausgibt (und da das bei dir anscheinend nicht besonders zeitkritisch
ist, könnte man sprintf zur Codevereinfachung einsetzen)
1 | /* Ein einzelnes Zeichen ausgeben */
| 2 | void uart_putc( char c )
| 3 | {
| 4 | while (!(USR & (1<<UDRE))) /* warten bis Senden moeglich */
| 5 | ;
| 6 |
| 7 | UDR = c;
| 8 | }
| 9 |
| 10 | /* Einen String ausgeben */
| 11 | void uart_puts( const char* string )
| 12 | {
| 13 | while( *string )
| 14 | uart_putc( *string++ );
| 15 | }
| 16 |
| 17 | /* Eine Fixed Point Zahl ausgeben. Die Zahl wird mit 2 Nachkommastellen
| 18 | angenommen
| 19 | */
| 20 | void uart_putn( int FixedPointNumber )
| 21 | {
| 22 | char buffer[10];
| 23 |
| 24 | sprintf( buffer, "%d,%02d" ), FixedPointNumber / 100, FixedPointNumber % 100 );
| 25 | uart_puts( buffer );
| 26 | }
| 27 |
| 28 | int main()
| 29 | {
| 30 | ....
| 31 |
| 32 |
| 33 | wert = .....
| 34 | uart_putn( wert );
| 35 | uart_puts( "mA" );
| 36 | ...
|
Dein ganzes Hauptprogramm schrumpft dann zu
1 | int main(void)
| 2 | {
| 3 |
| 4 | uint16_t analogwert;
| 5 | uint16_t analogwert2;
| 6 | uint16_t spannung ;
| 7 | uint16_t strom ;
| 8 | uint16_t leistung ;
| 9 | uint16_t ohm;
| 10 | float wert;
| 11 | float wert4;
| 12 | char buffer[20];
| 13 |
| 14 |
| 15 | // USART initialisieren
| 16 | uart_init();
| 17 |
| 18 | while(1)
| 19 | {
| 20 | analogwert2 = ReadChannel(4);
| 21 | analogwert = ReadChannel(1);
| 22 | analogwert = analogwert - analogwert2;
| 23 |
| 24 | wert = 0.004887585*analogwert; // 5/1023=0.00488...
| 25 | spannung = wert * 100;
| 26 | uart_putn( spannung );
| 27 | uart_puts( "V " );
| 28 |
| 29 | wert = 0.004887585*analogwert2; // 5/1023=0.00488...
| 30 | wert4 = wert * 0.2127;
| 31 | strom = wert4 * 100000;
| 32 | uart_putn( strom );
| 33 | uart_puts( "mA " );
| 34 |
| 35 | leistung = (spannung*0.01) * (strom*0.01);
| 36 | uart_putn( leistung );
| 37 | uart_puts( "mW " );
| 38 |
| 39 | strom2 = strom;
| 40 | ohm = spannung / (strom2*0.000001);
| 41 | sprintf( buffer, "%d", (int)ohm );
| 42 | uart_puts( buffer );
| 43 | uart_puts( "Ohm" );
| 44 | }
| 45 | }
|
und das ist dann gleich eine ganze Ecke übersichtlicher, als das
Code-Monster das du da hast.
Hier 1 | wert = 0.004887585*analogwert2; // 5/1023=0.00488...
| 2 | wert4 = wert * 0.2127;
| 3 | strom = wert4 * 100000;
|
gehts du ein bischen naiv an die Sache ran. Schnapp dir einen
Taschenrechner und rechne die Konstanten alle zusammen und mach nur 1
Multiplikation.
Erst einmal Dankeschön für deine Bemühung und für die schnelle Antwort.
Das ich nicht beliebig viel Kram in UDR rein packen kann, musste ich
leider auch merken... Jedoch wusste ich nicht, wie ich mir anders helfen
sollte.
Erstaunlich wie klein der Text geworden ist!
Das hätte ich nach meinem jetzigen Wissensstand niemals so hinbekommen.
Dankeschön nochmal!
Ich werde das bei mir jetzt alles nach deinen Vorschlägen editieren und
würde mich danach nochmal melden.
Bis dahin...
Lieben Gruß
Mike
Mike M. schrieb:
> Das ich nicht beliebig viel Kram in UDR rein packen kann, musste ich
> leider auch merken... Jedoch wusste ich nicht, wie ich mir anders helfen
> sollte.
Das avr-gcc-Tutorial ist dein Freund.
Da gibt es einen Abschnitt über die UART
> Erstaunlich wie klein der Text geworden ist!
> Das hätte ich nach meinem jetzigen Wissensstand niemals so hinbekommen.
> Dankeschön nochmal!
Das Geheimnis besteht darin, sich für immer wiederkehrende
Funktionalität eine eigene Funktion zu bauen.
Das Geheimnis besteht darin, den kompletten Code in sinnvolle Funktionen
aufzuteilen, selbst dann, wenn die Funktion nur 1 mal aufgerufen wird.
Das Geheimnis besteht darin, mehrere zusammengehörende Codezeilen als
'Funktionalität' zu begreifen, die es sich verdient haben, in eine
eigene Funktion ausgelagert zu werden. Im Hauptcode sinkt dadurch die
Zeilenzahl und man arbeitet weniger auf C-Anweisungen sondern auf der
Aneinanderreihung von 'Funktionalitäten'.
Das ist wie in der Elektronik. Man veschaltet da auch auf logischer
Ebene nicht mehr einen Widerstand mit einem Transistor und einem
Kondensator. Statt dessen verschaltet man Black-Boxen. Da wird der
Ausgang eines "Taktgenerators" in ein "Monoflop" gesteckt. Dass
Taktgenerator und Monoflop selbst wieder aus anderen Einheiten bestehen
ist klar, aber aus Gesamtsicht ziemlich uninteressant, wenn es darum
geht die Funktion der kompletten Schaltung zu verstehen.
nochmal danke für deine Mühe
so ich habe jetzt einen neuen Text mit deinen Funktionen zusammengesetzt
und leider bekomme ich jetzt keine vernüftige Ausgabe
er gibt nur wirkürliche Zeichen aus
ich habe deine Funktion zum ausgeben eines einzelnen Zeichens durch eine
andere ersetzt der er USR undecleard hat
es gibt keine Fehlermeldung aber 8 Warnungen
d:/programme/winavr/lib/gcc/../../avr/include/util/delay.h:85:3:
warning: #warning "F_CPU not defined for <util/delay.h>"
../Test2.c:4:1: warning: "F_CPU" redefined
d:/programme/winavr/lib/gcc/../../avr/include/util/delay.h:86:1:
warning: this is the location of the previous definition
../Test2.c: In function 'uart_putn':
../Test2.c:81: warning: implicit declaration of function 'sprintf'
../Test2.c:81: warning: incompatible implicit declaration of built-in
function 'sprintf'
../Test2.c:81: warning: left-hand operand of comma expression has no
effect
../Test2.c:81: warning: passing argument 2 of 'sprintf' makes pointer
from integer without a cast
../Test2.c: In function 'main':
../Test2.c:122: warning: incompatible implicit declaration of built-in
function 'sprintf'
Gruß Mike M.
Mike M. schrieb:
> d:/programme/winavr/lib/gcc/../../avr/include/util/delay.h:85:3:
> warning: #warning "F_CPU not defined for <util/delay.h>"
> ../Test2.c:4:1: warning: "F_CPU" redefined
> d:/programme/winavr/lib/gcc/../../avr/include/util/delay.h:86:1:
> warning: this is the location of the previous definition
#include <util/delay.h>
#define F_CPU 4530000UL
Setz das F_CPU vor den include. util/delay.h benötigt das F_CPU schon
richtig gesetzt. Das sagt ja auch schon die erste Warnung.
> ../Test2.c: In function 'uart_putn':
> ../Test2.c:81: warning: implicit declaration of function 'sprintf'
Für sprintf benötigst du noch den
#include <stdio.h>
> ../Test2.c:81: warning: incompatible implicit declaration of built-in
> function 'sprintf'
> ../Test2.c:81: warning: left-hand operand of comma expression has no
> effect
> ../Test2.c:81: warning: passing argument 2 of 'sprintf' makes pointer
> from integer without a cast
Das war mein Fehler.
Ich schrub
sprintf( buffer, "%d,%02d" ), FixedPointNumber / 100, FixedPointNumber
% 100 );
und anstelle die überzählige schliessende Klammer zu entfernen, hast du
einfach noch eine öffnende dazugemacht.
sprintf will so bedient werden
1 | sprintf( wo_soll_der_String_abegelegt_werden,
| 2 | nach_welchen_Formatierregeln_sollen_die_Argument_formatiert_werden,
| 3 | die_Argumente_selber );
|
> ../Test2.c: In function 'main':
> ../Test2.c:122: warning: incompatible implicit declaration of built-in
> function 'sprintf'
Ist mit dem #include <stdio.h> erledigt
da bin ich leider wieder
die Wahrnungen sind jetzt alle weg
doch leider gibt er jetzt gar nichts mehr aus
habe auch mal probiert mir analogwert und analogwert2 auszugeben um zu
gucken ob bei der Rechnung ein Fehler ist
aber auch diese Werte werden nicht ausgegeben
tut mir leid für die Mühe die ich mache
liebe Grüße
Maik M.
Mike M. schrieb:
> tut mir leid für die Mühe die ich mache
kein Problem
Du hast neue Funktionen hinzubekommen und die sollte man jetzt erst mal
durchtesten.
Neues Testprogramm
1 | int main()
| 2 | {
| 3 | ...
| 4 |
| 5 |
| 6 | while( 1 )
| 7 | uart_putc( 'X' );
| 8 | }
|
Kommt die Ausgabe?
Wenn ja, dann gehts weiter
1 | int main()
| 2 | {
| 3 | ...
| 4 |
| 5 |
| 6 | while( 1 )
| 7 | uart_puts( "Hallo World\n" );
| 8 | }
|
Funktioniert auch das, dann
1 | int main()
| 2 | {
| 3 | ...
| 4 |
| 5 |
| 6 | while( 1 )
| 7 | uart_putn( 578 );
| 8 | }
|
Also die Funktionen funktionieren
bei uart_putc gibt er X aus
bei uart_puts gibt er Hallo World aus aber den Zeilenumbruch macht er
nicht
und bei uart_putn gibt er 5,78 aus
liebe grüße
Mike M.
Mike M. schrieb:
> Also die Funktionen funktionieren
> bei uart_putc gibt er X aus
> bei uart_puts gibt er Hallo World aus aber den Zeilenumbruch macht er
> nicht
Das kann durchaus ok sein.
Dann müsste das
uart_puts( "Hallow World\r\n" );
lauten.
D.h. die UART Funktionen sind es nicht. Das ist ja schon mal was. Das
bedeutet, dass du die UART Funktionen für Testausgaben benutzen kannst
:-)
Neues Testprogramm
1 | int main(void)
| 2 | {
| 3 | ....
| 4 |
| 5 | // USART initialisieren
| 6 | uart_init();
| 7 |
| 8 | while(1)
| 9 | {
| 10 | uart_puts( "Starte Messung\r\n" );
| 11 |
| 12 | analogwert2 = ReadChannel(4);
| 13 | uart_putn( analogwert2 );
| 14 | }
| 15 | }
|
Und so gehts jetzt sukzessive weiter. Es kommt immer mehr Code von
deinem Programm dazu, bis klar ist, wo es hängt.
Es läuft!
Hatte, bevor ich die Testversion eingefügt habe, den PC neu gestartet.
Nun hab ich die ganz normale Code-Version genommen, quasi vor dem
Test-Versuch, und siehe da: Bis auf den Zeilenumbruch funktioniert alles
bestens :)
Großes Dankeschön an dich Karl! :)
Sollte ich demnächst nocheinmal Probleme beim programmieren haben, weiß
ich nun, wo ich damit auftauchen kann.
mikrocontroller.net kann man definitiv weiterempfehlen.
Lieben Gruß
Mike
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|