Forum: Mikrocontroller und Digitale Elektronik DS18S20 und ATTINY 2313


von Beks (Gast)


Lesenswert?

Hallo,

ich möchte einen DS18S20 an einem ATTINY 2313 betreiben. Habe mir 
verschiedene Codes aus dem Forum angeschaut. Diese sind für mich leider 
viel zu kompliziert vom Programmieraufwand. Mit anderen Worten, ich kann 
sie nicht nachvollziehen. Zum einen hatte ich den Code von Peter 
Dannegger.

Hat vielleicht jemand einen funktionierenden C-Code für den ATTINY 2313, 
bei dem ich eventuell nur den Clock und die Ports anpassen muss?

von ronnysc (Gast)


Lesenswert?

bitte schön:
http://avrs-at-leipzig.de/dokuwiki/projekte/thermometer_mit_ds18s20

Die Ansteuerung eines anderen Displays musst Du selbst implementieren.

von Beks (Gast)


Lesenswert?

Hallo Danke, genau danach hab ich gesucht. Das Display ist nicht das 
Problem. Allerdings bekomm ich den Quellcode dort auch nicht zum laufen 
:(

von Beks (Gast)


Lesenswert?

main.h hab ich folgend abgeändert. Der Sensor liegt bei mir auch an Pin 
D6. Beschaltung hab ich folgende:
DS18s20
GND  --> GND
DQ   --> auf ATTINY PortD6 und über 4k7 auf 5V
Vdd  --> 5V

Der µC läuft auf 1Mhz
1
#ifndef MAIN_H
2
#define MAIN_H
3
4
#define F_CPU 1000000UL
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#include <stdlib.h>
9
#include <stdint.h>
10
#include <Stdio.h>
11
#include <util/delay.h>
12
#include <avr/sleep.h>
13
14
/* Thermometer Connections (At your choice) */
15
#define THERM_PORT   PORTD
16
#define THERM_DDR   DDRD
17
#define THERM_PIN   PIND
18
#define THERM_DQ   PD6
19
/* Utils */
20
#define THERM_INPUT_MODE()     THERM_DDR&=~(1<<THERM_DQ)
21
#define THERM_OUTPUT_MODE()    THERM_DDR|=(1<<THERM_DQ)
22
#define THERM_LOW()       THERM_PORT&=~(1<<THERM_DQ)
23
#define THERM_HIGH()       THERM_PORT|=(1<<THERM_DQ)
24
25
#define THERM_CMD_CONVERTTEMP 0x44
26
#define THERM_CMD_RSCRATCHPAD 0xbe
27
#define THERM_CMD_WSCRATCHPAD 0x4e
28
#define THERM_CMD_CPYSCRATCHPAD 0x48
29
#define THERM_CMD_RECEEPROM 0xb8
30
#define THERM_CMD_RPWRSUPPLY 0xb4
31
#define THERM_CMD_SEARCHROM 0xf0
32
#define THERM_CMD_READROM 0x33
33
#define THERM_CMD_MATCHROM 0x55
34
#define THERM_CMD_SKIPROM 0xcc
35
#define THERM_CMD_ALARMSEARCH 0xec
36
37
/* Display Connections */
38
//#define A0         (1<<PD2)
39
//#define A1         (1<<PD3)
40
//#define WR         (1<<PD4)
41
42
//#define CU         (1<<PB7)
43
//#define PWM       (1<<PD5)
44
45
//#define DATA        PORTB
46
//#define DDR_DATA     DDRB
47
//#define CTRL        PORTD
48
//#define DDR_CMD      DDRD
49
50
//#define ASCII           1
51
//#define CMD             0
52
//#define seg_nix     0x20
53
//#define seg_c     0x1b
54
55
/* Light-ON Connections */
56
//#define light_port  PIND
57
//#define light_pin  PD0
58
59
#endif


Die main.c hab ich folgend geändert.
1
#include "main.h"
2
#include "temp_eigen.h"
3
#include "lcd-routines.h"
4
 
5
 
6
char array[4];
7
volatile uint8_t tick;
8
uint8_t scratchpad[2];
9
uint8_t error;
10
uint8_t light;
11
uint8_t flash;
12
13
ISR(TIMER1_COMPA_vect)          //aller 10msek.
14
{
15
  tick++;
16
}
17
18
int main(void)
19
{
20
//Timer0 PWM ~4kHz
21
//TCCR0A |= ((1<<WGM00)|(1<<WGM01)|(1<<COM0B1));
22
//TCCR0B |= 1<<CS01;
23
//OCR0B = 255;                  //max. Helligkeit
24
//DDR_CMD |= PWM;                 //PD5 als Ausgang
25
26
//Timer1 aller 10ms bei 8MHz Taktfrequenz
27
TCCR1B |= ((1<<WGM12) | (1<<CS11) | (1<<CS10));    // Modus 4 CTC, Prescaler 64
28
TIMSK |= (1<<OCIE1A);
29
OCR1A = 1250;        
30
31
//Sleep_Mode Init
32
set_sleep_mode(SLEEP_MODE_IDLE);        //Init Sleep-Modus auf IDLE
33
34
//Anzeige init
35
lcd_init();
36
37
//3x Minus-Zeichen am Anfang
38
array[0] = '-';    
39
array[1] = '-';
40
array[2] = '-';
41
array[3] = 'C';    //°C zeichen
42
43
44
   lcd_setcursor( 0, 1 );
45
  lcd_string("################");
46
   lcd_setcursor( 0, 2 );
47
  lcd_string(array);
48
49
sei();
50
51
  for(;;)
52
  {
53
    uint8_t digit;
54
  cli();
55
  switch (tick)
56
  {
57
    case 1:
58
    {
59
      if(therm_reset())
60
        error = 1;
61
      else
62
        error = 0;
63
      if (!(error))
64
      {
65
        therm_write_byte(THERM_CMD_SKIPROM);
66
        therm_write_byte(THERM_CMD_CONVERTTEMP);
67
      }
68
    break;
69
    }
70
//    case 20:                           //nach 200msek.
71
//    {
72
//      if ( light_port & (1 << light_pin) )
73
//        light = 1;
74
//      else
75
//      {
76
//        light = 0;
77
//        OCR0B = 255;                     //max. Helligkeit
78
//      }
79
//    break;
80
//    }
81
//    case 40:                           //nach weiteren 200msek.
82
//    {
83
//      if (light)
84
//      {
85
//        if ( light_port & (1 << light_pin) )
86
//          OCR0B = 80;                  //Helligkeit abdunkeln
87
//      }
88
//      else
89
//      {
90
//        light = 0;
91
//        OCR0B = 255;                     //max. Helligkeit
92
//      }
93
//    break;
94
//    }
95
    case 81:        //nach 800msek.
96
    {
97
      if (!(error))
98
      {
99
        therm_reset();
100
        therm_write_byte(THERM_CMD_SKIPROM);
101
        therm_write_byte(THERM_CMD_RSCRATCHPAD);
102
        scratchpad[0]=therm_read_byte();
103
        scratchpad[1]=therm_read_byte();
104
      }
105
    break;
106
    }
107
    case 82:
108
    {
109
      if (!(error))
110
      {
111
        if (scratchpad[1] != 0)    //negative Temperatur
112
        {
113
          digit = ((0xff-scratchpad[0]) +1)>>1;
114
          if (digit < 10)
115
          {
116
            array[0] = ' ';
117
            array[1] = '-';              //Minus-Zeichen setzen
118
            array[2] = (digit%10) + '0';
119
            array[3] = 'C';
120
          }
121
          else
122
          {
123
            array[0] = '-';              //Minus-Zeichen setzen
124
            array[1] = ((digit/10)% 10)+ '0';    //zehner Stelle
125
            array[2] = (digit%10) + '0';      //einer stelle
126
            array[3] = 'C';
127
          }
128
          
129
        }
130
        else
131
        {
132
          digit=scratchpad[0]>>1;
133
          if (digit < 10)
134
          {
135
            array[0] = ' ';          
136
            array[1] = ' ';            //vorstellen-Null ausblenden
137
            array[2] = (digit%10) + '0';
138
            array[3] = 'C';
139
          }
140
          else
141
          {
142
            array[0] = ' ';  
143
            array[1] = ((digit/10)% 10)+ '0';    //zehner Stelle
144
            array[2] = (digit%10) + '0';      //einer stelle
145
            array[3] = 'C';
146
          }
147
        }
148
      }
149
      else
150
      {
151
        if (!(flash))
152
        {
153
          array[0] = 'E';
154
          array[1] = 'r';
155
          array[2] = 'r';
156
          array[3] = ' ';
157
          flash = 1;
158
        }
159
        else
160
        {
161
          array[0] = 'S';
162
          array[1] = 'e';
163
          array[2] = 'n';
164
          array[3] = 's';
165
          flash = 0;
166
        }
167
      }
168
    break;
169
    }
170
    case 83:
171
    {
172
       lcd_setcursor( 0, 2 );
173
      lcd_string(array);
174
      tick = 0;
175
    break;
176
    }
177
    }
178
   sei();
179
   sleep_mode();
180
  }
181
}

Das Display zeigt mir in Zeile 1 alles wie gewünscht an. In Zeile 2 im 
ersten Moment auch "---C", dann allerdings kommen Err und Sens und 
irgendwann dann wilde Zeichenkombinationen, die sich im Verlauf der Zeit 
auch auf Zeile 1 ausweiten.

von Ronny S. (ronnysc)


Lesenswert?

Tja Dein µC läuft mit 1MHz, meiner mit 8MHz. Damit mußt Du die TIMER1 
Initialisierung auch anpassen.
1
//Timer1 aller 10ms bei 1MHz Taktfrequenz
2
TCCR1B |= ((1<<WGM12) | (1<<CS11));    // Modus 4 CTC, Prescaler 8
3
TIMSK |= (1<<OCIE1A);
4
OCR1A = 1250;
Dann ist die Frage wie lang ist das Anschlußkabel zum Sensor. Je länger 
desto kleiner der Pull-UP an DQ.
Die wilden Zeichenkombinatinen deuten auch auf falsches Timing des LCD 
hin. Versuche doch erstmal eine stehende LCD-Anzeige in beiden Zeilen 
hinzubekommen. Kannst ja in Zeile 2 eine Variable hochzählen lassen 
(Variable bei case 81 z.B. hochzählen lassen). Wen das klappt wendest Du 
Dich dem Sensor zu.

von Beks (Gast)


Lesenswert?

Hallo Ronny,

also auf dem LCD bekomm ich eigentlich eine stabile Anzeige. Es wechselt 
halt immer zwischen Err Sens und wilden Zeichen. Das mit dem Takt hab 
ich mir schon fast gedacht. Habe leider noch nie was mit Timern gemacht 
und versteh den Code von dir dazu auch nicht. Um die Zeiten des Sensors 
einzuhalten verwendest du den Timer?

von Beks (Gast)


Lesenswert?

Ich hab eine Vermutung, ich hab den Sensor an PD6 hängen und das LCD an 
D0-D5. Kann es sein, das die im Laufe des Programms auch verändert 
werden und das Display dewegen manchmal springt?

von Beks (Gast)


Lesenswert?

Also folgendes, wenn ich den Sensor nicht mit dem µC verbinde, dann 
zählt er wunderbar meine int test=0; im case 81 hoch und stellt sie in 
der 2. zeile des lcd dar. Sobald ich den Sensor anschließe, würfelt er 
das ganze lcd durcheinander und er zählt an allen beliebigen 
cursorpositionen hoch.

von Beks (Gast)


Lesenswert?

So ich hab jetzt das Display an Port B gehangen und an Port D hängt nur 
am D6 der Sensor. Ich lass in case 81 eine int hochzählen und die auf 
dem lcd in zeile 2 ausgeben. Die Ausgabe zählt auch hoch. Daneben lass 
ich array ausgeben, was immer zwischen Sens und Err wechselt. Damit hab 
ich die Zeitbedingungen wohl verletzt laut Flussdiagramm. Wie lös ich 
das Problem?

von Martin (Gast)


Lesenswert?

Beks schrieb:
> Daneben lass
> ich array ausgeben, was immer zwischen Sens und Err wechselt. Damit hab
> ich die Zeitbedingungen wohl verletzt laut Flussdiagramm. Wie lös ich
> das Problem?

Wie du im Flußdiagramm sehen kannst, bedeutet die wechselnde Anzeige, 
dass die Initialisierung des Sensors nicht funktioniert hat.
Guck dir die Signale, die zu Sensor geschickt werden an und vergleich 
das mit den Angaben im Datenblatt. Um die Taktfrequenz zu prüfen, kannst 
du auch auf einem anderen Port-Pin über Vorwiderstand eine LED 
anschließen und parallel zur Sensorabfrage blinken lassen. Wenn die LED 
nicht ungefähr im Sekundentakt blinkt, stimmt das Timing für die 
Sensorabfrage noch nicht.

mfg Martin

von Beks (Gast)


Lesenswert?

Martin schrieb:
> Wenn die LED
> nicht ungefähr im Sekundentakt blinkt, stimmt das Timing für die
> Sensorabfrage noch nicht.

Ich lass ja in der Case 81 eine int inkrementieren und dann am Ende auch 
ausgeben. Die zählt auch ungefähr im Sekundentakt hoch. Im gleichen Takt 
wechselt auch das array von Err auf Sens. Ja irgendwas passt da mit der 
Initialisierung nicht. Aber was?

Nochmal den Quellcode:
main.c
1
#include "main.h"
2
#include "temp_eigen.h"
3
#include "lcd-routines.h"
4
 
5
 
6
char array[4];
7
volatile uint8_t tick;
8
9
uint8_t scratchpad[2];
10
uint8_t error;
11
uint8_t light;
12
uint8_t flash;
13
14
int test=0;
15
char testa[3];
16
17
ISR(TIMER1_COMPA_vect)          //aller 10msek.
18
{
19
  tick++;
20
}
21
22
int main(void)
23
{
24
25
//Timer1 aller 10ms bei 1MHz Taktfrequenz
26
TCCR1B |= ((1<<WGM12) | (1<<CS11));    // Modus 4 CTC, Prescaler 8
27
TIMSK |= (1<<OCIE1A);
28
OCR1A = 1250;          
29
30
31
//Sleep_Mode Init
32
set_sleep_mode(SLEEP_MODE_IDLE);        //Init Sleep-Modus auf IDLE
33
34
//Anzeige init
35
lcd_init();
36
37
//3x Minus-Zeichen am Anfang
38
array[0] = '-';    
39
array[1] = '-';
40
array[2] = '-';
41
array[3] = 'C';    //°C zeichen
42
43
44
   lcd_setcursor( 0, 1 );
45
  lcd_string("-Happy Birthday-");
46
47
48
sei();
49
50
  for(;;)
51
  {
52
    uint8_t digit;
53
  cli();
54
  switch (tick)
55
  {
56
    case 1:
57
    {
58
      if(therm_reset())
59
        error = 1;
60
      else
61
        error = 0;
62
      if (!(error))
63
      {
64
        therm_write_byte(THERM_CMD_SKIPROM);
65
        therm_write_byte(THERM_CMD_CONVERTTEMP);
66
      }
67
    break;
68
    }
69
//    case 20:                           //nach 200msek.
70
//    {
71
//      if ( light_port & (1 << light_pin) )
72
//        light = 1;
73
//      else
74
//      {
75
//        light = 0;
76
//        OCR0B = 255;                     //max. Helligkeit
77
//      }
78
//    break;
79
//    }
80
//    case 40:                           //nach weiteren 200msek.
81
//    {
82
//      if (light)
83
//      {
84
//        if ( light_port & (1 << light_pin) )
85
//          OCR0B = 80;                  //Helligkeit abdunkeln
86
//      }
87
//      else
88
//      {
89
//        light = 0;
90
//        OCR0B = 255;                     //max. Helligkeit
91
//      }
92
//    break;
93
//    }
94
    case 81:        //nach 800msek.
95
    {
96
      if (!(error))
97
      {
98
        therm_reset();
99
        therm_write_byte(THERM_CMD_SKIPROM);
100
        therm_write_byte(THERM_CMD_RSCRATCHPAD);
101
        scratchpad[0]=therm_read_byte();
102
        scratchpad[1]=therm_read_byte();
103
      }
104
      test++;
105
106
    break;
107
    }
108
    case 82:
109
    {
110
      if (!(error))
111
      {
112
        if (scratchpad[1] != 0)    //negative Temperatur
113
        {
114
          digit = ((0xff-scratchpad[0]) +1)>>1;
115
          if (digit < 10)
116
          {
117
            array[0] = ' ';
118
            array[1] = '-';              //Minus-Zeichen setzen
119
            array[2] = (digit%10) + '0';
120
            array[3] = 'C';
121
          }
122
          else
123
          {
124
            array[0] = '-';              //Minus-Zeichen setzen
125
            array[1] = ((digit/10)% 10)+ '0';    //zehner Stelle
126
            array[2] = (digit%10) + '0';      //einer stelle
127
            array[3] = 'C';
128
          }
129
          
130
        }
131
        else
132
        {
133
          digit=scratchpad[0]>>1;
134
          if (digit < 10)
135
          {
136
            array[0] = ' ';          
137
            array[1] = ' ';            //vorstellen-Null ausblenden
138
            array[2] = (digit%10) + '0';
139
            array[3] = 'C';
140
          }
141
          else
142
          {
143
            array[0] = ' ';  
144
            array[1] = ((digit/10)% 10)+ '0';    //zehner Stelle
145
            array[2] = (digit%10) + '0';      //einer stelle
146
            array[3] = 'C';
147
          }
148
        }
149
      }
150
      else
151
      {
152
        if (!(flash))
153
        {
154
          array[0] = 'E';
155
          array[1] = 'r';
156
          array[2] = 'r';
157
          array[3] = ' ';
158
          flash = 1;
159
        }
160
        else
161
        {
162
          array[0] = 'S';
163
          array[1] = 'e';
164
          array[2] = 'n';
165
          array[3] = 's';
166
          flash = 0;
167
        }
168
      }
169
    break;
170
    }
171
    case 83:
172
    {
173
       lcd_setcursor( 0, 2 );
174
      itoa(test, testa,10);
175
      lcd_string(testa);
176
      lcd_setcursor( 4, 2 );
177
      lcd_string(array);
178
      tick = 0;
179
    break;
180
    }
181
    }
182
183
   sei();
184
   sleep_mode();
185
  }
186
}

main.h
1
#ifndef MAIN_H
2
#define MAIN_H
3
4
#define F_CPU 1000000UL
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#include <stdlib.h>
9
#include <stdint.h>
10
#include <Stdio.h>
11
#include <util/delay.h>
12
#include <avr/sleep.h>
13
14
/* Thermometer Connections (At your choice) */
15
#define THERM_PORT   PORTD
16
#define THERM_DDR   DDRD
17
#define THERM_PIN   PIND
18
#define THERM_DQ   PD6
19
/* Utils */
20
#define THERM_INPUT_MODE()     THERM_DDR&=~(1<<THERM_DQ)
21
#define THERM_OUTPUT_MODE()    THERM_DDR|=(1<<THERM_DQ)
22
#define THERM_LOW()       THERM_PORT&=~(1<<THERM_DQ)
23
#define THERM_HIGH()       THERM_PORT|=(1<<THERM_DQ)
24
25
#define THERM_CMD_CONVERTTEMP 0x44
26
#define THERM_CMD_RSCRATCHPAD 0xbe
27
#define THERM_CMD_WSCRATCHPAD 0x4e
28
#define THERM_CMD_CPYSCRATCHPAD 0x48
29
#define THERM_CMD_RECEEPROM 0xb8
30
#define THERM_CMD_RPWRSUPPLY 0xb4
31
#define THERM_CMD_SEARCHROM 0xf0
32
#define THERM_CMD_READROM 0x33
33
#define THERM_CMD_MATCHROM 0x55
34
#define THERM_CMD_SKIPROM 0xcc
35
#define THERM_CMD_ALARMSEARCH 0xec
36
37
/* Display Connections */
38
//#define A0         (1<<PD2)
39
//#define A1         (1<<PD3)
40
//#define WR         (1<<PD4)
41
42
//#define CU         (1<<PB7)
43
//#define PWM       (1<<PD5)
44
45
//#define DATA        PORTB
46
//#define DDR_DATA     DDRB
47
//#define CTRL        PORTD
48
//#define DDR_CMD      DDRD
49
50
//#define ASCII           1
51
//#define CMD             0
52
//#define seg_nix     0x20
53
//#define seg_c     0x1b
54
55
/* Light-ON Connections */
56
//#define light_port  PIND
57
//#define light_pin  PD0
58
59
#endif

von Ronny S. (ronnysc)


Lesenswert?

Oder Dein Sensor ist futsch. Schau Dir mal die Leitung wo Dein Sensor 
dran hängt (PIN DQ) mit dem Oszi an, Zuerst ohne Sensor und dann mit. Da 
muß ein Unterschied zu sehen sein.
Die Timings für die 1-Wire-Kommunikation mache ich mit der 
delay-Funktion. Bei mir funktioniert das System seit mehreren Monaten 
perfekt.

von Beks (Gast)


Lesenswert?

Im Quellcode ist kein Problem? Also ich hab die Verdrahtung auf einen 
Steckboard und ein Oszi hab ich leider noch nichr. Der Sensor könnte 
natûrlich hin sein, glaub aber eher das im Quellcode was nicht stimmt. 
Das mit.dem Timer und case versteh ich noch nicht, kann daher nicht 
erkennen ob ich nicht die Zeitbedingungen verletze.

von Beks (Gast)


Lesenswert?

Im Quellcode ist kein Problem? Also ich hab die Verdrahtung auf einen 
Steckboard und ein Oszi hab ich leider noch nichr. Der Sensor könnte 
natûrlich hin sein, glaub aber eher das im Quellcode was nicht stimmt. 
Das mit.dem Timer und case versteh ich noch nicht, kann daher nicht 
erkennen ob ich nicht die Zeitbedingungen verletze.

von Ronny S. (ronnysc)


Lesenswert?

Nein im Quellcode ist kein Problem, bei mir funktionierts ja auch. Ich 
habe das Ganze einmal auf dem Steckbrett aufgebaut gehabt und dann auf 
der Platine. Beides hat funktioniert mit verschiedenen DS18S20-Sensoren

Zum Timer:
Der Timer-Interrupt erfolgt aller 10ms. In der Interrupt-Routine wird 
nur die variable "tick" hochgezählt. in der int main(void) wird mit case 
die variable "tick" ausgewertet, d.h. nach 10ms wird der DS18S20 
resettet, alle Adressen angesprochen da nur ein Sensor am Bus hängt und 
eine Messung gestartet. Bei 810ms (case 81) wird wieder ein Reset 
ausgelöst, alle Adressen angesprochen und der Speicher des DS18S20 
ausgelesen. Bei 820ms erfolgt dann die Konvertierung des 
Temperaturwertes für die Anzeige. Das alles geschieht aber nur wenn der 
1.Reset erfolgreich war.

Näheres dazu hier: 
http://www.teslabs.com/openplayer/docs/docs/other/ds18b20_pre1.pdf

von beks (Gast)


Lesenswert?

1
//Timer1 aller 10ms bei 1MHz Taktfrequenz
2
TCCR1B |= ((1<<WGM12) | (1<<CS11));    // Modus 4 CTC, Prescaler 8
3
TIMSK |= (1<<OCIE1A);
4
OCR1A = 1250;

"The OCR1A or ICR1 define the top value for the counter, hence also its 
resolution." Auszug Datenblatt.

Warum wird OCR1A auf 1250 gesetzt?

von beks (Gast)


Lesenswert?

Und mein Controller läuft ja unverändert auf den Default Clock Source, 
also 1Mhz. Muss ich dann in folgender Zeile nicht ein no prescaling 
einstellen?
Also CS10 setzen?
1
TCCR1B |= ((1<<WGM12) | (1<<CS11));    // Modus 4 CTC, Prescaler 8

von ronnysc (Gast)


Lesenswert?

beschäftige Dich erstmal mit den Timer-Möglichkeiten die die 
AVR-Controller bieten, siehe hier: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR
Dort ist auch erklärt was die Variable OCR1A bewirkt. Der 
Timer1-Interrupt wird nicht als Overflow sondern als Compare ausgelöst.
Gut korrekterweise müßte es noch heißen:
OCR1A = 1250-1; //Compare bei 10ms

von ronnysc (Gast)


Lesenswert?

...und schon gab er auf. Nee nee das wird nix.

von beks (Gast)


Lesenswert?

Nein nein, ich bin beruflich nur gerade ziemlich eingebunden und bin 
noch nicht dazu gekommen. Das die Variable für einen Vergleich zuständig 
ist hab ich auch schon gelesen, aber noch nicht tiefergehend. Es ist 
auch sehr mühseelig sich in das Thema einzuarbeiten, wenn man keine 
Nachrichtentechnik studiert hat :)

