5Ton auswertung mittels Atmega8

OP #1838104
Lesenswert?

Hallo.
Ich weiß, das Thema gabs schon oft, jedoch komme ich nicht so wirklich 
weiter.

Was ich vorhabe:
Ich möchte mir einen Melder für die Feuerwehr bauen, da ich zurzeit noch 
keinen bekommen kann.

Equipment:
Labornetzteil, Multimeter, STK500, Notebook, Atmega8, 16Mhz Quarz, 5Ton 
Generator

Die 5Tonfolgen werden nach dem ZVEI Standart erstellt.
Kurz Zusammengefasst:
Vorlauf(600ms)|5Töne jeder 70ms lang|Pause(600ms)|5Töne jeder 70ms 
lang|Pause(600ms)

Ton:1|2|3|4|5|6|7|8|9|0|R
Frequenz:1060|1160|1270|1400|1530|1670|1830|2000|2200|2400|2600
Schwingungen in 70ms:74,2|81,2|88,9|98|107,1|116,9|128,1|140|154|168|182

Die Schwingungen pro 70ms habe ich aus der Frequenz berechnet. Sollte 
passen oder?

So stelle ich mir den Code vor.
Die CPU arbeitet mit 16mhz. Ein Timer mit ICP zählt bei Steigender 
Flanke hoch. Aus der Zeit des Timers, wird die Frequenz berrechnet. 
Dieser Frequenz wird ein Ton der 5Ton folge zugeordnet. Entspricht der 
Ton gleich dem letzten, wird zu einer Variable die Zeit eines Tones 
hinzuaddiert. Der 5-Ton 1 dauert z.b. eine Schwingung 0,94ms. Damit der 
TOn 70ms andauert, sollte ich doch ca 74 Schwingungen haben oder? Kommt 
jetzt ein anderer Ton, wird geschaut ob der letzte 70ms lang war. Ist 
dies der Fall gehts weiter, ansonsten wird die Messung abgebrochen.

Ich hoffe es ist euch klar, was ich erreichen will.

Mein versuchsaufbau bis jetzt:
Audioausgang vom Laptop direkt an GND vom STK500 und PB0(ICP) vom 
Atmega8.

Mein Code:
1
#define F_CPU 16000000
2
#include <avr/io.h>
3
#include <stdlib.h>
4
#include <stdint.h>
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7

8
#define BAUD 9600UL
9
#define UBRR_VAL ((F_CPU + BAUD * 8) / (BAUD * 16) - 1)
10
#define BAUD_REAL (F_CPU / (16 * (UBRR_VAL + 1)))
11
#define BAUD_ERROR ((BAUD_REAL * 1000) / BAUD)
12
 
13
#if ((BAUD_ERROR < 990) || (BAUD_ERROR > 1010))
14
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
15
#endif
16

17

18
void uart_init(void)
19
{
20
  UCSRB |= (1<<TXEN) | (1 << RXEN);  // UART TX einschalten
21
  UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
22
 
23
  UBRRH = UBRR_VAL >> 8;
24
  UBRRL = UBRR_VAL & 0xFF;
25
}
26

27
/* ATmega16 */
28
int uart_putc(unsigned char c)
29
{
30
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
31
    {
32
    }                             
33
 
34
    UDR = c;                      /* sende Zeichen */
35
    return 0;
36
}
37
 
38
 
39
/* puts ist unabhaengig vom Controllertyp */
40
void uart_puts (char *s)
41
{
42
    while (*s)
43
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
44
        uart_putc(*s);
45
        s++;
46
    }
47
  //uart_putc('\n');
48
}
49

50
uint8_t uart_getc(void)
51
{
52
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
53
        ;
54
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
55
}
56

57
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die während
58
                                        // der Messung passiert sind
59
volatile unsigned int  StartTime = 0;   // ICR-Wert bei 1.High-Flanke speichern
60
volatile unsigned int  EndTime = 0;     // ICR-Wert bei 2.High-Flanke speichern
61
volatile unsigned int UpdateDisplay = 0;
62

63
ISR( TIMER1_CAPT_vect )
64
{
65
  static unsigned char ErsteFlanke = 1;
66

67
  // Bei der ersten Flanke beginnt die Messung, es wird der momentane
68
  // Timer beim Input Capture als Startwert gesichert
69
  //
70
  if( UpdateDisplay )          // Das Display wurde mit den Ergebnissen der vorhergehenden
71
    return; 
72

73
  if( ErsteFlanke )
74
  {
75
    StartTime = ICR1;
76
    NrOverflows = 0;
77
    ErsteFlanke = 0;       // Die naechste Flanke ist das Ende der Messung
78
  }
79

80
  //
81
  // das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
82
  //
83
  else
84
  {
85
    EndTime = ICR1;
86
    UpdateDisplay = 1;      // Eine vollständige Messung. Sie kann ausgewertet werden
87
    ErsteFlanke = 1;        // Bei der naechsten Flanke beginnt der naechste Messzyklus
88
  }
89
}
90

