was kann man da sehen:
Amplitude:
Bei 10V/DIV und so wie ich das sehe ca. 0,5 DIV Höhe -> 5V
Periodendauer:
Ich sehe ca. 2 Perioden auf 5 DIV, bei 20µs/DIV:
0,00002 * 5 / 2 = 0,00005 s = 50 µs
Frequenz:
1 / Periodendauer = 20000 Hz = 20 kHz
Dazu ist die Rechteckschwingung nicht symmetrisch, sondern der (positive) Impuls ist kürzer als die Pause (= Nulllinie).
Ich sehe ca. 0,8 DIV Impuls und 1,7 DIV Pause, also ein Impuls-Pausenverhältnis von 32% zu 68%.
Du misst da also eine unsymmetrische Rechteckspannung von 5V mit einer Frequenz von 20 kHz und einem Duty-Cycle von 32%.
Gruß
Dirk
hi Dirk,
die ergebnisse und die auswertung muss ich erst begreifen. Ich habe jetzt weiter experimentiert - juhuu - die erste echte messung mit dem oszi!
die einstellungen:
VOLTS/DIV = 1
TIME/DIV = 20micro sec
TV SEP = off
TRIG = HF
schalter neben dem input = DC
ein wirklich stehendes bild, in dem die kurve auf die drehung des potis reagiert.
poti 0 ohm
poti 5K ohm
also die schaltung ist wohl ok? Deine interpretation dieser zwei bilder würde meinem verständnis dieser messungen sehr helfen...
ich vermute die frequenz liegt in beiden fällen unterhalb der 36kHz...
gruß inka
Hi inka,
beim 1. Bild sehe ich eine Periode auf etwa 5,2 DIV
beim 2. Bild habe ich eine Periode auf etwa 6,9 DIV
Jetzt geht's bei 20µs/DIV ans Rechnen analog zu meiner Auswertung von 15:32.
Viel Erfolg!
Übrigens: Besser wird die Auswertung, wenn man viele gerade noch einzeln zählbare Perioden auf möglichst die ganze Breite (also möglichst viele DIVs) darstellen kann, weil man dann exakter rechnen kann.
Gruß
Dirk
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 16: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
@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 19:19 Uhr)
Sind Sie auch ambivalent?
ich habe jetzt das problem, dass das register 30 immer mit dem wert 004 ausgegeben wird. Habe alle änderungen rückgängig gemacht, dann wurde natürlich der wert des registers 30 nicht ausgegeben.
nach dem erneuten ändern des slave programms und des ausführenden programms in der m32 wird das reg 30 wieder sofort mit 004 ausgegeben, auch wenn die bake nicht mal in der nähe des RP6 ist!
wie werden die register behandelt, sind sie einmal definiert bleiben sie vorhanden? Auch mit dem wert? Werden irgendwo alle werte der register gelöscht? Das passiert evtl auch, nur nicht für das reg 30? Oder muss ich es im programm immer wieder auf 0 setzetn?
Geändert von inka (28.11.2013 um 14:06 Uhr)
gruß inka
Hi,
Das ist ja auch richtig so.wird das reg 30 wieder sofort mit 004 ausgegeben, auch wenn die bake nicht mal in der nähe des RP6 ist!
Gruß
Dirk
Lesezeichen