Forum: Compiler & IDEs Attiny10 Problem AVR Studio 6


von Jürgen F. (snipor)


Lesenswert?

Ich wollte mit dem Attiny10 eine Frequenzmessung durchführen.
Leider gibt es da beim Compilieren Probleme.

Um meinen Code weitesgehend auszuschließen habe ich hier einen fertigen 
Code aus dem Forum mal getestet.

Leider kommt es hier ebenfalls zu einem Problem.

Ich möchte mit der If Abfrage ganz unten den Pin PB0 auf High setzen
sobald die Frequenz größer als 50 Hz ist.
1
   
2
Erg = F_CPU / Erg;       // f = 1 / t
3
4
Freq = Erg;
5
      
6
      
7
if (Freq>50)
8
{
9
PORTB |= (1<<PORTB0);
10
}

Beim Compilieren mit dem aktuellen AVR Studio 6.1 erhalte ich allerdings
folgende Fehlermeldung.

ld returned 1 exit status  collect2.exe

Das setzen des Portpins scheint dieses Problem zu verursachen.
Ein setzen des Portpins außerhalb der If Abfrage mit der selben 
Anweisung funktioniert ohne Probleme, aber nicht innerhalb der 
verschachtelten If Abfrage.

Schreibe ich aber z.B.
1
Freq = 45;
2
      
3
      
4
if (Freq>50)    
5
{
6
PORTB |= (1<<PORTB);
7
}

geht es auch ohne Probleme.