91

92
ISR( TIMER1_OVF_vect )
93
{
94
  NrOverflows++;
95
}
96

97

98
int check(int ton, int tonlaenge)
99
{
100
  int a = 68;
101
  int b = 72;
102
  if((ton == 1) && (tonlaenge > a && tonlaenge < b)) return 1;
103
  else if((ton == 2) && (tonlaenge > a && tonlaenge < b)) return 1;
104
  else if((ton == 3) && (tonlaenge > a && tonlaenge < b)) return 1;
105
  else if((ton == 4) && (tonlaenge > a && tonlaenge < b)) return 1;
106
  else if((ton == 5) && (tonlaenge > a && tonlaenge < b)) return 1;
107
  else if((ton == 6) && (tonlaenge > a && tonlaenge < b)) return 1;
108
  else if((ton == 7) && (tonlaenge > a && tonlaenge < b)) return 1;
109
  else if((ton == 8) && (tonlaenge > a && tonlaenge < b)) return 1;
110
  else if((ton == 9) && (tonlaenge > a && tonlaenge < b)) return 1;
111
  else if((ton == 10) && (tonlaenge > a && tonlaenge < b)) return 1;
112
  else if((ton == 0) && (tonlaenge > a && tonlaenge < b)) return 1;
113
  else return 0;
114
}
115

116
int main(void)
117
{
118
  char s[32];
119
  double Erg = 0.0;
120
  int numbers[5], i, c, x, ton, lastton = 0, tonlaenge = 0;
121

122
  uart_init();
123

124
  DDRC = 0b00000000;
125

126
  TCCR1B = (1<<ICES1)  | (1<<CS10); // Input Capture Edge, kein PreScale
127
   TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture + Overflow
128

129
    sei();
130
  
131

132
  for(i = 0; i < 5; i++) numbers[i] = 0;
133
  c = 0;
134

135
  while(1)
136
  {
137
    if(UpdateDisplay)
138
    {
139
      Erg = (NrOverflows * 65536) + EndTime - StartTime;
140
          Erg = F_CPU / Erg;       // f = 1 / t
141
      x = Erg;
142
      
143
      if((x > 1000) && (x < 1110)) ton = 1;
144
      else if((x >= 1110) && (x < 1190)) ton = 2;
145
      else if((x >= 1190) && (x < 1335)) ton = 3;
146
      else if((x >= 1335) && (x < 1475)) ton = 4;
147
      else if((x >= 1475) && (x < 1600)) ton = 5;
148
      else if((x >= 1600) && (x < 1750)) ton = 6;
149
      else if((x >= 1750) && (x < 1915)) ton = 7;
150
      else if((x >= 1915) && (x < 2100)) ton = 8;
151
      else if((x >= 2100) && (x < 2300)) ton = 9;
152
      else if((x >= 2300) && (x < 2500)) ton = 0;
153
      else if((x >= 2500) && (x < 2700)) ton = 10;
154
      else ton = 11;
155
      uart_puts(itoa(ton, s, 10));
156
/*
157
      if(ton < 11)
158
      {
159
        uart_puts(itoa(numbers[i], s, 10));
160
        if(ton == lastton)
161
        {
162
          tonlaenge++;
163
        }
164
        else
165
        {
166
          if(check(lastton, tonlaenge))
167
          {
168
            numbers[c++] = lastton;
169
            lastton = ton;
170
            tonlaenge = 0;
171

172
            if(c == 5)
173
            {
174
              uart_puts("ende");
175
            }
176
          }
177
          else
178
          {
179
            for(i = 0; i < 5; i++) numbers[i] = 0;
180
            c = 0;
181
            lastton = 0;
182
            tonlaenge = 0;
183
          }
184
        }
185
        if(c == 0) numbers[c++] = ton;
186
        else if(numbers[c - 1] != ton)
187
        {
188
          //if(ton == 10) ton = numbers[c - 1];
189
          numbers[c++] = ton;
190
          if(c == 5)
191
          {
192
            for(i = 0; i < 5; i++)
193
            {
194
              if(i && (numbers[i] == 10)) numbers[i] = numbers[i - 1];
195
              uart_puts(itoa(numbers[i], s, 10));
196
            }
197
            c = 0;
198
            uart_puts("ende");
199
            long_delay(200);
200
          }
201
        }
202
      }*/
203
    }
204
    UpdateDisplay = 0;
205
  }
206
  return 0;
207
}
Das ausgeklammerte ignorieren wir jetzt erstmal.

Es funktioniert schon ganz gut. Ich kann halt jetzt mit einem ComPort 
Monitor, wie hterm mein Ergebnis anschauen.
Normalerweise müsste er jede Schwingung ausgeben.


Meine Probleme:
Zwischendrin habe ich mal wieder ein Ton, der nicht reinpasst.
Die anzahl der Schwingungen stimmt auch nicht.
Hier mal ein Ergebnis:
222222222226666666666666666660000000000000000000000000055555555555534444 
4444444
Die Generierte folge war 26054
Die 3 nach den 5en passt nicht. Nach meinen berrechnungen müsste ich 
81,2 Schwingungen von der 2 haben. Hier habe ich aber nur 11. Habe ich 
da einen Denkfehler?

Sollte ich das Signal eventuell aufberreiten? Komparator? Wenn ja, 
welchen könnte ich nehmen?
Habe es mit einer Diode versucht in die Signalleitung, dann kam aber 
leider garnichts mehr an. Dafür müsste ich das Signal wohl verstärken.

Bin um alle Anregungen und Tipps dankbar.

MFG Daniel
#1838832
Lesenswert?

Du bekommst doch während eines Tones mehrere "Auslöser", dass die 
Frequenz erkannt wurde. Die beim Wechsel auftretenden Zahlen lassen sich 
so sehr einfach aus dem Weg räumen, indem du deine Zahlenfolge aus dem 
Test pufferst, bis sagen wir mal mal 5-6 mal ein neuer Ton erkannt 
wurde. Dadurch wird zum Einen z.B. die in deinem kurzen Test störende 
"3" wirksam ausgeblendet und zum anderen ein größerer Störabstand 
erreicht.

Frage meinerseits an dich: Gibt es Tonfolgen, die mehrmals denselben Ton 
hintereinander enthalten?
also z.B. (1400Hz)-(1400Hz)-(1400Hz)-(1060Hz)-(1060Hz)-(600ms Pause)?
Oder enthält die von dir zu erkennende Tonsequenz immer nach jedem Ton 
einen Wechsel?

mf
OP #1839280
Lesenswert?

Hallo.
Eure Fragen habt ihr euch ja gegenseitig beantwortet.
Ja das Gerät dient nur zum Empfangen und auswerten
Wenn ein Ton das zweite mal kommen soll, wird anstatt des Tones das R 
gesendet(2600Hz).

http://home.arcor.de/output/elektronik/5ton-AVR.pdf
Die Seite kenne ich schon. Habe nahe an dem Code entwickelt.
Ich werde das mit dem Durchschnitt in meinen Code reinnehmen, wird denke 
ich bessere Ergebnisse liefern.
Jetzt meine Frage:
Welcher Eingang ist besser geeignet?
Der ICP Pin für steigende Flanken oder der AIN Komperator mit dem AIN1 
gegen Masse und Signal auf AIN0?

MFG Daniel
Gast #1840386
Lesenswert?

> Ich möchte mir einen Melder für die Feuerwehr bauen, da ich zurzeit
> noch keinen bekommen kann.

Dein Vorhaben in aller Ehre, abr so wichtig bist Du nun auch wieder 
nicht...

Und wenn die Gemeinde angeblich kein Geld dafür hat, warum hast Du dann 
Freizeit übrig für die Gemeinde?
OP #1840443
Lesenswert?

Ex-FFW-Mitglied schrieb:
>> Ich möchte mir einen Melder für die Feuerwehr bauen, da ich zurzeit
>> noch keinen bekommen kann.
>
> Dein Vorhaben in aller Ehre, abr so wichtig bist Du nun auch wieder
> nicht...
>
> Und wenn die Gemeinde angeblich kein Geld dafür hat, warum hast Du dann
> Freizeit übrig für die Gemeinde?

Das hat mich wichtig garnichts zutun. Jedoch wohne ich genau in einem 
Dreieck von Sireenen verschiedener Wehren. In letzter Zeit kam es 
desöfteren vor, dass ich vor verschlossenem Feuerwehrhaus stand. War 
wieder mal ne Sirene von einer anderen Wehr.

Was soll angeblich heißen? Es ist fakt!!!
Persönliche Seite #1840451
Lesenswert?

Tag,

ich glaub nicht, dass er keinen bekommen kann, weil die Gemeinde kein 
Geld dafür hat. Ich vermute schwer, dass er entweder keine 
Grundausbildung hat, noch nicht Volljährig ist, oder eben beides 
zusammen.

Wenn es so sein sollte: Das mit dem Melder kannst dir sparen, es wird 
dich kein vernünftiger Gruppenführer sofort mitnehmen, höchstens als 
Ersatz oder bei ungefährlichen Dingen.

