Forum: Mikrocontroller und Digitale Elektronik ersten postiven und negativen Wert des nulldurchgang bestimmen


von Jens G. (Firma: fa. Seuffer) (willi-helmchen)


Lesenswert?

Hallo,
wollte mal fragen ob der eine oder andere einen guten Tip für nen 
Suchalgo hat den ich Programmieren muss.

Ich hab einen Sinus mit <1Khz, davon lese ich mittels ADC ca. eine 
Periode ein, Phasenlage ist dabei nicht bekannt. Diese lege ich mittels 
DMA in 32 Werten im Speicher ab.

Ich muss nun den Nulldurchgang der steigenden Flanke (also von negativ 
nach positiv) bestimmen. Das heist ich muß zwei aufeinanderfolgende 
Werte aus der Tabelle suchen.
Den an Null nähsten negativen Wert und desen folge Wert welcher 
logischerweise positiv sein muss. Somit habe ich die Zwei Werte (den 
negativen und darauf folgende postive) die dem Nullpunkt am nähsten 
sind.
Ich weis jetzt nur nicht wie ich die Suche in C umsetze kann ohne einen 
riesen Code zu bekommen der mir ein haufen der Rechenleistung frisst.

Hat zufällig jemand nen guten Ansatz??

P.S. Hardware Lösungen gehen nicht, da ich den Sinus einlesen muss um 
noch andere Sachen damit anzustellen.
Das ganze soll dann auf einem dsPIC33 bzw PIC24 laufen.

von Stefan K. (_sk_)


Lesenswert?

Suche im Array nach dem ersten negativen Wert.
Ab dem gefundenen Index+1 suche nach dem ersten positiven Wert.

Der erste gefundene positive Wert hat automatisch einen negativen Wert 
als Vorgänger -> Nulldurchgang.

Dabei das Abbruchkriterium Index >= 31 beachten.

Viele Grüße, Stefan

von Jens G. (Firma: fa. Seuffer) (willi-helmchen)


Lesenswert?

Hört sich gut an deine idee, aber ich hab bedenken das der Code probleme 
macht wenn die Abtastung bei negativer halbwelle beginnt.

Aber ich hab mir gestern Abend nochmal ein bisschen das Hirn zermatert 
und da ist folgender pseudo Code rausgekommen.

a=0;
b=1;

while(Startbit = 1)
{
if(a=30 || b=31)
{
Setze Startbit zurück;
}

if(Speicher[a]<0 && Speicher[ b]>0)
{
Schreibe Speicher[a] in Variable; //Negativer Wert
Schreibe Speicher[ b] in Variable; //postiver Wert
}
else
{
a++;
b++;
}
}

Die While Schleife wird bei setzen des Startbit  30 mal durchlaufen und 
dabei immer 2 aufeinander folgende Werte überprüft ob der erste noch 
negativ (<0) und der zweite positiv(>0) ist. Wenn das der Fall ist hab 
ich den Nulldurchgang von neg nach pos. Wenn nicht gehe eine Stelle 
weiter (a++, b++).
jetzt muss ich nur noch ein "Abbruch" Kriterium oder Meldung einabuen 
wenn kein Nulldurchgang detektiert ist.

von Karl H. (kbuchegg)


Lesenswert?

Jens Großmann wrote:
> Hört sich gut an deine idee, aber ich hab bedenken das der Code probleme
> macht wenn die Abtastung bei negativer halbwelle beginnt.

Dann überprüfst du eben den ersten Arrayeintrag ob er nicht schon
negativ ist.

> Aber ich hab mir gestern Abend nochmal ein bisschen das Hirn zermatert
> und da ist folgender pseudo Code rausgekommen.

Mal im Ernst:
Programmieren ist nicht so deins, oder?
Selten ein so kompliziertes Konstrukt for eine simple for-Schleife
gesehen.


> Die While Schleife wird bei setzen des Startbit  30 mal durchlaufen und
> dabei immer 2 aufeinander folgende Werte überprüft ob der erste noch
> negativ (<0) und der zweite positiv(>0) ist.

D.h. du hast insgesamt 5 Vergleiche pro Schleifendurchlauf !

Nicht schlecht im Vergleich zu den 2, die Stefan vorschlägt.
Satte 150% mehr.

von Jens G. (Firma: fa. Seuffer) (willi-helmchen)


Lesenswert?

Hehe gut hast recht.
Ich komm auch eher aus der Hardware Gegend und muß für meine 
Diplomarbeit nun einen Controller programmieren.
Ich hatte zwar mal im zweiten und dritten Semester C-Programmierung aber 
halt nur auf dem PC und nur oberflächlich ohne Vertiefung, meine 
Controller Erfahrungen waren bisher auch nur in Form von Assampler auf 
nem 8051.
Und nun darf ich das bisschen Restwissen von C und Controllern zusammen 
bringen und mein Glück versuchen. Aber es ist ja noch kein Meister vom 
Himmel gefallen :-)

Dann werde ich mir dochnochmal Stefans Konstrukt durch den Kopf gehen 
lassen und mal mein Code mit ner for Schleife testen.

von Karl H. (kbuchegg)


Lesenswert?

Wenn schon in einer Schleife, dann so
1
  for( i = 0; i < 32 - 1; ++i )
2
    if( Speicher[i] < 0 && Speicher[i+1] > 0 )
3
      break;
4
5
  if( i == 32 - 1 )
6
    // kein positiver Nulldurchgang gefunden
7
  else
8
    // Nulldurchgang bei Speicher[i] und Speicher[i+1]

Sind immer noch 3 Vergleiche pro Schleifendurchgang. Weniger
werdens nur mit einer Strategie wie Stefan sie vorschlägt.
Das klassische "space-for-time" Verhalten: Man gewinnt
Laufzeit, indem man in die Codegröße investiert. Ob das
allerdings bei einer Arraygröße von 32 viel ausmacht?

von yalu (Gast)


Lesenswert?

Eine klassische Dreizeilenlösung nach dem Vorschlag von Stefan:
1
#define N 32
2
int speicher[N];
3
4
int get_zero(void) {
5
  int i;
6
7
  for(i=0; i<N && speicher[i]>=0; i++);
8
  for(   ; i<N && speicher[i] <0; i++);
9
  return i<N ? i : 0;
10
}

Der Funktionswert ist der Index des ersten nichtnegativen 
Array-Elements,
dessen Vorgänger negativ ist, oder 0, falls ein solches Element nicht
existiert.

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.