Hallo

Ich habe auch einen RA2, gesponsert von arexx. Es handelt sich allerdings um ein Versuchsgerät das teilweise nicht dem Auslieferstand entspricht. Da ich den Arm eh nach eigenen Vorstellungen zusammengebaut habe, kann ich zu den mechanischen Mängeln nichts sagen. Das ID-Problem hatte ich auch mit der Installation das aktuellen Loaders gelöst. Das Resetproblem umgehe ich mit einer langen Pause beim Programmstart. Erst nach dieser Pause aktiviere ich die Servos, weil ich den Verdacht habe, dass der Start der Servos erneut einen Reset auslöst. Flashprobleme treten bei mir nicht mehr auf, seit ich das Board mit 4X4000mA-Babyzellen versorge. Da mein Arm auf dem RP6 sitzt, habe ich erfolglos versucht, beide mit den Akkus des RP6 zu versorgen. Die nominalen 7,2V sind aber scheinbar zu wenig für den Spannungsregler auf der arm64-Platine. Selbst mit überbrückter D1 hatte das nicht funktioniert. Möglicherweise liegt das aber auch an den Akkus meines RP6, es ist immer noch der erste Satz den ich gnadenlos mit mit einem Steckernetzteil über Nacht nachlade ;)

Leider habe ich noch nicht viel damit angestellt. Mein Hauptproblem war die fehlende Erfahrung mit I2C. Da ich bisher keine Erweiterungsplatinen hatte, war das völliges Neuland für mich. Erste zaghafte Schritte waren die Anpassung der m32-Lib an das arm64 um den RP6 über I2C und und das RP6-Slave-Demo zu steuern:
Code:
// RA2 steuert RP6                                                   1.11.2010 mic

// Das I2C-Masterdemo6 des m32 angepasst an das arm64-Modul.
// Eine Ergänzung in der Abfrage des Keypads ermöglicht gleichzeitige Bewegungen
// aller Servos und des RP6.
// Auf dem RP6 läuft das unveränderte I2C-Slave-Demo.

// Verbindung zwischen RP6-XBUS Pin8(E_INT), Pin10(SCL), Pin12(SDA) und Pin14(GND)
// und IIC Pin 8-14 auf dem arm64. Beide Boards werden getrennt versorgt.

// PollSwitch16() liefert ein 16bit Abbild der Tasten
// scan_keyboard1() liefert die Tastennummer mit geänderter Portabfrage

// Infos zum Portexpander
// http://www.mikrocontroller.net/artic...pander_PCF8574

#include "RobotArmBaseLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"

#define I2C_RP6_BASE_ADR 10 // The default address of the Slave Controller (RP6)

/*****************************************************************************/
// 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');
}


/*****************************************************************************/
// Motor 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 );
}

#define CMD_MOVE 7

#define FWD 0
#define BWD 1