Nun wieder OnTopic: Den Code vom Martin hab ich in C fast 1:1 
nachprogrammiert. Erste Tests (mit Sound vom Rechner mit Rauschen 
simuliert, etc) waren ziemlich erfolgreich.

Grüße,
Michael
Gast #1840557
Lesenswert?

Michael 93 schrieb:
> Nun wieder OnTopic: Den Code vom Martin hab ich in C fast 1:1
> nachprogrammiert. Erste Tests (mit Sound vom Rechner mit Rauschen
> simuliert, etc) waren ziemlich erfolgreich.

Möchtest du den Code vielleicht publizieren? Kämpfe gerade mit der 
FFT-Routine rum und würde das gerne vergleichen.

vg
#1840566
Lesenswert?

if((x > 1000) && (x < 1110)) ton = 1;
      else if((x >= 1110) && (x < 1190)) ton = 2;
      else if((x >= 1190) && (x < 1335)) ton = 3;
      else if((x >= 1335) && (x < 1475)) ton = 4;
      else if((x >= 1475) && (x < 1600)) ton = 5;
      else if((x >= 1600) && (x < 1750)) ton = 6;
      else if((x >= 1750) && (x < 1915)) ton = 7;
      else if((x >= 1915) && (x < 2100)) ton = 8;
      else if((x >= 2100) && (x < 2300)) ton = 9;
      else if((x >= 2300) && (x < 2500)) ton = 0;
      else if((x >= 2500) && (x < 2700)) ton = 10;


Ich würde die Erkennungsgrenzen kleiner machen, dann sollte es gehen.

+-50 Hz sollten reichen
Gast #1840758
Lesenswert?

Nimm einen Goertzelfilter, dann klappt es auch noch, wenn das Signal 
rauscht.
Der wird zwar häufig für DTFM empfohlen (weil er auch mehrere Töne 
gleichzeitig erkennen kann), funktioniert bei 5Ton aber genau so gut.
OP #1840927
Lesenswert?

Michael 93 schrieb:
> Tag,
>
> ich glaub nicht, dass er keinen bekommen kann, weil die Gemeinde kein
> Geld dafür hat. Ich vermute schwer, dass er entweder keine
> Grundausbildung hat, noch nicht Volljährig ist, oder eben beides
> zusammen.
>
> Wenn es so sein sollte: Das mit dem Melder kannst dir sparen, es wird
> dich kein vernünftiger Gruppenführer sofort mitnehmen, höchstens als
> Ersatz oder bei ungefährlichen Dingen.
>

Das ihr immer so aus der Ferne wisst, was sache ist das verwundert mich.
1. Ich bin seid 4 Jahren der Feuerwehr.
2. Grundausbildung habe ich sehr wohl.
3. Zusätzlich habe ich Funker und AGT.
4. Ich bin bei fast jedem Einsatz auf dem Auto.

Jeder Wehr ist eine Anzahl Melder zugeordnet. Mehr gibt es nicht!
Und was tut das hier überhaupt zur sache? Garnichts!
Gast #1840957
Lesenswert?

Hi,
ist selber kaufen dann nicht einfacher bevor du dir selber was baust? 
Der ist dann auch Tragbar ;-) und die gebrauchten werden dir teilweise 
hinter her geschmissen.
OK reizen würds mich auch mal sowas selber zu bauen. Aber warum tut eure 
Wehr nicht noch n paar FME her. Müssen ja keine neuen sein, tun doch 
auch gebrauchte. Wir sind inzwischen schon dazu übergegangen bewust 
leuten die sich selber schon einen kaufen wollten, dann doch einen zu 
spendieren mit dem Hintergrund -> irgendwann in weiter Ferne die ich mit 
meinen 25J vielleicht gar nimmer erleben werde, wird/soll von analog auf 
digital umgebaut (Bayern). Je mehr Melder die Gemeinde besitzt, um so 
einfacher wird die Ersatzbeschaffung.

Kameradschaftliche Grüße
Stefan
#1841024
Lesenswert?

Select Case Durchschnitt
Case 1050 To 1070 : Ton = "1"
Case 1150 To 1170 : Ton = "2"
Case 1260 To 1280 : Ton = "3"
Case 1390 To 1410 : Ton = "4"
Case 1520 To 1540 : Ton = "5"
Case 1660 To 1680 : Ton = "6"
Case 1820 To 1840 : Ton = "7"
Case 1990 To 2010 : Ton = "8"
Case 2190 To 2210 : Ton = "9"
Case 2390 To 2410 : Ton = "0"
Case 2590 To 2610 : Ton = "w"
Case Else : Goto Main
End Select

Im Bascom Quelltext werden die +-1 % in etwa eingehalten, das könnte 
dein Problem sein.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren