PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 Slave und M32 Slave



fabqu
24.09.2011, 10:05
Hi!
Hab da noch mal eine Frage zum Thema Slaves.
Ich möchte, dass der RP6 auch die Werte der beiden ADCs und der I/Os (als Inputs verwendet) ins Register schreibt.
Habe folgendes im Slave-Beispiel:

/************************************************** ***************************/
// I2C Registers that can be read by the Master. Their names should
// be self-explanatory and directly relate to the equivalent variables/functions
// in the RP6Library

#define I2C_REG_STATUS1 0
#define I2C_REG_STATUS2 1
#define I2C_REG_MOTION_STATUS 2
#define I2C_REG_POWER_LEFT 3
#define I2C_REG_POWER_RIGHT 4
#define I2C_REG_SPEED_LEFT 5
#define I2C_REG_SPEED_RIGHT 6
#define I2C_REG_DES_SPEED_LEFT 7
#define I2C_REG_DES_SPEED_RIGHT 8
#define I2C_REG_DIST_LEFT_L 9
#define I2C_REG_DIST_LEFT_H 10
#define I2C_REG_DIST_RIGHT_L 11
#define I2C_REG_DIST_RIGHT_H 12
#define I2C_REG_ADC_LSL_L 13
#define I2C_REG_ADC_LSL_H 14
#define I2C_REG_ADC_LSR_L 15
#define I2C_REG_ADC_LSR_H 16
#define I2C_REG_ADC_MOTOR_CURL_L 17
#define I2C_REG_ADC_MOTOR_CURL_H 18
#define I2C_REG_ADC_MOTOR_CURR_L 19
#define I2C_REG_ADC_MOTOR_CURR_H 20
#define I2C_REG_ADC_UBAT_L 21
#define I2C_REG_ADC_UBAT_H 22
#define I2C_REG_ADC_ADC0_L 23
#define I2C_REG_ADC_ADC0_H 24
#define I2C_REG_ADC_ADC1_L 25
#define I2C_REG_ADC_ADC1_H 26
#define I2C_REG_RC5_ADR 27
#define I2C_REG_RC5_DATA 28
#define I2C_REG_LEDS 29


/**
* This very important function updates ALL registers that the Master can read.
* It is called frequently out of the Main loop.
*/
void task_updateRegisters(void)
{
if(!I2CTWI_readBusy)
{
I2CTWI_readRegisters[I2C_REG_STATUS1] = (uint8_t)(interrupt_status.byte);
I2CTWI_readRegisters[I2C_REG_STATUS2] = (uint8_t)(status.byte);
I2CTWI_readRegisters[I2C_REG_MOTION_STATUS] = (uint8_t)(drive_status.byte);
I2CTWI_readRegisters[I2C_REG_POWER_LEFT] = (uint8_t)(mleft_power);
I2CTWI_readRegisters[I2C_REG_POWER_RIGHT] = (uint8_t)(mright_power);
I2CTWI_readRegisters[I2C_REG_SPEED_LEFT] = (uint8_t)(getLeftSpeed());
I2CTWI_readRegisters[I2C_REG_SPEED_RIGHT] = (uint8_t)(getRightSpeed());
I2CTWI_readRegisters[I2C_REG_DES_SPEED_LEFT] = (uint8_t)(getDesSpeedLeft());
I2CTWI_readRegisters[I2C_REG_DES_SPEED_RIGHT] = (uint8_t)(getDesSpeedRight());
I2CTWI_readRegisters[I2C_REG_DIST_LEFT_L] = (uint8_t)(getLeftDistance());
I2CTWI_readRegisters[I2C_REG_DIST_LEFT_H] = (uint8_t)(getLeftDistance()>>8);
I2CTWI_readRegisters[I2C_REG_DIST_RIGHT_L] = (uint8_t)(getRightDistance());
I2CTWI_readRegisters[I2C_REG_DIST_RIGHT_H] = (uint8_t)(getRightDistance()>>8);
I2CTWI_readRegisters[I2C_REG_ADC_LSL_L] = (uint8_t)(adcLSL);
I2CTWI_readRegisters[I2C_REG_ADC_LSL_H] = (uint8_t)(adcLSL>>8);
I2CTWI_readRegisters[I2C_REG_ADC_LSR_L] = (uint8_t)(adcLSR);
I2CTWI_readRegisters[I2C_REG_ADC_LSR_H] = (uint8_t)(adcLSR>>8);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURL_L] = (uint8_t)(adcMotorCurrentLeft);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURL_H] = (uint8_t)(adcMotorCurrentLeft>>8);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURR_L] = (uint8_t)(adcMotorCurrentRight);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURR_H] = (uint8_t)(adcMotorCurrentRight>>8);
I2CTWI_readRegisters[I2C_REG_ADC_UBAT_L] = (uint8_t)(adcBat);
I2CTWI_readRegisters[I2C_REG_ADC_UBAT_H] = (uint8_t)(adcBat>>8);
I2CTWI_readRegisters[I2C_REG_ADC_ADC0_L] = (uint8_t)(adc0);
I2CTWI_readRegisters[I2C_REG_ADC_ADC0_H] = (uint8_t)(adc0>>8);
I2CTWI_readRegisters[I2C_REG_ADC_ADC1_L] = (uint8_t)(adc1);
I2CTWI_readRegisters[I2C_REG_ADC_ADC1_H] = (uint8_t)(adc1>>8);
I2CTWI_readRegisters[I2C_REG_LEDS] = (uint8_t)(statusLEDs.byte);
I2CTWI_readRegisters[I2C_REG_RC5_ADR] = (uint8_t)((lastRC5Reception.device)|(lastRC5Recept ion.toggle_bit<<5));
I2CTWI_readRegisters[I2C_REG_RC5_DATA] = (uint8_t)(lastRC5Reception.key_code);
if(I2CTWI_dataWasRead && I2CTWI_dataReadFromReg == 0)
clearInterrupt();
}
}

