Forum: Mikrocontroller und Digitale Elektronik Thermomixer noch einmal neu - dieses mal nur ein MEGA16


von Rocco L. (kaufparkangucker)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bins wieder. Ich habe mein Lötchaos beisete gestellt und möchte gern 
noch einmal von vorn Anfangen. Diesesmal gleich mit eurer Hilfe.

Ich möchte diesesmal nur einen (statt vorher 5) Mikrocontroller 
einsetzen. Dazu würde ich gern einen MEGA16 nehmen (schon deswegen weil 
der hier rum liegt ;-)

Ich würde gern an die C-Pins 3Stück DS18S20 anschließen und an PortA, 
PortB, PortD die LED Anzeige zum Ablesen der Temperatur.

Ich habe schon mal den ersten Teil des Codes geschrieben und mit Eagle 
einen Schaltplan gezeichnet (ich hoffe das passt so, da ich damit noch 
keine großen Erfahrungen habe)

Zunächst wollte ich erst mal einen DS18S20 an PC0 anschließen und den 
über PORTB die Temperatur ausgeben.

Die Temperatur würde ich gern wieder über LED anzeigen lassen:
PB0 = 1°C
PB1 = 2°C
PB2 = 4°C
PB3 = 8°C
PB4 = 10°C
PB5 = 20°C
PB6 = 40°C
PB7 = 80°C

Je nachdem welche LED's brennen kann dann durch addieren die Temperatur 
ermittelt werden.

Ok, so weit so gut - kommen wir zu meinem ersten Problem:
Trotz das ich einen 8,000Mhz Quarz benutze und entweder im Quelltext
#define F_CPU 8000000
oder Testweise auch unter Project -> Configuration Options -> Frequency 
eine 8000000
eingebe blinken die LED (Zeilen 133-139) nur etwa 2,45 Sekunden anstatt 
10 Sekunden.
Fuses habe ich so gesetzt wie im Bild im Anhang zu sehen ist.
Woran kann diese falsche Blinkzeit liegen?
^^ich denke deswegen wird auch z.Z. keine Temperatur angezeigt. 
Stattdessen Leuchtet nur das LED an PB0, nachdem das Blinken (Zeilen 
133-139) abgeschlossen ist.
Ich nutze das AVR Studio 4.18 und habe erst mal alles auf einem 
Steckbrett aufgesteckt.

Gruß Rocco

: Verschoben durch Moderator
von Krapao (Gast)


Lesenswert?

> blinken die LED (Zeilen 133-139) nur etwa 2,45 Sekunden anstatt
> 10 Sekunden.

Ich weiss nicht ob delay... Funktionen mit const Werten zurecht 
kommen. Mit normalen Variablen kommen sie nicht zurecht, weil zur 
Compilierzeit das
Argument bekannt sein muss.

Ich würde

> const uint16_t pause = 1000;
> ...
> _delay_ms(pause);

durch

#define PAUSE 1000
_delay_ms(PAUSE);

ersetzen.

von P. Liamle (Gast)


Lesenswert?

Rocco L. schrieb:
> Ich würde gern an die C-Pins 3Stück DS18S20 anschließen und an PortA,
>
> PortB, PortD die LED Anzeige zum Ablesen der Temperatur.

Für drei 1-wire-Sensoren braucht man keine drei Portpins. Einer reicht. 
Im Schaltplan ist jedoch nur einer zu sehen?

von Volkmar D. (volkmar)


Lesenswert?

BTW: Wieso hast Du eigentlich im Schaltplan an jedem Bauteilpin einen 
Knoten? Die sind nur an den Stellen nötig, wo sich 2 (oder mehr) 
Leitungen treffen und verbunden sein sollen.

Volkmar

von Volkmar D. (volkmar)


Lesenswert?

Rocco L. schrieb:
> Woran kann diese falsche Blinkzeit liegen?

Hast Du mal versucht es im AVRstudio zu simulieren?

Hast Du mal mit anderen Werten für F_CPU experimentiert? Falls ja, was 
passiert dann, ergeben sich auch Änderungen im Verhalten?

von 7z (Gast)


Lesenswert?

