Perimeter Startlinienerkennung

Schaltung hat den Föntest gut überstanden. Ich habe das Modul mit Spule für 5 min auf ca. 75°C erwärmt und das Signal ist konstant geblieben. Jedoch habe ich während des Versuchs mein Smartphone in der Spule liegen lassen. Resultat war, dass es 10 min lang keinen Mux mehr gemacht hat ;)

Ich habe den Strom heute mal mit einem 27 Ohm last-Widerstand gemessen. Hierbei habe ich einen Spannungsabfall von 1,6 V Amplitude. Somit ergibt sich gerade mal ein Strom von 0,06 A. Bei einer Spannung von 12 V kommen ich ja dann nur auf eine Leistung von 0,72 W. Daher versteh ich nicht, warum dann der Motortreiber über 12 V nicht mehr funktioniert, da der bis 35 V und 25 W angegeben ist. Die anderen Bauteile, wie die Spule und der Elko interessiert das ja nicht!?!


Des weiteren habe ich mal das Arduino Forum nach Auslesen eines Amplitudensignals an einem Analogpin durchsucht. Jedoch habe ich leider nix gefunden.
Mein Plan: ich würde gerne die Amplitude des Signals auslesen. Wenn Sie über einen gewissen Wert steigt, würde ich gerne abwarten bis die Amplitude wieder abfällt. Somit versuche ich die Mitte der Perimeterschleife zu ermitteln.
Kann mir einer einen Hinweis geben, wie ich die Amplitude über eine Analogsignal bekomme?

Ich würde das Maximum suchen und dann schauen wann das Signal danach wieder ansteigt und dann das Minimum vom Maximum abziehen. Jedoch glaube ich, dass das einfach und vorallem schneller geht. Ich will ja nicht das Signal verpassen, nur weil ich zulange Rechenzeiten habe.

Vielen Dank für eure Hilfe.
 
Ich habe mir heute auch noch das Problem mit der nicht leuchtenden LED am Sender angeschaut. Ich habe mal die Spannung am PIN mit dem Oszi gemessen. Ich habe gerade mal kleine Spannungsspitzchen von unter 0,1 V. Das reicht nicht aus um die LED leuchten zu lassen. Wenn ich den Finger auf die Leiterbahn lege, reicht es aus um die LED leuchten zu lassen.

An was könnte das liegen? Ich versuche mal den Schwellwert runterzusetzen, aber das ist ja eigentlich nicht der richtige Weg.


Nachtrag: Habe jetzt den Schwellwert auf 0,3 gesetzt und mir den aufsummierten Wert im Serialen Monitor angeschaut. der Wert liegt immer so zwischen 0,37 und 0,48. Also habe ich ihm mit 0,5 grad so verfehlt.
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/4008/IMG_20170102_170906.jpg/
 
Zuletzt bearbeitet von einem Moderator:
Hallo Marc,

toll wie Deine Lösung langsam ausreift! Was das ADC-Sampling anbetrifft, schau Dir mal folgendes Beispiel an (ungetestet). Das Programm startet ADC Sampling per Interrupt. Für jeden ADC-Sample-Wert wird das neue Maximum gehalten. Das Programm gibt in der Hauptschleife das Maximum aus. Dort könnte auch durch Setzen von "adcMax" auf Null die Messung z.B. neu gestartet werden.

Gruss,
Alexander


Code:
#define ADCPIN A0
volatile short adc = 0; 
volatile short adcMax = 0; 
volatile unsigned long adcMaxTime = 0;
unsigned long adcMaxPrint = 0;
int channel = ADCPIN-A0;

void setup()
{
  Serial.begin(19200);
  // free running ADC mode, f = ( 16MHz / prescaler ) / 13 cycles per conversion 
  ADMUX = _BV(REFS0) | channel; // | _BV(ADLAR); 
  // ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1); //prescaler 64 : 19231 Hz 
  ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // prescaler 128 : 9615 Hz
}

// ADC Interrupt (wird mit 9615 Hz aufgerufen, Anzahl Befehle gering halten!)
ISR(ADC_vect)
{
  adc = ADC;  
  if (adc > adcMax){
    adcMax = adc; // neues Maximum und Zeit merken
    adcMaxTime = millis();
  }
}