Kann ich hier einfach noch #define`s anfügen? Oder muss man dafür mehr machen? Was genau macht eigentlich folgende Zeilen:


I2CTWI_readRegisters[I2C_REG_ADC_ADC0_L] = (uint8_t)(adc0);
I2CTWI_readRegisters[I2C_REG_ADC_ADC0_H] = (uint8_t)(adc0>>8);
I2CTWI_readRegisters[I2C_REG_ADC_ADC1_L] = (uint8_t)(adc1);
I2CTWI_readRegisters[I2C_REG_ADC_ADC1_H] = (uint8_t)(adc1>>8);

Ebenso soll die M32 als Slave verwendet werden. Hier möchte ich alle ADCs auslesen...
Habe folgenden Code von Fabian E.:


/************************************************** ***************************/
// I2C Registers that can be read by the Master. Their names should
// be self-explanatory and directly relate to the equivalent variables/functions
// in the RP6Library

#define I2C_MICROPHONEPEAKLOW 0
#define I2C_MICROPHONEPEAKHIGH 1
#define I2C_BUTTON 2
#define I2C_ADC_2 3
#define I2C_ADC_3 4
#define I2C_ADC_4 5
#define I2C_ADC_5 6
#define I2C_ADC_6 7
#define I2C_ADC_7 8


/**
* This very important function updates ALL registers that the Master can read.
* It is called frequently out of the Main loop.
*/
void task_updateRegisters(void)
{
if(!I2CTWI_readBusy)
{
uint16_t mic = getMicrophonePeak();
I2CTWI_readRegisters[I2C_BUTTON] = (getPressedKeyNumber());
I2CTWI_readRegisters[I2C_MICROPHONEPEAKLOW] = (mic & 0x00ff);
I2CTWI_readRegisters[I2C_MICROPHONEPEAKHIGH] = (mic & 0xff00) >> 8;
I2CTWI_readRegisters[I2C_ADC_2] = (uint16_t)readADC(ADC_2);
I2CTWI_readRegisters[I2C_ADC_3] = (uint16_t)readADC(ADC_3);
I2CTWI_readRegisters[I2C_ADC_4] = (uint16_t)readADC(ADC_4);
I2CTWI_readRegisters[I2C_ADC_5] = (uint16_t)readADC(ADC_5);
I2CTWI_readRegisters[I2C_ADC_6] = (uint16_t)readADC(ADC_6);
I2CTWI_readRegisters[I2C_ADC_7] = (uint16_t)readADC(ADC_7);
if(I2CTWI_dataWasRead && I2CTWI_dataReadFromReg == 0)
clearInterrupt();
}
}

Hier werden auch wieder einige ADC (Nummern 2 bis 7 ) abgerufen, sind das schon die ADCs, die man selbst verwenden kann?
Wie kann ich hier den Rest der ADCs ( 8 sollten es ja sein) reinsetzen?

Tja, und dann kommt noch der Teil mit der M128, aber eins nach dem Anderen... :D

Sorry, ich glaube ich frage wieder mal totales Anfänger-Zeugs :( Aber danke schon mal für eure Hilfe!
Ich arbeite gerade an einer kompletten Fernsteuerung mit LabView und Fabian E.s Programmen. Ich hoffe, ich schaffe es auch, dass man den Robot dann via LabView in gewisse Routinen (Lichtverfolgung, Wärmequellen suchen mit SnakeVision, ...) bringen kann. Darüber hinaus soll man eben auch alle ADCs, I/Os etc verwenden können. Wenns soweit ist, kann ichs ja mal posten.

Grüße!
Fabian

danimath
24.09.2011, 18:25
Moin Fabian,

die Werte der beiden ADCs stehen schon im readReg-Feld. Das sind die vier Werte ab Index I2C_REG_ADC_ADC0_L.

Du kannst mehr Werte anfügen, indem Du noch defines an die Liste anhängst, ABER: die sollten die Länge des Feldes I2CTWI_readRegisters nicht überschreiten. Die ist in der RP6-Lib definiert (ich glaube 48, bin aber nicht ganz sicher) .

Die beiden ADC-Variablen sind als uint16_t (als zwei Byte lang) definiert, das readReg-Feld besteht aber aus unit8_t (ein Byte). Mit den vier Befehlen, nach denen Du fragst, wird ein zwei-Byte-Wert in zwei Ein-Byte-Werte geschrieben.

Warum willst Du die M32 als slave benutzen? Das Teil ist viel leistungsfähiger als die Base. (Ich habe gerade ein Programm laufen, in dem die Base nur die Steuerung und das Ausweichen übernimmt, und die M32 dann ein paar Werte auf dem Display anzeigt. Später soll dann die M32 noch weitere Aufgaben übernehmen.


Sorry, ich glaube ich frage wieder mal totales Anfänger-Zeugs.

Ja und? Wir haben doch alle mal angefangen ;) Wer nicht fragt, bleibt auch Anfänger :p

viele Grüße
Andreas

fabqu
24.09.2011, 20:27
Danke Dir :D
Ich wollte ursprünglich noch die M128 draufsetzen, aber ich glaube ich machs jetzt erst mal einfacher:
Ich nehme nun doch nur die Base als Slave und die M32 als Master. Die M128 lasse ich weg, weil ich einfach nicht durchblicke, was ich noch alles verändern müsste.

Die Base hat 4 I/Os, 2 ADCs. Ich möchte die ADC-Werte (genauer Wert) und zwei der I/O-Werte (1 oder 0) auf den I2C schreiben.
Die M32 soll diese beiden ADC-Werte der Base, die beiden I/O-Werte der Base auslesen und via Bluetooth senden.
Außerdem soll die M32 die beiden übrigen I/Os der Base an-/aus- schalten können.
Außerdem soll die M32 alle 6 eigenen ADC-Werte (genaue Werte, nicht nur high und low) via Bluetooth senden, die 8 I/Os der M32 verwende ich komplett für Servos.

Für die Base liegt der Code zum Register oben, hier muss ich wohl noch die beiden I/Os, die ich auslesen will, anfügen. Aber wo muss ich die I/Os anfügen, die ich schalten will? Sie müssen ja von der M32 aus geschaltet werden.

Der Code für das Auslesen der Rigister von der M32 ist hier:


/************************************************** ***************************/
// Sensors/ADCs:

// ADCs:
uint16_t adcBat;
uint16_t adcMotorCurrentLeft;
uint16_t adcMotorCurrentRight;
uint16_t adcLSL;
uint16_t adcLSR;
uint16_t adc0;
uint16_t adc1;

// Measured Speed:
uint8_t mleft_speed;
uint8_t mright_speed;

// Distance
uint16_t mleft_dist;
uint16_t mright_dist;

// Desired Speed:
uint8_t mleft_des_speed;
uint8_t mright_des_speed;

// Power
uint8_t mleft_power;
uint8_t mright_power;

uint8_t sensorBuf[24];

/**
* In order to use the same register names as in the RP6Lib, this
* function reads all ADC channels and all motor parameters into
* the same values as in the RP6Lib.
* Of course this function needs some time to read all these
* 24 registers via the I2C Bus.
*/
void getAllSensors(void)
{
I2CTWI_readRegisters(I2C_RP6_BASE_ADR, I2C_REG_POWER_LEFT, sensorBuf, 24);
mleft_power = sensorBuf[0];
mright_power = sensorBuf[1];
mleft_speed = sensorBuf[2];
mright_speed = sensorBuf[3];
mleft_des_speed = sensorBuf[4];
mright_des_speed = sensorBuf[5];
mleft_dist = sensorBuf[6] + (sensorBuf[7]<<8);
mright_dist = sensorBuf[8] + (sensorBuf[9]<<8);
adcLSL = sensorBuf[10] + (sensorBuf[11]<<8);
adcLSR = sensorBuf[12] + (sensorBuf[13]<<8);
adcMotorCurrentLeft = sensorBuf[14] + (sensorBuf[15]<<8);
adcMotorCurrentRight = sensorBuf[16] + (sensorBuf[17]<<8);
adcBat = sensorBuf[18] + (sensorBuf[19]<<8);
adc0 = sensorBuf[20] + (sensorBuf[21]<<8);
adc1 = sensorBuf[22] + (sensorBuf[23]<<8);
}

/**
*
*/
void getLightSensors(void)
{
I2CTWI_readRegisters(I2C_RP6_BASE_ADR, I2C_REG_ADC_LSL_L, sensorBuf, 4);
adcLSL = sensorBuf[0] + (sensorBuf[1]<<8);
adcLSR = sensorBuf[2] + (sensorBuf[3]<<8);
}



Und hier der Code für die M32, für das Senden der Daten über RS232:


void printSensors(void)
{
if(sendData)
{
StartDataFrame();

if(HasRP6)
{
writeString_P("Bat:");
writeInteger(adcBat, DEC);
writeString_P("\n");

writeString_P("SpeedL:");
writeInteger(mleft_speed, DEC);
writeString_P("\n");

writeString_P("SpeedR:");
writeInteger(mright_speed, DEC);
writeString_P("\n");

writeString_P("PowerL:");
writeInteger(adcMotorCurrentLeft, DEC);
writeString_P("\n");

writeString_P("PowerR:");
writeInteger(adcMotorCurrentRight, DEC);
writeString_P("\n");

writeString_P("LightL:");
writeInteger(adcLSL, DEC);
writeString_P("\n");

writeString_P("LightR:");
writeInteger(adcLSR, DEC);
writeString_P("\n");

writeString_P("BumpL:");
writeInteger(bumper_left, DEC);
writeString_P("\n");

writeString_P("BumpR:");
writeInteger(bumper_right, DEC);
writeString_P("\n");

writeString_P("ObsL:");
writeInteger(obstacle_left, DEC);
writeString_P("\n");

writeString_P("ObsR:");
writeInteger(obstacle_right, DEC);
writeString_P("\n");
}

if(HasSRF02)
{
writeString_P("Distance:");
writeInteger(SRF02_Dist, DEC);
writeString_P("\n");
}

if(HasM32)
{
writeString_P("Mic:");
writeInteger(getMicrophonePeak(),DEC);
writeString_P("\n");
}
EndDataFrame();
}
}

void SendDebugData(void)
{
if (getStopwatch1() >=timeBetweenFrames)
{
getAllSensors();
getLightSensors();
printSensors();
setStopwatch1(0);
}
}

Und ich glaube das hier ist der Code, der die PC-Befehle empfängt und verarbeitet (in der M32):


void task_Commands(void)
{
if(getBufferLength())
{
char tmp = readChar();
if (tmp =='#')
{
mSleep(10);
counter = 0;
}
text[counter] = tmp;
text[counter + 1] = '\0';
counter++;
clearPosLCD(1,0,15);
setCursorPosLCD(1,0);
writeStringLCD(text);
}
int cmd = getCommand();
if(cmd)
{
switch(cmd)
{
case CMD_SET_SPEED:
moveAtSpeed(params[1],params[2]);
changeDirection(params[3]);
break;
case CMD_SET_SERVO:
servo_position[params[2]] = params[3];
break;
case CMD_SET_LEDS:
switch(params[1])
{
case LEDS_RP6:
setRP6LEDs(params[2]);
break;
case LEDS_M32:
setLEDs(params[2]);
break;
}
break;
case CMD_SET_BEEP:
beep(params[2],params[3]);
break;
case CMD_SET_START_MELODY:
{
uint8_t ToneCount = params[1];
uint8_t currCount = params[2];
uint8_t currPitch = params[3];
uint16_t currTime = params[4];
SPI_EEPROM_writeByte(3,ToneCount);
while(SPI_EEPROM_getStatus() & SPI_EEPROM_STAT_WIP);
uint8_t buffer[3];
buffer[0] = currPitch;
buffer[1] = currTime & 0x00ff;
buffer[2] = (currTime & 0xff00) >>8;
SPI_EEPROM_writeBytes(4+((currCount-1)*3),buffer,3);
while(SPI_EEPROM_getStatus() & SPI_EEPROM_STAT_WIP);
if(ToneCount == currCount)
{
SPI_EEPROM_writeByte(0,8); //Die Checkbytes schreiben
SPI_EEPROM_writeByte(1,12);
SPI_EEPROM_writeByte(2,91);
}
}
break;
case CMD_SET_FEATURE:
switch(params[1])
{
case SET_FEATURE_RP6:
HasRP6 = params[2];
break;
case SET_FEATURE_M32:
HasM32 = params[2];
break;
case SET_FEATURE_SERVOM32:
HasServoM32 = params[2];
break;
case SET_FEATURE_LCDM32:
HasLCDM32 = params[2];
break;
case SET_FEATURE_SRF02:
HasSRF02 = params[2];
break;
case SET_FEATURE_SRF02_1:
HasSRF02_1 = params[2];
break;
case SET_FEATURE_SRF02_2:
HasSRF02_2 = params[2];
break;
case SET_FEATURE_SRF08:
HasSRF08 = params[2];
break;
}
break;
case CMD_SET_STOP: stop();
break;
case CMD_SET_CONNECTION_SPEED:
if(params[1] < 0)
{
sendData = 0;
timeBetweenFrames = 1000;
}
else
{
sendData = 1;
timeBetweenFrames = params[1];
}
break;
case CMD_SET_MELODY:
{
int current;
int all;
int currTime;
int currPitch;
current = params[1];
all = params[2];
currTime = params[3];
currPitch = params[4];
if((current >= 0 && current < 100) || current == -99)
{
if(current == -99)
{
PlayMelody(all);
return;
}
MelodyTimes[current] = currTime;
MelodyPitches[current] = currPitch;

}
else
{
StartDebugFrame();
writeString_P("Ton-Counter ist falsch!Counter: ");
writeInteger(current,DEC);
EndDebugFrame();
}
}
break;
case CMD_SET_ACSPOWER:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_ACS_POWER, params[1]);
break;
case CMD_SET_TEST:
switch(params[1])
{
case TEST_LCD:
TestLCD();
break;
case TEST_BEEPER:
TestBeeper();
break;
case TEST_LED:
TestLEDs();
break;
case TEST_EXTERNAL_MEMORY:
TestExternalMemory();
break;
case TEST_I2CLED:
TestI2CLEDs();
break;
case TEST_I2CMOTOR:
TestI2CMotor();
break;
case TEST_MIC:
TestMic();
break;
}
break;
}
cmd= 0;
}
}

Was muss ich denn jetzt hier machen?
Sorry, ist wohl echt viel Zeugs...
Aber danke Euch schon mal für Eure Hilfen!

Grüße,
Fabian

Dirk
25.09.2011, 14:40
@fabqu:
Die I/Os müßten alle in statusLEDs.byte, also im "Register" 29 (I2C_REG_LEDS) zu finden sein, so dass du alle I/Os ohne Änderung des I2C-Slave Programms der Base lesen kannst.
Auch das Ansteuern der I/Os der Base über I2C von der M32 klappt ohne Änderungen über den Befehl CMD_SETLEDS z.B. so: I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SETLEDS, irgendwas);

fabqu
25.09.2011, 15:30
Ah, danke. Schon mal klasse, die ADCs und I/Os der Base sind dann ja schon alle dort, wo ich sie haben will. Ich muss die daten nur noch an den PC schicken, ist aber kein Problem, sollte ja gehen mit Code wie diesem:

writeString_P("ObsR:");
writeInteger(obstacle_right, DEC);
writeString_P("\n");

Ich baue das mal ein und versuche auch die Befehle zum Schalten der Base-I/Os via PC einzubauen. Wenns nicht klappt (bestimmt kalppts bei mir nicht), würd ich mich heut noch mal an Euch Profis wenden :D

Grüße und Danke

fabqu
25.09.2011, 18:16
So :D
Soweit hat alles geklappt!!! Ich sende die Daten mit dem unteren Code.
Nur die I/Os der Base fehlen noch, die wusste ich nicht, wie ich die ordentlich einbinden soll.
Vielleicht gibts da noch nen Tip von Euch?!?


void printSensors(void)
{
if(sendData)
{
StartDataFrame();

if(HasRP6)
{
writeString_P("Bat:");
writeInteger(adcBat, DEC);
writeString_P("\n");

writeString_P("SpeedL:");
writeInteger(mleft_speed, DEC);
writeString_P("\n");

writeString_P("SpeedR:");
writeInteger(mright_speed, DEC);
writeString_P("\n");

writeString_P("PowerL:");
writeInteger(adcMotorCurrentLeft, DEC);
writeString_P("\n");

writeString_P("PowerR:");
writeInteger(adcMotorCurrentRight, DEC);
writeString_P("\n");

writeString_P("LightL:");
writeInteger(adcLSL, DEC);
writeString_P("\n");

writeString_P("LightR:");
writeInteger(adcLSR, DEC);
writeString_P("\n");

writeString_P("BumpL:");
writeInteger(bumper_left, DEC);
writeString_P("\n");

writeString_P("BumpR:");
writeInteger(bumper_right, DEC);
writeString_P("\n");

writeString_P("ObsL:");
writeInteger(obstacle_left, DEC);
writeString_P("\n");

writeString_P("ObsR:");
writeInteger(obstacle_right, DEC);
writeString_P("\n");

writeString_P("ADC0_Base:");
writeInteger(adc0, DEC);
writeString_P("\n");

writeString_P("ADC1_Base:");
writeInteger(adc1, DEC);
writeString_P("\n");

writeString_P("ADC2_M32:");
writeInteger(ADC_2, DEC);
writeString_P("\n");

writeString_P("ADC3_M32:");
writeInteger(ADC_3, DEC);
writeString_P("\n");

writeString_P("ADC4_M32:");
writeInteger(ADC_4, DEC);
writeString_P("\n");

writeString_P("ADC5_M32:");
writeInteger(ADC_5, DEC);
writeString_P("\n");

writeString_P("ADC6_M32:");
writeInteger(ADC_6, DEC);
writeString_P("\n");

writeString_P("ADC7_M32:");
writeInteger(ADC_7, DEC);
writeString_P("\n");

}

if(HasSRF02)
{
writeString_P("Distance:");
writeInteger(SRF02_Dist, DEC);
writeString_P("\n");
}

if(HasM32)
{
writeString_P("Mic:");
writeInteger(getMicrophonePeak(),DEC);
writeString_P("\n");
}
EndDataFrame();
}
}