Wenn dir Temperaturen bis 99°C reichen, kommst du mit 2 4511-Bausteinen 
und 2 7-Segmentanzeigen und genausovielen Portpins wie jetzt auch hin - 
nur könnte es das Ablesen stark vereinfachen...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Krapao schrieb:
> Ich weiss nicht ob delay... Funktionen mit const Werten zurecht
> kommen.

In solch einfachen Fällen sollte das durchaus klappen.

von Michael M. (technikus)


Lesenswert?

Wenn ich das richtig sehe, willst Du mit _delay_ms(1000) 1 s verzögern. 
Das klappt so nicht. Im Handbuch der avr-libc steht: "The maximal 
possible delay is 262.14 ms / F_CPU in MHz." also bei 8 MHz knapp 33 ms.
Mach mal _delay_ms(20) und dafür mehr Schleifendurchläufe.

Außerdem klappt

for(int a=0; a<10; a++)
{
  PORTB = ~aa;
  for(int a=0; a<10; a++){ _delay_ms(pause);}
  PORTB = ~bb;
  for(int a=0; a<10; a++){ _delay_ms(pause);}
}

imho so auch nicht! Die große for-schleife wird nach dem ersten 
Durchlauf abgebrochen, weil a von der Verzögerungsschleife ja schon 10 
ist. Nimm da eine andere Variable.

Servus
Michael

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael M. schrieb:
> Wenn ich das richtig sehe, willst Du mit _delay_ms(1000) 1 s verzögern.
> Das klappt so nicht.

Doch, das klappt.  Du solltest das Handbuch auch bis zu Ende lesen.

von Michael M. (technikus)


Lesenswert?

Jörg Wunsch schrieb:
> Doch, das klappt.  Du solltest das Handbuch auch bis zu Ende lesen.

Danke für den Hinweis, das hatte ich anders in Erinnerung. War das bei 
früheren Versionen der avr-libc auch schon so?

Bevor ich mich gleich nochmal blamiere: Seit wann gibt es eigentlich 
binäre Konstanten? Also
int8_t aa = 0b00000000;
int8_t bb = 0b11111111;

Servus
Michael

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael M. schrieb:

> Danke für den Hinweis, das hatte ich anders in Erinnerung. War das bei
> früheren Versionen der avr-libc auch schon so?

Ich müsste jetzt nachsehen, seit wann das geht.

> Bevor ich mich gleich nochmal blamiere: Seit wann gibt es eigentlich
> binäre Konstanten? Also
> int8_t aa = 0b00000000;
> int8_t bb = 0b11111111;

Seit GCC meinen diesbezüglichen Patch akzeptiert hat.  Ist nun auch
schon wieder einige Jährchen her (WinAVR hatte ihn bereits davor
mitgenommen).  Das Ganze war eigentlich mehr aus Spaß daher
entstanden, dass dieses Feature hier immer wieder nachgefragt worden
ist, und ich irgendwann mal die Nase voll hatte und zeigen wollte,
dass das mit relativ wenig Aufwand im GCC zu implementieren ist.

Der Hintergrund, dass ich es dann wirklich offiziell durchgeboxt habe,
ist der blöde Kommentar im C99 Rationale, der da meint:
1
6.4.4.1 Integer constants
2
...
3
A proposal to add binary constants was rejected due to lack of
4
precedent and insufficient utility.

Wenn die Damen und Herren Standardisierer denn schon so verbohrt
sind, dass sie ``insufficient utility'' darin sehen, so sollen sie
nun, da GCC es offiziell implementiert hat, zumindest nicht wieder
einen ``lack of precedent'' konstatieren können, wenn sie das
nächste Mal darüber befinden.

von Rocco L. (kaufparkangucker)


Lesenswert?

P. Liamle schrieb:
> Rocco L. schrieb:
>> Ich würde gern an die C-Pins 3Stück DS18S20 anschließen und an PortA,
>>
>> PortB, PortD die LED Anzeige zum Ablesen der Temperatur.
>
> Für drei 1-wire-Sensoren braucht man keine drei Portpins. Einer reicht.
> Im Schaltplan ist jedoch nur einer zu sehen?