void loop(){
  if (adcMax > adcMaxPrint){
    adcMaxPrint = adcMax;
    // neues Maximum und Zeit ausgeben
    Serial.print("time=");
    Serial.print(adcMaxTime);
    Serial.print("  adcMax=");
    Serial.println(adcMax);
  }
}
 
Mit dem Fön meinte ich eigentlich nur sehr dicht danebenlegen und das Ausgangssignal angucken. Der Fön hat schon einiges an elektromagnetischen Störungen. So könntest du im Vorfeld schon mal sehen, ob deine Schaltung empfindlich ist gegen andere Einflüsse.
Aber nun hast du auch einen Hitze-test gemacht :)

Ich glaube da stimmt was nicht mit deiner Stromessung. Deine Spule hat vielleicht einen Widerstand von 4 Ohm und wenn du einen Widerstand von 27 Ohm davorschaltest, muss hier wesentlich mehr Spannung bei 12 V abfallen - wenn ich richtig liege. Falls du mit dem Oszi gemessen hast, kann es sein, dass dieses Masse über die Erdung des Stromkabel zieht und somit falsch Werte angezeigt werden. Ich habe für diese Messung die Erdungssanschlüsse des Oszis im Stromstecker mit Isolierband getrennt. Nicht die feine Art und auf eigene Gefahr.
Aus meiner Sicht muss die Schleife einen Widerstand haben von R=U/Imax. Beispiel: 12V werden verwendet. Maximaler Treiberstrom 2A => 12V/2A=6 Ohm. Wenn deine Spule weniger hat, wird der Motortreiber überlastet bzw. du hast schon fast einen Kurzschluss. Ggf. noch eine Reserve einrechnen.

Für die Abtastung muss das Nyquist-Shannon-Theorem eingehalten werden. Das bedeutet du musst mit mindestens 2*fmax abtasten (2*7,8khz). Besser wäre noch 4faches overspampling, sonst wirst du die Maxima wohl nicht richtig erwischen.

Die Idee mit dem Maxima könnt funktionieren. Allerdings darf die Schleife nicht zu breit sein. Sonst wird es in der Mitte weniger als am Rand. Ich frage mich allerdings auch, wieviele Wellen du messen kannst, wenn du die Schleife mit 100km/h überfährst.
Grundsätzlich muss die Auswertung auf 10ms genau sein. Das bedeutet aber nicht, dass du das Ergebnis bereits nach 10ms haben musst. Du könntes die Wert in ein Array bzw. Ringbuffer ablegen und danach erst mit unterschiedlichen Mitteln untersuchen.
Eine Möglichkeit wäre, die negative Halbwelle rechnerisch hochzuklappen und dann das Intergral über ein Intervall zu berechnen. Somit bist du etwas resistener gegen fluktuationen im Signal.
Weiterhin findet eine Phasenverschiebung des Signals von 180 Grad von außen nach innen statt. Das wäre auch eine Möglichkeit den Startpunkt zu erkenne.
 
Den Code werde ich nachher sofort mal analysieren und schauen ob ich ihn verstehe. Danke!!!

@Roland: Haha, ich dachte bei Fön erstmal an Hitze ;) das mit der Störung werde ich morgen gleich testen!

Bei der Stromberechnung war ich mir auch sehr sicher, dass das nicht sein kann. Die Schleife weißt einen Widerstand von 2,5 Ohm auf. Wenn da dann die gesamte Spannun abfällt, erhalte ich einen Strom von 4,8 Amper, was der Motortreiber eigentlich garnicht schaffen sollte. Und warm wurde er aber auch nicht.

Das mit dem Nyquist-Theorom habe ich auch schon gelesen. dann muss ich mal schauen ob ich das mit den 16 MHz hinbekomme. Aber jetzt muss ich erstmal den Code verstehen.

Ich habe jetzt einen Abstand der Schleife von 50 cm. Dabei ist kein Abfall der Amplitude zu erkennen, daher sollte das passen.
 