Und noch eine Sache: Habe gerade die Daten mit hterm angesehen. Zum Die ADCs der M32 sind momentan LEER, da hängt nichts dran, ebenso der ADC1 der Base. Am ADC0 der Base ist ein Sharp-Abstandsmodul.
Das seltsame: Die Werte, die ich für die ADCs 2 bis 7 der M32 erhalte entsprechen je ihrer Nummer, der ADC1 der Base ist immer gleich mit dem ADC0 der Base:


ADC0_Base:82<\n>ADC1_Base:83<\n>ADC2_M32:2<\n>ADC3_M32:3<\n>ADC4_M32:4<\n>ADC5_M32:5<\n>ADC6_M32:6<\n>ADC7_M32:7

Stimmt da was nicht?

Grüße

Dirk
25.09.2011, 19:53
Zu den I/Os:
Wenn du die RP6Control_I2CMasterLib verwendest, werden ja die Register 27..29 nicht gelesen.
Du könntest das Register 29 über I2C allein in ein Byte einlesen und mit writeInteger(Byte, BIN); binär anzeigen. Dann müßten die I/O-Zustände (1/0) der Bumper bzw. I/O1..4 gut erkennbar sein.

ADC0/1 der Base:
Probier mal, ADC1 der Base auf GND oder +5V zu legen. Dann müßte der Wert 0 bzw. 1023 richtig angezeigt werden.

fabqu
25.09.2011, 21:35
Du meinst den Teil "void getAllSensors(void)", oder?
Dort müsste ich dann die beiden I/Os, die ich als Eingänge haben möchte, anfügen.
Die meisten ADCs werden dort in zwei Buffereinträge geschrieben. (Warum?)
Aber wie genau meinst du das mit "allein in ein Byte"?
Meinst du sowas wie "InOut=sensorBuf[29]"? Dort steht ja dann so was wie 0100 (LED 2 an) !?
Wenns so ist, dann ists einfach.

Zu Den ADCs der M32: Sie zeigen wieder nur ihre nummer an, auch bei +5V oder Gnd am ADC.
Aber ich finde den Fehler grad nicht, Code siehe oben, mein letzter Beitrag, die untersten "writeString"-Einträge
Das Ergebnis ist das gleiche, wenn ich im oberen Code folgendes eingebe:

writeString_P("ADC2_M32:");
writeInteger(readADC(2), DEC);
writeString_P("\n");

usw für die anderen ADCs.

Grüße

danimath
26.09.2011, 09:22
Die meisten ADCs werden dort in zwei Buffereinträge geschrieben. (Warum?)


Die ADCs werden mit 10 Bit aufgelöst - d.h.: Du hast zwischen min- und max-Wert (0V und 5V) 1024 Abstufungen. 10 Bit passen aber nicht in eine 8-Bit-Variable, deshalb werden zwei 8-Bit-Variablen (bzw. ein 2-Byte-Variable) dafür vorgesehen.

viele Grüße
Andreas

Dirk
27.09.2011, 17:58
Aber wie genau meinst du das mit "allein in ein Byte"? Meinst du sowas wie "InOut=sensorBuf[29]"?
Wenn du die RP6Control_I2CMasterLib verändern willst, könntest du die Funktion getAllSensors() so ändern:

void getAllSensors(void)
{
I2CTWI_readRegisters(I2C_RP6_BASE_ADR, I2C_REG_POWER_LEFT, sensorBuf, 27);
mleft_power = sensorBuf[0];
mright_power = sensorBuf[1];
mleft_speed = sensorBuf[2];
mright_speed = sensorBuf[3];
mleft_des_speed = sensorBuf[4];
mright_des_speed = sensorBuf[5];
mleft_dist = sensorBuf[6] + (sensorBuf[7]<<8);
mright_dist = sensorBuf[8] + (sensorBuf[9]<<8);
adcLSL = sensorBuf[10] + (sensorBuf[11]<<8);
adcLSR = sensorBuf[12] + (sensorBuf[13]<<8);
adcMotorCurrentLeft = sensorBuf[14] + (sensorBuf[15]<<8);
adcMotorCurrentRight = sensorBuf[16] + (sensorBuf[17]<<8);
adcBat = sensorBuf[18] + (sensorBuf[19]<<8);
adc0 = sensorBuf[20] + (sensorBuf[21]<<8);
adc1 = sensorBuf[22] + (sensorBuf[23]<<8);
leds = sensorBuf[26];
}
Dann stehen die I/Os in der Variablen leds (global als uint8_t definieren!).


Dort steht ja dann so was wie 0100 (LED 2 an) !?
Genau.

fabqu
28.09.2011, 11:16
Danke dir.
Er kompiliert zwar, bringt aber folgenden Fehler:
[code]Compiling: ../../Library/RP6control/RP6Control_I2CMasterLib.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=../../Library/RP6control/RP6Control_I2CMasterLib.lst -I../../Library -I../../Library/RP6control -I../../Library/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Control_I2CMasterLib.o.d ../../Library/RP6control/RP6Control_I2CMasterLib.c -o ../../Library/RP6control/RP6Control_I2CMasterLib.o
../../Library/RP6control/RP6Control_I2CMasterLib.c: In function 'getAllSensors':
../../Library/RP6control/RP6Control_I2CMasterLib.c:172: warning: array subscript is above array bounds[\code]


Was kann ich denn gegen das ADC-Problem auf der M32 machen?
Wie schreibe ich deren Werte in zwei Buffer?

Grüße

radbruch
28.09.2011, 11:20
uint8_t sensorBuf[24];

sensorBuf[] ist nicht groß genug für leds = sensorBuf[26];

fabqu
28.09.2011, 12:25
ahh, klar. Danke !!!
Das hab ich Vergessen :|

Und die ADC-Sache?

fabqu
01.12.2011, 10:34
Hi!
Ich möchte gerade die ADCs der M128 via BT senden.
Habe dafür folgendes im Manual gefunden:

Syntax
word ADC_Set(byte v_ref,byte channel);
Sub ADC_Set(v_ref As Byte,channel As Byte) As Word
Beschreibung
Die Funktion ADC_Set initialisiert den Analog-Digital_Wandler. Die Referenzspannung und der Messkanal
werden ausgewählt, und der A/D Wandler für die Messungen vorbereitet. Der Meßwert wird danach mit
ADC_Read() ausgelesen.
Parameter
channel Portnummer (0..7) des ADC (Port A.0 bis A.7 bei Mega32, Port F.0 bis F.7 bei
Mega128)
v_ref Referenzspannung (siehe Tabelle)

Ich mache das mit Fabian E.'s Code:


print("Bat:");
printInteger(adcBat);
print("\n");
oldBat = adcBat;


Daher, denke ich, muss es dann folgendermaßen aussehen:


ADC_Set(ADC_VREF_VCC,0)
print("ADC0_M128:");
printInteger(ADC_Read(void));
print("\n");


Leider kommt da nix bei mir an...

Vg,
Fabian

Dirk
01.12.2011, 17:37
Was ist "nix"? Null?
Was hast du an PF0 (ADC-Stecker Pin 4) angeschlossen?

fabqu
01.12.2011, 17:49
Gar nix:
#*#*#

PowerL:3
LightL:887
LightR:875


PowerL:4
LightL:886
LightR:874
Temp:2469

Code ist wie oben, erst et, dann print(read).

fabqu
02.12.2011, 10:02
mit den Status LEDs der Base klappts auch nicht:


print("LEDs_Base:");
printInteger(I2C_REG_LEDS);
print("\n");

fabqu
02.12.2011, 17:12
Also das mit den LEDs klappt! Doofer fehler.
Aber wie lese ich denn vernünftig die ganzen ADCs der M128 aus und sende sie?

Vg