^^ das würde ich gern so lösen, übersteigt aber meine (Un-)Fähigkeiten 
al Programmierer. Ich versuche ja immer noch Peters One Wire Routine zu 
verstehen...
Kann mir da jemand helfen? Diesbezüglich habe ich leider echt keinen 
Plan... :(

Volkmar Dierkes (volkmar) schrieb:
>BTW: Wieso hast Du eigentlich im Schaltplan an jedem Bauteilpin einen
>Knoten? Die sind nur an den Stellen nötig, wo sich 2 (oder mehr)
>Leitungen treffen und verbunden sein sollen.

Das war mir nicht ganz klar - werde ich aber in zukunft anders machen.

Rocco L. schrieb:
>> Woran kann diese falsche Blinkzeit liegen?

>Hast Du mal versucht es im AVRstudio zu simulieren?

Kenne mich mit der Debugfunktion nicht wirklich gut aus, weis aber das 
man dann sieht was an den einzelnen PORTS passiert - aber wie kann ich 
dort herausfinden warum der bei 8MHZ nur 2,45Sekunden für eigentlich 10 
Sekunden braucht (mit dem internen RC Oszi ist das auch nicht besser, 
habe eigentlich nur deswegen den Quarz angeschlossen)?

>Hast Du mal mit anderen Werten für F_CPU experimentiert? Falls ja, was
>passiert dann, ergeben sich auch Änderungen im Verhalten?

Da ergibt sich dann so langsam ein Muster:

#define F_CPU 8000000 führ dazu das 10 Sekunden Pause in 2,5 Sekunden 
vorbei sind
#define F_CPU 16000000 macht aus 10 Sekunden nur noch 5 (und das 
Thermometer funktioniert plötzlich)
#define F_CPU 32000000 macht dann endlich aus 10 Sekunden auch 10 
Sekunden und das Thermometer läuft auch an.

Wie gesagt - es ist ein 8.000MHz Quarz angeschlossen...
Kapier ich zwar nicht, nehm ich aber hin.

Der Tip war jedenfals Gold wert.

von 0^0 (Gast)


Lesenswert?

Rocco L. schrieb:
> eingebe blinken die LED (Zeilen 133-139) nur etwa 2,45 Sekunden anstatt
> 10 Sekunden.

wenn es 2,54 Sekunden wären würde ich Angelsächsiche Frequenzmessung 
hinter dem Problem vermuten :D

von Volkmar D. (volkmar)


Lesenswert?

Rocco L. schrieb:
> #define F_CPU 16000000 macht aus 10 Sekunden nur noch 5 (und das
> Thermometer funktioniert plötzlich)

Dies zeigt zumindest das F_CPU berücksichtigt wird. Ich bin hier jetzt 
auch ratlos! Es hört sich so an, als ob der mit 32MHz rennt, das wäre 
aber etwas schnell... Und das auch mit dem internen Takt, wie Du 
schreibst.

Was mir am Schaltplan noch aufgefallen ist: Du hast AREF mit VCC 
verbunden, ich gehe aber davon aus, daß Du die Analog-Eingänge gar nicht 
verwenden willst. Dann solltest Du einfach nur 100nF gegen GND 
anschließen.

Gruß
Volkmar

von Volkmar D. (volkmar)


Lesenswert?

Eine Idee ist mir noch gekommen: Probiere mal
1
#define F_CPU 8000000L
aus. Beachte das 'L' am Ende.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Volkmar Dierkes schrieb:
> Eine Idee ist mir noch gekommen: Probiere mal
>
1
#define F_CPU 8000000L
> aus. Beachte das 'L' am Ende.

