Forum: Mikrocontroller und Digitale Elektronik 2Punktregler_Atmega8_SMT160-30


von Christian R. (s3mt3x)


Lesenswert?

Hi Leute nachdem ich glaube ich endgültig am verzweifeln bin und mir die 
Zeit im Nacken sitzt wende ich mich jetzt mit meinem Problem an euch als 
Letze Anlaufstelle.

Zu meinem Problem, Ich habe vor im Zuge eines Projekts einen 2 
Punktregler
mithilfe eines Atmega8 zu realisieren. Das Problem ich bin der totale 
Anfänger. Ich habe mich erst seit 2 Wochen mit den Atmegas 
auseinandergesetzt
und zu Beginn alles über AVRStudio6 programmiert und dann alles mithilfe 
von PonyProg und einer Parallelen-Schnittstelle auf meinen Atmega 
geflasht.

Ich möchte mithilfe einer PWM die mir von meinem 
SMT160-30(http://www.smartec.nl/pdf/DSSMT16030.PDF) erzeugt wird den 
dutcycle berechnen und dann damit E/A Zeitpunkt festlegen.

Natürlich habe ich nicht nur einen Sensor was das ganze zusätzlich 
erschwert und ich muss das ganze auch noch multiplexen dazu habe ich 
folgendes gefunden: 
http://www.is-line.de/produkte/temperatur/smt160-30/eigenerwaermung-des-temperatursensor-smt-160-30-bei-ein-und-mehrkanalapplikationen/

Nachdem ich am Anfang die Idee hatte das alles über INT0 und INT1 laufen 
zu lassen viel mir am Oszilloskop auf das die Zeiten beim toggeln des 
Signal nach der ISR nicht gepasst haben also hab ich das Datenblatt 
nochmal zur Hand genommen und siehe da Seite82 stands dann um den 
dutycycle oder Frequenzen zu bestimmen nimmt man den ICP1 Pin.

Gut Ansatz hatte ich dann schon wieder einen neuen, nach weiterer 
Recherche kam ich dann auf die AVR135 
Bibliothek(http://www.atmel.com/Images/AVR135.zip ) die Atmel zur 
Verfügung stellt.

Auch da hab ich mich durchgewurstet und hab ein halbwegs anständigen 
Code zusammengestellt.

Das Problem besteht jetzt darin herauszufinden ob dieser Code so 
funktioniert oder nicht ich habe noch Zeit bis Montag um es zum laufen 
zu bekommen sonst wird meine Idee verworfen und das wäre für mich die 
Hölle!

Natürlich ist er noch nicht ganz fertig. Das liegt zum einen daran das 
ich seit heute ein STK500 hier habe und erstmal verstehen muss wie das 
alles funktioniert und im Moment will er meine seriellen Ports(Ich 
benutze AVRStudio6 habe aber auch 4 versucht) nicht erkennen und ich 
bekomme ein Connection failed! Der andere Grund warum er unfertig ist 
ist eben das ich keine Ahnung habe wie ich das am besten Testen soll. 
Wieso benutzen die ständig diese #pragma geschichten in Ihrer Bibliothek 
das stößt mir sauer auf weil ich das bisher nicht kenne.

Ich wäre für jede Hilfe dankbar.

Ausserdem kann mir vielleicht wer sagen ob die ISR so richtig wäre :)?
1
/*
2
 * _2_Punktregler_Temp_SMT_160_30.c
3
 *
4
 * Created: 19.09.2013 10:48:00
5
 *  Author: Administrator
6
 */ 
7
8
9
#include <avr/io.h>
10
#include <avr/interrupt.h>
11
#include "icp.h"
12
13
/* Atmega8 Portdefinitionen */
14
#define  ICP_PIN    PINB      /* ICP1 GPIO Wert  */
15
#define  ICP_PORT  PORTB      /* ICP1 GPIO Port  */
16
#define  ICP_DDR    DDRB      /* ICP1 GPIO DDR  */
17
#define  ICP_BIT    PB0        /* ICP1 GPIO Pin  */
18
/*Timerdefinitionen*/
19
#define  ICP_OCR    OCR1A      /* ICP1 Ausgabe Vergleichsregister    */
20
#define  ICP_OC_IE  OCIE1A      /* ICP1 Timer Ausgabe Vergleich EIN */
21
#define  ICP_OC_IF  OCF1A      /* ICP1 Timer Ausgabe Vergleichs Flag  */
22
#define  ICP_IE    TICIE1      /* ICP1 Unterbrechung EIN      */
23
#define  ICP_IF    ICF1      /* ICP1 Unterbrechungs Flag        */
24
#define  ICP_CTL_A  TCCR1A      /* ICP1 Timer Kontrollreg        */
25
#define  ICP_CTL    TCCR1B      /* ICP1 Unterbrechungs Kontrollreg      */
26
#define  ICP_SENSE  ICES1      /* ICP1 Unterbrechung bei  (steigend/fallend) */
27
#define  ICP_PRESCALE ((0 << CS12) | (0 << CS11) | (1 << CS10))  /* Vorteiler /1 */
28
29
#define  ICP_START_SENSE  (1 << ICP_SENSE)  /* starte mit steigender Flanke  */
30
/*Demodulationsvaraiblen*/
31
typedef unsigned int icp_timer_t;      /* von der selben Bitlänge wie TCNT1    */
32
icp_timer_t icp_start_time, icp_stop_time;
33
icp_timer_t icp_period;
34
35
/*speichert demodulierte Abtatswerte*/
36
icp_sample_t icp_rx_q[ICP_RX_QSIZE];
37
38
void icp_init(void)
39
{
40
  /*
41
   * Nothing interesting to set in TCCR1A
42
   */
43
  ICP_CTL_A = 0;
44
45
  /*
46
   * Setting the OCR (timeout) to 0 allows the full TCNT range for
47
   * the initial period.
48
   */
49
  ICP_OCR  = 0;
50
51
  /*
52
   * Set the interrupt sense and the prescaler
53
   */
54
  ICP_CTL  = ICP_START_SENSE | ICP_PRESCALE;
55
56
  /*
57
   *  Enable both the Input Capture and the Output Capture interrupts.
58
   *  The latter is used for timeout (0% and 100%) checking.
59
   */
60
  TIMSK  |= (1 << ICP_IE) | (1 << ICP_OC_IE);
61
62
  return;
63
}
64
65
/**
66
 * icp_rx_tail, icp_rx_head
67
 *
68
 * Queue state variables for icp_rx_q.
69
 *
70
 * The rx_head and rx_tail indices need to be wide enough to
71
 * accomodate [0:ICP_RX_QSIZE). Since QSIZE should generally
72
 * not be very large, these are hard-coded as single bytes,
73
 * which gets around certain atomicity concerns.
74
 */
75
unsigned char icp_rx_tail;    /* icp_rx_q insertion index */
76
#if  !ICP_ANALOG  /* ICP_DIGITAL */
77
unsigned char icp_rx_head;    /* icp_rx_q retrieval index */
78
#endif
79
80
81
/**
82
 * icp_enq()
83
 *
84
 * Stores a new sample into the Rx queue.
85
 */
86
#if __GCC__
87
__inline__
88
#else  /* assume IAR */
89
#pragma inline      /* for next function */
90
#endif
91
static void icp_enq(icp_sample_t sample)
92
{
93
  unsigned char t;
94
95
  t = icp_rx_tail;
96
#if  ICP_ANALOG
97
  icp_total += sample - icp_rx_q[t];
98
#endif
99
  icp_rx_q[t] = sample;
100
  if (++t >= ICP_RX_QSIZE)
101
    t = 0;
102
#if  !ICP_ANALOG
103
  if (t != icp_rx_head)    /* digital: Check for Rx overrun */
104
#endif
105
    icp_rx_tail = t;
106
  return;
107
}
108
109
/**
110
 *  icp_duty_compute()
111
 *
112
 *  This function computes the value of (ICP_SCALE*pulsewidth)/period.
113
 *  It is effectively a divide function, but uses a successive-approximation
114
 *  (moral equivalent of long division) method which:
115
 *  1) Doesn't require 32-bit arithmetic (the numerator is 24+ bits nominal).
116
 *  2) For an 8-bit result, only needs 8 loops (instead of 16 for general 16/16).
117
 *  3) Compiles nicely from C.
118
 *  We get away with this because we know that pulsewidth <= period, so
119
 *  no more than log2(ICP_SCALE) bits are relevant.
120
 */
121
#if __GCC__
122
__inline__
123
#else  /* assume IAR */
124
#pragma inline      /* for next function */
125
#endif
126
static icp_sample_t icp_duty_compute(icp_timer_t pulsewidth, icp_timer_t period)
127
{
128
  icp_sample_t r, mask;
129
130
  mask = ICP_SCALE >> 1;
131
  r = 0;
132
  do
133
  {
134
    period >>= 1;
135
    if (pulsewidth >= period)
136
    {
137
      r |= mask;
138
      pulsewidth -= period;
139
    }
140
    mask >>= 1;
141
  } while (pulsewidth != 0 && mask != 0);
142
  return(r);
143
}
144
145
146
ISR(TIMER1_CAPT_vect)
147
{
148
  icp_timer_t icr, delta;
149
  unsigned char tccr1b;
150
151
  /*
152
   * Capture the ICR and then reverse the sense of the capture.
153
   * These must be done in this order, since as soon as the
154
   * sense is reversed it is possible for ICR to be updated again.
155
   */
156
  icr = ICR1;              /* capture timestamp  */
157
158
  do
159
  {
160
    tccr1b = ICP_CTL;
161
    ICP_CTL = tccr1b ^ (1 << ICP_SENSE);    /* reverse sense    */
162
  
163
    /*
164
     * If we were waiting for a start edge, then this is the
165
     * end/beginning of a period.
166
     */
167
    if ((tccr1b & (1 << ICP_SENSE)) == ICP_START_SENSE)
168
    {
169
      /*
170
       * Beginning of pulse: Compute length of preceding period,
171
       * and thence the duty cycle of the preceding pulse.
172
       */
173
      icp_period = icr - icp_start_time;  /* Length of previous period */
174
      delta = icp_stop_time - icp_start_time; /* Length of previous pulse */
175
      icp_start_time = icr;        /* Start of new pulse/period */
176
177
      /*
178
       * Update the timeout based on the new period. (The new period
179
       * is probably the same as the old, give or take clock drift.)
180
       * We add 1 to make fairly sure that, in case of competition,
181
       * the PWM edge takes precedence over the timeout.
182
       */
183
      ICP_OCR = icr + icp_period + 1;    /* Move timeout window    */
184
      TIFR = (1 << ICP_OC_IF);      /* Clear in case of race  */
185
186
      /*
187
       * Compute the duty cycle, and store the new reading.
188
       */
189
      icp_enq(icp_duty_compute(delta,icp_period));
190
  
191
      /*
192
       * Check for a race condition where a (very) short pulse
193
       * ended before we could reverse the sense above.
194
       * If the ICP pin is still high (as expected) OR the IF is
195
       * set (the falling edge has happened, but we caught it),
196
       * then we won the race, so we're done for now.
197
       */
198
      if ((ICP_PIN & (1 << ICP_BIT)) || (TIFR & (1 << ICP_IF)))
199
        break;
200
    }
201
    else
202
    {
203
      /*
204
       * Falling edge detected, so this is the end of the pulse.
205
       * The time is simply recorded here; the final computation
206
       * will take place at the beginning of the next pulse.
207
       */
208
      icp_stop_time = icr;    /* Capture falling-edge time */
209
210
      /*
211
       * If the ICP pin is still low (as expected) OR the IF is
212
       * set (the transition was caught anyway) we won the race,
213
       * so we're done for now.
214
       */
215
      if ((!(ICP_PIN & (1 << ICP_BIT))) || (TIFR & (1 << ICP_IF)))
216
        break;
217
    }
218
    /*
219
     * If we got here, we lost the race with a very short/long pulse.
220
     * We now loop, pretending (as it were) that we caught the transition.
221
     * The Same ICR value is used, so the effect is that we declare
222
     * the duty cycle to be 0% or 100% as appropriate.
223
     */
224
  } while (1);
225
226
  return;
227
}
228
229
230
int main(void)
231
{
232
  
233
    while(1)
234
    {
235
  //(Hier steht noch nichts!)  
236
237
  }
238
}

von Christian R. (s3mt3x)


Lesenswert?

push re

von Hubert G. (hubertg)


Lesenswert?

Sag mal lässt sich das überhaupt kompilieren?
Du solltest im main zumindest mal icp init aufrufen.
Was hast du auf den ATmega überhaupt schon programmiert? Deine return 
und while wirken da etwas bunt hinein gewürfelt.

von Christian R. (s3mt3x)


Lesenswert?

ja lässt sich alles kompilieren ist ja nur ne leere main, programmiert 
hab ich schon so einiges aber noch nie auf nem Atmega.

Wie gesagt das sind alles Original Funktionen aus der Bibliothek und ich 
habe nur die ISR Routine vom alten Signal(), ins neue ISR() geändert.

ich vversteh nur nicht ganz was ich hier in die main klopfen sollte 
auser icp_init(), was nebenbei bemerkt klar sein sollte sry :).