SlyD
03.12.2011, 10:54
> printInteger(ADC_Read(void));

void übergibt man i.d.R. nicht - das ist nur nen platzhalter bei der Deklaration von Funktionen und steht für NIX.
Aber das nur nebenbei.


Teste es doch einfach mal mit dem Beispielprogramm Example_03_IO_Threads
Da werden alle ADCs ausgelesen (den Start Taster paar mal drücken!).


MfG,
SlyD

fabqu
03.12.2011, 13:17
Danke dir, hab das mal gemacht:


char tmp[16];
word result;

ADC_Set(ADC_VREF_VCC,0); // Kanal wählen...
Thread_Delay(25); // ... warten ...
result = ADC_Read(); // ... und auslesen.

// Messwert ausgeben:
print("ADC_M128(0): ");
Str_WriteInt(result,tmp,0);
Serial_WriteText(0,tmp);
print("\n");

ADC_Set(ADC_VREF_VCC,7); // Kanal wählen...
Thread_Delay(25); // ... warten ...
result = ADC_Read(); // ... und auslesen.

// Messwert ausgeben:
print("ADC_M128(7): ");
Str_WriteInt(result,tmp,0);
Serial_WriteText(0,tmp);
print("\n");


erste Frage: Was soll das tmp[16]?
Zweite: Wo kann ich das Setzen des ADCs (ADC_Set(ADC_VREF_VCC,0) ) und das thread_delay sonst hintun?
Ich brauche ja nach dem ADC-anschalten etwas Zeit, um die Messung abzuwarten... oder kann man das einfach rauslassen?

SlyD
03.12.2011, 13:58
> Was soll das tmp[16]?

für den String.
Ist lange lange her aber ich glaube der Code wurde geschrieben bevor es eine Funktion printInteger in der RP6CCLib gab.
Die macht natürlich das gleiche.


> Wo kann ich das Setzen des ADCs (ADC_Set(ADC_VREF_VCC,0) ) und das thread_delay sonst hintun?

Da wo es in Deinem Programm hinpasst?!
;-)

Auf der CCPRO Unit kannst Du - wie das Beispielprogramm auch zeigt - Multithreading benutzen d.h. während des Delays können andere Threads laufen.

MfG,
SlyD

fabqu
03.12.2011, 15:34
Aber bei mir geht das leider nicht richtig, seit ich oben gezeigte Codezeilen drin hab, stockt das Programm ziemlich und der RP6 reagiert nur noch langsam.
Habe es gerade ganz ohne Delay gemacht, klappt wunderbar ;)

Grüße

fabqu
04.12.2011, 12:43
So, jetzt gibts ein neues Problem.
Ich habe nun zum Register, das die M128 ausließt, die Base-LED-Zustände hinzugefügt sowie die Adresse und den Tastencode von RC5-Daten:

void getAllSensors(void)
{
RP6_readRegisters(RP6_BASE_ADR, I2C_REG_POWER_LEFT, messageBuf, 27);
mleft_power = messageBuf[0];
mright_power = messageBuf[1];
mleft_speed = messageBuf[2];
mright_speed = messageBuf[3];
mleft_des_speed = messageBuf[4];
mright_des_speed = messageBuf[5];
mleft_dist = messageBuf[6] + (messageBuf[7]<<8);
mright_dist = messageBuf[8] + (messageBuf[9]<<8);
adcLSL = messageBuf[10] + (messageBuf[11]<<8);
adcLSR = messageBuf[12] + (messageBuf[13]<<8);
adcMotorCurrentLeft = messageBuf[14] + (messageBuf[15]<<8);
adcMotorCurrentRight = messageBuf[16] + (messageBuf[17]<<8);
adcBat = messageBuf[18] + (messageBuf[19]<<8);
adc0 = messageBuf[20] + (messageBuf[21]<<8);
adc1 = messageBuf[22] + (messageBuf[23]<<8);
RC5_adr = messageBuf[24];
RC5_data = messageBuf[25];
status_leds_base = messageBuf[26];
}

Und genau dort muss ein Fehler liegen, irgendwie beim Registerlesen von den RC5-Daten. Genauer, bei Auslesen von RC5_adr. Denn wenn ich diese Zeile rausnehme, läuft mein Programm wunderbar. Habe ich diese Zeile drinnen, kommt mein Programm gerne ins stocken. Um genau zu sein, geht alles gut,bis ich einen Fahrbefehl rausgebe. Solange der RP6 sich bewegt, dauert es locker drei-vier Sekunden, bis das ACS Objekte erkennt bzw. erkennt, dass sie nicht mehr da sind.

Wär schön zu wissen, was da schief läuft...

Danke Euch