von beks (Gast)


Lesenswert?

So ich hab mir jetzt den Text mal durchgelesen zu den Timern und weiß 
leider immernoch nicht mehr bescheid.
1
TCCR1B |= ((1<<WGM12) | (1<<CS11));    // Modus 4 CTC, Prescaler 8
Warum wähl ich als Vorteiler 8 bei einen Clock von 1Mhz? Damit hab ich 
eine reduzierten Takt von 125 Khz. Dann wird das WGM12 (CTC1) Bit 
gesetzt, damit wird der Wert OCR1A = 1250;  mit dem aktuellen Zählwert 
verglichen und bei Gleichheit der aktuelle Zählwert Null gesetzt. Dabei 
seh ich aber irgendwie immer noch nicht in welchen Zeittakt der Timer 
nun zählt? Mit 125 kHz? Das heißt die Periode wäre 1/125kHz = 8µs. Dann 
zählt er aller 8µs einen Wert hoch?

von ... (Gast)


Lesenswert?

Rechne mal nach: Wenn der Timer mit 125 kHz zählt und bei Zählerstand 
1250 ein ISR ausgelöst wird, in welchen Zeitabständen passiert das dann?

von Karl H. (kbuchegg)


Lesenswert?

beks schrieb:
> So ich hab mir jetzt den Text mal durchgelesen zu den Timern und weiß
> leider immernoch nicht mehr bescheid.
>
>
1
> TCCR1B |= ((1<<WGM12) | (1<<CS11));    // Modus 4 CTC, Prescaler 8
2
>
> Warum wähl ich als Vorteiler 8 bei einen Clock von 1Mhz? Damit hab ich
> eine reduzierten Takt von 125 Khz. Dann wird das WGM12 (CTC1) Bit
> gesetzt, damit wird der Wert OCR1A = 1250;  mit dem aktuellen Zählwert
> verglichen und bei Gleichheit der aktuelle Zählwert Null gesetzt. Dabei
> seh ich aber irgendwie immer noch nicht in welchen Zeittakt der Timer
> nun zählt? Mit 125 kHz? Das heißt die Periode wäre 1/125kHz = 8µs. Dann
> zählt er aller 8µs einen Wert hoch?