So, habe den Code mal ve´rsucht zu analysieren. Und natürlich kommen da Fragen auf.

Zum einen weiß ich nicht, was dies Zeile macht:

ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // prescaler 128 : 9615 Hz

Mir reicht ein Name, nach was ich google muss ;)


Zum Anderen stellt sich mir die Frage, warum ich die Abfrage des Wertes am Pin A0 über einen Interrupt mache, der nur 9615 Hz kann. Kann ich die Abfrage nicht einfach in der Loop Funktion machen? Wäre das dann nicht ein bisschen schneller, wenn ich in der Loop den Pin A0 auslese und dann vergleiche ob der Wert größer ist?
Oder geht der Interrupt auf die Maximas? Denn dann würde ja die Abtastrate reichen.
 
Genutzt wird die "Free Running Samping" Funktion des ADC:
http://meettechniek.info/embedded/arduino-analog.html http://yaab-arduino.blogspot.de/2015/02/fast-sampling-from-analog-input.html http://www.glennsweeney.com/tutorials/interrupt-driven-analog-conversion-with-an-atmega328p
Du könntest natürlich die ADC-Werte auch in einer Schleife einlesen(probier's aus), allerdings kannst Du dann nicht sampeln während Du andere Befehle ausführst. Per Interrupt läuft das Sampling quasi "im Hintergrund", d.h. das laufende Programm wird unterbrochen und springt in die Interrupt-Funktion, führt diese aus und springt wieder an die laufende Programmstelle zurück.

Die Sampling-Frequenz kannst Du auch erhöhen (durch Wahl eines anderen Prescalers - einen Prescaler für 19 Khz habe ich oben im Code aktualisiert, mit noch niedrigeren Prescalern kann man mit noch höherer Frequenz sampeln).
Beim Interrupt-Code musst Du nur aufpassen dass die Befehle im Interrupt nicht mehr Zeit brauchen als bis zum nächsten Interrupt. Andernfalls würde der nächste Interrupt nicht stattfinden (solange die CPU noch im Interrupt ist).
 
Oh, dass muss ich erstmal analysieren. Muss ich morgen machen, das geht heute nicht mehr rein.

Habe in der Zwischenzeit mal einen "Anfänger"-Code geschrieben.

Ich schau mir an wie lange ein Wert steigt. Wenn er nicht mehr steigt, setze ich diesen Wert als Maximum und suche nach dem Minimum. Wenn ich das Minimum gefunden habe, bilde ich die Amplitude. Dann schaue ich ob die Amplitude größer ist als die Vorherige. Ist das nicht der Fall springe ich in die Funktion senden. Danach alles auf Null.

Jetzt muss ich nur noch recherchieren, wie lange die einzelnen Arduino Code Segmente benötigen.



Code:
#define ADCPIN A0
volatile short adc = 0;
volatile short adcMin = 0; 
volatile short adcMax = 0; 
volatile short amplitude = 0; 
volatile short amplitude_old = 0;
char i = 0;
char rise = 1;

void setup()
{
  Serial.begin(19200);
}


void sendID(){

    // neues Maximum und Zeit ausgeben
    Serial.print("IDxxx");
    adc = 0;
    adcMin = 0; 
    adcMax = 0; 
    amplitude = 0; 
    amplitude_old = 0;
    rise = 1;
    i = 0;
    
}

void loop(){
  
  adc = analogRead(ADCPIN); 

if(adc < 600){
  i = 1;
}

while(i){
if(rise == 1){
  if (adc > adcMax){
    adcMax = adc;
  }
  else{
    rise = 0;
    amplitude = adcMax - adcMin;
    if (amplitude < amplitude_old)
    {
      sendID();
    }
    else{
      amplitude = amplitude_old;
    }
  }
}
else{
  if (adc < adcMin){
    adcMin = adc;
    }
  else{
    rise = 1;
    amplitude = adcMax - adcMin;
    if (amplitude < amplitude_old)
    {
      sendID();
    }
    else{
      amplitude = amplitude_old;
    }
  }
}
}
  
}
 
Beim schreiben hast du oben Icons. Da ist auch eines für Code.

Ich glaube du meinst: amplitude_old = amplitude; Bzw. diese Zeile vermisse ich.

Da die Amplitude immer mit: Amplitude = adcMax - adcMin; berechnet wird,
kann: if (amplitude < amplitude_old) eigentlich gar nicht zutreffen.
Vielleicht verstehe ich hier auch was falsch, aber amplitude_old wird nie gesetzt und ist immer 0. Genauso wird adcMax und adcMin immer nur gesetzt wenn das Max/Minimum vorhanden ist. Wie soll da die Amplitude jemals geringer werden? Weiterhin bleibt bei rise == 1 adcMin immer 0. Und wenn i=1 ist, wird adc niemals aktualisiert. Aus meiner Sicht kann der Code nicht funktionieren.

Zu Steigerung der Geschwindigkeit würde ich auf jeden Fall den Analogen Wert direkt aus dem Register lesen und auf die Arduinofunktion verzichten, da diese sehr langsam ist. Oder die fastRead funktion verwenden. Einfach mal googlen.
 
Da fällt mir gerade noch ein, du kannst einen Pin togglen und als zweites Signal zum Sinus auf dem Oszi anzeigen. Dann siehst du wie häufig abgetastet wird.
 
Zunächst einmal vielen Dank für den Code und die Links. Die waren echt super! So hab ich das sogar verstanden!

In deinem Code triggerst du ja auf einen festen Schwellwert acdMaxPrint. Jetzt habe ich jedoch das Problem, dass wenn ich auf einen festen Wert triggere, dass die Start-Ziellinie sich verschieben kann. Wenn zum Beispiel das Fahrzeug in der ersten Runde eingefedert ist, ist es "näher" an der Schleife und wird früher ein stärkeres Siganl bekommen. Wenn es nun in der nächsten Runde im Extremfall ausgefedert ist, wird der Schwellwert erst an einer späteren Stelle erreicht. Somit ist die Runde um ein paar Zentimeter kürzer. Genau das gleich "Problem" hat man mit verschiedene Fahrzeugen. Bei manachen muss vielleicht der Transponder etwas höher montiert werden als bei anderen. Das würde bedeuten, dass wenn beide Fahrzeuge gleichzeitig über die Linie fahren würden, das Fahrzeug mit dem tiefer montierten Transponder früher die Start-Ziellinie überqueren würde, was ja nicht stimmt.
Natürlich muss man auch sehen, dass es sich bei ca. 60 km/h und einer angenommenden zu frühen Erkennung des Signals von 5 cm um einen Fehler von nur 3 ms handelt.
Perfekterweise würde man ja schauen wann die Amplitude nicht mehr ansteigend ist.

Danke, Roland für den Hinweis mit dem Toggeln. Funktioniert echt gut. Jetzt kann ich wenigsten mal testen wie lang welche Sequenz dauert.

Ich hätte noch eine Frage Abtastung und dem Nyquist-Theorem. Wenn ich mir einer Abtastrate > 2 der Frequenz abtaste, kann ich die abgetastete Frequenz erkennen. Jedoch ist mir in meinem Fall ja nicht die Frequenz wichtig sondern die Maxima und die Minima. Im blödesten Fall taste ich das Signal so ab, wie in dem letzten Graphen dargestellt ab und sehen niemals ein Maxima. Noch blöder wäre es wenn ich bei einer höheren Amplitude zu früh abtaste und dann denke, dass das diese Amplitude niedriger ist als die vorherige.
Dies ist nur mal eine generelle Frage, wie ich mit sowas umgehe.


alias_ex2.gif

Attachment: https://forum.ardumower.de/data/media/kunena/attachments/4008/alias_ex2.gif/
 
Zuletzt bearbeitet von einem Moderator:
Hallo Marc,

"adcMaxPrint" war nur gedacht als "zuletzt ausgegebener Maximal-Wert", damit das Programm nicht ständig Werte anzeigen muss sondern nur neu gefundene Maxima.

Das Problem mit der Ungenauigkeit wird man wohl nur mit einer höheren Abtastfrequenz lösen können (Prescaler heruntersetzen).

Aber was ganz anderes: könntest Du das Stattfinden der Phasenverschiebung nicht ausnutzen indem man z.B. 2 Spulen im geringfügigem Abstand vergleicht. Sobald sie phasenverschoben zueinander sind wurde die Schleife überquert...
 
Wenn die Amplitude steigt, wird der Abstand der Punkte größer. Vermutlich wirst du nie das Maxima richtig treffen. Die Frequenzen zwischen Sender und Empfänger werden niemals 100%ig gleich sein. Du wirst sehen, dass das Abtastsignal relative zum Sinus wandert. Daher ist eine hohe Abtastrate aus meiner Sicht sinnvoll. Ob es wirklich später funktioniert, wie du es machen möchtest, kann ich nicht sagen.
 
Ich habe mal versucht, den Prescaler auf 16 zu setzen und das sieht von der Codelänge auf dem Oszi ganz gut aus.

Das mit den 2 Spulen könnte funktionieren. Jedoch sind diese beiden Spulen dann nur wenige Millimeter voneinander entfernt. Das bedeutet, dass die Zeit zur Erkennung des Phasenwechseln nur recht kurz ist. Ist es daher möglich den Interrupt an zwei Pins anzuwenden??
Das andere bei dem ich keine Ahnung habe, würden Sie die beiden Schwingkreise vielleicht stören, wenn Sie nur wenige Millimeter auseinander sind?


Des weiteren habe ich heute den Föntest durchgeführt. Bei einem Abstand von 10 cm ist noch nichts am Signal zu erkennen. Wenn ich dann der Spule näher komme wird das Signal stark verrauscht. Die Amplitude ist wie auch bei der Schleife 4 V, was der maximalen Verstärkung des Verstärkers entspricht. Also wenn ich davon ausgehen muss, dass in der unmittelbaren Umgebung des Transponders eine Lichtmaschine sitzt, reicht der Schwingkreis nicht aus, um das Signal zu isolieren. Würde es dann zu dem Schwingkreis noch Sinn machen einen Bandpass zwischen Schwingkreis und Verstärker zu hängen?
 
So, ich habe mich jetzt mal die letzten zwei Tage mit der Filterung des Signals befasst, jedoch keine sinnvolle Lösung gefunden.

Ich habe mir gedacht, dass ich einfach einen Bandpassfilter vor zwischen Arduino und den Verstärker hänge und somit nur das Signal mit meiner Resonanzfrequenz von 7431 Hz durchkommt. Hierzu habe ich einen Bandfilter nach https://upload.wikimedia.org/wikipe...ass_filter.svg/220px-Band_pass_filter.svg.png gebaut. Jedoch konnte ich nach dieser Modifikation am Oszi kein Signal mer feststellen. Ich gehe davon aus, dass dies daran liegt, dass der Schwingkreis auch schon ein Filter ist und die beiden Kreis sich somit stören. Liege ich mit dieser Annahme richtig?

Im Internet konnte ich leider nicht finden wie man einen Schwingkreis nachträglich noch filtern kann. Einer von euch einen Hinweis?

Des Weiteren habe ich heute mal untersucht, wie der Empfänger auf verschiedene Frequenzen reagiert. Siehe Anhnag. Es fällt auf, dass die Amplitute meines Signals bei 2000 Hz sogar höher ist als die eigentliche Zielfrequenz von 7341 Hz. Auch bei 12000 Hz ist die Amplitute noch recht hoch. Bei einer Amplitude von 50 kHz ist das Signal dann kaum zu sehen. Dann habe ich einfach mal ausprobiert, wie sich das System mit einem parallelen Schwingkreis verhält. Leider war das Signal nicht gerade anders.
Laut http://elektroniktutor.de/analogtechnik/rei_swkr.html sollte doch eine starke Dämpfung auftreten?

So wie der Empfänger auf jede Art von Anregung reagiert, kann ich ihn nicht einsetzen. Entweder ich finde noch eine Möglichkeit das Signal über einen Filter zu filtern oder vielleicht mit der Idee von Alexander mit 2 Spulen. Dazu müsste ich aber wissen ob ich auch mehrere PINs mit einem ISR versehen kann und ob ich dann trotzdessen noch eine sehr hohe Abtastfrequenz wählen kann.

Eine weitere Idee, die vielleicht vereinfacht funktionieren könnte:
Wenn ich das ganze System auf eine höhere Frequenz auslege (ca. 35 kHz) und mit einem 16 Prescale abtaste ( 76,8 kHz, was eine Abtastung >2 ergibt) und dann noch eine FFT mit weniger Bins (ca. 76) durchführe (falls das möglich ist), könnte das dann irgendwie funktionieren oder benötigt die FFT Funktion alleine dafür zu lange? Bei 76 Bins würde ich dann also eine Abtastung von 1 ms erreichen. Wenn aber eine ungenauigkeit von 3 ms zugelassen wird könnten sogar 227 Bins durchgeführt werden.
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/4008/Frequenzen_2017-01-05.png/
 
Zuletzt bearbeitet von einem Moderator:
Ich habe aus meinem Archive noch ein Schaltplan gefunden, wie der Robomow dieses haben soll. Ob es stimmt, weiß ich nicht.
Mit zwei Spulen wirst du die Frequenzverschiebung nach meiner Ansicht nicht messen können, wenn diese so dicht beieinander sitzen.

Bezüglich Filter weiss ich nicht, ob ein Filter erster Ordnung ausreichen würde. Anbei mal ein Link für aktive Filter.
http://www.electronics-tutorials.ws/filter/filter_7.html http://www.electronics-tutorials.ws/category/filter http://www.electronics-tutorials.ws/filter/second-order-filters.html Attachment: https://forum.ardumower.de/data/med...6/ROBOMOWBegrenzungsdrahtsignalaufnehmer.pdf/
 
Zuletzt bearbeitet von einem Moderator:
In aktive Filter habe ich mich auch schon reingelesen, jedoch habe ich nirgens was in Verbindung mit einem Schwingkreis gefunden. Daher war ich mir nicht sicher ob das funktionieren könnte, da es mit einem passiven Bandpass ja leider keinen Erfolg gebracht hat. Wenn es jedoch in anderen Applikationen so angewandt wird, wäre das für mich auf jeden Fall einen Versuch wert!
Ich danke dir vielmals!!
 
Genau das habe ich gemacht. Hab den Filter nach upload.wikimedia.org/wikipedia/commons/t..._pass_filter.svg.png aufgebaut und zwischen den Verstärker und den Arduino, beziehungsweise zwischen das Oszi gehängt. Vin habe ich vom Verstärkerausgang gezogen, Vout ging an das Oszi. Jedoch hatte ich dann kein Signal mehr.

Ich habe mir jetzt mal die Schaltung von Roland angeschaut. Im Grunde habe ich sie glaube ich ganz gut verstanden, jedoch ein paar Fragen zum Verständnis.
Die Schaltung besteht aus zwei Tiefpässen, die hintereinander geschalten sind (siehe Anhang). Beide Tiefpässe sind identisch und haben eine Verstärkung von 2. Wäre es da nicht sinnvoll die Verstärkung höher zu setzen? Oder würde eine hohe Verstärkung die Filterung verschlechtern?
Zudem habe ich Probleme nachzuvollziehen was die Orange markierten Bauteile bewirken und warum die Filter anstatt auf GND auf VCC/2 geschalten wird.

Ich werde mal versuchen, die Schaltung in LT Spice nachzubauen, um sie besser zu verstehen.
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/4008/Schaltung.png/
 
Zuletzt bearbeitet von einem Moderator:
Bin gestern auf die Seite http://everycircuit.com/app gestoßen. Tolle Simulation. Du kannst die Frequenz ändern und und er zeigt dir gleich die Ergebnisse an. Ich habe einen Account angelegt und nach "bandpass filter" gesucht und "Active Bandpass Filter" ausgewählt. Ist zwar nicht die Schaltung, die du vermutlich benötigst, aber für die Simulation echt toll und super einfach zu bedienen.
 
Oben