Habe ein großes Problem mit der Temperaturmessung mit einem DS1820. Habe das 1-wire Protokoll nach der Application Note 162 von Maxim imlementiert und auch verstanden. Allerdings liefert der Sensor keine vernünftigen Werte. Ich bin mir jetzt nicht schlüssig, ob der Fehler beim Sensor liegt oder in meinem Zeitdelay: void delay_us(unsigned int x){//x in µSekunden eingeben TCNT1=0x0000; TCCR1A=0b00000000;//Normal PORT Operation //Normal Timer/Counter TCCR1B=0b00000001; //Normal Timer/Counter,CLK(1MHZ) while(x>=TCNT1){} //Timer soll bis x laufen(ca. x µsekunden) } //Timer-Funktion schließen Als Prozessor benutze ich einen Atmega48 mit 1Mhz internem Oszillator. Die Datenleitung ist an PB0 angeschlossen. Anschließend wird die Temperatur auf einem LCD ausgegeben. Die Presence-Funktion erkennt den Sensor(Geht von 1 auf 0 wenn der Sensor angeschlossen wird), allerdings muss im Schreib oder Lesevorgang ein Fehler auftreten. Kann mir jemand ungefähr sagen, was die gesamte delay_us Funktion in echt an µSekunden braucht?Ich besitze leider kein Oszilloskop. Vielleicht liegt das Problem darin, daß wenn ich delay_us(15) eingebe, nicht 15µSekunden als Ergebnis rauskommen, sondern entsprechend mehr was im Endeffekt zu dem Fehler führt. Bin für jede Hilfe dankbar!
Kann denn wirklich keiner etwas dazu sagen? Keiner Idee oder sonst irgendeinen Hinweis?
Ich würde persönlich einen externen Quarz verwenden. Die delay_us ist schon relativ genau, aber wie sieht es mit dem internen RC-Oszillator aus? Der hat schon eine ziemliche Ungenauigkeit, deshalb kann man ihn ja abeichen. Gruß Elektrikser
Laut Datenblatt wird der ATmega48 mit einem Kalibrierregister auf 8MHz genau getaktet und dann durch 8 geteilt. Aber vielleicht hast du recht und nicht mal auf das kann man sich verlassen. Ist der 1-wire Bus denn so Zeitempfinglich?
Der interne Takt des mega48 ist einfach miserabelst stabil. Irgendwo in de Codesammlung gibt es schon fertige Routinen für den DS1820 von peter danegger.
Hallo Elektrikser! Ich verstehe zwar nichts von C, habe aber mit Bascom mit dem DS gearbeitet. Du kannst den Sensor selbst abfragen, wann er mit dem Umwandeln fertig ist. Dann brauchst Du keine Zeit zu programmieren; er gibt ja selbst die Meldung zurück. Das steht im Datenblatt von Dallas/Maxim und geht auch so. MfG Paul bis er fertig ist
Wie sieht es denn mit dem internen RC-Oszillator vom Mega8 aus? Ist der auch so miserabel? Den hätte ich nämlich hier noch auf Lager und ließe sich schnell tauschen!
Hallo Paul, das ist vollkommen richtig. Hat aber meines Wissens einen Nachteil: Wenn man mit delays arbeitet ist aber die Buszeit kürzer. Das Setzen/Rücksetzen von einen Bit in einem I/O-Register benötigt bei den delays z.B. einen Zyklus, aber 14 Zyklen beim variablen Bus (wenn man auf die Meldung vom Sensor immer wartet). Gruß Elektrikser
Hallo Elektrikser! Alles klar, da habe ich wieder was Neues erfahren. Naja, wie gesagt ich habe stur den Ablauf, wie er im Datenblatt stand in ein Programm eingesetzt, die Berechnungsformel "zersägt" (Bascom kann nicht mehr als 2Terme auf einmal bearbeiten) und es mißt. Ich erzeuge einen Interrupt mit 1 Sekunde Abstand und in der Interruptroutine drin sitzt die Abfrage des Fühlers. MfG Paul
Hallo Das gleiche Problem hatte ich auch mit einem DS1822 und dem M16c62 Mikrocontroller! Das Problem liegt einen einen Zeitschlitzen!! die müssen genau so lang sein wie es im Datenblatt steht! Ich habe das Problem mit einem Logikanalyser gefunden! die Zeiten waren viel zu lang!!
Ich komme einfach nicht mehr weiter. Mittlerweile kann ich die 1-wire Funktionen auswendig. Vielleicht hat jemand Lust sich meine Routinen anzuschauen, ob er noch einen Fehler entdeckt. Ich kann keinen mehr finden, außer dass es an den Zeitroutinen liegen könnte oder der Sensor kaputt ist. Danke für eure Hilfe! Hier der Code: void DQhigh(void){ DDRB=0x00; //PORTB ist Eingang PORTB=0x00; //High-Z } void DQlow(void){ DDRB=0xFF; //PORTB ist Ausgang PORTB=0x00; } void delay_us(unsigned int x){ //Zeitverzögerung in µSekunden TCNT1=0x0000; //Zähler auf 0 setzen TCCR1A=0b00000000; //Normal PORT Operation, //NormalTimer/Counter TCCR1B=0b00000001; //Normal Timer/Counter,CLK(1MHZ) while(x>=TCNT1){} //Timer soll bis x laufen(ca. x usekunden) } //Timer-Funktion schließen unsigned char ow_reset(void){ unsigned char presence,temp; DQlow(); //pull DQ line low delay_us(480); //leave it low for 480µs DQhigh(); //allow line to return high delay_us(70); // wait for presence temp=PINB&0x01; presence=(PINB&0x01); //get presence signal delay_us(400); //wait for end of timeslot return(presence); //presence signal returned } // 0=presence OK ; 1= no part False unsigned char read_bit(void){ unsigned char i,temp; DQlow(); //pull DQ low to start timeslot DQhigh(); //then return high delay_us(15); //delay 15µs from start of timeslot temp=PINB&0x01; //DQ einlesen delay_us(100); return(temp); //return value of DQ line } unsigned char read_byte(void){ unsigned char i; unsigned char value=0; for(i=0;i<8;i++){ if(read_bit())value|=0x01<<i; //reads byte in,one bit at a time and then shifts left delay_us(120); //wait for rest of timeslot } return(value); } void write_bit(char bitval){ DQlow(); //pull DQ low to start timeslot if(bitval==1)DQhigh(); //return DQ high if write 1 delay_us(100); DQhigh(); } void write_byte(char val){ unsigned char i; unsigned char temp; for(i=0;i<8;i++){ temp=val>>i; temp&=0x01; write_bit(temp); } delay_us(100); } unsigned char read_temp(void){ { unsigned char get[10],i; unsigned char temp_lsb,temp_msb; int k; unsigned char temp_f,temp_c; ow_reset(); write_byte(0xCC); //Skip ROM write_byte(0x44); // Start Conversion for(i=0;i<20;i++){ delay_us(64000);} //Warten bis Wandlung fertig ow_reset(); write_byte(0xCC); // Skip ROM write_byte(0xBE); // Read Scratch Pad for (k=0;k<9;k++){get[k]=read_byte();} temp_msb = get[1]; // Sign byte + lsbit temp_lsb = get[0]; // Temp data plus lsb return temp_lsb; } }
Hallo das sollte dir helfen! http://www.m16c.de/PDF/AppNotes/APP_EXTMEM/reu05b0037_m16cap.pdf Viel Spaß damit! damit läuft es bei mir!
Teste mal die delay()-Routine. Geht auch ohne Oszi. Beispielsweise ein 10µs-Delay 100000mal hintereinander, und dann, also offiziell jede Sekunde, eine LED umschalten. Ich glaube kaum, dass es auch nur annähernd 0,5Hz werden. Weil die Routine auch bei delay_us(0) schon um die 10µs mehr verbrutzelt als vorgesehen.
Test war erfolgreich. Hab ein Delay von 100µSekunden eingestellt und das 10000 mal in einer Schleife durchlaufen lassen. Kam auf jeden Fall was unter einem Hertz raus. Hat denn jemand eine Idee wie ich dann einen so kurzen delay von etwa 15µSekunden mit einem Takt von 1MHz realisieren kann? Wenn ich eine For-Schleife benutze bin ich doch bestimmt auch bei for(i=0;i<0;i++){} auch schon wieder über 15µSekunden,oder nicht? Danke schon mal für eure Tips.So weiß ich immerhin schon mal, dass das Problem am Delay liegt und nicht an den Funktionen selber.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.