: Bearbeitet durch User
von Hubert G. (hubertg)


Lesenswert?

Lässt sich nicht kompilieren.
Mit so einem zusammenkopierten Kode, der so sicher nicht funktioniert 
und den du allem Anschein nach nicht verstehst, wirst du nicht weit 
kommen.
Ich sehe da bis Montag schwarz für dich.

von Christian R. (Gast)


Lesenswert?

jo seh ich grad auch! Ich glaube ich habs langsam ich poste nachher 
wieder wenn ich weiter bin als copy paste, naja war eben alles ein wenig 
viel aufeinmal aber nur wers versucht kanns auch schaffen ich sagte ja 
vollnoob in Atmega :)

von Chrsitian R. (Gast)


Lesenswert?

So hab mir jetzt mal was zusammengebaut das meiner Ansicht nach kein 
totaler Schwachsinn ist aber ich hab leider im moment keine 
Testmöglichkeiten.

Wenn also noch wer drauf schauen könnte wäre das Klasse :)
1
/*
2
 * _2_Punktregler_Temp_SMT_160_30.c
3
 *
4
 * Created: 19.09.2013 10:48:00
5
 *  Author: Administrator
6
 */ 
7
8
9
#include <avr/io.h>
10
#include <avr/interrupt.h>
11
//#include "icp.h"
12
13
14
/* Atmega8 Portdefinitionen */
15
#define  ICP_PIN    PINB      /* ICP1 GPIO Wert  */
16
#define  ICP_PORT  PORTB      /* ICP1 GPIO Port  */
17
#define  ICP_DDR    DDRB      /* ICP1 GPIO DDR  */
18
#define  ICP_BIT    PB0        /* ICP1 GPIO Pin  */
19
20
/*Timerdefinitionen*/
21
#define  ICP_OCR    OCR1A      /* ICP1 Ausgabe Vergleichsregister    */
22
#define  ICP_OC_IE  OCIE1A      /* ICP1 Timer Ausgabe Vergleich EIN */
23
#define  ICP_OC_IF  OCF1A      /* ICP1 Timer Ausgabe Vergleichs Flag  */
24
#define  ICP_IE    TICIE1      /* ICP1 Unterbrechung EIN      */
25
#define  ICP_IF    ICF1      /* ICP1 Unterbrechungs Flag        */
26
#define  ICP_CTL_A  TCCR1A      /* ICP1 Timer Kontrollreg        */
27
#define  ICP_CTL    TCCR1B      /* ICP1 Unterbrechungs Kontrollreg      */
28
#define  ICP_SENSE  ICES1      /* ICP1 Unterbrechung bei  (steigend/fallend) */
29
#define  ICP_PRESCALE ((0 << CS12) | (0 << CS11) | (1 << CS10))  /* Vorteiler /1 */
30
31
#define  ICP_START_SENSE  (1 << ICP_SENSE)  /* starte mit steigender Flanke  */
32
33
#define sensor_const1 .320
34
#define sensor_const2 .00470
35
36
#define  ICP_SCALE 256U
37
typedef unsigned int icp_timer_t;      /* same as TCNT1    */
38
icp_timer_t icp_start_time, icp_stop_time;
39
icp_timer_t icp_period, duty_cycle;
40
41
void icp_init(void)
42
{
43
44
  DDRD = (1 << PIND);
45
46
  ICP_CTL_A = 0;
47
48
  ICP_OCR  = 0;
49
50
  ICP_CTL  = ICP_START_SENSE | ICP_PRESCALE;
51
52
  TIMSK  |= (1 << ICP_IE) | (1 << ICP_OC_IE);
53
54
}
55
56
57
ISR(TIMER1_CAPT_vect)
58
  {
59
      volatile icp_timer_t icr;
60
      unsigned char tccr1b;
61
      icr=ICR1;
62
    do
63
    {
64
      tccr1b = ICP_CTL;
65
      ICP_CTL = tccr1b ^ (1 << ICP_SENSE);  
66
      if ((tccr1b & (1 << ICP_SENSE)) == ICP_START_SENSE)
67
        {
68
        icp_period = icr - icp_start_time;  
69
        duty_cycle = icp_stop_time - icp_start_time;
70
        icp_start_time = icr;  
71
        if ((ICP_PIN & (1 << ICP_BIT)) || (TIFR & (1 << ICP_IF)))
72
        break;
73
        }
74
      else
75
      {
76
      icp_stop_time = icr;    /* Capture falling-edge time */
77
      if ((!(ICP_PIN & (1 << ICP_BIT))) || (TIFR & (1 << ICP_IF)))
78
        break;
79
    }
80
  } while (1);
81
82
  return;
83
}
84
  
85
      
86
87
88
89
90
int main(void)
91
{
92
  unsigned int temp;
93
  icp_init();
94
  sei();
95
  
96
    while(1)
97
    {
98
    temp = ((duty_cycle-sensor_const1)/sensor_const2);
99
    if(temp>0)
100
    {
101
      PORTD ^= 0x01;
102
    }
103
    else
104
      PORTD ^=0x02;
105
    
106
  }
107
}

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.