PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frage zum Thema RP6 Base erweitert mit Control m32



Roandl
14.03.2012, 16:52
Hi

Hab seit kurzen mit die Erweiterung Control M32 gekauft und gleich mit der RP6 Base erweitert.
Hab ein bissal mit Master und Slave Programme experiementiert und kamm immer auf den selben Fehler.
Wenn ich mein Programm ausführen will macht er nur ein Teil und dann Stoppt er von selber.

z.B. er bewegt den Servo nur zur Mittelstellung und beendet das Programm, obwohl des Programm noch weiter geht.

Schreibt dann im Terminal [RP6BOOT], [READY] obwohl ich ihn nicht gestoppt habe.

Dieses Problem ist aber nicht bei jeder Funktion nur bei paar bestimmten.

Danke für die Hilfe
Roandl




Programm hier:


#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, 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...
*/


uint8_t Datenaustausch[4]; // temporary transmit buffer
// A global variable saves space on the heap...

#define MOVE_AT_SPEED 5



/**
* 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_moveAtSpeed(uint8_t leftspeed, uint8_t rightspeed)
{
Datenaustausch[0] = 0;
Datenaustausch[1] = MOVE_AT_SPEED;
Datenaustausch[2] = leftspeed;
Datenaustausch[3] = rightspeed;

I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, Datenaustausch, 4 );
}




void ADC1(void)
{

uint8_t adc1[2];

I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 25);
I2CTWI_readBytes(I2C_RP6_BASE_ADR, adc1, 2);

writeString_P("ADC1:\n");
writeInteger(adc1[0], DEC);
writeInteger(adc1[1], DEC);
writeString_P("\n");
writeString_P("ADC1 Kanal:"); writeInteger(adc1[0] + (adc1[1]<<8), DEC);
writeString_P("\n");

setCursorPosLCD(1, 11);
writeIntegerLengthLCD(adc1[0] + (adc1[1]<<8), DEC, 3);

}

uint8_t Schaltbefehl[4];


#define INT1_SET_H 13
#define INT1_SET_L 14


void Relaisplatine(void)
{
Schaltbefehl[0] = 0;
Schaltbefehl[1] = INT1_SET_H;

I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, Schaltbefehl, 2 );

mSleep(2000);

Schaltbefehl[0] = 0;
Schaltbefehl[1] = INT1_SET_L;

I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, Schaltbefehl, 2 );
}

uint8_t ServobefehlR[2];


#define SERVO_RECHTSLAUF 15


void Servo_Rechtslauf(void)
{



ServobefehlR[0] = 0;
ServobefehlR[1] = SERVO_RECHTSLAUF;

I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, ServobefehlR, 2 ); // Impulsstart


}

uint8_t ServobefehlL[2];


#define SERVO_LINKSLAUF 16

void Servo_Linkslauf(void)
{


ServobefehlL[0] = 0;
ServobefehlL[1] = SERVO_LINKSLAUF;

I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, ServobefehlL, 2 ); // Impulsstart



}

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_transmissio nError);

// 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!



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("ADC1", "KANAL:");
ADC1();
break;
case 2: // Read and display ALL registers of the slave controller:
setLEDs(0b0010);
showScreenLCD("Servo", "Steuerfunktion");
Servo_Linkslauf();
break;
case 3: // Read the light sensors and show value on display:
setLEDs(0b0100);
showScreenLCD("Servo", "Steuerfunktion");
Servo_Rechtslauf();
break;
case 4: // Rotate a very small distance to the left:
setLEDs(0b1000);
showScreenLCD("Fahren", "TEST");
RP6_moveAtSpeed(70,70);
break;
case 5: // Rotate a very small distance to the right:
setLEDs(0b1001);
showScreenLCD("Relaisplatine", "Schaltfunktion");
Relaisplatine();
break;
}
}
}
return 0;
}

SlyD
15.03.2012, 16:03
Hallo,

wie und wo hast Du den Servo an die Versorgungsspannung angeschlossen?
(Tipp: Nutze die Suchfunktion im RP6 Forum - da gibt es sehr viele Threads zum Thema Servos).

Kann natürlich auch irgendwo in dem Code ein Fehler sein - kannst Du leicht testen indem Du den Servo Stecker mal abziehst und schaust ob das Programm dann fehlerfrei läuft.

MfG,
SlyD

Roandl
15.03.2012, 16:23
Hi Danke für die schnelle Antwort.

Hab den Servo am ADC0 auf der RP6Base angeschlossen siehe Bild.
21825

Kommt mir irgendwie so vor das es dem Control m32 zuviel wird und dann einfach abschaltet.

Wenn ich die Standart Beispielprogramme Master Slave in die Base und dem Control m32 lade läuft er ohne Probleme.
Auch wenn der Servo angesteckt ist.

Roandl
15.03.2012, 16:43
Hab jetzt des Programm für den RP6Base (Slave) umgeschrieben.

Ausschnitt vom Programm.

uint8_t y;
uint8_t x=6;
uint8_t v;

void Servo_Linkslauf(void)
{

while(v<=18)
{

for(y=0; y<15; y++) // 100 Impulse senden, das dauert ca. 1 Sekunde
{
PORTA |= ADC0; // Impulsstart
sleep(x); // 1,2ms warten = Servoposition 1
PORTA &= ~ADC0; // Impulsende
sleep(80); // 19ms warten
}

if (x<=24)
{
x++;
}

v++;
}

x=6;
v=0;
}

uint8_t w;
uint8_t z=24;
uint8_t u;

void Servo_Rechtslauf(void)
{

while(u<=18)
{

for(w=0; w<15; w++) // 100 Impulse senden, das dauert ca. 1 Sekunde
{
PORTA |= ADC0; // Impulsstart
sleep(z); // 1,2ms warten = Servoposition 1
PORTA &= ~ADC0; // Impulsende
sleep(80); // 19ms warten
}

if (z>=6)
{
z--;
}

u++;
}

z=24;
u=0;

}

Macht seine Läufe jetzt normal aber er schaltet sich ab wenn ich zwei mal Rechtslauf mach. Wenn er also wieder in seine Anfangsstellung laufen muss um den Rechtslauf wieder zu beginnen.

Danke für Antworten

Roandl

SlyD
15.03.2012, 16:45
Abschalten tut sich da nichts, es wird ein RESET ausgelöst da die Spannung kurz einbricht wenn der Servo viel Strom zieht.
(oder in Deinem Programm büchst irgendwo ein Pointer aus und er springt in den Bootloader aber ich vermute es liegt an dem Servo)

Da ist ja schon immerhin ein Elko (Kapazität?).
Empfohlen ist jedoch eine Induktivität/Drossel in serie und dahinter dann der Elko parallel, damit das auch tatsächlich eine gute Filterwirkung hat.
Such im Forum nach LC Tiefpass Filter und Servos.

Check auch bitte Deine Akkus - sind die noch in Ordnung?
(nicht nur die Spannung anschauen sondern auch vom Alter und allgemeinem Zustand her, alle Zellen grob balanciert und nicht eine einzelne zu schwach?)


MfG,
SlyD

PS:
Nutze bitte Code Tags wie Radbruch es oben schon für Dich editiert hatte.

Roandl
15.03.2012, 17:03
Danke für die Antwort werd meine Akkus mal überprüfen, hab auch festgestellt das die Hintergrundbeleuchtung vom LCD Display bei jeder Servo bewegung schwach wird.

Ja alles klar benutzt ich nächstes mal.#

Roandl