An was könnte dies liegen? Irgendwo ist doch der Wurm drin?
1
/*
2
3
/////////////////////////////////////////////////////////////////////
4
// Frequenzmesser
5
//
6
// Holger Brenner
7
//
8
// Das zu messende Signal wird an den Input Capture Pin des Prozessors
9
// angelegt. Zur Freqenzbestimmung wird mittels Timer1 die Perioden-
10
// dauer des Signals von einer steigenden Flanke bis zur naechsten
11
// steigenden Flanke ermittelt. Daraus laesst sich dann die Frequenz
12
// errechnen.
13
//
14
// Das Beispiel benutzt die LCD Funktionen von ....
15
// Für andere Ausgabemedien muss das entsprechend angepasst werden
16
//
17
// 8. Feb. 2007
18
/////////////////////////////////////////////////////////////////////
19
20
//
21
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
22
// beim Aufruf des C Compilers gab.
23
//
24
#ifndef F_CPU
25
#define F_CPU 4000000
26
#endif
27
28
29
#include <avr/io.h>
30
#include <avr/interrupt.h>
31
#include <util/delay.h>
32
33
#include <stdlib.h>
34
35
36
#ifndef TRUE
37
#define TRUE 1
38
#define FALSE 0
39
#endif
40
41
42
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die während der Messung passiert sind
43
volatile unsigned int  StartTime = 0;   // ICR-Wert bei 1.High-Flanke speichern
44
volatile unsigned int  EndTime = 0;     // ICR-Wert bei 2.High-Flanke speichern
45
volatile unsigned char JobFlag;   // Job Flag
46
47
48
49
ISR( TIM0_CAPT_vect )
50
{
51
  static unsigned char ErsteFlanke = TRUE;
52
53
  if( JobFlag )          // Das Display wurde mit den Ergebnissen der vorhergehenden
54
  return;                    // Messung noch nicht upgedated. Die naechste Messung
55
  // verzögern, bis die Start und EndTime Variablen wieder
56
  // gefahrlos beschrieben werden koennen
57
58
  //
59
  // Bei der ersten Flanke beginnt die Messung, es wird der momentane
60
  // Timer beim Input Capture als Startwert gesichert
61
  //
62
  if( ErsteFlanke )
63
  {
64
    StartTime = ICR0;
65
    NrOverflows = 0;
66
    ErsteFlanke = FALSE;       // Die naechste Flanke ist das Ende der Messung
67
  }
68
69
  //
70
  // das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
71
  //
72
  else
73
  {
74
    EndTime = ICR0;
75
    JobFlag = TRUE;      // Eine vollständige Messung. Sie kann ausgewertet werden
76
    ErsteFlanke = TRUE;        // Bei der naechsten Flanke beginnt der naechste Messzyklus
77
  }
78
}
79
80
81
ISR( TIM0_OVF_vect )
82
{
83
  NrOverflows++;
84
}
85
86
int main()
87
{
88
  
89
  double Erg = 0.0;
90
  uint8_t Freq;
91
92
  
93
  TCCR0A = (1<<ICES0)  | (1<<CS00); // Input Capture Edge, kein PreScale
94
  TIMSK0 = (1<<ICIE0) | (1<<TOIE0); // Interrupts akivieren, Capture + Overflow
95
  
96
    DDRB |=(1<<DDB0);
97
  
98
  
99
  sei();
100
  
101
  while(1)
102
  {
103
    //
104
    // liegt eine vollständige Messung vor?
105
    //
106
    if( JobFlag )
107
    {
108
109
      //
110
      // Die Zeitdauer zwischen den Flanken bestimmen
111
      // Da EndTime und StartTime unsigned sind, braucht nicht
112
      // darauf Ruecksicht genommen werden, dass EndTime auch
113
      // kleiner als StartTime sein kann. Es kommt trotzdem
114
      // das richtige Ergebnis raus.
115
      // Allerdings muss die Anzahl der Overflows in der Messperiode
116
      // beruecksichtigt werden
117
      //
118
      // Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
119
      // beiden gemessenen Flanken berechnet ...
120
      Erg = (NrOverflows * 65536) + EndTime - StartTime;
121
122
      // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
123
      Erg = F_CPU / Erg;       // f = 1 / t
124
125
      Freq = Erg;
126
      
127
      
128
    if (Freq>50)
129
    {
130
      PORTB |= (1<<PORTB0);
131
    }
132
  
133
    
134
135
      // die naechste Messung kann starten
136
      //
137
      JobFlag = FALSE;
138
    }
139
  }
140
}

: Bearbeitet durch User
von Jürgen F. (snipor)


Lesenswert?

Ausgabe aus dem AVR Studio:

1
------ Neues Erstellen gestartet: Projekt: Fan, Konfiguration: Debug AVR ------
2
Der Buildvorgang wurde gestartet.
3
Projekt "Fan.cproj", ReBuild Ziel(e):
4
Erstellung mit der Toolsversion 2.0.
5
Das Ziel "PreBuildEvent" wurde übersprungen, da die Bedingung "false" war . ('$(PreBuildEvent)'!='') wurde als (''!='') ausgewertet.
6
Ziel "CoreRebuild" in Datei "C:\Program Files (x86)\Atmel\Atmel Studio 6.1\Vs\Compiler.targets" aus Projekt "C:\Users\Admin\Desktop\Projekt\1\Fan\Fan.cproj" (Ziel "ReBuild" ist davon abhängig):
7
  RunCompilerTask-Aufgabe
8
    C:\Program Files (x86)\Atmel\Atmel Studio 6.1\shellUtils\make.exe clean all 
9
    rm -rf  Fan.o   
10
    rm -rf  Fan.d   
11
    rm -rf "Fan.elf" "Fan.a" "Fan.hex" "Fan.lss" "Fan.eep" "Fan.map" "Fan.srec"
12
    Building file: .././Fan.c
13
    Invoking: AVR/GNU C Compiler : 3.4.2
14
    "C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-gcc.exe"  -funsigned-char -funsigned-bitfields -DDEBUG  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=attiny10 -c -std=gnu99 -MD -MP -MF "Fan.d" -MT"Fan.d" -MT"Fan.o"   -o "Fan.o" ".././Fan.c"
15
    Finished building: .././Fan.c
16
    Building target: Fan.elf
17
    Invoking: AVR/GNU Linker : 3.4.2
18
    "C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-gcc.exe" -o Fan.elf  Fan.o   -Wl,-Map="Fan.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=attiny10 
19
    c:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.2.1002/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.7.2/../../../../avr/lib/avrtiny\libm.a(divsf3.o):/data2/home/toolsbuild/jenkins-knuth/workspace/avr8-gnu-toolchain/src/avr-libc/libm/fplib/divsf3.S:40: undefined reference to `__divsf3x'
20
    c:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.2.1002/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.7.2/../../../../avr/lib/avrtiny\libm.a(divsf3.o):/data2/home/toolsbuild/jenkins-knuth/workspace/avr8-gnu-toolchain/src/avr-libc/libm/fplib/divsf3.S:41: undefined reference to `__fp_round'
21
    c:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.2.1002/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.7.2/../../../../avr/lib/avrtiny\libm.a(fixunssfsi.o):/data2/home/toolsbuild/jenkins-knuth/workspace/avr8-gnu-toolchain/src/avr-libc/libm/fplib/fixunssfsi.S:69: undefined reference to `__fp_splitA'
22
collect2.exe(0,0): ld returned 1 exit status
23
    make: *** [Fan.elf] Error 1
24
    Der Befehl wurde mit dem Code 2 beendet.
25
  Die Ausführung der RunCompilerTask-Aufgabe ist abgeschlossen -- FEHLER.
26
Die Erstellung des Ziels "CoreRebuild" im Projekt "Fan.cproj" ist abgeschlossen -- FEHLER.
27
Die Erstellung des Projekts "Fan.cproj" ist abgeschlossen -- FEHLER.
28
29
Fehler beim Erstellen
30
========== Alles neu erstellen: 0 erfolgreich, Fehler bei 1, 0 übersprungen ==========

: Bearbeitet durch User
von Mitleser (Gast)


Lesenswert?


von g457 (Gast)


Lesenswert?

Das..
1
    c:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.2.1002/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.7.2/../../../../avr/lib/avrtiny\libm.a(divsf3.o):/data2/home/toolsbuild/jenkins-knuth/workspace/avr8-gnu-toolchain/src/avr-libc/libm/fplib/divsf3.S:40: undefined reference to `__divsf3x'
2
    c:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.2.1002/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.7.2/../../../../avr/lib/avrtiny\libm.a(divsf3.o):/data2/home/toolsbuild/jenkins-knuth/workspace/avr8-gnu-toolchain/src/avr-libc/libm/fplib/divsf3.S:41: undefined reference to `__fp_round'
3
    c:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.2.1002/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.7.2/../../../../avr/lib/avrtiny\libm.a(fixunssfsi.o):/data2/home/toolsbuild/jenkins-knuth/workspace/avr8-gnu-toolchain/src/avr-libc/libm/fplib/fixunssfsi.S:69: undefined reference to `__fp_splitA'
..sind die Fehler die Du beheben musst.

von Jürgen F. (snipor)


Lesenswert?

Habe schon danach gesucht. Habe leider nichts zur Behebung gefunden.

von Jürgen F. (snipor)


Lesenswert?

Hat jemand eine Idee wie man das beheben könnte, bzw an was es liegt?

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


Lesenswert?

Jürgen F. schrieb:
> Hat jemand eine Idee wie man das beheben könnte, bzw an was es liegt?

Schreib deinen Code in Assembler.

Die ganze C-Implementierung dafür ist völlig halbherzig, teilweise
meiner Erinnerung nach auch buggy, und praktisch die gesamte avr-libc
(außer den Headerfiles) wird vom Bauen ausgeschlossen, wenn das Target
ein "tiny core"-AVR ist, da sich nie einer die Mühe gemacht hat, den
Bibliothekscode auf diesen "halben AVR" anzupassen.

von Tim  . (cpldcpu)


Lesenswert?

Jörg Wunsch schrieb:
> Schreib deinen Code in Assembler.

Das wird es auch nicht einfacher machen, floating-point Operationen auf 
einem ATtiny10 durchzuführen.

Jürgen F. schrieb:
> Ich wollte mit dem Attiny10 eine Frequenzmessung durchführen.
> Leider gibt es da beim Compilieren Probleme.

Das Problem liegt hier:
1
double Erg = 0.0;
2
uint8_t Freq;
3
4
...   
5
Erg = F_CPU / Erg;       // f = 1 / t
6
7
Freq = Erg;

Der Code verlangt hier eine floating-point Division mit anschließendem 
casting nach int. Das Einbinden der entsprechenden Libraries erzeugt die 
Fehlermeldungen. Ich vermute dass es die Library entwedner für den 
Attiny10 nicht gibt, oder sie zu groß für die 1kb Programmspeicher sind.

Du solltest den Code so umschreiben, dass er nur mit integer-Variablen 
arbeitet. Am besten eliminierst Du auch Multiplikationen und Divisionen, 
so weit es geht. Der ATtiny ist für komplexe Arithmetik ungeeignet, da 
er nur 16 Register hat.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tim    schrieb:
> Das wird es auch nicht einfacher machen, floating-point Operationen auf
> einem ATtiny10 durchzuführen.

Für einen ATtiny40 würde ich das ja zur Not noch gelten lassen, aber
auf einem 10er ist das aussichtslos.  Wer's nicht glaubt, kann das
Projekt ja für den Anfang versuchen, für einen ATtiny13 zu compilieren:
gleiche Menge Flash, aber einen Core, der zumindest von den Libs
unterstützt wird.  Selbst, wenn es diese Libs für den 10er gäbe (bzw.
man einen anderen Compiler nimmt, der sowas hat): der Code kann mit
dem "halben Core" nur größer werden.

von Tim  . (cpldcpu)


Lesenswert?

Jörg Wunsch schrieb:
> Tim    schrieb:
>> Das wird es auch nicht einfacher machen, floating-point Operationen auf
>> einem ATtiny10 durchzuführen.
>
> Für einen ATtiny40 würde ich das ja zur Not noch gelten lassen, aber
> auf einem 10er ist das aussichtslos.  Wer's nicht glaubt, kann das
> Projekt ja für den Anfang versuchen, für einen ATtiny13 zu compilieren:
> gleiche Menge Flash, aber einen Core, der zumindest von den Libs
> unterstützt wird.  Selbst, wenn es diese Libs für den 10er gäbe (bzw.
> man einen anderen Compiler nimmt, der sowas hat): der Code kann mit
> dem "halben Core" nur größer werden.

Ja, nur das Problem ist doch nicht die Programmiersprache, sondern die 
Tatsache dass der ATtiny10 nur die halbe Anzahl an Registern und kaum 
Speicher hat :)

von Jürgen F. (snipor)


Lesenswert?

Ich habe die float Variable durch eine Integer ersetzt, so lässt sich 
der Code zwar Compilieren allerdings funktioniert das ganze trotzdem 
noch nicht so wirklich.

Ich möchte in Abhängigkeit der gemessenen Frequenz (Rechteck 50-150Hz) 
ein neues um 20Hz erhöhtes Signal erzeugen.

Leider funktioniert das so wie ich es gemacht habe nicht.
1. Die ausgegebene Frequenz schwankt dauernd sehr stark.
2. Die zusätzlichen 20 Hz sind gar nicht bemerkbar.


Hat jemand eine Idee wie ich das stabil hinbekommen kann?
1
/////////////////////////////////////////////////////////////////////
2
// Frequenzmesser
3
//
4
// Holger Brenner
5
//
6
// Das zu messende Signal wird an den Input Capture Pin des Prozessors
7
// angelegt. Zur Freqenzbestimmung wird mittels Timer1 die Perioden-
8
// dauer des Signals von einer steigenden Flanke bis zur naechsten
9
// steigenden Flanke ermittelt. Daraus laesst sich dann die Frequenz
10
// errechnen.
11
//
12
// Das Beispiel benutzt die LCD Funktionen von ....
13
// Für andere Ausgabemedien muss das entsprechend angepasst werden
14
//
15
// 8. Feb. 2007
16
/////////////////////////////////////////////////////////////////////
17
18
//
19
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
20
// beim Aufruf des C Compilers gab.
21
//
22
//#ifndef F_CPU
23
#define F_CPU 1000000
24
//#endif
25
26
27
#include <avr/io.h>
28
#include <avr/interrupt.h>
29
#include <util/delay.h>
30
31
#include <stdlib.h>
32
33
34
#ifndef TRUE
35
#define TRUE 1
36
#define FALSE 0
37
#endif
38
39
40
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die während der Messung passiert sind
41
volatile unsigned int  StartTime = 0;   // ICR-Wert bei 1.High-Flanke speichern
42
volatile unsigned int  EndTime = 0;     // ICR-Wert bei 2.High-Flanke speichern
43
volatile unsigned char JobFlag = FALSE;   // Job Flag
44
volatile signed long int Erg = 0;
45
volatile signed long int Mittelwert = 0;
46
47
48
ISR( TIM0_CAPT_vect )
49
{
50
  static unsigned char ErsteFlanke = TRUE;
51
52
  if( JobFlag )          // Das Display wurde mit den Ergebnissen der vorhergehenden
53
  return;                    // Messung noch nicht upgedated. Die naechste Messung
54
  // verzögern, bis die Start und EndTime Variablen wieder
55
  // gefahrlos beschrieben werden koennen
56
57
  //
58
  // Bei der ersten Flanke beginnt die Messung, es wird der momentane
59
  // Timer beim Input Capture als Startwert gesichert
60
  //
61
  if( ErsteFlanke )
62
  {
63
    StartTime = ICR0;
64
    NrOverflows = 0;
65
    ErsteFlanke = FALSE;       // Die naechste Flanke ist das Ende der Messung
66
  }
67
68
  //
69
  // das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
70
  //
71
  else
72
  {
73
    EndTime = ICR0;
74
    JobFlag = TRUE;      // Eine vollständige Messung. Sie kann ausgewertet werden
75
    ErsteFlanke = TRUE;        // Bei der naechsten Flanke beginnt der naechste Messzyklus
76
    
77
        //
78
        // liegt eine vollständige Messung vor?
79
        //
80
        if( JobFlag )
81
        {
82
83
84
          //
85
          // Die Zeitdauer zwischen den Flanken bestimmen
86
          // Da EndTime und StartTime unsigned sind, braucht nicht
87
          // darauf Ruecksicht genommen werden, dass EndTime auch
88
          // kleiner als StartTime sein kann. Es kommt trotzdem
89
          // das richtige Ergebnis raus.
90
          // Allerdings muss die Anzahl der Overflows in der Messperiode
91
          // beruecksichtigt werden
92
          //
93
          // Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
94
          // beiden gemessenen Flanken berechnet ...
95
          Erg = (NrOverflows * 65536) + EndTime - StartTime;
96
97
          // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
98
          Erg = ((F_CPU/8) / Erg);       // f = 1 / t
99
                }
100
      }
101
102
}
103
104
ISR( TIM0_OVF_vect )
105
{
106
  NrOverflows++;
107
108
}
109
110
int main()
111
{
112
  int i=0;
113
  int j=10;
114
   
115
  CCP=0xD8;
116
    CLKMSR=0x00;
117
  CCP=0xD8;
118
  CLKPSR=0x03;
119
  
120
  TCCR0B |= ((1<<ICES0) | (1<<CS00)); // Input Capture Edge, kein PreScale
121
  TIMSK0 |= ((1<<ICIE0) | (1<<TOIE0)); // Interrupts akivieren, Capture + Overflow
122
    TCCR0A |= ((1<<WGM01) | (1<<WGM00) | (1<<COM0A0) | (0<<COM0A1));
123
    TCCR0B |= ((1<<WGM03) | (1<<WGM02)| (1<<ICNC0) | (1<<CS01));
124
                                                                          //Fast PWM Mode 15 auf Pin OC0A, Taktteiler 8,  Noise Canceler 
125
    DDRB=0x00;  
126
    DDRB |=(1<<DDB0);
127
    
128
  
129
  
130
  
131
  sei();
132
  
133
134
  
135
  while(1)
136
  {
137
     for( i=0; i<j; i++)  
138
            {
139
      Mittelwert = Mittelwert+Erg;
140
      }
141
        
142
      Mittelwert = Mittelwert/j;
143
      
144
      OCR0A =(F_CPU/8)/(2*(Mittelwert+20));
145
      
146
      
147
      Mittelwert=0;
148
      
149
        JobFlag=FALSE;
150
      //
151
      // Das wars: Display ist wieder up to date
152
      // die naechste Messung kann starten
153
      //
154
      
155
    }
156
157
}

: Bearbeitet durch User
von Tim  . (cpldcpu)


Lesenswert?

Jürgen F. schrieb:
> Ich habe die float Variable durch eine Integer ersetzt, so lässt sich
> der Code zwar Compilieren allerdings funktioniert das ganze trotzdem
> noch nicht so wirklich.

Und bist Du Dir sicher, dass die gleichen Berechnungen ohne Änderung 
auch in Integer-Arithmetik durchgeführt werden? Vermutlich musst Du noch 
mehr anpassen.
1
    for( i=0; i<j; i++)  
2
            {
3
      Mittelwert = Mittelwert+Erg;
4
      }
5
        
6
      Mittelwert = Mittelwert/j;

Diese Schleife wird wesentlich häufiger aufgerufen als der Interrupt. 
Daher hat die Mittelwertbildung hier keine Funktion.

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


Lesenswert?

Tim    schrieb:
> Ja, nur das Problem ist doch nicht die Programmiersprache, sondern die
> Tatsache dass der ATtiny10 nur die halbe Anzahl an Registern und kaum
> Speicher hat :)

Das mit dem "kaum Speicher" wäre für den ATtiny13 aber das gleiche.

Jürgen F. schrieb:
> Ich habe die float Variable durch eine Integer ersetzt, so lässt sich
> der Code zwar Compilieren allerdings funktioniert das ganze trotzdem
> noch nicht so wirklich.

Siehe oben: meiner Erinnerung nach ist das, was die Leute bei Atmel da
in den Compiler gehackt haben, um den tiny-Core unterstützt zu bekommen,
alles andere als vertrauenswürdig.  Daher mein Rat, das alles komplett
in Assembler zu schreiben.  Für die 512 Befehlsworte, die du maximal
hast, sollte das überschaubar bleiben.  (Versteh' mich recht: du wirst
diesen Ratschlag von mir sonst eher nicht hören.)

von Tim  . (cpldcpu)


Lesenswert?

Jörg Wunsch schrieb:
> Tim    schrieb:
>> Ja, nur das Problem ist doch nicht die Programmiersprache, sondern die
>> Tatsache dass der ATtiny10 nur die halbe Anzahl an Registern und kaum
>> Speicher hat :)
>
> Das mit dem "kaum Speicher" wäre für den ATtiny13 aber das gleiche.

Naja, das sind jetzt nur noch Spitzfindigkeiten: Aber der ATtiny10 hat 
nur halb so viel SRAM wie der ATtiny13 und mit halber Registeranzahl 
steigt die Stacknutzung...

> Jürgen F. schrieb:
>> Ich habe die float Variable durch eine Integer ersetzt, so lässt sich
>> der Code zwar Compilieren allerdings funktioniert das ganze trotzdem
>> noch nicht so wirklich.
>
> Siehe oben: meiner Erinnerung nach ist das, was die Leute bei Atmel da
> in den Compiler gehackt haben, um den tiny-Core unterstützt zu bekommen,
> alles andere als vertrauenswürdig.  Daher mein Rat, das alles komplett
> in Assembler zu schreiben.  Für die 512 Befehlsworte, die du maximal
> hast, sollte das überschaubar bleiben.  (Versteh' mich recht: du wirst
> diesen Ratschlag von mir sonst eher nicht hören.)

Ja, nur das Problem vom Fragesteller hat ziemlich wenig damit zu tun das 
er nicht Assembler benutzt, sondern das er seinen Code nicht versteht. 
Da ist ein Tip wie "Mach alles in Assembler" wenig hilfreich.

Wenn man Assembler kann, kann man übrigens auch immer ins *.lss file 
schauen und überprüfen ob der Compiler alles richtig macht. Das ist 
immer noch wesentlich effizienter als gleich alles in Assembler zu 
programmieren.

Ich habe den ATiny10 bisher ausschließlich in C programmiert und bin 
noch nicht auf Compilerfehler gestossen. Allerdings habe ich auch eine 
ziemlich gute Vorstellung davon, was mit dem Code auf Maschinenebene 
passiert und probiere gar nicht erst so etwas wie float-Divisionen :)

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


Lesenswert?

Tim    schrieb:
> Ich habe den ATiny10 bisher ausschließlich in C programmiert und bin
> noch nicht auf Compilerfehler gestossen.

Dann hast du einfach nur Glück gehabt.

von Jürgen F. (snipor)


Lesenswert?

Jörg Wunsch schrieb:
> Siehe oben: meiner Erinnerung nach ist das, was die Leute bei Atmel da
> in den Compiler gehackt haben, um den tiny-Core unterstützt zu bekommen,
> alles andere als vertrauenswürdig.  Daher mein Rat, das alles komplett
> in Assembler zu schreiben.  Für die 512 Befehlsworte, die du maximal
> hast, sollte das überschaubar bleiben.  (Versteh' mich recht: du wirst
> diesen Ratschlag von mir sonst eher nicht hören.)

Ich fürchte Du hast Recht mit dem Assembler, aber dann werde ich das 
Programm erst in 10 Jahren fertig haben.

Tim    schrieb:
> Und bist Du Dir sicher, dass die gleichen Berechnungen ohne Änderung
> auch in Integer-Arithmetik durchgeführt werden? Vermutlich musst Du noch
> mehr anpassen.

Wie meinst Du das? Denkst Du dass so etwas anderes berechnet wird als 
mit float, abgesehen von den Rundungsfehlern?

Tim    schrieb:
> for( i=0; i<j; i++)
>             {
>       Mittelwert = Mittelwert+Erg;
>       }
>
>       Mittelwert = Mittelwert/j;
>
> Diese Schleife wird wesentlich häufiger aufgerufen als der Interrupt.
> Daher hat die Mittelwertbildung hier keine Funktion.

Ich hatte es vorher ohne Mittelwertbildung, das Ausgangssignal hatte da 
das gleiche Verhalten. Das mit der Mittelwertbildung war nur ein 
Versuch, der Code dazu stammt hier aus dem Forum.

Brauche ich den überhaupt eine Mittelwertbildung? Wenn ich zB. 50Hz 
anlege dann dürfte er doch nicht so große Messfehler bekommen, oder?
Die Ausgangsfrequenz schwankt bei angelegten 50Hz zwischen 20Hz und 
50Hz.

Ich denke mein Ansatz passt nicht so recht. Wie sollte ich da besser 
vorgehen?

Da ich leider weder Display noch Serielle Schnittstelle habe kann ich 
mir auch nicht wirklich ausgeben lassen was er bei der Frequenzmessung 
als Ergebnis bekommt :(

: Bearbeitet durch User
von Tim  . (cpldcpu)


Lesenswert?

Jürgen F. schrieb:

>Wie meinst Du das? Denkst Du das so etwas anderes berechnet wird als mit
float, abgesehen von den Rundungsfehlern?

Es könnte Überläufe geben usw.

> Brauche ich den überhaupt eine Mittelwertbildung? Wenn ich zB. 50Hz
> anlege dann dürfte er doch nicht so große Messfehler bekommen, oder?
> Die Ausgangsfrequenz schwankt bei angelegten 50Hz zwischen 20Hz und
> 50Hz.

Ich denke das hängt von der Stabilität Deines Eingangssignal ab.

>
> Ich denke mein Ansatz passt nicht so recht. Wie sollte ich da besser
> vorgehen?
>
> Da ich leider weder Display noch Serielle Schnittstelle habe kann ich
> mir auch nicht wirklich ausgeben lassen was er bei der Frequenzmessung
> als Ergebnis bekommt :(

Das könnte das Hauptproblem sein. Wahrscheinlich verbergen sich irgendwo 
noch logische Fehler. Kannst Du zum testen nicht erst einmal einen 
größeren Controller mit entsprechenden Debug-Möglichkeiten nutzen?

Ansonsten nutze ich zum Debuggen manchmal einfach einen Soft-UART über 
einen Pin.

von Jürgen F. (snipor)


Lesenswert?

Tim    schrieb:
>>Wie meinst Du das? Denkst Du das so etwas anderes berechnet wird als mit
> float, abgesehen von den Rundungsfehlern?
>
> Es könnte Überläufe geben usw.

Kann das trotz der long int Variablen passieren?

Tim    schrieb:
>> Brauche ich den überhaupt eine Mittelwertbildung? Wenn ich zB. 50Hz
>> anlege dann dürfte er doch nicht so große Messfehler bekommen, oder?
>> Die Ausgangsfrequenz schwankt bei angelegten 50Hz zwischen 20Hz und
>> 50Hz.
>
> Ich denke das hängt von der Stabilität Deines Eingangssignal ab

Das Signal stammt hier für die Versuche aus meinem Funkionsgenerator und 
ist sehr stabil. Daran kann es eigentlich nicht liegen.

Könnte es sein dass er für die Berechnung zu lange braucht?

Kann ich das OCR0A überhaupt direkt so beschreiben?

Das schwanken könnte aber auch doch auf Überläufe zurückzuführen sein?

: Bearbeitet durch User
von Jürgen F. (snipor)


Lesenswert?

Ich habe herausgefunden dass die Frequenzmessung über den Capture Pin 
nicht mehr funktioniert sobald ich Fast PWM Mode 15 aktiviere.
Kann mir jemand sagen weshalb das dann nicht mehr richtig arbeitet?

Geht Fast PWM und Input Capture nicht gleichzeitig?

: Bearbeitet durch User
von Jürgen F. (snipor)


Angehängte Dateien:

Lesenswert?

Ok, also man sollte das Datenblatt doch mal genau lesen :)

Die Zeitmessung ging ja davon aus dass der Zähler erst bei 65536 
überläuft.
Da ich ja aber im Fast PWM Mode 15 mit OCR0A vorgebe bis wie weit er 
zählen soll muss ich natürlich auch für die Zeitmessung mit diesem Wert 
rechnen.

Jetzt habe ich das Problem dass sich das ganze natürlich aufschauckelt, 
und dann bis hoch in den kHz ausgibt.

Wie gehe ich da am besten vor um ein aufschauckeln zu vermeiden?

von Stefan E. (sternst)


Lesenswert?

Jürgen F. schrieb:
> Jetzt habe ich das Problem dass sich das ganze natürlich aufschauckelt,
> und dann bis hoch in den kHz ausgibt.
>
> Wie gehe ich da am besten vor um ein aufschauckeln zu vermeiden?

Da schaukelt sich nichts auf, wenn die Berechnung der Pulslänge stimmen 
würde.

1
Erg = (NrOverflows * OCR0A) + EndTime - StartTime;
Zum einen ist der Multiplikator für die Überläufe nicht OCR0A, sondern 
OCR0A+1, zum anderen funktioniert das "EndTime - StartTime" jetzt nicht 
mehr für EndTime<StartTime.

von Jürgen F. (snipor)


Lesenswert?

Und wie kann ich die Berechnung dann machen?

: Bearbeitet durch User
von Jürgen F. (snipor)


Lesenswert?

Stefan Ernst schrieb:
> zum anderen funktioniert das "EndTime - StartTime" jetzt nicht
> mehr für EndTime<StartTime.

Könnte das jemand erklären? Ich bekomme es nicht hin, egal was ich mache 
es schwingt sich sehr schnell auf.

noch eine Frage zum Verständis:
Wird der Timer beim Wert aus OCR0A auf 0 zurückgesetzt oder nur das 
Overflow Bit gesetzt?

Danke

: Bearbeitet durch User
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.