Hi,
das sieht ja gut aus: Hardware fertig ...
Software:
Wird auch klappen. Für den Anfang brauchst du als Basis eine Kombination aus RP6Control_09_Move.c und RP6Control_08_I2CMaster.c.
Damit würde ich erst mal starten ...
Hi,
das sieht ja gut aus: Hardware fertig ...
Software:
Wird auch klappen. Für den Anfang brauchst du als Basis eine Kombination aus RP6Control_09_Move.c und RP6Control_08_I2CMaster.c.
Damit würde ich erst mal starten ...
Gruß
Dirk
Kurze Ergänzung noch zur Hardware:
1. Wer diese induktive Ladung von inka nachbauen will:
Pollin hat in seinem Katalog 1-2014 folgende Teile aufgenommen:
a) Induktions-Lademodul Sender (37-351 339)
b) Induktions-Lademodul Empfänger (37-351 340)
c) Induktions-Lademodul Sender + USB-Ladebuchse (37-351 338 )
Das sind alles "nackte" Platinen + Spulen ohne Gehäuse zum Einbau in eigene Konstruktionen, so wie inka das auf seinen Bildern zeigt. Strom angeblich bis 1A.
2. @inka: Wie wäre es auf der Empfängerseite noch mit einer Spannungsmessung am Ausgang des Empfängers? Damit könnte der RP6 seine Position auf der Senderspule evtl. korrigieren (optimale Ladeposition) bzw. überhaupt prüfen, ob er auf der Ladespule steht.
... nur so 'ne Idee ...
Gruß
Dirk
hi,
das ist toll, dass man die teile nun auch in Deutschland bekommt, die preise sind - verglichen mit den sonstigen preisen bei Conrad oder Pollin - überraschend niedrig...
Ich denke ich kann jetzt dieses kapitel schließen, bin mit dem erreichten durchaus zufrieden, musste nur noch die leitungen zu den empfängerspule von unten (bodenwanne) auf die hauptplatine verlegen und mit steckern versehen um eine evtl. demontage zu erleichtern:
auch habe ich die spule in den vorderen bereich der bodenwanne (in die nähe des linienfolgemoduls) verlegt, damit der RP vor dem auffahren auf die ladestation nicht auch noch gedreht werden muss.
die alte auflage:
auf der der RP6 stehen konnte auch bei tests, bei denen die ketten in bewegung waren habe ich nun durch eine neue ersetzt
in der er auch geladen werden kann. Die positionierung des RP6 zu spule passiert in der breite durch die seitlichen profile und die räder des RP6 (1mm spiel auf jeder seite), in der länge durch das erhöhte "kopfteil".
Die blaue fixierung der spule - da habe ich einen flexiblen lockenwickler in zwei teile zerschnitten - meine frau möge mir verzeihen![]()
gruß inka
@Dirk;
ich wollte eigentlich eine "mechanische" lösung (quasi "nach gehör" fahren), aber die messung wäre sicher eleganter. Wäre die reaktion darauf auch schnell genug möglich? Realisierung mit "LTC2990_measure()", oder hast Du da an was anderes gedacht?
@fabqu,
tja, die sind noch ein bischen teuer...Jetzt nen 3D-Drucker kaufen, und das Ding serienmäßig produzieren...
gruß inka
Hi inka,
ja, ich hatte da an eine Spannungsmessung am Ausgang der Spule bzw. zwischen Spule und Spannungswandler gedacht.
Man könnte einen nicht genutzten ADC-Kanal der M32 (z.B. ADC_2) dafür nehmen. Der Eingang ist auf der MultiIO am J_ADC Jumperblock Pin "2".
Man braucht dann noch einen Spannungsteiler aus 2 Widerständen, weil der ADC ja nur bis 5V messen kann (oder ist die Spannung da nicht höher?).
Gruß
Dirk
Hi Dirk,
der tip war wieder einmal goldwert: es funktioniert, mit diesem
kann ich dann später (von der ladestation ist unter dem RP6 ja nichts zu sehen, er ist aber an) eine LED oder was auch immer als zeichen dafür, dass geladen wirkt blinken lassen...Code:void acculadung(void) { clearLCD(); setCursorPosLCD(0, 0); writeStringLCD(" ADC2: "); uint16_t adc2 = readADC(ADC_2); // Read ADC Channel 2 setCursorPosLCD(0, 9); writeIntegerLCD(adc2, DEC); if (adc2 > 650) { setCursorPosLCD(2, 0); writeStringLCD(" ladespannung ok "); setMultiIOLED1(1); } }
btw. da kommen nur 3.5V an, an der empfängerspule. Eigenttlich sollten es 5V sein, aber durch eine etwas größere entfernung zu der sendespule reduziert sich das. Da gabs auch probleme am anfang mit dem einschwingen des spannungwandlers, inzwischen läuft der problemlos an...
ich habe mich in letzter zeit mit der linienverfolgung beschäftigt und wollte jetzt wieder schauen, wie es mit dem finden der bake zusammenzubringen wäre. Und prompt geht wieder nix.
daß das auffinden der bake schon funktioniert hat, dafür gibts ja beweise bei youtube- immerhin, nur hilft mir das jetzt nicht weiter...
dieser
hat damals funktioniert. Es ist nicht nur dieser code, der nicht geht, ich habe mehrere varianten ausprobiert, das verhalten des RP6 ist gleich:Code:#include "RP6ControlLib.h" #include "RP6I2CmasterTWI.h" #include "RP6Control_MultiIOLib.h" #include "RP6Control_I2CMasterLib.h" #include "RP6Control_LFSBumperLib.h" #include "RP6ControlServoLib.h" #include "standard.h" #define I2C_RP6_BASE_ADR 10 /******************variablen***************************/ //uint8_t transmit_buffer[10]; uint8_t RP6data[32]; uint8_t i, j, t; int16_t x, y, z; uint8_t temp; //uint8_t ir_value[0]; uint8_t temp_IR[0]; //uint8_t feld_IR[200]; /*******************************************************************************/ void readAllRegisters(void) { I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 0); // Start with register 0... I2CTWI_readBytes(I2C_RP6_BASE_ADR,RP6data, 31); // and read all 30 registers up to // register Number 29 ! // Now we output the Data we have just read on the serial interface: writeString_P("\nREADING ALL RP6 REGISTERS:"); uint8_t i = 0; for(i = 0; i < 31; i++) { if(i % 8 == 0) // add some newline chars otherwise everything writeChar('\n'); // is printed on ONE single line... else writeString_P(" | "); writeChar('#'); writeIntegerLength(i,DEC,2); writeChar(':'); writeIntegerLength(RP6data[i],DEC,3); } writeChar('\n'); } /***************************************************************************/ uint8_t read_IR_value(void) { // uint8_t temp = 0; I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 30); // Start with register 30 I2CTWI_readBytes(I2C_RP6_BASE_ADR, temp_IR, 1); return temp; } /******************************************************************/ void I2C_requestedDataReady(uint8_t dataRequestID) { checkRP6Status(dataRequestID); } /********************hauptprogramm*****************************/ int main(void) { initRP6Control(); multiio_init(); initLCD(); //orientation_init(); setLEDs(0b1111); mSleep(500); setLEDs(0b0000); I2CTWI_initMaster(100); I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); I2CTWI_setRequestedDataReadyHandler(I2C_requestedDataReady); showScreenLCD(" RP6Control M32", " bake_suche_1", "", ""); mSleep(1500); clearLCD(); accuspannung(); mSleep(1500); clearLCD(); while(true) { setLEDs(0b0100); readAllRegisters(); startStopwatch3(); t=0; do { if(getStopwatch3() > 50) { temp = read_IR_value(); if (temp !=0) { setMultiIOLED1(1); setMultiIOLED1(0); rotate(80, RIGHT, 5, false); temp = read_IR_value(); if (temp == 0) stop(); //break; if(bumper_left && bumper_right) //stop();//break; { stop(); } } temp = read_IR_value(); if (temp == 0) { x = getStopwatch3(); setMultiIOLED3(1); setMultiIOLED3(0); if (t<10) { t++; if (t == 10) { y = getStopwatch3(); z = y-x; /* writeInteger(x, DEC); writeChar('\n'); writeInteger(y, DEC); writeChar('\n'); writeInteger(z, DEC); writeChar('\n'); */ t=0; setStopwatch3(0); if (z< 600) { move(100, FWD, DIST_MM(100), false); setStopwatch3(0); t=0; mSleep(400); task_checkINT0(); task_I2CTWI(); if(bumper_left && bumper_right) { stop(); } } } } } } task_checkINT0(); task_I2CTWI(); } while(!bumper_left && !bumper_right); stop(); } return 0; }
er ignoriert die abfrage des vorher eingelesenen (nicht vorhandenen) IR signals ( if (temp !=0)) , die rote multiIO LED blinkt, der RP6 dreht sich nicht und sucht, sondern fährt in den 10cm steps vor (die abfrage if (temp == 0 wird als wahr erkannt) , als hätte er IR empfangen. Die bake ist dabei außer betrieb. Die bake selber habe ich überprüft (oszi), sie sendet an der richtigen frequenz, wird auch - sporadisch - empfangen...
woran kann das denn wieder liegen? Ich musste jetzt nachdenken, was ich an hardwareänderungen eingeführt hätte - außer der verbindung von dem pin2 des J_ADC zu der spule des ladegeräts - sonst nix...
gruß inka
Hi inka,
Ich denke nicht an ein Hardware-Problem.woran kann das denn wieder liegen?
Leider habe ich das Problem, dass ich deinen Such-Code nicht ganz verstehe, und so auch nicht "mitdenken" kann.
Ich habe mal die Haupt-Suchschleife auf das hier:
... reduziert.Code:while(true) { startStopwatch3(); t=0; do { if(getStopwatch3() > 50) { temp = read_IR_value(); if (temp !=0) { // Rotiere RECHTS 5° temp = read_IR_value(); if (temp == 0) stop(); //break; if(bumper_left && bumper_right) //stop();//break; { stop(); } } temp = read_IR_value(); if (temp == 0) { x = getStopwatch3(); if (t<10) { t++; if (t == 10) { y = getStopwatch3(); z = y-x; t=0; setStopwatch3(0); if (z< 600) { Fahre VORWÄRTS 10cm setStopwatch3(0); t=0; mSleep(400); task_checkINT0(); task_I2CTWI(); if(bumper_left && bumper_right) { stop(); } } } } } } task_checkINT0(); task_I2CTWI(); } while(!bumper_left && !bumper_right);
Wenn ich das so sehe, stellen sich ein paar Fragen (quasi als Bemühen, das zu verstehen):
1. In der Hauptschleife wird ja alle 50ms (if(getStopwatch3() > 50) ) "etwas" gemacht. Verfolgt man erstmal das, was passiert, wenn die 50ms NICHT um sind:
Dann laufen nur task_checkINT0(); und task_I2CTWI(); durch und die Schleife soll durchlaufen werden, solange KEIN Bumper gedrückt wird.
Das dürfte aber so nicht funktionieren, weil die Variablen bumper_left u. bumper_right sich in der Schleife nicht verändern (es erfolgt ja keine Veränderung dieser Variablen abhängig von den Bumpern!).
2. Wenn man dann in die alle 50ms angesprungene Verzweigung schaut, wird da IR gelesen (temp = read_IR_value ). Abhängig vom Ergebnis (Bake wahrgenommen oder nicht) soll ja eine Reaktion erfolgen. Es soll gedreht werden, wenn die Bake nicht erkannt wurde und geradeaus gefahren werden, wenn die Bake erkannt wird.
Da ich diesen Teil nicht verstehe, lasse ich das mal außen vor. Aber trotzdem stellen sich Fragen:
a) Wenn ich mich richtig an die IR-Empfänger-Abfrage erinnere, dann ist das Ergebnis von read_IR_value() NULL, wenn die Bake empfangen wurde und GRÖSSER NULL, wenn sie aus ist oder nicht in Sicht. Wenn das so ist, verstehe ich deinen Code -wie gesagt- nicht.
b) Im 50ms-Teil wird der IR-Sensor ZWEIMAL abgefragt und nach dem Rechts-Rotieren sogar noch einmal. Was bedeutet das? Eigentlich sollte das IR-Signal nur EINMAL alle 50ms abgefragt werden, weil eine erneute Abfrage direkt nach der ersten durchaus ein anderes Ergebnis bringen kann und dann deine Logik durcheinander bringt. Vorschlag: IR nur EINMAL am Anfang des 50ms-Teils abfragen und in einer Variablen speichern ODER direkt in die beiden Zweige:
... einmünden lassen.Code:if (temp !=0) // Bake AUS { // Drehe rechts-links bis Bake wieder da } else // Bake AN { // Fahre geradeaus }
c) Die 50ms sind vermutlich viel zu kurz. Allein die I2C-Kommunikation dauert (Abfrage IR) fast schon länger,- an die Fahrbefehle gar nicht zu denken.
d) Das nicht blockierende Drehen und Fahren erzeugt kaum einschätzbare Phänomene. Wann ist das Fahren zuende? Meine Einschätzung: Der 50ms-Teil wird mind. schon 50 bis 200x wieder angesprungen, während der letzte Fahrbefehl noch aktiv ist. Folgen: ???
e) Pause 400ms nach dem Vorwärts-Fahrbefehl. Das bedeutet letztlich fast schon ein blockierendes Fahren, weil ja fast 1/2 Sekunde gewartet wird. Das bringt aber die schnelle Hauptschleife durcheinander, so dass die weiteren Abläufe nicht mehr transparent sind.
Vielleicht hilfst du mir beim Verständnis: Dann kann ich wieder mitziehen ...![]()
Gruß
Dirk
Hi Dirk,
danke für detailierte antwort...
nachdem das programm "RP6Control_10_Move2.c" problemlos funktioniert glaube ich das auch nicht, ich gerate bei problemen, die ich eigentlich als gelöst (und wenigstens ein bischen verstanden) abgehakt habe, leicht in panik...
prinzipiell: wenn kein signal empfangen wird, sollte der RP6 ständig im kreis drehen und die bake suchen...
hier meine kommentare zum ablauf in der do-schleife:
Code:do { if(getStopwatch3() > 50) //evtl. zu früh beim ersten durchlauf, beim nächsten - die ganze haupt-if-schleife //wird ja übersprungen - und wieder stopwatch >50 abgefragt, oder? { temp = read_IR_value(); //erstes einlesen des IR-signals if (temp !=0) //wenn kein signal, drehe um 5° { setMultiIOLED1(1); setMultiIOLED1(0); rotate(80, RIGHT, 5, false); temp = read_IR_value(); //lese IR noch einmal nach der drehung ein if (temp == 0) stop(); //break; //wenn signal empfangen, stoppe drehung (stop(), oder break()?) if(bumper_left && bumper_right) //stop();//break; // wenn hindernis, stoppe drehung { stop(); } } temp = read_IR_value(); //lese noch einmal IR signal, ob immer noch IR-signal empfangen wird if (temp == 0) // wenn empfang... // die wände erzeugen reflektionen, um zu verhindern dass diese mit der original IR verwechselt werden, soll überprüft // werden ob das signal 10x hintereinander empfangen wird... { x = getStopwatch3(); //speichere stand der stopuhr des ersten empfangs setMultiIOLED3(1); setMultiIOLED3(0); if (t<10) //10 empfang prüfen { t++; if (t == 10) // wenn 10 x empfangen { y = getStopwatch3(); //speichre stand der stopuhr des 10ten empfangs z = y-x; //berechne dauer zwischen erstem und zehntem empfang t=0; setStopwatch3(0); //stopwatsch auf null if (z< 600) //prüfe ob in einem zeitraum von <0,6sec { move(100, FWD, DIST_MM(100), false); // dann fahre 100mm vorwärts setStopwatch3(0); //setze stopuhr auf null, evtl. zu viel... t=0; mSleep(400); // weiss nicht wozu, ohne ging es vorher nicht... task_checkINT0(); task_I2CTWI(); if(bumper_left && bumper_right) // stoppe beim hindernis beim geradeausfahren { stop(); } } } } } } task_checkINT0(); task_I2CTWI(); } while(!bumper_left && !bumper_right);//führe do-schleife solange bis hindernis(ladestation) stop();
sie kommentar im code...
ja...(im prinzip)...aber halt nicht nach dem (erstbesten) signal...
ja, mit dieser funktion wird das register 30 (Pb2, IR signal) eingelesen:
wenn empfang temp=0, wenn kein empfang temp>0...Code:uint8_t read_IR_value(void) { // uint8_t temp = 0; I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 30); // Start with register 30 I2CTWI_readBytes(I2C_RP6_BASE_ADR, temp_IR, 1); return temp; }
reflektionen, ansonsten siehe kommentare
muss darüber nachdenken, was ist mit den reflektionen?
ich stehe mit den "s.watches" noch auf dem kriegsfus
ich habe es so verstanden, dass es besser ist das nicht blockierende drehen und fahren zu verwenden, da gibt es wohl unterschiedliche auffasungen/anwendungsfälle - die auch mit den stopwatches zusammenhängen?
siehe kommentar im code...
habs versucht ...
gruß inka
hallo Dirk,
ich kann verstehen, dass Du Dich zurückziehst, die diskussion über meine software ist ein geeignetes mittel um leute zu vergraulen, ich werde es lassen...
habe hier aber ein anderes problem:
die verbindung wurde so verlegt, es funktioniert auch, was mir beim ersten test nicht auffiel ist, dass beim erreichen der ladespannung am ausgang der empfängerspule (also ab start der ladung) die 4 roten LEDs der m32 schwach leuchten und beim LCD die hintergrundbeleuchtung auch schwach an ist (der bRP6 ist aus!). Ich weiss nicht warum das so ist. Ist das ein problem, oder nur ein unangenehmer nebeneffekt?
Ich habe schon überlegt ob ich einen anderen freien ADC-kanal verwenden könnte, trotz wirklich sehr intensiver Suche gelang mir das nicht, es in der doku zu finden, welche ADCs noch frei sind und wo sie evtl. auf der multiIO herausgeführt sind...
Im schaltplan der m32 ist nur der kanal 0 für micro und 1 für die taster als belegt angegeben, im RN wissen für IO-board fand ich außer zahlreichen hinweisen auf ADC nur noch das hier:
------------------
Ähnlich wie im gerade genannten Fall ist es auch beim 10-poligen Wannenstecker SV_ADC_MXXX. Jedoch sind hier manche Pins (1, 3, 5 und 6) direkt auf einen Wähl-Jumper JP1,2,4 gelegt, wo sie mit Jumpern weiter auf Signale gelegt werden können. Nur Pin 6 ist nicht weitergeführt und steht zur eigenen Verfügung, ist jedoch nur bei dem M128-Modul als ADC verwendbar, auf allen anderen Modulen liegt hier GND an.
----------------
und stehe nach wie vor aufm schlauch...
wer hilft weiter?
thanks
gruß inka
Hi inka,
ich glaube nicht das Du auf der MIO einen freien ADC Port findest ohne auf irgend etwas verzichten zu müssen.
Am Pin 6 der SV_ADC_MXXX liegt doch bei Verbindung mit der M32 GND an. Was wolltest Du denn da machen ?
Was ist denn mit den ADC vom Basis Board hast Du die alle in Verwendung ?
Gruß TrainMen
Lesezeichen