Kontrolle:
Ich sehe z.B. 6 Perioden auf 8,4 DIVs (Bild!) bei TIME/DIV von 20 µs:
Periode: 0,00002 * 8,4 / 6 = 0,000028 s = 28 µs
Frequenz: 35,7 kHz
Bei der Messung würde ich die Perioden immer ganzzahlig lassen und nur die DIVs auf +-0,1 ablesen.
Ja, genau. Das Oszilloskop ist (wie sein Name schon sagt) auch kein idealer Frequenzmesser. Daher ist die Genauigkeit nicht hoch.ich glaube das messen (oder ist es eher ein schätzen?) einer frequenz ist relativ einfach - wenn man weiss, wie was einzustellen und zu lesen ist...
Vielleicht bekommst du ja doch auch noch Werte vom "M32-Messgerät", so dass du die Frequenz optimal einstellen kannst.
Für den IR-Empfänger auf dem RP6 ist eine leichte Abweichung nicht so dramatisch, wobei seine Hauptempfindlichkeit halt bei 36 kHz liegt.
Gruß
Dirk
(Ot)
Hallo,
Es gibt sicher bessere Möglichkeiten Frequenzen zu _messen_ ... im Sinn eines Takt- oder Nulldurchgangszählers ... aber nicht alle Signale sind immer digital.
Geht es um die Flankensteilheit (hier ist sie gut) oder um die Signalform allgemein (z.b. zur Berechnung von Filtern) , ist ein Oszi unverzicht- und unersetzbar. Aber aus der Physik ist bekannt, das man sowieso keine absoluten Werte messen kann sondern es nur mehr oder weniger genaue Näherungsverfahren gibt.
http://de.wikipedia.org/wiki/Heisenb...%A4rferelation
In sofern ist messen immer ein "schätzen" mit mehr oder weniger genauen Referenzen als Hilfsmittel.
Aber davon ab finde ich die Aktion mit der "Fernmessung" am Oszi hier mal richtig gut - zeigt es doch was man damit erreichen kann - was sonst nur im stillen Kämmerlein in der Hobbyecke passiert. 3 Daumen hoch!
Gruß RolfD
(/Ot)
Geändert von RolfD (26.11.2013 um 17:12 Uhr)
Sind Sie auch ambivalent?
Das Datenblatt zum Oszi "HM203-6" ist bei www.hameg.com zu finden. Darin findet man Aussagen zur Genauigkeit der Vertikal-Anzeige, Bandbreite etc. und eben auch zur Zeitbasis, jeweils garantierte Werte für ein Neugerät nach Werkskalibrierung. Dazu kommt noch der Fehler durch die Ablesung, besonders dann, wenn man Zwischenwerte ohne Teilstrich ablesen muss.
Was den IR-Sensor betrifft, sollte auch hier im Datenblatt eine Angabe über den Empfindlichkeitsabfall in Abhängigkeit von der Lichtwellenlänge zu finden sein: wenigstens eine 50%-Bandbreite (oder 30% oder ...) oder sogar ein Diagramm.
Geändert von RoboHolIC (26.11.2013 um 19:00 Uhr) Grund: Ergänzung
hallo,
ich habe folgendes versucht um eine verifizierung des empfangs der signale der bake am RP6 zu bekommen, durchgeführt von der M32 aus:
verwendet habe ich das programm "RP6Control_06_I2CMaster.c"
Code:/* * **************************************************************************** * RP6 ROBOT SYSTEM - RP6 CONTROL M32 Examples * **************************************************************************** * Example: I2C Master * Author(s): Dominik S. Herwald * **************************************************************************** * Description: * Now we will use the I2C Bus Interface to send commands to the Controller * on the Mainboard and read sensor values. * This program does not do anything directly, it checks for pressed buttons * and then runs a small I2C Bus example depending on which button has * been pressed. * * You need to program the Controller on the Mainboard with the I2C Bus Slave * Example program from the RP6Base examples! Otherwise it will not work! * * ############################################################################ * The Robot does NOT move in this example! You can simply put it on a table * next to your PC and you should connect it to the PC via the USB Interface! * ############################################################################ * **************************************************************************** */ /*****************************************************************************/ // Includes: #include "RP6ControlLib.h" // The RP6 Control Library. // Always needs to be included! #include "RP6I2CmasterTWI.h" /*****************************************************************************/ #define I2C_RP6_BASE_ADR 10 // The default address of the Slave Controller // on the RP6 Mainboard /*****************************************************************************/ // I2C Error handler /** * This function gets called automatically if there was an I2C Error like * the slave sent a "not acknowledge" (NACK, error codes e.g. 0x20 or 0x30). * The most common mistakes are: * - using the wrong address for the slave * - slave not active or not connected to the I2C-Bus * - too fast requests for a slower slave * Be sure to check this if you get I2C errors! */ void I2C_transmissionError(uint8_t errorState) { writeString_P("\nI2C ERROR - TWI STATE: 0x"); writeInteger(errorState, HEX); writeChar('\n'); } /*****************************************************************************/ // Rotate function uint8_t transmit_buffer[10]; // temporary transmit buffer // A global variable saves space on the heap... #define CMD_ROTATE 8 #define LEFT 2 #define RIGHT 3 /** * Rotate function - you can define nearly the same functions as you have on * the RP6 and just forward the commands with I2C Bus transfers... * We will make an improved version of this and other functions in another example! */ void RP6_rotate(uint8_t desired_speed, uint8_t dir, uint16_t angle) { transmit_buffer[0] = 0; transmit_buffer[1] = CMD_ROTATE; transmit_buffer[2] = desired_speed; transmit_buffer[3] = dir; transmit_buffer[4] = ((angle>>8) & 0xFF); transmit_buffer[5] = (angle & 0xFF); I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, transmit_buffer, 6 ); } /*****************************************************************************/ // Read all registers function uint8_t RP6data[32]; // This array will contain all register values of RP6 // after you called readAllRegisters() // It is better to keep such big arrays GLOBAL as // they otherwise fill up the stack in memory... /** * This function reads ALL registers available in the standard I2C Bus Slave * Example program for the Robot Base and outputs their values on the serial interface. * You will see a lot of zeros when the Motors are not running. The main values that are not * zero are the two Light Sensors and the two free ADC Channels. */ 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'); } /** * Here we demonstrate how to read a few specific registers. * It is just the same as above, but we only read 4 registers and * start with register Number 13... * We also show how to combine values from high and low registers * back together to a 16 Bit value... */ void readLightSensors(void) { uint8_t lightSens[4]; I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 13); // Start with register 13 (LSL_L)... I2CTWI_readBytes(I2C_RP6_BASE_ADR, lightSens, 4); // and read all 4 registers up to // register Number 16 (LSR_H) ! writeString_P("Light Sensor registers:\n"); writeString_P(" | LSL_L:"); writeInteger(lightSens[0], DEC); writeString_P(" | LSL_H:"); writeInteger(lightSens[1], DEC); writeString_P(" | LSR_L:"); writeInteger(lightSens[2], DEC); writeString_P(" | LSR_H:"); writeInteger(lightSens[3], DEC); writeString_P("\n\n Light Sensor Values:"); writeString_P(" | LSL:"); writeInteger(lightSens[0] + (lightSens[1]<<8), DEC); writeString_P(" | LSR:"); writeInteger(lightSens[2] + (lightSens[3]<<8), DEC); writeChar('\n'); setCursorPosLCD(1, 3); writeIntegerLengthLCD(lightSens[0] + (lightSens[1]<<8), DEC, 4); setCursorPosLCD(1, 11); writeIntegerLengthLCD(lightSens[2] + (lightSens[3]<<8), DEC, 4); } /*****************************************************************************/ // Main function - The program starts here: int main(void) { initRP6Control(); // Always call this first! The Processor will not work // correctly otherwise. initLCD(); // Initialize the LC-Display (LCD) // Always call this before using the LCD! writeString_P("\n\nRP6 CONTROL M32 I2C Master Example Program!\n"); // IMPORTANT: I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation // with 100kHz SCL Frequency // Register the event handlers: I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); // Play two sounds: sound(180,80,25); sound(220,80,25); setLEDs(0b1111); // Turn all LEDs on! showScreenLCD("################", "################", "", ""); mSleep(500); showScreenLCD("I2C-Master", "Example Program 1", "", ""); mSleep(1000); // --------------------------------------- setLEDs(0b0000); // All LEDs off! uint8_t counter = 1; while(true) { // We check the buttons - just like the buttons example - but here we // generate several I2C Bus requests and commands when a key // is pressed AND released again... uint8_t key = checkReleasedKeyEvent(); if(key) { switch(key) { case 1: // Increment a counter and send value to LEDs of the // Slave Controller: setLEDs(0b0001); showScreenLCD("INCREMENT", "LED COUNTER", "", ""); I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, 3, counter); counter++; break; case 2: // Read and display ALL registers of the slave controller: setLEDs(0b0010); showScreenLCD("READ ALL RP6", "REGISTERS", "", ""); readAllRegisters(); break; case 3: // Read the light sensors and show value on display: setLEDs(0b0100); showScreenLCD("LIGHT SENSORS:", "L: R:", "", ""); readLightSensors(); break; case 4: // Rotate a very small distance to the left: setLEDs(0b1000); showScreenLCD("ROTATE A BIT...", "... LEFT!", "", ""); RP6_rotate(35,LEFT,40); break; case 5: // Rotate a very small distance to the right: setLEDs(0b1001); showScreenLCD("ROTATE A BIT...", "... RIGHT!", "", ""); RP6_rotate(35,RIGHT,40); break; } } } return 0; }
mit foltgenden änderungen:
in der "RP6Base_I2CSlave.c":
zeile inhalt 85 uint8_t pb2_value; hinzu 231 #define I2C_REG_PB2_VALUE 30 hinzu 272 I2CTWI_readRegisters[I2C_REG_PB2_VALUE] = (uint8_t)(pb2_value); hinzu 483 pb2_value = (PINB & (1<<PINB2)); hinzu
in der "RP6Control_06_I2CMaster.c":
103 I2CTWI_readBytes(I2C_RP6_BASE_ADR,RP6data, 30); von I2CTWI_readBytes(I2C_RP6_BASE_ADR,RP6data, 31); in 109 for(i = 0; i < 30; i++) von for(i = 0; i < 31; i++) in
benutzt habe ich die fukntion zum ausdrucken aller register "void readAllRegisters(void)", hier das ergebnis:
ursprünglich 30 register:
READING ALL RP6 REGISTERS:
#00:000 | #01:000 | #02:000 | #03:000 | #04:000 | #05:000 | #06:000 | #07:000
#08:000 | #09:001 | #10:000 | #11:002 | #12:000 | #13:099 | #14:003 | #15:220
#16:002 | #17:000 | #18:000 | #19:000 | #20:000 | #21:023 | #22:003 | #23:217
#24:002 | #25:212 | #26:002 | #27:000 | #28:000 | #29:000
31 register, ohne signale der bake:
READING ALL RP6 REGISTERS:
#00:000 | #01:000 | #02:000 | #03:000 | #04:000 | #05:000 | #06:000 | #07:000
#08:000 | #09:001 | #10:000 | #11:002 | #12:000 | #13:098 | #14:003 | #15:225
#16:002 | #17:000 | #18:000 | #19:000 | #20:000 | #21:023 | #22:003 | #23:220
#24:002 | #25:216 | #26:002 | #27:000 | #28:000 | #29:000 | #30:004
31 register, mit signalen der bake:
READING ALL RP6 REGISTERS:
#00:000 | #01:000 | #02:000 | #03:000 | #04:000 | #05:000 | #06:000 | #07:000
#08:000 | #09:001 | #10:000 | #11:001 | #12:000 | #13:107 | #14:003 | #15:247
#16:002 | #17:000 | #18:000 | #19:000 | #20:000 | #21:019 | #22:003 | #23:242
#24:002 | #25:238 | #26:002 | #27:000 | #28:000 | #29:000 | #30:000
ist die änderung des reg '30 von 004 in 000 der erhoffte nachweis? Wenn ja, könnte ich doch jetzt abhängig vom inhalt des reg 30 verschiedenes an funktionen ausführen?
Geändert von inka (27.11.2013 um 17:21 Uhr) Grund: schreibfehler
gruß inka
Hi inka,
nicht schlecht.
Das kann so klappen, wobei ich die Änderungen nicht im Detail angesehen habe.
Die 4 in Register 30 ist ok:
Wenn kein IR-Signal anliegt, hat der Empfänger High-Pegel, daher ist deine Variable pb2_value binär = 0b00000100 (dezimal 4), das heißt, dass PINB2 (also Bit 2) gesetzt ist.
Wenn ein IR-Signal anliegt, ist das Bit nicht gesetzt, also Register 30 = 0.
Noch 2 Ideen/Vorschläge zu deiner tollen Umsetzung:
1. Mit pb2_value = (PINB & (1<<PINB2)); aktualisierst du den Wert bei jedem Durchlauf der Hauptschleife im Slave. Das kann man machen,- von der Programmstruktur her gehört das aber eher ans Ende der Funktion task_update().
Das Ergebnis ist dasselbe, aber das ganze "sauberer".
2. Grundsätzlich kann man das machen, dass man ein weiteres Register ergänzt. Es gibt noch einen weiteren Weg: Im Status-Byte (Register 1) sind noch Bits frei. Man könnte da ein weiteres Bit definieren:
... und auch im Master auswerten. Das muss man aber nicht so machen.Code:// Some status bits with current settings and other things. union { uint8_t byte; struct { uint8_t powerOn:1; uint8_t ACSactive:1; uint8_t watchDogTimer:1; uint8_t wdtRequest:1; uint8_t wdtRequestEnable:1; uint8_t IRreception:1; uint8_t unused:2; }; } status;
Im Grunde zeigst du ja mit deiner Lösung, wie man den Base-Slave um eigene (Lese-)Funktionen erweitern kann. Klasse!
Genauso kann man auch zusätzliche Befehle definieren.
Gruß
Dirk
Wir hatten es oben schon mal von Toleranzen... der Wertebereich am Port wird vermutlich 0-255 haben.. 10% übliche Fehler wären 25.. wenn dein Teil nur um 4 Punkte ausschlägt stimmt entweder etwas nicht.. oder es kommt nur ein vernachlässigbar kleines Signal an. Jedenfalls liegen 4 Punkte im Bereich normaler schwankungen.. und sind als Signal nicht überzegend auswertbar. Ich würde das ohne M32 und dem Slave-geraffelss versuchen.. und die Werte des Port schlicht und einfach über eine serielle Verbindung an den PC ausgeben. Für dich lesenswert dürfte dazu ein Codeschnipsel von Dirk sein, welcher mal hier rum ging und IR Signale als Morse zwischen 2 Bots übertrug.
http://www.rn-wissen.de/index.php/RP...en.2Fempfangen
Gruß
Nachtrag... ach so.. der Port schaltet nur digital.. stimmt ...nix mit 0-255 ... tja plöt .. mein Kommentar wie auch deine Ausgangslage!
Sind Sie auch ambivalent?
@Dirk, @RofD:
vorschlag 1 werde ich durchführen, vorschlag 2 erstmal anschauen, für meine "quick & dirty" lösung habe ich schon einen tag gebraucht...
zwei weitere problemchen:
1) die reichweite der bake liegt bei 30cm, das ist ein bischen wenig
2) der treiber-transistor wird trotzdem recht warm (finger kann man nicht draulfassen)
hier noch einmal der schaltplan;
zu 1)
- an den IR-dioden fließen 20mA, das kann man sicher erhöhen - die vorwiderstände haben 47 Ohm, auf wieviel sollte/könnte ich runter? Ich habe an der stelle schon recht viel rumgelötet
(Ich habe dort 5 dioden parallel an dem transistor mit jeweils einem R)
zu 2)
- den 2N2222 könnte ich durch BD135, auch NPN und leistungsstärker (hatte ich noch in der kiste) ersetzen
- wie ist es mit dem basiswiderstand - wie könnte der zur leistungssteigerung der IR-dioden beitragen?
@RofD.
beruhigend, wenn auch profis mal daneben greifen - nichts für ungut...
was meinst Du mit meiner ausgangslage?
gruß inka
Also ich bin bestimmt kein Profi... und mache selbstverständlich auch Fehler. Aber du beschreibst deine Lage selbst.. dein Bot kann nun in Umkreis von 30cm feststellen ... per 0 oder 1 ... ob die Bake sendet. Das ist weit von einer vernünftigen Raumortung entfernt und entspricht etwa den IR-Abstandssensoren, die es so zu kaufen gibt... vielleicht reicht dir das ja als Bake.
Jetzt kann man (z.B. aus der Funktechnik, Licht ist elektrisch gesehen auch eine art elektromagnetische Schwinung) wissen, das man für die Verdoppelung von Reichweiten eine 4-fache Leistung braucht - oder anders gesagt, die Leistung steigt zur Reichweite im Quadrat. D.H. um auf 60 cm Reichweite zu kommen muss du entweder 20 LEDs nehmen... oder irgendwie 80mA Durchschnittsstrom durch deine 5 LEDs schicken was auf dauer keine normale IR-LED überlebt! Um auch diese Leistung zu verdoppeln brauchst du wiederum das 4 fache... also 80 Leds auf 1,20 m ... usw usw... oder dir einen empfindlicheren Empfänger selbst bauen.
Vielleicht wird nun klar das es kaum möglich ist ein, Raum mit herkömlichen IR-Dioden von einem Punkt aus komplett auszuleuchten. Selbst mit modernen LED-Leuchtmitteln braucht man 5 Watt im normalen Lichtwellenbereich um ein Raum so zu beleuchten das einfache LDR-Sensoren das anmessen. Du arbeitest da derzeit mit ca. 50 Milliwatt .. also 1%! Und trotz aller Überlegung hast du bisher (noch?) keine Info über die Stärke des Lichtsignals im RP6...
Gruß Rolf
Geändert von RolfD (27.11.2013 um 20:19 Uhr)
Sind Sie auch ambivalent?
Lesezeichen