Bringt nichts.  8000000 übesteigt den Zahlenbereich von `int' und
`unsigned int' des AVR-GCC, damit ist die Konstante automatisch
`long'.

Außerdem könnte er auch
1
#define F_CPU 8E6

schreiben, dann spart er es sich, die vielen Nullen zu schreiben. ;-)
Die Ausdrücke werden intern ohnehin in Gleitkomma gerechnet und
müssen dann vom Optimierer zu Ganzzahlkonstanten gewandelt werden.

von Volkmar D. (volkmar)


Lesenswert?

Hallo Jörg,

das hatte ich schon 'befürchtet'. Danke für die Klarstellung.

Volkmar

von Peter D. (peda)


Lesenswert?

Rocco L. schrieb:
> #define F_CPU 8000000 führ dazu das 10 Sekunden Pause in 2,5 Sekunden
> vorbei sind

Dann benutzt Du AVRStudio5, stimmts?
Der GCC darin hat mindestens einen Bug (Delay-Bug).

Benutze besser den WINAVR-20100110, der ist zwar älter, dafür aber 
ausgereifter.


Die 2 häufigsten Delay-Fehler:

Delay 4-mal zu schnell: AVRStudio5
Delay 8-mal zu langsam: DIV8-Fuse


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Der GCC darin hat mindestens einen Bug (Delay-Bug).

Nein, die avr-libc ist es.

Er könnte statt des nunmehr doch schon reichlich alten WinAVR auch
eine aktuellere Version der AVR-Toolchain von Atmel benutzen.
"Viel ausgereifter" ist das alte WinAVR nun auch nicht wirklich,
es war einfach Pech für die Atmel-Entwickler der AVR-Toolchain, dass
sie den schwarzen Peter gezogen haben und eine avr-libc-Version
erwischt haben, die mit einem derartigen bis dahin unerkannten Bug
daher kam.  Das hätte Eric mit seinem WinAVR genauso gut treffen
können.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch schrieb:
> Das hätte Eric mit seinem WinAVR genauso gut treffen
> können.

Bloß hätte Eric dann deutlich schneller reagiert und eine korrigierte 
Version bereit gestellt. Z.B 2008 gabs 3 Versionen in Folge.


Peter

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Delay 4-mal zu schnell: AVRStudio5
Dann kann ich sagen: der ist raus, das Delay tut.
Zumindest in der Version 5.0.1163, die ich hier habe...

von Rocco L. (Gast)


Lesenswert?

Habe jetzt AVR Studio5 drauf gehauen - leider wird mein Diamex USB ISP 
nicht erkannt. Naja was solls, nutze ich das Studio 5 eben zum 
Programmieren und das Studio 4 zum Brennen.

Jedenfals funktioniert jetzt F_CPU 8000000 wieder ordnungsgemäß.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rocco L. schrieb:
> Naja was solls, nutze ich das Studio 5 eben zum
> Programmieren und das Studio 4 zum Brennen.

Aua. ;-)

Kannst du nicht einfach eine Kommandozeile dafür benutzen?  Kann
man ja irgendwo hinter einem Bildchen verstecken, wenn dir das
<cursor hoch><enter> zu viel an Tipperei ist, um die letzte Aktion
zu wiederholen.

Entweder avrdude nehmen dann, oder das entsprechende Kommandozeilen-
tool aus dem AVR-Studio-4-Verzeichnis (wahrscheinlich stk500.exe,
aber ich kenne deinen Programmer nicht).

von Rocco L. (kaufparkangucker)


Lesenswert?

mich stört das nicht weiter... dachte nur ich bin zu doof meinen 
Programmer zum Laufen zu bringen.

Kann mir jemand helfen die restlichen 2 DS18S20 zum Laufen zu bringen?

Gruß Rocco

von Rocco L. (kaufparkangucker)


Angehängte Dateien:

Lesenswert?

So wie ich es verstehe muss ich auf jedenfall diese Funktion anpassen 
(Zeile 92)
1
void w1_command( uint8_t command )
2
{
3
        w1_reset();                             //zuerst die restet prozedur
4
        w1_byte_wr( SKIP_ROM );                 //dann alle DS1820 simultan ansprechen
5
        w1_byte_wr( command );                  //dann das Kommando
6
}

Irgendwie muss da noch SEARCH_ROM (0xF0) mit rein um die 64 Bit Adressen 
der angeschlossenen DS18S20 zu identifizieren. Anschließend muss ich 
dann mit MATCH_ROM (0x55) gefolgt von der gelesenen 64Bit Adresse jeden 
DS18S20 einzeln ansprechen und Auslesen.

Nur wie speichere ich die 3 64 Bit Adressen die SEARCH_ROM liefert? Bzw. 
sind es gleich alle 3 Adressen die SEARCH_ROM liefert - und wie kann ich 
die Trennen und in einzelnen Variablen unterbringen um die Adressen dann 
anschließend zum Ansprechen der einzelnen DS18S20 zu nutzen?

Gruß Rocco

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.