Eigenbau Mähroboter Begrenzungsschleife

corsagsi16v

New member
Hallo zusammen,

ich bin seid einiger Zeit an meinem Mähroboter Projekt tätig. Anfangs bin ich auch gut voran gekommen. Der Roboter fährt, Bumper funktionieren, Ultraschallsensoren, Regensensoren Spannungssensoren auch.
Nur die Induktionsschleife bekomme ich nicht ans laufen.
Ich habe hier schon einige verschiedene Möglichkeiten ausprobiert.

Erstmal ein paar Angaben zum Projekt:

Mähroboter
- Atmega 16 - 16Mhz
- Soundsensor(wie Ardumower) mit einer Spule an ADC http://wiki.ardumower.de/images/3/3f/Perimeter_v2_receiver_circuit.png

Perimeter_Sender
- Atmega16 1Mhz(intern)
- 2 Ausgänge an Schrittmotor Modul mit L298N https://tronixlabs.com.au/news/tutorial-l298n-dual-motor-controller-module-2a-and-arduino/
- Perimeterschleife direkt an Schrittmotor Modul mit integriertem Widerstand



Laut Oszi kommt das benötigte Signal aus dem Sender heraus. Ich empfange am Analogeingang auch etwas, was ich an einem sich änderndem Messwert ablesen kann wenn die Spule in Betrieb ist.

Der Analog Eingang steht auf einem Messwert von 505 im Ruhezustand (Sender aus).

Wenn ich nun innerhalb oder außerhalb der Spule bin erhalte ich vergleichbare Ergebnisse. Ich dachte wenn ich innerhalb bin komme ich z.B. auf 600 und außerhalb z.B. auf 400, dann könnte ich ganz einfach zwischen innen und außen unterscheiden.
Jedoch ist dem nicht so, der Wert pendelt innen sowie außen eher im höheren Bereich zwischen 500 und 600.

Hier mal die Programmschnipsel des Senders:

Code:
int8_t sign_code[] = {1,1,2,2,1,2,1,2,2,1,2,1,1,2,2,1,2,2,1,2,2,1,1};
int sign_length =  24;
int sign_step = 0;

	


int main(void)
{
Initialize_timer0();
DDRD |= (1<<PD1); // Pin PD1 an Port D als Ausgang
DDRD |= (1<<PD2); // Pin PD2 an Port D als Ausgang
signal = signalstart;
sei();

while (1) 
{

}
}
ISR (TIMER0_COMP_vect)
{
if (caseswitch <= caseswitch_end)
{
	caseswitch++;
}
else
{
	if (sign_step < sign_length)
	{
		signal = sign_code[sign_step];
		sign_step++;
	}
	else
	{
		sign_step = 0;
		signal = sign_code[sign_step];
	}
	caseswitch = 2; // Standard = 0 für zusätzlichen prescaler bzw. impulsbreite
}

switch(signal)
{
	case 0:
	PORTD &= ~(1<<PD1);
	break;
	
	case 1:
	PORTD |= (1<<PD1);
	PORTD |= (1<<PD2);
	break;
	
	case 2:
	PORTD |= (1<<PD1);
	PORTD &= ~(1<<PD2);
	break;
	
	default:
	break;

}
}


Hier noch die Konfiguration des Timers:


Code:
void Initialize_timer0()  
{
OCR0 = 5;// 5ms
TCCR0 |= (1 << CS00)|(1<<CS02); ; //1024 prescaling
TCCR0 |= (1<<WGM01);
TIMSK |= (1 << OCIE0); //Timer overflow interrupt enable
}




Und hier die Auswertung im Mähroboter:

Code:
void Perimeter_Abfrage_compare_inside_outside()
{
if (Perimeter_gestartet<1)
{
	A0 = 505;			//Ausgangswert der Sensor 1 (ohne Impuls)
	Max = 550;		//oberer Grenzwert Sensor1
	Min = 450; //- Grenzwert;		//unterer Grenzwert Sensor1
	Perimeter_gestartet++;
}
			// In Code 112212122121122122122112
			// Ex Code 221121211212211211211221
if (Signal_value<50)
{
	if (Signal_In==1)
	{
		if (S0<Min)
		{
			Signal_Receive[Signal_value] = 2;
			Signal_In = 2;
			Signal_value++;

		}
	}
	else if (Signal_In==2)
	{
		if (S0>Max)
		{
			Signal_Receive[Signal_value] = 1;
			Signal_In = 1;
			Signal_value++;

		}
	}
}

if (Signal_value>=50)
{
	for (j=0;j<16;j++)  // hier ist 16 die Länge empfangenes (50 Zeichen) - erwartetem Signal (24 Zeichen)
	{
		for(i=0;i<24;i++)  // hier ist 24 die Länge des erwarteten Signals
		{
			Signalcorr[j] += Signal_Receive[i+j]*sign_code[i];
		
		}
	}



	// Minium 48
	// Maximum 63

	for(i=0;i<16;i++)  // Länge des Korrelations Arrays (16 Zeichen)
	{
		if (Signalcorr[i]>Signal_Max) Signal_Max = Signalcorr[i];
		if (Signalcorr[i]<Signal_Min) Signal_Min = Signalcorr[i];
		Auswertung = 1;

	}

	if (Signal_Max >= 63) Perimeter=1;
	if (Signal_Min <= 48) Perimeter=0;


	if (Auswertung == 1)
	{
	Signal_value = 0; // Signal auffangen wiederholen.
	Auswertung = 0;

	}
}



Wäre schön wenn mir jemand helfen könnte. Wenn ich Daten bzw. Angaben vergessen habe, gebt mir bitte kurz ne Info.

Vielen Dank vorab!

Gruß
Christian
 
Hallo Christian,

ohne mich jetzt genau mit deinem Code auseinandergesetzt zu haben: wie soll denn dein Sender-Signal aussehen? Du willst vermutl. innen von außen im Empfänger unterscheiden, also ob sich die Polarität geändert hat (Spiegelung um Null-Achse). Und vermutl. willst Du dafür im Empfänger eine Korrelation (Matched Filter) mit dem bekannten Signal durchführen. Ist Dein Sender-Signal so aufgebaut dass es nur als ganzes korreliert, also bei Verschiebung keine hohe Korrelation entsteht? https://www.youtube.com/watch?v=NIer_kITelc
Hier ein Simulator wo Du das Prinzip Korrelation/Matched Filter mit verschiedenen Signalen (auch eigenen) ausprobieren kannst. Die Peaks im "Matched Filter" geben an wo das Signal korreliert. Ziel ist ein Signal zu finden wo die Peaks nur im positiven auftreten. Wenn man nun die Schleife überquert (Button "Invert") wechselt der Peak auf die negative Seite. http://www.grauonline.de/alexwww/ardumower/filter/filter.html
Vielleicht helfen Dir diese Grundlagen zum Verständnis weiter?

Gruss,
Alexander
 
Hallo Alexander,

vielen Dank für deine Antwort.

Das Video ist wirklich sehr schön gemacht, auch vielen Dank für den Code auf der Seite.

Ich werde damit auf jeden Fall weiterarbeiten.


Hier nochmal der Code den der Sender verarbeiten soll:
int8_t sign_code[] = {1,1,2,2,1,2,1,2,2,1,2,1,1,2,2,1,2,2,1,2,2,1,1};

Ich lese das Array aus und entscheide dann ob ich die Richtung des Schrittmotormoduls ändere oder nicht (je nachdem eine 1 oder eine 2 drin steht), so entstehen dann die abwechselnden Peaks.
Alle 5ms wiederhole ich das Ganze in einem Timer Interrupt.

Wie weit bewegt sich der Messwert aus der Erfahrung in die beiden Richtungen?

In der Grundstellung bin ich bei 505.

Gruß
Christian
 
Leider verstehe ich deinen Mähroboter Code nicht bzw. was dieser bezwecken soll.
Am analogen Signal kannst du nicht erkennen, ob du innen oder außen bist.

Grundsätzlich empfängst du das Signal mit mindestens doppelter Länge und speicherst es in ein Array.
Dann ziehst du den Offset ab.
Dann die Kreuzkorrelation berechnen.
Ergebnins auswerten.

Habe hier mal Code für den DUE reingestellt. Vielleicht hilft es ja.
http://www.ardumower.de/index.php/d...-due-zur-auswertung-des-schleifensignals#9379
Ob deine Signale richtig sind, kann ich nicht beurteilen. Da helfen am besten Oszi Bilder vom Sender, vom Empfänger hinter der Spule+Verstärker und die Zahlenreihe des Empfangsarrays. Dann die Zahlenreihe des Empfängerarrays nach Abzug des Offsets.
 
Ich seh beim Empfänger nicht wie das Signal reinkommen soll.

Das Signal liegt auch nicht 5ms lang am Empfänger an, das ist nur ein kurzer Impuls beim Wechsel high/low.

Probiere sowas auch gerade erfolglos in normalem C, leider ohne Oszi und daher ziemlich im Blindflug.
 
Hallo zusammen,

vielen Dank für die Beiträge.

Hier habe ich mal ein paar Bilder vom Oszi gemacht.

Das 1. Bild zeigt ein Bild des Oszi am Ausgang des Senders.
Der gesendete Code lautet: 1,1,2,2,1,2,1,2,2,1,2,1,1,2,2,1,2,2,1,2,2,1,1

Das 2. Bild zeigt den Eingang im Mähroboter nach dem Verstärker.

Das 3. Bild zeigt nochmals das Signal des Senders jedoch vor dem Schrittmotortreiber L298N


So wird übrigens der Sensor im Mähroboter ausgewertet:
adcval_2 = ADC_Read_Avg(1, 1); // Auslesen von analog Wert Perimeter Sensor 1;

/* ADC0 initialisieren */
void ADC_Init(void)
{
// die Versorgungsspannung AVcc als Referenz wählen:
ADMUX = (1
 
Aus meiner Sicht sind deine Flankenabstände zu lang ca. 10ms. Dadurch bekommst du nur Peaks hinter dem Verstärker zu sehen bei gleicher Zeiteinstellung des Oszis. Hier solltest du das Signal aber einigermaßen erkennen können. So wirst du vermutlich nie die Daten richtig Samplen können.

Versuch mal einen Flankenabstand von 104uS hinzubekommen. Dann sendest du mit 9600Baud. Am besten mal gucken wie es der Ardumower Sender macht.
Samplen würde ich dann mit 4-fachem Oversampling also 38400Baud oder mehr wenn es der Prozessor hergibt.

Weiterhin würde ich die Werte erstmal einlesen und erst wenn das ganze Array voll ist, bearbeiten. So kannst du immer sehen, was du eingelesen hast. Aktuell kann ich nicht erkennen, wo du das Array einliest.
 
Habe noch meine ersten Anfängertests in diesem Bereich rausgekramt.

Den Sender verwende ich immer noch. UNO mit Motor Shield. Läuft seit Ende 2015 ohne Probleme.
Empfänger ist auch ein UNO mit LCD Display.
Ich verwende aber einen anderes Perimetersignal als das original Ardumower. Den müsste man nach eigenem Bedarf anpassen.
Viel Erflog beim Umsetzen :)
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/2936/SchleifenSensorUNO.zip/
 
Zuletzt bearbeitet von einem Moderator:
Zuletzt bearbeitet von einem Moderator:
Roland schrieb:
Deine vorherige Post fehlt hier.

Hier ist der Beitrag, er wurde bei der Systemumstellung leider gelöscht.

Christian schrieb:
Hallo zusammen,

Vielen Dank für die Hilfe!

Und, Entschuldigung das ich mich erst jetzt zurück melde.
Ich hatte leider erst heute Zeit etwas zu probieren.

Ich hatte auch nen kleinen Erfolg denke ich

Ich habe das Signal meiner Sendeschleife etwas schneller gemacht.

Habe nun:
- den internen Takt von 1Mhz
- Vorteiler 1
- Overflow OCR nach 104 Takten

Hier das Bild des Oszi´s am Ausgang des Prozessors zum Schrittmotormodul


1-2.jpg



Das Signal das ich nun direkt hinter dem Soundmodul mit dem Oszi messen kann, sieht schon nach einem Signal aus;-)


2-2.jpg



Sieht das bei euch ähnlich aus?


Gruß
Christian
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/191/1-2.jpg/
 
Zuletzt bearbeitet von einem Moderator:
Hallo zusammen,

mein Signal nach dem Verstärker sieht nun so aus:
20170305_195236.jpg


Jetzt arbeite ich gerade an der Signalverarbeitung/Auswertung.
Ich habe derzeit das Problem das mein Atmega16 nicht genügend RAM zur Verfügung hat, bzw. benötige ich derzeit zu viel. Deshalb kann ich nicht 4-fach samplen.
Irgendwie kann ich das Signal noch nicht sicher abfangen, so das es reproduzierbar wäre.

Gruß
Christian
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/3604/20170305_195236.jpg/
 
Zuletzt bearbeitet von einem Moderator:
Du brauchst nur 4x das Sendesignal in einem Array, 22 Werte x 4 x2 Bytes(für 16 Bit zahlen) = 176 Bytes.
Da geht mit dem Atmega16 noch einiges mehr.
 
Oben