Bis hier her alles richtig.
Und wenn der Timer jetz mit diesem "alle 8µs 1 weiter zählen" bei 1250 
angelangt ist, löst er einen Compare Match aus und fängt wieder bei 0 
an.
WIe oft kommt daher dieser Comapre Match?

(Du bist am Compare Match interessiert! Das ist der Teil mit dem du 
arbeiten kannst indem du zb eine ISR anhängst)

von beks (Gast)


Lesenswert?

... schrieb:
> Rechne mal nach: Wenn der Timer mit 125 kHz zählt und bei Zählerstand
> 1250 ein ISR ausgelöst wird, in welchen Zeitabständen passiert das dann?

125 Khz --> 8 µs zwischen den Zählsignalen und wenn er bis 1250 zählt, 
sind das 1250 * 8 µs = 10 ms

von beks (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Bis hier her alles richtig.
> Und wenn der Timer jetz mit diesem "alle 8µs 1 weiter zählen" bei 1250
> angelangt ist, löst er einen Compare Match aus und fängt wieder bei 0
> an.
> WIe oft kommt daher dieser Comapre Match?

Ich glaub ich versteh es. Dann kommt aller 10 ms dieser "compare match" 
und bei dem Quellcode oben wird in der ISR die Variable tick 
inkrementiert. Nach 10ms ist die 1, dann nochmal 10ms und tick = 2 und 
zeit war 20ms, ... , nach 80 mal 10ms ist tick=80 und die verstrichene 
Zeit war 800 ms.

von Karl H. (kbuchegg)


Lesenswert?

Gratuliere. Du hast gerade den Rechengang nachvollzogen, mit dem die 
Verbdindung von hier

Beitrag "Re: DS18S20 und ATTINY 2313"
> "The OCR1A or ICR1 define the top value for the counter,
> hence also its resolution." Auszug Datenblatt.
>
> Warum wird OCR1A auf 1250 gesetzt?

zu hier

Beitrag "Re: DS18S20 und ATTINY 2313"
> Zum Timer:
> Der Timer-Interrupt erfolgt aller 10ms.

hergestellt wird.

von beks (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Gratuliere.

Danke :) Leider hängt der Sensor aber dennoch irgendwie im Errormodus 
fest. Er zeigt immer nur Err und Sens im Wechsel an.

von ronnysc (Gast)


Lesenswert?

schön das Du am Ball bleibst... Und ich habe auch nicht studiert.

es wird auch nicht an der Timer-Auswertung liegen. Die Zeiten für den 
Sensor werden mit der delay-Funktion erzeugt. Was noch möglich ist das 
die 1MHz zu langsam sind. Du kannst auch den ATTINY2313 mit 8MHz laufen 
lassen ohne externen Quarz. Dazu die Clockdiv. Variable in den Fuse-Bits 
deaktivieren.
siehe hierzu: http://www.mikrocontroller.net/articles/AVR_Fuses und 
hier:
http://www.ladyada.net/learn/avr/fuses.html

von beks (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab den jetzt auf internen 8 Mhz Takt umgestellt (siehe dazu 
Anhang). In meinen Quellcode hab ich natürlich in meiner Lcd-header-file 
die Freq. auf 8 Mhz angepasst und nun zeigt er mir nur noch wilde Sachen 
in der zweiten Zeile an. Die erste Zeile ist komplett leer, wobei dort 
auch etwas stehen sollte. Also ist dabei wohl etwas schief gegangen.

von beks (Gast)


Lesenswert?

Ich schäm mich, ich hatte den Sensor verpolt. Das mit den 8 Mhz versteh 
ich aber dennoch nicht. Der Sensor läuft jetzt aber Klasse auf 1 Mhz und 
so soll das auch bleiben!

von beks (Gast)


Lesenswert?

Ronny, auf meinen LCD bekomm ich die Ausgabe für °C nicht hin. Das 
Datenblatt gibt eigentlich kaum was dazu her. Auf deine Art hab ich es 
auch schon versucht über den ASCII Code. Und mit '°C' nimmt er auch 
nicht. Hab ein LCD-Modul TC1602E-01.

von Ronny S. (ronnysc)


Lesenswert?

Gratulation,
warum es mit 8MHz nicht funktioniert kann ich Dir nicht sagen, wird aber 
an der LCD-Routine liegen. Das ASCII-Zeichen von mir ist dem Datenblatt 
meiner Anzeige entnommen. Für Dein LCD ist aber nicht viel zu finden. 
Nach langer Suche habe ich es hier im Forum gefunden: 
http://www.mikrocontroller.net/attachment/72821/SPLC780D001BC.pdf
Das "°C"-Zeichen gibt es auf Deinem LCD nicht, also setzt Du es aus 2 
Symbolen zusammen. Zuerst das "°"-Symbol mit
1
array[3] = 0xB2;
und dann der Buchstabe "C"
1
array[4] = 'C';
Die Größe des Arrays muß natürlich am Anfang auch noch angepasst werden:
1
char array[5];
fertig...

von ronnysc (Gast)


Lesenswert?

...und har es funktioniert?

von beks (Gast)


Lesenswert?

ronnysc schrieb:
> ...und har es funktioniert?

War das Wochenende über nicht da. Habs gerade getestet und leider klappt 
es nicht. Das ° hatte ich auch schon versucht über '°' dazustellen, was 
natürlich nicht funktionierte. Deine Variante über 0xB2 klappt leider 
auch nicht. Hab mir grad bei den Link mal die ganzen möglichen Zeichen 
angeschaut und leider das dargestellt nicht gefunden. Weiterhin hab ich 
etwas komisches festgestellt. Wenn ich den µC von Spannung nehme und 
dann wieder anlege, wird in der ersten Zeile mein Text kurz angezeigt 
und dann in wilde Zeichen gewandelt. Wenn ich dann das Programm wieder 
neu aufspiele, dann bleibt der Text in der ersten Zeile korrekt stehen. 
Nehm ich den µC wieder von Spannung und leg wieder an, gleicher Effekt.

von beks (Gast)


Lesenswert?

Ich hab ein Datenblatt mit den richtigen Character Codes gefunden. Dies 
wäre es gewesen:
http://www.adafruit.com/datasheets/TC1602A-01T.pdf

Also 0xDF sollte den ° ergeben.

von ronnysc (Gast)


Lesenswert?

Also ich gehe immer noch davon aus das die Ansteuerung des LCD falsch 
ist bzw. das Timing nicht stimmt. Packe mal Dein komplettes Programm in 
eine ZIP-Datei und poste das mal hier.

von beks (Gast)


Angehängte Dateien:

Lesenswert?

Ich muss zugeben, die LCD Routine wurde nicht selbst geschrieben, 
funktioniert aber eigentlich ganz gut. Ich hab den Quellcode mal gepackt 
und er befindet sich im Anhang.

von beks (Gast)


Lesenswert?

Ein kleinen Fehler hab ich schonmal, das array sollte char array[5] 
sein! Dennoch löscht er mir den Text aus der ersten Zeile, wenn ich das 
System stromlos schalte.

von Ronny S. (ronnysc)


Angehängte Dateien:

Lesenswert?

Tja das liegt an was anderem. Du hast den Fehler in Deiner Ansteuerung 
des LCD, siehe: 
http://www.mikrocontroller.net/articles/String-Verarbeitung_in_C

Die Routine ist in Ordnung, Du mußt nur das String-Ende auch setzen. 
Ansonsten läuft die Routine "lcd_string" ewig. Der Quellcode im Anhang 
ist dahingehend von mir korrigiert und noch ein paar Extras :).
Probiere das mal aus.

von beks (Gast)


Lesenswert?

Ich vermute es liegt hier irgendwo der Fehler. Für diesen Code wird nach 
dem wegnehmen der Spannung und wieder zuschalten, die erste Zeile 
richtig dargestellt. Allerdings aktualisiert die zweite Zeile nicht 
mehr, was sich darin äußert, dass die Temperaturanzeige nur durch einen 
µC-Reset aktualisiert.
1
  case 83:
2
  {
3
  //Ausgabe GrundLCD
4
  lcd_setcursor( 0, 2 );
5
  lcd_string("Temperatur:");
6
  lcd_setcursor( 11, 2 );
7
  lcd_string(array);
8
  lcd_home();
9
  lcd_string(" HAPPY BIRTHDAY ");
10
  tick = 0;
11
break;

Im folgenden Fall, aktualisiert der µC nach dem stromlos schalten die 
zweite Zeile (Temperaturanzeige), allerdings wird die Zeile durch wilde 
Zeichen dargestellt.
1
  case 83:
2
  {
3
  //Ausgabe GrundLCD
4
  lcd_home();
5
  lcd_string(" HAPPY BIRTHDAY ");
6
  lcd_setcursor( 0, 2 );
7
  lcd_string("Temperatur:");
8
  lcd_setcursor( 11, 2 );
9
  lcd_string(array);
10
  tick = 0;
11
break;

von Ronny S. (ronnysc)


Lesenswert?

schau Dir mal mein Quellcode an, die Posts haben sich jetzt 
überschnitten...

von beks (Gast)


Lesenswert?

Ach mist, das Backslash 0 :) Ja so ist das wenn man zu wenig übt. Ja das 
hab ich natürlich vergessen bei dem char array. Danke dir - es 
funktioniert so wunderbar. Vielleicht sollten wir mal icq nummern 
tauschen ;)

Du setzt den Sensor ja in den sleep mode idle. Könnte ich den auch in 
den Power Save Modus schalten und anstelle des Timer 1, den Timer 2 
benutzen? Die Stromaufnahme reduziert sich dann ja schonmal erheblich.

von Ronny S. (ronnysc)


Lesenswert?

Na dann schick mir mal Deine per PN.
Power Safe Mode nützt sicher nicht so viel, da das Programm aller 10ms 
wieder aus dem Schlaf geweckt wird. Ich nutzt den Sleepmode eigentlich 
nur um das Programm am Ende der for-Schleife anzuhalten. Damit habe ich 
immer einen definierten Einstieg.
Könnte man sicher auch mit dem Watchdog hinbekommen. Den aller 10ms 
anschlagen lassen und den Controller in den Power Down Modus am Ende der 
Schleife schicken. Ist zwar mit der Brechstange, ginge aber. Fraglich 
ist aber was das an Strom wirklich spart...

von Ronny S. (ronnysc)


Lesenswert?

aber freut mich das es jetzt funktioniert. Für die endgültige Version 
empfehle ich Dir aber einen Quarz. Der interne Oszillator ist nicht 
unbedingt frequenzstabil bei unterschiedlichen Temperaturen.

von Bernhard S. (bernhard)


Lesenswert?


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.