void RP6_move(uint8_t desired_speed, uint8_t dir, uint16_t ticks)
{
	transmit_buffer[0] = 0;
	transmit_buffer[1] = CMD_MOVE;
	transmit_buffer[2] = desired_speed;
	transmit_buffer[3] = dir;
	transmit_buffer[4] = ((ticks>>8) & 0xFF);
	transmit_buffer[5] = (ticks & 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, 30); // 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 < 30; 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 PollSwitch16(void)
{
	int i, j, mask=0, x=0;

	for(j=0; j<4; j++)
	{
		DDRA = (1<<j); 		// PAj auf Ausgang
		PORTA = ~(1<<j);		// PA7 bis PA4 ist Eingang mit Pullup, PAj ist LOW (Tilde!)
		sleep(10);           // Warten auf Pegel
		x=(PINA>>4);        	// Eingang PA7-4 wird zu Bit3-0 in x
		for(i=0; i<4; i++)   // Bits 0-3 überprüfen
			if(!(x & (1<<i))) // Wenn Eingang low ist wurde die Taste gedrückt
				mask += (1 << (i*4)) * (1<<j); // entsprechendes Bit in Maske setzen
	}
	PORTA = 0;              // Port A deaktivieren
	DDRA = 0;

	return(mask);
}

int scan_keyboard1(void)
{
	int i, mask = PollSwitch16();

	for(i=0; i<16; i++)     // wurde eine Taste gedrückt?
	{
	   if(mask & (1<<i))    // Taste i gedrückt?
	   {
		   if(mask & ~(1<<i))
	         return(0); 		// mehrere Tasten gleichzeitig gedrückt!
			else
			   return(i+1); 	// Tastennummer zurückgeben
		}
	}
	return(0);					// keine Taste gedrückt
}

int speed;
void Event( int x )
{
	if(x == 0)
	{
		if(PING & LED_GREEN) PowerLEDoff(); else PowerLEDgreen();
		mSleep(300);
	}
	else
	{
		PowerLEDred();
		//Power_Servos();
		if(x & (1<<0)) { Pos_Servo_1-=speed; Power_Servos();}
		if(x & (1<<1)) { Pos_Servo_1+=speed; }
		if(x & (1<<2)) { Pos_Servo_2+=speed; } // Drehrichtung invers!
		if(x & (1<<3)) { Pos_Servo_2-=speed; }
		if(x & (1<<4)) { Pos_Servo_3-=speed; }
		if(x & (1<<5)) { Pos_Servo_3+=speed; }
		if(x & (1<<6)) { Pos_Servo_4-=speed; }
		if(x & (1<<7)) { Pos_Servo_4+=speed; }
		if(x & (1<<8)) { Pos_Servo_5-=speed; Pos_Servo_6-=speed; }
		if(x & (1<<9)) { Pos_Servo_5+=speed; Pos_Servo_6+=speed; }
		if(x & (1<<10)) { PowerLEDorange(); speed=5; }
		if(x & (1<<11)) { PowerLEDorange(); speed=1; }
		if(x & (1<<12)) { RP6_rotate(35,BWD,40); }
		if(x & (1<<13)) { RP6_rotate(35,FWD,40); }
		if(x & (1<<14)) { RP6_rotate(35,RIGHT,40); }
		if(x & (1<<15)) { RP6_rotate(35,LEFT,40); }
	}
/*
	writeInteger(Pos_Servo_1, 10);
	writeString_P(" | ");
	writeInteger(Pos_Servo_2, 10);
	writeString_P(" | ");
	writeInteger(Pos_Servo_3, 10);
	writeString_P(" | ");
	writeInteger(Pos_Servo_4, 10);
	writeString_P(" | ");
	writeInteger(Pos_Servo_5, 10);
	writeString_P(" | ");
	writeInteger(Pos_Servo_6, 10);
	writeString_P("\n");
	*/
}
int  Batterie(void)
{
	#define BATTERIE 6
	ADMUX = (1 << REFS0) | (1 << REFS1) | BATTERIE;	// internal 2.56V reference with external capacitor
	ADCSRA |= (1 << ADSC);			// Start conversion
	while (!(ADCSRA & (1 << ADIF)));	// wait for conversion complete
	ADCSRA |= (1 << ADIF);			// clear ADCIF
	return ADCL + (ADCH << 8);
}

void printUBat(uint16_t ubat)
{
	writeIntegerLength((((ubat/204.8f)+0.1f)), DEC, 2);
	writeChar('.');
	writeIntegerLength((((ubat/2.048f)+10)), DEC, 2);
	writeChar('V');
}
int main(void)
{
	initRobotBase();
	PORTA = 0;              // Port A deaktivieren
	DDRA = 0;

	writeString_P("\n\nRA2 arm64 I2C Master Example Program!              3.11.2010 mic\n\n");
	int ubat = readADC(ADC_UBAT);
	printUBat(ubat);
	writeString_P("\n");
	

	// IMPORTANT:
	I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
							// with 100kHz SCL Frequency
	// Register the event handlers:
	I2CTWI_setTransmissionErrorHandler(I2C_transmissionError);

	//char counter = 1;

	//Start_position(); //Use this function to set the servomotor in the centre.
					  //This function must be called before using Power_Servos();

	speed=1; //Speed for servo from '1'(slow) - '10'(fast!)
   Pos_Servo_1=1500;
	Pos_Servo_2=1530;
	Pos_Servo_3=1100;
	Pos_Servo_4=1640;
	Pos_Servo_5=580;
	Pos_Servo_6=580;
	//Power_Servos();  //Use this function to power the servo motors on

	while(true)
	{
		Event(PollSwitch16());

/*
		if(scan_keyboard1())
		{
			writeInteger(scan_keyboard1(), 10);
			writeChar('\n');
			switch(0)
			{
				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;
			}
			while(scan_keyboard1());
		}
*/
	}
	return 0;
}
Außerdem mußte ich meine Tastenabfrage ändern, weil das Keypad nicht vollständig bestückt war:
http://www.arexx.com/forum/viewtopic.php?f=19&t=1179

Mein Arm ist nicht drehbar, dafür besitzt er die zwei gespiegelten Servos die ich noch rumliegen hatte:
https://www.roboternetz.de/phpBB2/vi...=462535#462535

Das Keypad und ein LCD betreibe ich inzwischen über I2C mit je einem PCF8574:
https://www.roboternetz.de/phpBB2/ze...=525681#525681

Mein RA2 auf dem RP6 sieht im Moment so aus:

Bild hier  
(Leider wie immer extrem unscharf)

Weiter bin ich nicht gekommen, denn dann bin ich über das Pong gestolpert. Und zur Zeit versuche ich den RP6 zu einer Ladestation zu locken. Es gibt noch viel zu erforschen ;)

Gruß

mic