- fchao-Sinus-Wechselrichter AliExpress         
Seite 2 von 7 ErsteErste 1234 ... LetzteLetzte
Ergebnis 11 bis 20 von 66

Thema: Dicker Fehler in der RP6I2CmasterTWI.h der RP6Lib + Bugfix

  1. #11
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    21.04.2009
    Beiträge
    523
    Anzeige

    Praxistest und DIY Projekte
    Zitat Zitat von SlyD
    Hallo,

    zunächst vorweg allgemein zur Erläuterung:
    Es kann durchaus sein, dass einige Dinge alles andere als optimal implementiert sind - war auch nicht das Ziel und dazu war auch keine Zeit.
    Es gab damals (2007) eine Deadline und 10 Baustellen (bei Hard- und Software)
    gleichzeitig.
    Nachdem es funktionsfähig war, kamen dann schon wieder andere Dinge...

    Steht in der Baselib auch dabei
    "This Code works OK, but it is not optimal! There is a lot potential for tuning!"
    Und das gilt für die gesamte Lib!


    Ziel war eine bessere Software Ausgangsbasis für den Anwender
    als beim ASURO und beim alten CCRP5 Vorgänger.
    Nicht mehr und nicht weniger. Dem bisherigen Feedback der Mehrzahl der Anwender nach zu urteilen ist das auch gut gelungen - von kleinen Details mal abgesehen.

    Naja, wenn sofort alles perfekt wäre, bliebe für fortgeschrittene Anwender
    wie euch auch nix interessantes mehr zu tun.



    Zum Thema:
    Ja das mit den Delays habe ich aus genau dem Grund eingebaut wie RolfD
    oben schon rausgefunden hat. Natürlich nur eine "Notlösung" hat aber
    für das was ich getestet hatte erstmal funktioniert.
    Ich weiss nicht mehr genau, da es schon sehr lange her ist, aber ich meine
    ich hätte es auch mit dem TWINT Bit getestet hat aber nicht
    zufriedenstellend funktioniert. Hatte dann auch keine Zeit mir
    was besseres auszudenken also ists einfach so ein unschönes Delay geworden.

    Könnt ihr also gerne versuchen besser zu lösen


    MfG,
    SlyD
    Ja, da hast du vollkommen Recht! Beim RP6 ist ganze wesentlich besser gelöst, als noch beim ASURO.
    Mir ging es ja auch nur darum, zu erfahren, ob wir da in allen Punkten Recht haben, nicht darum deine Software schlecht zu machen

    Wie du gesagt hast, funktioniert das ganze soweit super, die kleineren Probleme die ich hatte konnte ich immer umschiffen.
    Auch die Anfänger kommen nach ein paar dutzend Fragen, die auch alle im Handbuch erläutert sind, damit zurecht.

    Du hast sicherlich viel Zeit in die Library gesteckt und ich finde das Ergebnis kann sich durchaus sehen lassen! =)

    Vielleicht könntest du ja (wenn RolfD das möchte) darüber nachdenken, die Multimaster-Version mit aufzunehmen...

  2. #12
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    @SlyD
    Du brauchst dich nicht zu entschuldigen, ich möchte nur die "Macken" finden und entfernen. Das es Macken sind weis ich, und wie sie entstanden sind kann ich mir so ca. denken. Unter Zeitdruck proggen ist übel. Wie man sie behebt... da arbeite ich dran und am Schluß sollte eine Lib raus kommen die allen nutzt. Schließlich steht die Software under GPL.

    Übrigends habe ich noch keine Software im Bereich AVR gesehen, die eine continuierliche interruptgesteuerte Verarbeitung am TWI zulässt, selbst die AMTEL Beispiele enden meist mit "Disable Interrupt..." was irgendwie wenig produktiv ist. Das was wir mit der RP6Lib haben ist bereits gut ... oder zumindest eine gute Idee. Sie muss nur noch rund laufen.

    Ich bastel mal weiter... ich bräuchte dringend einen zweiten USB Adapter damit ich nicht dauernd umstecken muss.. *seufz
    LG Rolf

    EDIT: Ich habe mal ein wenig rumgeforscht und da ist mir die Arduino-Plattform incl. Source (GPL) begegnet. Sollte es mal ein RP7 geben... ... ... irgendwann... ... in ferner Zukunft... dann wäre es schön wenn man sich beim entwickeln der Libs etwas mehr daran orientieren würde... die haben nämlich z.B. eine 1.A funktionierende TWI Schnittstelle! Nur kriegt man die leider nicht mal eben so an das RP6Lib System portiert. *seufz

  3. #13
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    Jetzt antworte ich mir schon auf meine eigenen Posts... tsts

    Und dann das..

    "Deine Nachricht darf nicht mehr als 20000 Zeichen enthalten."



    Aber es gibt ein guten Grund... für die Betatester hab ich was zu tun.
    Ich betone BETATESTER... der Code ist noch nicht reif, das man ihn auf die Menschheit und insbesondere arglose RP6 Nutzer loslassen kann

    Es folgen eine twi_target.h, eine include Datei um ein paar Dinge zu vereinfachen, hauptsächlich Präprozessordirektiven die es erlauben den Quelltext abhängig vom Zielsystem zu bauen. Sie muss also entsprechend geändert werden, da sie aber im Projektverzeichnis liegt und jedes Projekt eine eigene haben darf, spart man sich bissel arbeit. Dort gibts auch ein debug Flag welches die Ausgabe der Zustände am I2C Bis und Datenbytes ausgibt. Bei vielen Daten streikt allerdings das Konsolenterminal des Loaders...

    Dann eine RP6I2CTWI.h, in der Hauptsache ein Verbund aus den beiden alten includes + paar Änderungen.

    Dann die RP6I2CTWI.c als eingentliche Lib. Die alten Libs werden nicht includiert.

    Meine Testumgebung ist ein RP6 mit einem modifizierten Slave Programm + einer I2C pcf8583 sowie einem aufgestecktem M32. Die M32 spielt mit dem Programm Example_08_I2CMaster Master, die PCF8583 spielt Slave für das Baseboard, man kann aber auch ein anderes I2C Device nehmen... lcd, ein SRF oder sonst was... Ich lasse die Base ein wenig in den Registern und RAM der Uhr spielen. Die Base als Slave (für die M32) ist also zugleich auch Master für das PCF8583. Ich katte noch keine Zeit mir ein richtiges Stress und Benchmarks system aufzubauen, dazu fehlt mir vor allem ein zweiter USB Adapter und ohne den ist debuggen wirklich im trüben fischen...

    Alles in allem läuft das so auch so wie gedacht. Allerdings treten noch Probleme (wahrscheinlich Timing) auf und daher sage ich ganz deutlich: Das ist alles wirklich noch beta! Allerdings gibts in der Lib auch keine nennenswerten statischen Delays.

    Die Änderungen im einzelnen zu beschreiben und zu begründen würde ein Buch füllen, ihr werdet euch also ggf. den Code anschauen müssen. Vielleicht spuckt "diff" was sinnvolles aus... keine Ahnung. Er ist zu 99% komapibel mit der alten Lib, es gibt allerding kleine Änderungen.

    __I2CTWI_initMaster gibts nicht mehr und ein paar Variabelen die scheinbar gedacht waren um den ISR zu monitoren sind statisch gesetzt (waus auch zu problemen führen kann, da such ich noch, hat aber keine Priorität grade... Der Mastermode ist nur Master (und wenn man das in twi_target.h auch einträgt spart man einiges an Platz), der Slave Mode kann beides, Slave und Master. Sonst ist das meiste ähnlich zu beachten wie in den ursprünglichen Libs. Meinem Gefühl nach ist die Lib deutlich stabiler als die alte. Das würde ich aber gern auch von euch erfahren.

    Bin für Fragen, Vorschläge, Verbesserungen usw. immer offen. Ich hoffe auf Feedback.

    EDIT1: Im makefile nicht vergessen:
    #SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CslaveTWI.c
    #SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CmasterTWI.c
    SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CTWI.c

    EDIT2:
    Es spricht nichts dagegen, z.B. mit eigenen I2C Funktionen auf dem I2C Bus zu arbeiten, allerdings sollte man dann für die Zeit Interrupts unterbinden und die I2C Register (TWSR) überwachen. In jedem Fall muss man nach einem übertragenem Datenpaket eine Stop Condition setzen. Viele Slaves vertragen zwar den repeated Start ... also Start,Daten,Start,Daten,Start,Daten, usw., allerdings wird der Bus so nie frei und andere Master bekommen ggf. keine Gelegenheit zum senden. Wichtig für mehrere Master auf einem Bus ist also Start,Daten,Stop,Start,Daten,Stop usw... Es wäre auch ein Repeated Start durch Start,Daten,Start,Daten,Stop denkbar.. wenn man verhindern will das andere Master einem in die Devices schreiben wärend man noch im Zugriff ist. Aber ein Stop am Ende ist quasi Pflicht. Sinnvoller Weise müsste man ein RepStart nach einer gewissen Zeit unterbinden z.B. auch um nicht anfällig für Signalstörungen auf dem Bus zu sein.

    Schreibt man eigene Funktionen und will die ISR nutzen, sollte man vor einem Start im TWCR mit bitset(TWI_statusReg,STR_isr); die ISR "reservieren" und nach einem Stop mit bitclr(TWI_statusReg,STR_isr); freigeben. bitset und bitclr sind gängige Macros:
    #define bitset(var, bit) ((var) |= (1 << (bit)))
    #define bitclr(var, bit) ((var) &= (unsigned)~(1 << (bit)))
    Repstarts kann die Lib als Master derzeit noch nicht... bzw konnte sie glaube ich auch noch nie, bin ich mir jetzt nicht sicher. Steht aber auf meiner Todo. Sinnvoll wäre dies z.B bei Funktionen die in einem Rutsch ein Pointer setzen und dann lesen - wie in RAMs/EEPROMs üblich.
    LG Rolf
    Angehängte Dateien Angehängte Dateien

  4. #14
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    21.04.2009
    Beiträge
    523
    Na das sieht ja schon mal gut aus. Ich hoffe heute oder am Wochenende noch zum Testen zu kommen.
    Ich habe jetzt noch nicht in die Dateien reingeguckt, aber prinzipiell wäre es bestimmt nicht schlecht, wenn du ein Beispielprojekt posten würdest.
    Dann könnten vielleicht noch mehr Leute etwas testen.

    Fabi

  5. #15
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    21.04.2009
    Beiträge
    523
    Also dann erst mal meine ersten Eindrücke dazu:
    • Szenario: Base läuft mit unverändertem Slave-Programm,
      M32 mit angepasstem Multimaster Remotrol,
      M128 nicht angeschlossen (hab ich mich bezüglich Multimaster noch nicht drum gekümmert)
    • Konvertierung verlief problemlos, keine Fehler beim compilieren
    • Normale Funktionstests klappen soweit schon gut, habe dort keine Fehler festgestellt.
      (LEDs ansteuern, Motoren steuern, Werte auslesen, etc...)
    • Mein eigener Stresstest für die Verbindung PC->RP6 klappt auch problemlos (der benutzt im Endeffekt auch die RP6SetLeds), die Perfomance ist etwa die selbe
    • I2C Selbstests klappen
    • Jetzt habe ich den I2CLED Test mal etwas modifiziert:
      -mSleep(100) nach jedem Durchgang entfernt-->kein Problem,
      -mSleep(50) zwischen Setzen der RP6 LEDs und Auslesen selbiger von der M32 --> ca 500 Fehler bei 2400 Versuchen.
      Bei diesem Versuchsuafbau wird überhaupt nicht mehr gewartet, die einzigen Pausen ergeben sich durch das Schreiben auf UART.
      Ich denke aber fast, dass diese Pause dort rein muss und du da auch nichts gegen machen kannst. Liegt wohl eher am Prinzip des Ganzen.
    • Ich bilde mir ein, dass bei meinen Tests per Hand wesentlich mehr Steuerbefehle auf der Strecke geblieben sind (Verhältnis 5:1), das ist aber keine qualifizierte Aussage, sondern nur ein Eindruck.
      Kann sein, dass das Zufall war.


    Läuft also bis her recht gut

    Als nächstes werde ich dann mal die Base anpassen und schauen, was die M128 dazu sagt.

    Habe ich das eigentlich richtig verstanden, dass der Slave-Modus mehr kann als der Master-Modus?
    Das solltest du umbennen, vielleicht in Master und MasterSlave. Ist sonst etwas verwirrend.

  6. #16
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    Ich habe auch schon je ein Testprog für die Base und M32 geschrieben und werde am Wochenende ausgiebig testen.

    @RolfD:
    Noch eine kleine Anregung/Frage:
    Wenn man die RP6I2CTWI Lib in der "normalen" RP6-Umgebung ins Verzeichnis /RP6lib/RP6common tut, müßte man dahin auch die twi_target.h tun.
    Das bedeutet beim Kompilieren von Programmen für die Base und M32, dass man immer die twi_target.h neu anpassen muss. Das ist ziemlich lästig und fehlerträchtig, wenn man beim Proggen zwischen M32 und Base wechselt.
    Vielleicht kann man das noch anders regeln (z.B. je eine twi_target.h in das Programmverzeichnis der einzelnen Programme o.ä.).
    Ist 'ne Kleinigkeit, wäre aber wirklich praktisch ... und die neue Lib wäre dann besser im bisherigen Konzept einsetzbar.

    So, dann werde ich mal testen ...

    Gruß Dirk

  7. #17
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    Hallo,
    erst mal nur eine kurze Antwort.
    Danke fürs testen an euch.
    Dann @Dirk, die twi_target.h kommt ins PROJEKTverzeichnis und nicht in die Common. Es ist genau so gedacht wie du es auch anregen wolltest.

    Also es sind definitiv noch nicht alle Probleme behoben aber ich bin zuversichtlich. Ich werde am WE weiter daran proggen, ich fummel mir grade ein I2C Display an die Base damit ich dort Ausgaben besser überwachen kann wärend ich mit dem USB Dongle an der M32 hänge.

    @Fabian, ich bin auf weitere Tests gespannt. Zum Thema Master/Slave...
    Ja der Slavemode kann _auch_ Master Funktionen. Der Master nur Master. Wenn Du ein I2C Display hast, kannst du jetzt z.B. das Display in der ersten Zeile vom Master beschreiben lassen, in der 2.ten Zeile vom "Slave". (vorausgesetzt beide setzen den Cursor richtig )
    Radbruch hatte hier https://www.roboternetz.de/phpBB2/ze...ag.php?t=41805 schon mal gezeigt wie das von der Base aus gehen kann, die M32 kann das bis auf die Ausgabe auf den Portbaustein ja quasi schon.
    LG Rolf

  8. #18
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    So, ich habe mal mit diesen Programmen getestet:

    RP6 Base (Slave):
    Code:
    /* 
     * ****************************************************************************
     * RP6 ROBOT SYSTEM - ROBOT BASE TESTS
     * ****************************************************************************
     * Example: I2C Slave - I2C Receive Test
     * Author(s): D. Ottensmeyer
     * ****************************************************************************
     * Description:
     *
     * This Example receives data via I2C as slave.
     *
     *
     * ############################################################################
     * 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 "RP6RobotBaseLib.h"	// The RP6 Robot Base Library. 
    								// Always needs to be included!
    #include "RP6I2CTWI.h"			// Include the new I2C-Bus Library
    
    /*****************************************************************************/
    // Defines:
    
    // The Slave Address on the I2C Bus can be specified here:
    #define RP6BASE_I2C_SLAVE_ADR 10
    
    #define CMD_SHOW_DATA 99		// Command to display the data
    
    #define TEXT_OUTPUT				// Show text
    
    /*****************************************************************************/
    // Variables:
    
    uint16_t cnt = 0;
    uint16_t error_cnt = 0;
    uint8_t controlbyte; 
    uint8_t highbyte = 0; 
    uint8_t lowbyte = 0; 
    
    /*****************************************************************************/
    // Main function - The program starts here:
    
    int main(void)
    { 
    
    	initRobotBase(); 
    
    	setLEDs(0b111111);
    	mSleep(500);	   
    	setLEDs(0b000000);
    
    	I2CTWI_initSlave(RP6BASE_I2C_SLAVE_ADR); 
        
    	while (true) 
    	{    
    		if (I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy) { 
    			controlbyte = I2CTWI_writeRegisters[0];		// Read control byte
    			I2CTWI_writeRegisters[0] = 0;				//  and reset it (!!!)
    			lowbyte = I2CTWI_writeRegisters[1];			// Read lowbyte 
    			highbyte = I2CTWI_writeRegisters[2];		// Read highbyte 
    			if (controlbyte == CMD_SHOW_DATA) { 
    				cnt = ((highbyte << 8) | lowbyte);		// Restore 16-bit value 
    #ifdef TEXT_OUTPUT
    				writeString_P("Received: ");			//  and show it
    				writeInteger(cnt, DEC);
    #endif
    				if (!cnt) error_cnt = 0;				// Reset error counter
    				else error_cnt++;						// Error counter + 1
    				if (cnt != error_cnt) {
    					writeString_P(" ERROR!\n");
    					error_cnt = cnt;
    				}
    #ifdef TEXT_OUTPUT
    				else writeChar('\n');
    #endif
    				controlbyte = 0;
    			}
    		}
    	} 
    	return 0;
    }
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 19.02.2011 by D. Ottensmeyer
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    RP6 M32 (Master):
    Code:
    /* 
     * ****************************************************************************
     * RP6 ROBOT SYSTEM - RP6 CONTROL M32 EXAMPLES
     * ****************************************************************************
     * Example: I2C Master - I2C Send Test
     * Author(s): D. Ottensmeyer
     * ****************************************************************************
     * Description:
     *
     * This Example sends data via I2C as master.
     *
     *
     * ############################################################################
     * 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 "RP6I2CTWI.h"			// Include the new I2C-Bus Library
    
    /*****************************************************************************/
    // Defines:
    
    // The Slave Address on the I2C Bus can be specified here:
    #define RP6BASE_I2C_SLAVE_ADR 10
    
    #define CMD_SHOW_DATA 99		// Command to display the data
    
    #define TEXT_OUTPUT				// Show text
    
    /*****************************************************************************/
    // I2C Event handlers:
    
    /**
     * 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 IS: 0x");
    	writeInteger(errorState, HEX);
    	writeChar('\n');
    }
    
    /*****************************************************************************/
    // Variables:
    
    uint16_t cnt = 0;
    uint8_t buffer[4];
    
    /*****************************************************************************/
    // Main - The program starts here:
    
    int main(void)
    { 
    	initRP6Control(); 
    
    	initLCD(); 
    
    	I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
    							// with 100kHz SCL Frequency
    	
    	// Register the event handlers:
    	I2CTWI_setTransmissionErrorHandler(I2C_transmissionError);
    
    	setLEDs(0b1111);
    	mSleep(500);	   
    	setLEDs(0b0000);
    	
    	while(true)  
    	{
    		if (!I2CTWI_isBusy()) {
    			cnt++;									// TEST: COUNTER!!!
    			if (cnt > 32767) cnt = 0;
    			buffer[0] = 0;
    			buffer[1] = CMD_SHOW_DATA;
    			buffer[2] = cnt;
    			buffer[3] = (cnt >> 8);
    			I2CTWI_transmitBytes(RP6BASE_I2C_SLAVE_ADR, buffer, 4);
    #ifdef TEXT_OUTPUT
    			setCursorPosLCD(0, 0); 
    			writeStringLCD_P("I2C has sent:");		// What was sent? 
    			setCursorPosLCD(1, 0); 
    			writeIntegerLCD(cnt, DEC);
    #endif
    		}
    	} 
    	return 0; 
    }
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 19.02.2011 by D. Ottensmeyer
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    Ergebnis:
    Der Zähler zählt immer 3 Stellen hoch, danach wird eine Stelle ausgelassen. Da pro Zähler 4 Bytes übertragen werden, flutschen wohl immer ca. 12 Bytes, bevor eins verloren geht.

    Gruß Dirk

    ... ich bleibe dran ...

  9. #19
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    hm.... hm....
    also erst mal danke für das "testsystem", das ist ein schöner Test und genau das was ich als Ansporn brauche um hier weiter zu basteln. Und ggf. auch ein Hinweis woran es liegen kann. Ich hab beide Sources compiliert und kann dein Ergebnis bestätigen, allerdings weis ich noch nicht wieso das so ist - es ist jedenfalls nicht gut das es so ist!

    Mir drängt sich der Verdacht auf, das es mit anderen Interrupts im System zu tun hat, z.B. dem Timerinterrupt. Oder die Messung aller Sensoren... Das würde zumindest die relative Regelmässigkeit der Errors erklären. Die TWI-isr versucht ja alles anzunehmen was kommt aber wenn jemand extern mit cli/sei den Interrupt abdreht, kriegt die ISR das ja nicht mit, folglich schlagen Bytes auf, die in der isr nicht verarbeitet werden und schon meldet dein Programm ein Fehler oder die TWI rising Buserros oder so'n quark.
    Würde man das jetzt perfektionieren wollen, würde man wie im Ethernet bzw. ISO-OSI Modell eine logische Netzwerkschicht mit Fehlererkennung einbauen.. sprich alle Daten mit CRC-Prüfsumme versehen. Dann kann der Client (Base) ein retransmit anfordern. Nur das ist beim TWI mit Kanonen auf Spatzen geschossen und für die Datenübertragung zu I2C Slaves auch garnicht machbar (und bei einer Fehlerquote von 33% eh witzlos). Das Problem betrifft vor allem den Slavemodus, mit dem Sender (Master) hat das nur so viel zu tun da er viel sendet, aber weit weniger als der TWI Bus zulässt. Es ist auch nicht auf die Geschwindigkeit allgemein zu schieben, die bewegt sich im Bereich wo auch jedes normale UART läuft. Als Master führt man den SCL-Takt, wird ein Timerinterrupt ausgeführt geht nichts verloren, der Slave merkt nur das der Master "ruckelt" beim arbeiten. Als Slave muss er aber immer und zu jeder Zeit alle Datenbytes annehmen können oder ein NACK senden worauf hin der Master normal die Übertragung abbricht. Im Fall von verlorenen Bytes kann der Slave aber nicht mal NACKen... Ist also auch keine Lösung.

    Die resultierende Frage ist also.... : Wie bringt man dem Rest der Lib bei, die Füße still zu halten bzw. sich mit der TWI zu arrangieren so lange eine Übertragung am TWI läuft?

    Zweite Frage: betrifft das nur den Slave oder ist auch der Master Receiver Mode betroffen (lesen von großen Datenmengen aus einem EPROM als Master z.B.) Ich vermute stark, es ist nur der Slave betroffen.
    @Dirk, kannst Du dein Programm mal umschreiben so das der Master (M32) möglichst große Datenmengen beim Slave (Base) liest und verifiziert. Das wäre eine wichtige Frage das zu klären. Danke schon mal.

    *kopfkratz
    SlyD hast Du eine Idee bzw. kannst Du den Gedankengang bestätigen?
    Ich grübel mal weiter. SO ist das TWI jedenfalls kein wirklicher Gewinn für den RP6 mit Zusatzboards. Aber ich bin sicher, das geht noch besser....

    Ich schau mir das jetzt erst mal genauer an... ich habe übrigends mal
    //#define TEXT_OUTPUT // Show text
    im Slave ausgeschaltet und prompt habe ich auf ca. 3500 übertragene Werte nur noch ca. 20 Fehler... also unter 1% ... und nicht mehr jedes dritte Datum im Eimer. Ein Hinweis das auch die (Echtzeit)UART-Ausgabe hier nicht ganz unbeteiligt an der Fehlerdichte ist.
    Ich hab nur leider keine wirkliche Idee, wie man das in den Griff bekommt... Slyds Worte oben bekommen grade einen ganz neuen Sinn für mich...

    "This Code works OK, but it is not optimal! There is a lot potential for tuning!"

    Man muss aber fairer Weise dazu sagen, das Amtel für Multiprozessorkommunikation den UART vorgesehen hat... und nicht das TWI, der UART hat sogar ein besonderen Modus dafür. Man könnte sich auch anders behelfen, z.B. indem man ein pcf8583.h mit immerhin 240 Byte RAM im System vorsieht auf den beide CPU's als Master zugreifen und dort Daten austauschen. Nur dafür ist ab Werk weder der RP6 noch die Software ausgelegt. Wenn man zuverlässige Ergebnisse erwartet, sollte man z.Z auf den Slavemode wohl eher verzichten - oder/und fehlertolerant proggen und tatsächlich sowas wie ne CRC vorsehen. Kommt halt auf den Zeck an.

    *grins

    Aber für uns Robotbauer wäre es immerhin schon mal interssant wenn der Multimastermode richtig funktioniert und die Daten zuverlässig ankommen wie sie abgeschickt wurden... das war bisher nicht immer der Fall und da lohnt es sich die Lib noch zu verbessern. Den Slavemode... tja... mal sehen aber ich denke das schaut nicht gut aus... vielleicht ists aber auch nur ein kleiner fieser Bug... mal sehen.

    EDIT:
    Für die Betatester eine kleine Änderung am Include File, bitte

    #define I2CTWI_isBusy() ((TWCR & (1<<TWINT)))
    durch
    #define I2CTWI_isBusy() (bit_is_set(TWI_statusReg,STR_isr))

    ersetzen. Hintergrund ist, das TWINT Bit spielt für die Übertragung eines kompetten "Satzbaus" im TWI (Start Daten Stop) keine Rolle, eine Aussage darüber ob die TWI frei ist gibt hingegen das STR_isr in TWI_statusReg (abhängig von der Stop condition) , folglich muss das geändert werden. Die Lowlevelfunktionen warten eh auf das STR_isr aber um festzustellen ob ein Task Rechenzeit braucht - wie in dem Master testprogramm - sollte es natürlich die richtigen Bedingungen abfragen.

    Gruß RolfD

  10. #20
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    Hallo,

    tja ist schon lange her das ich was dran gemacht habe aber mal kurz überlegen... ohne den neuen I2C Lib Code angeschaut zu haben - also keine Garantie auf garnix


    Der Master sollte eigentlich kein Problem sein.

    Es ist natürlich logisch, dass wenn der Slave lange an irgendwelchen anderen Sachen rumrechnet in dieser Zeit keine Daten aus den I2C "Registern" (dem Array) abgeholt werden können. Auch UART Ausgaben kosten Rechenzeit, da die ja relativ langsam mit 38400 Baud laufen... mach mal ein mSleep(100) in den Slave Code das dürfte dann noch etwas drastischer werden.
    Das Abholen und Interpretieren der Daten wird ja nicht in der ISR erledigt, das muss noch immer im Hauptprogramm erfolgen.

    Die Daten kommen vermutlich sogar korrekt in den Registern (in demI2CTWI_writeRegisters[] Array) an, aber das Programm holt die nicht schnell genug ab und werden dann schon wieder vom nächsten Datenpaket überschrieben.
    Vermute ich jedenfalls mal.

    Kannst ja einfach mal nen Zähler in die I2C ISR reinpacken und hochzählen wieviele Datenpakete tatsächlich IN DER ISR empfangen und in das Array geschrieben wurden.
    Den dann im Hauptprogramm neben einem zweiten Zähler für die Zahl der dort ausgewerteten Daten ausgeben lassen.


    In Dirks Programm oben wird übrigens noch gar nichts von den ganzen aufwändigen Sachen in der Lib ausser der Timer ISR ausgeführt - in den ganzen task_xxxxxx Funktionen wird die eigentliche Arbeit erledigt in der Timer ISR wird nur ein bisschen was mit RC5 Empfang gemacht und einige Flags für Software Timer gesetzt.
    Zum Testen kannst Du die natürlich deaktivieren (s. initRP6...() funktionen).


    > ISO-OSI Modell ... mit Fehlererkennung


    Ich denke es geht auch ein wenig einfacher, man muss ja nur die Rechenzeit / Pausen überbrücken in der das aktuelle "Datenpaket" (bei I2C werden eigentlich immer nur einzelne Register gesetzt oder gelesen) nicht vom Anwendungsprogramm aus den Registern abgeholt werden kann weils mit anderen Dingen beschäftigt ist.
    Echte Übertragungsfehler sollten beim I2C Bus eher nicht passieren.

    Als kleiner Denkanstoß - wenn denn tatsächlich viele Daten schnell hintereinander an den Slave geschickt werden müssen: man könnte es ggf. ähnlich wie beim UART Empfang über einen kleinen Ring Buffer lösen in den im Slave Modus die empfangenen Bytes geschrieben werden.
    Muss hier natürlich etwas anders aufgebaut werden da es ja zusammenhängende Datenpakete und nicht nur einzelne Zeichen sind...


    MfG,
    SlyD

    PS:
    Viele I2C Slaves brauchen eine ganze Weile um Befehle zu verarbeiten.
    Das ist eigentlich normal das man da nicht beliebig schnell hintereinander Befehle absetzen kann.
    Man kann aber mit einem Befehl viele Register (z.B. 32 Stück) in einer einzigen Übertragung setzen - probiert das doch bitte auch mal aus.
    Vorher natürlich I2CTWI_SLAVE_WRITE_REGISTERS entsprechend erhöhen.
    Hab ich damals sicherlich auch getestet, weiss ich aber nicht mehr.

Seite 2 von 7 ErsteErste 1234 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress