PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] strukturen, ein- und ausstieg



inka
07.07.2013, 16:18
ich versuche mir eine teststruktur für software-varianten aufzubauen:


#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_MultiIOLib.h"
#include "RP6Control_I2CMasterLib.h"
#include "RP6Control_MultiIO.h"
#include "RP6ControlServoLib.h"

#define I2C_RP6_BASE_ADR 10


uint16_t servopos;
uint8_t i;
uint8_t taste;

/*********************I2C-fehlermeldungen******************/

void I2C_transmissionError(uint8_t errorState) //gibt I2C fehlermeldungen über LCD aus
{
clearLCD();
writeStringLCD_P("I2C ERROR -->");
setCursorPosLCD(1, 0); // line 2
writeStringLCD_P("TWI STATE: 0x");
writeIntegerLCD(errorState, HEX);
}







/*************** hauptprogramm ***********/

int main(void)
{


initRP6Control();
multiio_init();
initLCD();


setLEDs(0b1111);
mSleep(500);
setLEDs(0b0000);

I2CTWI_initMaster(100);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError); //aktiviert I2C fehlermeldungen

showScreenLCD(" RP6Control M32", " servo_test");
mSleep(1500);
clearLCD();


setServoPower(0);
while(true)
{

/*****************anzeige gedrückter buttons****************/


clearLCD();
pressedMultiIOButtonNumber = getMultiIOPressedButtonNumber();
setCursorPosLCD(0, 0);
writeStringLCD("Button: ");
writeIntegerLCD(pressedMultiIOButtonNumber, DEC);
mSleep(500);

uint8_t key = getMultiIOPressedButtonNumber();


/********************funktion der buttons*********************/
if(key)
{
switch(key)
{
case 1://
setLEDs(0b0001);
multiio_init();


servopos = SERVO1_LT;
while(true)
{
setServoPower(1);
initSERVO(SERVO1 | SERVO2 | SERVO3 );

setLEDs(0b0001);
setServo(1, servopos);
mSleep(50);
servopos += 5;
if (servopos > SERVO1_MP) servopos = SERVO1_LT;
mSleep(100);

setLEDs(0b0001);
setServo(2, servopos);
mSleep(50);
servopos += 5;
if (servopos > SERVO1_MP) servopos = SERVO1_LT;
mSleep(100);
task_SERVO();

setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(servopos, DEC);
writeStringLCD_P(" ");
mSleep(50);
setServoPower(0);
}

break;
//main();

case 2://
setLEDs(0b0010);
taste=2;
multiio_init();
setServoPower(1);
initSERVO(SERVO1 | SERVO2 | SERVO3);

while(true)

{
clearLCD();
setCursorPosLCD(0, 0);
writeStringLCD("Funktion: ");
writeIntegerLCD(taste, DEC);

setServo(3, SERVO_75);
mSleep(500);
setServo(3, SERVO1_MP);
mSleep(500);
setServo(3,SERVO_105);
mSleep(500);

/*
do
if (pressedMultiIOButtonNumber == 4)
main();
while (pressedMultiIOButtonNumber);
*/

do
{
// mSleep(50);
releasedMultiIOButtonNumber = checkMultiIOReleasedButtonEvent();
task_I2CTWI();
if (releasedMultiIOButtonNumber == 2)
main();
}
while (releasedMultiIOButtonNumber);



task_SERVO();

}

main();
break;
// main();
// setServoPower(0);

case 3://

setLEDs(0b0100);
multiio_init();
setServoPower(1);
initSERVO(SERVO1 | SERVO2 | SERVO3 );


for (i=1; 5;i++);
{
setServo(3, SERVO_75);
mSleep(500);
setServo(3, SERVO1_MP);
mSleep(500);
setServo(3,SERVO_105);
// mSleep(5000);

task_SERVO();
}
break;
setServoPower(0);

case 4://
setLEDs(0b1000);

break;

}
// setServoPower(0);
//main();
}

}

return 0;
}


in dem code ist bei case2 folgender code in der while schleife eingefügt:


do
{
// mSleep(50);
releasedMultiIOButtonNumber = checkMultiIOReleasedButtonEvent();
task_I2CTWI();
if (releasedMultiIOButtonNumber == 2)
main();
}
while (releasedMultiIOButtonNumber);

1) das programm reagiert aber recht träge auf das drücken, bzw. hier loslassen der taste. ist das normal?

2) gibt es alternativen zum manuellen beenden einer unterschleife und der rückkehr ins hauptprogramm als die, die ich hier anwende?

TrainMen
08.07.2013, 10:51
Hi,
was verstehst Du denn unter träge ? Natürlich muss erst einmal z.B. case 1 abgearbeitet sein bevor er auf z.B. auf case 2 reagieren kann. Wenn alles steht sollte aber auf Tastendruck die Servos loslegen.
Benutze doch mal die Taster der M32, hast Du da das gleiche Gefühl ? Ich bin nämlich meinen MIO Tastern nicht so zufrieden, ich will schon seit x-Wochen die Werte in der Lib anpassen. Ich hatte das schon mal gemacht, danach war ich dann zufrieden. Aber mit irgendeinem Update, oder rumkopiererei war die Version dann weg.
Ich habe bei meinen Test Programm die Tastenabfrage als Funktion geschrieben (ich weiß garnicht ob man das so nennt ) und rufe diese dann aus der Main While Schleife aus. Auch habe ich keine Pausen wie Du in den einzelnen Servoschritten. Auch das ständige zu und abschalten der Servospannung habe ich nicht weil meine Servos mit der Last umfallen wenn die Spannung weg ist. Ich kann nicht sagen das da was träge reagiert. Wenn es dich interessiert kann ich ja mal das Programm mit der alten Servolib raussuchen. Bin z.Zt aber im Krankenhaus bis vorraussichtlich Donnerstag.

inka
08.07.2013, 12:35
jetzt zu allererst gute besserung...


was verstehst Du denn unter träge ? Natürlich muss erst einmal z.B. case 1 abgearbeitet sein bevor er auf z.B. auf case 2 reagieren kann. Wenn alles steht sollte aber auf Tastendruck die Servos loslegen.

mit "träge" meine ich, dass das programm auf den taster, der die servobewegung beenden soll, erst nach dem zweiten/dritten bewegungsablauf reagieren...

dass man direkt von case1 zu case2 wechseln könnte wäre mir neu? das geht doch erst nach dem neustart des programms, oder? Deshalb suche ich ja nach einer routine/funktion, die es mir möglich macht den programmablauf z.b. in case2 zu unterbrechen, ohne das ganze programm zu stoppen. Das was ich mi dem code



do
{
// mSleep(50);
releasedMultiIOButtonNumber = checkMultiIOReleasedButtonEvent();
task_I2CTWI();
if (releasedMultiIOButtonNumber == 2)
main();
}
while (releasedMultiIOButtonNumber);




erreiche ist ja auch nur das stoppen des programms und neustart...


Benutze doch mal die Taster der M32, hast Du da das gleiche Gefühl ?
die taster habe ich seit ich die IO habe noch nicht benutzt, sie sitzen auch recht ungünstig...


Ich bin nämlich meinen MIO Tastern nicht so zufrieden, ich will schon seit x-Wochen die Werte in der Lib anpassen. Ich hatte das schon mal gemacht, danach war ich dann zufrieden. Aber mit irgendeinem Update, oder rumkopiererei war die Version dann weg. an dieser änderung hätte ich auch interesse...


Ich habe bei meinen Test Programm die Tastenabfrage als Funktion geschrieben (ich weiß garnicht ob man das so nennt ) und rufe diese dann aus der Main While Schleife aus. wie hast du diese funktion geschrieben?


Auch habe ich keine Pausen wie Du in den einzelnen Servoschritten. die habe ich nur deshalb, weil die servos sonst (zumindest zum testen) zu schnell sind...


Auch das ständige zu und abschalten der Servospannung habe ich nicht weil meine Servos mit der Last umfallen wenn die Spannung weg ist. Ich kann nicht sagen das da was träge reagiert. Wenn es dich interessiert kann ich ja mal das Programm mit der alten Servolib raussuchen. Bin z.Zt aber im Krankenhaus bis vorraussichtlich Donnerstag. wäre net...

fabqu
08.07.2013, 13:04
Hi!
Ich weiß, die Taster sind mir nicht wirklich gelungen... Das hätte man auch anders machen können, um vor allem auch mehrere Taster gleichzeitig zu detektieren.
Sorry dafür! Wenn es eine V2 gibt, wird das natürlich geändert...
Eine Variante, die man aber versuchen könnte, wäre, eine passende Widerstandskaskade mit Tastern (beliebig vielen) auf einer Lochrasterplatine selbst aufbauen und dann mit drei Litzen (5V, GND und ADC) an die MultiIO anzustecken - den Stecker dafür habe ich ja bereits vorbereitet.

Lg

TrainMen
08.07.2013, 17:39
Hi,
@fabqu
also an der miesen Lösung mit den Tastern haben wir ja auch ein Anteil, die Platine und ihre Möglichkeiten haben wir den ja hier besprochen. Keiner hat eine bessere Lösung gedacht.
Der Hinweis mit dem vorbereiteten Stecker bringt ja nichts, denn auch hier ist ja nur eine Abfrage wie mit den 4 Tastern der MIO oder der 5 Taster der M32 möglich. Ich habe da manchmal eine 4x4 Matrix Tastatur dran, aber der ständige Wechsel der Lib nervt dann.
Wenn dann eine Matrix wie beim Asuro, aber da braucht man dann freie 2 Ports. Ich glaube Mic wollte da mal was machen.

@inka
Ja Danke für die Genesungs Wünsche, irgendwann habe ich die Scheiss Dinger besiegt.
Ich muss mich gleich mal endschuldigen, ich komme hier mit dem Touchpad nicht klar und habe auch nur eine Hand wirklich frei, Antworte also mal ohne zu zitieren.
Ja ich kann mich erinnern Du hast Deine Platinen gegenüber, schon klar dann kommst du nicht an die Taster der M32.
Die Änderung der Taster Abfrage musst Du alleine machen, es wär ja möglich dass Du andere Werte hast. Messe einfach mal am ADC Port nach und passe die Werte an.
Abgefragt wird ja in etwa so: if(keys <100)
return 1;
if(keys < 700)
return 2; u.s.w
ich bilde mir ein besseres Ergebnis gehabt zu habe wenn ich das Eingrenze. Also >90 und < wie 105 zum Beispiel. Aber bin mir nicht wirklich sicher.
Ich verstehe nicht warum Du da ein Stop in Deinem Programm brauchst.
Ein Programm läuft doch ständig durch. Das Programm startet und "guckt" ob Du eine Taste gedrückt hast. Ja Du hast Button 1 gedrückt. Der Servo fährt also in der genannten Position. Fertig und schon ist das Programm wieder an der Tastaturabfrage und Du hast Button 2 gedrückt der Servo fährt zurück oder eine LED geht an oder was weiss ich und Du weisst was jetzt kommt, Dein Programm steht wieder an der Tastaturabfrage........
Ich versteh nicht wirklich Dein Problem, aber ich bin selber noch Azubi in diesen Dingen. Vielleicht kann dir unser Guru - Hallo Dirk ;) - das besser erklären.
So jetzt gibts Abendbrot, haha ans Bett gebracht, schönen Abend noch.

Dirk
08.07.2013, 18:02
@TrainMen:

Vielleicht kann dir unser Guru - Hallo Dirk https://www.roboternetz.de/phpBB2/images/smiles/icon_wink.gif - das besser erklären.
Guru??? GURU???
Sei froh, dass du krank bist,- sonst würde ich ... :Haue

Nein, besser hätte ich das auch nicht erklären können.

Gute Besserung!

TrainMen
11.07.2013, 14:09
Hi inka,
wie versprochen hier das Programm zur Tasterabfrage der M32.
Du musst das natürlich anpassen, ich habe es nur schnell überflogen und überflüssiges gelöscht. So das es deutlich wird was ich in meinte.

inka
12.07.2013, 12:22
danke TrainMen,

die nächste frage:

die abfrage taucht mehrmals in meinem programm auf, kann ich diese abfrage zu einer funktion "void abbruch (void)" machen, oder wird es wegen der schleife und der if abfrage nicht funktionieren?



do
{
pressedMultiIOButtonNumber = checkMultiIOPressedButtonEvent();
task_I2CTWI();
if (pressedMultiIOButtonNumber == 4)
main();
}
while (pressedMultiIOButtonNumbe

Dirk
12.07.2013, 22:00
@inka:
Der Aufruf der main() und auch noch ohne Abbruch der do-while Struktur ist keine gute Idee!
Das dürfte irgendwann zu einem Stacküberlauf und zum Programmende führen.
Das sind dann schwer zu findende Fehler!

Was du ja wohl machen willst ist eine Art "Menüstruktur". Du drückst eine Taste und ein Programmteil startet. Dann beendet man das wieder durch einen Tastendruck und kommt zurück ins Auswahlmenü.
Das braucht etwas mehr Aufwand, als per brute-force in die main zurückzuspringen.
Du kannst aber z.B. im RP6Base_SELFTEST.c sehen, wie man ein solches Menü bauen kann.

inka
13.07.2013, 16:43
Was du ja wohl machen willst ist eine Art "Menüstruktur". Du drückst eine Taste und ein Programmteil startet. Dann beendet man das wieder durch einen Tastendruck und kommt zurück ins Auswahlmenü.
Der Aufruf der main() und auch noch ohne Abbruch der do-while Struktur ist keine gute Idee!

genau. und wenn es mit "brutaler kraft" sein muss - ich hatte keine idee und dachte eher an das gute alte "goto" aus basic-zeiten. Würde das ein eingesetztes break abmildern, oder ist die ganze idee für die katz?



Das braucht etwas mehr Aufwand, als per brute-force in die main zurückzuspringen.
Du kannst aber z.B. im RP6Base_SELFTEST.c sehen, wie man ein solches Menü bauen kann.

meinst Du das hier?



test = receiveBuffer[0] - 48;

if(receiveBuffer[0] == 's')
{
speed_control();
}
else if(receiveBuffer[0] == 'd')
{
testMoveDistance();
}
else if(receiveBuffer[0] == 'c')
{
testEncoderDutyCycle();
}
else if(test > 8)
{
writeString_P("You need to enter a single number from 0 to 8, s, d or c!");
continue;
}
else
{

switch(test)
{
case 0:
testPowerOn();
testLEDs();
testVoltageSensor();
testBumpers();
testLightSensors();
testACS();
testRC5();
testMotorsAndEncoders();
break;
case 1: testPowerOn(); break;
case 2: testLEDs(); break;
case 3: testVoltageSensor(); break;
case 4: testBumpers(); break;
case 5: testLightSensors(); break;
case 6: testACS(); break;
case 7: testRC5(); break;
case 8: testMotorsAndEncoders(); break;
}
}


ich erkenne hier eher eine einstufige abfragesituation und innerhalb der einzelnen cases oder if-abfragen läuft hier keine while-schleife...

Dirk
13.07.2013, 17:53
@inka:

...und dachte eher an das gute alte "goto" aus basic-zeiten. Würde das ein eingesetztes break abmildern, oder ist die ganze idee für die katz?
Goto gibt's immer noch,- ist aber ziemlich verpönt. Es läßt sich auch sehr gut umgehen ...

...ich erkenne hier eher eine einstufige abfragesituation und innerhalb der einzelnen cases oder if-abfragen läuft hier keine while-schleife...
Das sieht nur so aus. In den einzelnen Funktionen des Testprogramms wird teilweise auch eine Abbruchbedingung abgefragt.
D.h.: Die Einzelfunktionen bestimmen selbst, ob sie einmalig durchlaufen oder dauerhaft bis zu einer Abbruchbedingung. Daher braucht es in der case Struktur keine do-while Schleife.

inka
20.08.2013, 15:09
Hi allerseits,

ich nutze jetzt mal diesen thread, auch wenn es mir diesmal um andere strukturen geht:

nachdem das kompilieren mit code:blocks bei mir offensichtlich immer noch mit fehlern behaftet ist habe ich das, was ich momentan mache auf reines make umgestellt. So weit so gut, so ganz zufrieden bin ich nicht:

1) die strukturen sind ganz flach. Ich kann sie natürlich mit hinzufügen von "/.." im jeweiligen makefile erweitern, das wahre ist das aber nicht...

2) es stört mich z.b. das in jedem verzeichnis, welches für ein programm angelegt ist auch die dateien, wie z.b. die libs der multi_io sind. So habe ich - befürchte ich - in einigen wochen dutzende von z.b. "RP6Control_MultiIO.h" oder "RP6Control_Orientation.h", je nach dem wo ich gerade drann bin und etwas ändere. Gibt es hier, bei make, eine möglichkeit es zentral handzuhaben? Zum beispiel alle "RP6mio" oder "RP6servo" in einem verzeichnis zusammenzufassen und jeweils nur auf EINE dateiversion (in der man ändert, hinzufügt, auskommentiert...) zuzugreifen? kann man dazu z.b. den

"RP6_LIB_PATH_OTHERS= $(RP6_LIB_PATH)/RP6control $(RP6_LIB_PATH)/RP6common"

erweitern?

das hier, z.b.


SRC += $(RP6_LIB_PATH)/RP6control/RP6ControlLib.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6uart.c


hat schon mal mit "RP6_LIB_PATH_OTHERS"

also so:

SRC += $(RP6_LIB_PATH_OTHERS)/RP6ControlLib.c
SRC += $(RP6_LIB_PATH_OTHERS)RP6uart.c

irgendwie nicht funktioniert...


wie handhabt ihr (die, die mit make arbeiten und drauf schwören) so etwas?

Dirk
20.08.2013, 16:33
Hi inka,
wenn man mal die Struktur der RP6 Examples als Beispiel nimmt:
1. Im makefile geht alles aus von DEM Ordner, in dem makefile steht bzw. make all ausgeführt wurde. Das ist der Ordner, in dem also dein Programm steht (Programmordner).

2. RP6_LIB_PATH ist dann im makefile als ../../RP6Lib definiert, d.h. 2 Ebenen aufwärts im Verzeichnisbaum (RP6CONTROL_EXAMPLES -> RP6) und dort dann der Ordner RP6Lib.
Die Struktur sieht also so aus:
RP6 --- RP6CONTROL_EXAMPLES --- Programmordner
RP6 --- RP6Lib
RP6_LIB_PATH weist dann also auf den Ordner RP6Lib.

3. Wenn es um die M32 geht, dann befinden sich die meisten Libs für die M32 im Ordner:
RP6 --- RP6Lib --- RP6control
Dahin tue ich auch alle Libs, die ich selbst für die M32 habe. Wenn du also für die MultiIO Libs eine zentrale Stelle haben willst, wäre dieser Ordner doch gut geeignet, oder?

4. Im makefile müßtest du also alle MultiIO Libs, die du in den Ordner RP6control kopiert hast, so eintragen:
SRC += $(RP6_LIB_PATH)/RP6control/RP6Control_MultiIOLib.c
(Hier am Beispiel der MultiIO Haupt-Lib)

5. Im Programm selbst müßten die include Befehle nicht verändert werden.

Wenn du eine andere Ordner-Struktur nutzt, must du natürlich die Pfadangaben anpassen.

inka
03.10.2013, 17:34
hallo,

ich versuche nun bestimmte funktionen, die ich in unterschiedlichen programmen verwenden möchte in eine lib "standard" (c & h) auszulagern...

mit solchen z.b. klappt es einwandfrei:


void accuspannung(void)

sobald der funktion als rückgabewert z.b. eine variable zugeordnet wird wie hier:


void batteryVoltageLow(uint8_t isVoltageLow)

- in der standard.h steht dann:


void batteryVoltageLow(void)

funktioniert es nicht, die fehlermeldunge lautet:
../../RP6Lib/standard/standard.h|37|note: previous declaration of ‘batteryVoltageLow’ was here|


wobei der eintrag in der standard.h moniert wird. Muss dort bei der deklaration auch die variable rein? wenn ich es dann mache:


void batteryVoltageLow(uint8_t isVoltageLow)

wird eine klammer verlangt:


../../RP6Lib/standard/standard.h|38|error: expected ‘)’ before ‘isVoltageLow’|

seltsammerweise funktioniert es hier:

standard.c:
void I2C_transmissionError(uint8_t errorState)

standard.h: steht nichts, da die funktion in der "RP6Control_I2CMasterLib.h" deklariert wird, und zwar so:


void I2C_transmissionError(uint8_t errorState);

könnte bitte jemand versuchen mir das zu erklären?

Dirk
03.10.2013, 19:28
Wenn es eine Funktion void batteryVoltageLow(uint8_t isVoltageLow) gibt, muss sie auch im Header (.h) so deklariert werden. Dabei reicht es auch, nur void batteryVoltageLow(uint8_t) anzugeben.
Was man oft vergißt, ist auch, dass hinter den Funktionsdeklarationen im Header jeweils ein ; stehen muss.

Peter(TOO)
03.10.2013, 19:54
Hallo Inka,

Du wirfst noch etwas falsch mit den Begriffen um dich ;-)

1. Rückgabewert, der steht links
Also
int f(void);
Darf dann so verwendet werden:

int f(void)
{
return (1);
}

void x(void)
{
int a;
a = f();
}

2. void bedeutet nichts!
Da wo also void steh gibt es keinen Parameter

void f(void); // nimmt keine Werte an und liefert nichts zurück

Folglich führt folgendes immer zu einem Fehler:

int a;
a = f(); // Error
f(123); // Error

3. Parameter, Übergabeparameter
Das sind die Variablen welche in der Klammer stehen.
void batteryVoltageLow(uint8_t isVoltageLow);
Verlangt also nach ein Parameter , welcher beim Aufruf übergeben werden muss.
In einem Fall kann die Funktion auch den Wert von sVoltageLow, im aufrufenden Teil, nicht verändern. Der Funktion wird nur eine Kopie von sVoltageLow übergeben.

MfG Peter(TOO)

inka
04.10.2013, 09:16
danke erstmal für die antworten...

hier mein problem noch einmal (etwas detailierter):

RP6Control_08_I2CMaster.c , auskommentierter bereich:

/** * This is a new Event Handler and it gets called when the Battery Voltage
* is getting low! The Parameter isVoltageLow is true, when the voltage
* is low and false, when the voltage is OK.
*/
/*
void batteryVoltageLow(uint8_t isVoltageLow)
{
if(isVoltageLow)
{
writeString_P("\nBattery Voltage low: ");
// Send Battery voltage to UART:
writeIntegerLength((((adcBat/102.4f)+0.1f)), DEC, 2);
writeChar('.');
writeIntegerLength((((adcBat/1.024f)+10)), DEC, 2);
writeString_P("V\n");
}
else
{
writeString_P("\nBattery Voltage is OK!\n");
}
}
*/


standard.c, funktion hinzugefügt:



/************battery_voltage_low******************* ******/



void batteryVoltageLow(uint8_t isVoltageLow)
{
if(isVoltageLow)
{

writeString_P("\nBattery Voltage low: ");
// Send Battery voltage to UART:
writeIntegerLength((((adcBat/102.4f)+0.1f)), DEC, 2);
writeChar('.');
writeIntegerLength((((adcBat/1.024f)+10)), DEC, 2);
writeString_P("V\n");
}
else
{
writeString_P("\nBattery Voltage is OK!\n");
}
}



standard.h, deklaration (die zeile, die moniert wird hervorgehoben):



//void receiveRC5Data(void (RC5data_t) (rc5data));

//void batteryVoltageLow(void);
void batteryVoltageLow (uint8_t isVoltageLow);
//void printAllSensorValues(void);
//void task_LCDHeartbeat(void);
//void watchDogRequest(void);



erstellungsprotokoll beim kompilieren:



-------------- Erstellen: RP6Control_08_I2CMaster in m32_samples ---------------


Compiliere: ../../RP6Lib/RP6common/RP6I2CmasterTWI.c
../../RP6Lib/RP6common/RP6I2CmasterTWI.c: In function ‘I2CTWI_requestedDataReady_DUMMY’:
../../RP6Lib/RP6common/RP6I2CmasterTWI.c:55:46: warning: unused parameter ‘requestID’
../../RP6Lib/RP6common/RP6I2CmasterTWI.c: In function ‘I2CTWI_transmissionError_DUMMY’:
../../RP6Lib/RP6common/RP6I2CmasterTWI.c:62:45: warning: unused parameter ‘requestID’
Compiliere: ../../RP6Lib/RP6common/RP6uart.c
Compiliere: ../../RP6Lib/RP6control/RP6ControlLib.c
Compiliere: ../../RP6Lib/RP6control/RP6Control_I2CMasterLib.c
../../RP6Lib/RP6control/RP6Control_I2CMasterLib.c: In function ‘IRCOMM_RC5dataReady_DUMMY’:
../../RP6Lib/RP6control/RP6Control_I2CMasterLib.c:62:42: warning: unused parameter ‘rc5data’
../../RP6Lib/RP6control/RP6Control_I2CMasterLib.c: In function ‘BATTERY_lowVoltage_DUMMY’:
../../RP6Lib/RP6control/RP6Control_I2CMasterLib.c:93:39: warning: unused parameter ‘isVoltageLow’
Compiliere: ../../RP6Lib/RP6mio/RP6Control_MultiIOLib.c
Compiliere: ../../RP6Lib/standard/standard.c
In file included from ../../RP6Lib/standard/standard.c:1:0:
../../RP6Lib/standard/standard.h:38:33: error: expected ‘)’ before ‘isVoltageLow’
Prozess wurde mit Status 1 beendet. (0 Minuten, 0 Sekunden)
1 Fehler, 4 Warnungen

ich kann keinen fehler erkennen, wüsste ich auch nicht wo ich dort die ")" hinzufügen soll?

Peter(TOO)
04.10.2013, 09:41
Hallo inka,

Das ist eine schwäche von C.
Der Fehler ist immer zwischen dem Anfang der Datei und der Stelle welche der Compiler angibt!

BTW: woher kennt der Compiler uint8_t ??
Da müsste irgendwo eine Definition davon ein, vielleicht in einer Headerdatei, welche vergessen wurde?

MfG Peter(TOO)

Dirk
04.10.2013, 09:46
uint8_t kennt der Compiler in diesem Fall.
Der Fehler liegt VOR dieser Fehlerzeile.
Such mal die ganze Header-Datei ab oder poste sie hier (keine Ausschnitte, sondern den kompletten Header, so wie er kompiliert wurde).

inka
04.10.2013, 13:29
das hier ist der komplette header:


#ifndef STANDARD_H_
#define STANDARD_H_

#endif /*STANDARD_H_*/




void accuspannung(void);

void accuzustand(void);

void watchDogRequest(void);

void task_LCDHeartbeat(void);

void printAllSensorValues(void);


//void writeDoubleLCD(void);

//void writeDouble(void);

//void I2C_transmissionError();

//void show_buttons();

//ACS_setStateChangedHandler(acsStateChanged);

void acsStateChanged(void);

void bumpersStateChanged(void);

//void receiveRC5Data(void);

//void receiveRC5Data(void (RC5data_t) (rc5data));
//void batteryVoltageLow(void);
void batteryVoltageLow (uint8_t isVoltageLow);
//void printAllSensorValues(void);
//void task_LCDHeartbeat(void);
//void watchDogRequest(void);


//ACS_setStateChangedHandler(void);
//ACS_setStateChangedHandler(acsStateChanged);

Peter(TOO)
04.10.2013, 14:33
Hallo Dirk,


uint8_t kennt der Compiler in diesem Fall.


Woher ?

MfG Peter(TOO)

- - - Aktualisiert - - -

Hallo Inka,

Und wie sieht das Hauptprogramm aus?

Besonders: Welche Header bindest du da ein und in welcher Reihenfolge?

Ich bin immer noch der Meinung, dass der Compiler zu diesem Zeitpunkt nicht weiss was uint8_t sein soll.

MfG Peter(TOO)

Wsk8
04.10.2013, 14:35
#endif /*STANDARD_H_*/

Das kommt ganz ans Ende der Datei.


Das ist eine schwäche von C.
Der Fehler ist immer zwischen dem Anfang der Datei und der Stelle welche der Compiler angibt!
Sorry, aber lern doch bitte wie man die Fehlermeldungen liest. Die sind zu 98% immer sehr genau an der entsprechenden Stelle! Nur bei fehlenden Klammern ist die Meldung verstreut, aber dafür gibts jetzt ja die Möglichkeit sie mit Autocomplete sofort zu schließen.


error: expected ‘)’ before ‘isVoltageLow’
Der Compiler will hinter uint8_t eine Klammer. Warum ist mir jetzt auch nicht bewusst. Evtl liegts am uint8_t.

EDIT: Nach kurze Suche, sollte es wirklich daran liegen, dass uint8_t unbekannt ist. Tauch es mal mit "unsigned char" aus, dann sollte es gehen


mfg

inka
04.10.2013, 15:45
hallo,

das "#endif /*STANDARD_H_*/" habe ich ans programmende verschoben - das problem löst es aber nicht...


das hauptprogramm:

/************************************************** ***************************/
// Includes:

#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!

#include "RP6I2CmasterTWI.h" // I2C Master Library
#include "../../RP6Lib/standard/standard.h"
#include "RP6Control_I2CMasterLib.h"


/**************************ACS_state_changed******* ***************************/

//siehe standard.c

/********************bumpers_state_changed********* ***************************/

//siehe standard.c

/**
* And the RC5 Event Handler is the same as on the Robot Base, too.
*/

void receiveRC5Data(RC5data_t rc5data)
{
// Output the received data:
writeString_P("RC5 Reception --> Toggle Bit:");
writeChar(rc5data.toggle_bit + '0');
writeString_P(" | Device Address:");
writeInteger(rc5data.device, DEC);
writeString_P(" | Key Code:");
writeInteger(rc5data.key_code, DEC);
writeChar('\n');
}

/**
* This is a new Event Handler and it gets called when the Battery Voltage
* is getting low! The Parameter isVoltageLow is true, when the voltage
* is low and false, when the voltage is OK.
*/
/*
void batteryVoltageLow(uint8_t isVoltageLow)
{
if(isVoltageLow)
{
writeString_P("\nBattery Voltage low: ");
// Send Battery voltage to UART:
writeIntegerLength((((adcBat/102.4f)+0.1f)), DEC, 2);
writeChar('.');
writeIntegerLength((((adcBat/1.024f)+10)), DEC, 2);
writeString_P("V\n");
}
else
{
writeString_P("\nBattery Voltage is OK!\n");
}
}
*/
/********************print_all_sensor_values******* **************/
//siehe standard.c
/************************************************** **********/

/************** * Heartbeat function*************************/
//siehe standard.c
/************************************************** **********/

/***************************watchDog_Request******* ***************/
// siehe standard.c
/************************************************** ***************/
// I2C Requests:

/**
* The I2C_requestedDataReady Event Handler is now a lot smaller.
* It is free for your own request routines.
* You can put them in the Block of the if condition.
* (similar to the RP6 Base Example programs...)
*/
void I2C_requestedDataReady(uint8_t dataRequestID)
{
// We need to check if this is an INT0 Request from the Robot Base unit.
// The Function call inside the if condition returns true if it was an
// interrupt request, so we have to negate it here and if it was NOT
// an interrupt request from the Robot base we can check any other sensors
// from which you may have requested data...
if(!checkRP6Status(dataRequestID))
{
// Here you can Check other sensors/microcontrollers with their own
// request IDs - if there are any...
}
}

/******************************I2C Error handler******************************/
// siehe standard.c
/************************************************** ***************************/


// Main function - The program starts here:

int main(void)
{
initRP6Control();
initLCD();

writeString_P("\n\nRP6 CONTROL M32 I2C Master Example Program!\n");
writeString_P("\nInterrupts - part 2...\n");

// ---------------------------------------
// The Event Handlers can be set the same way as with the
// RP6Lib:
ACS_setStateChangedHandler(acsStateChanged);
BUMPERS_setStateChangedHandler(bumpersStateChanged );
IRCOMM_setRC5DataReadyHandler(receiveRC5Data);
// New LowBat Event Handler:
BATTERY_setLowVoltageHandler(batteryVoltageLow);
// New Watchdog Request Event Handler:
WDT_setRequestHandler(watchDogRequest);

// ---------------------------------------
// Init TWI Interface:
I2CTWI_initMaster(100);
I2CTWI_setRequestedDataReadyHandler(I2C_requestedD ataReady);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);

sound(180,80,25);
sound(220,80,25);

setLEDs(0b1111);

showScreenLCD("################", "################");
mSleep(500);
showScreenLCD("I2C-Master", "Example Program 3");
mSleep(1000);
setLEDs(0b0000);
clearLCD();
accuspannung();
mSleep(1500);

// ---------------------------------------
// Setup ACS power:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_ACS_POWER, ACS_PWR_MED);
// Enable Watchdog for Interrupt requests:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true);
// Enable timed watchdog requests:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT_RQ, true);

showScreenLCD("ACS Status:", "");

startStopwatch1();
startStopwatch2();

while(true)
{
task_LCDHeartbeat();
task_checkINT0();
task_I2CTWI();
accuzustand();
}
return 0;
}

standard.c:

#include "standard.h"
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_MultiIOLib.h"
#include "RP6Control_I2CMasterLib.h"
#include "RP6ControlServoLib.h"
#include "RP6Control_OrientationLib.h"


/************************ Write a floating point number to the LCD or terminal. ******/
/*
* Example:
*
* // Write a floating point number to the LCD (no exponent):
* writeDoubleLCD(1234567.890, 11, 3);
*
* The value of prec (precision) defines the number of decimal places.
* For 32 bit floating point variables (float, double ...) 6 is
* the max. value for prec (7 relevant digits).
* The value of width defines the overall number of characters in the
* floating point number including the decimal point. The number of
* pre-decimal positions is: (width - prec - 1).
*/

void writeDoubleLCD(double number, uint8_t width, uint8_t prec)
{char buffer[width + 1];
dtostrf(number, width, prec, &buffer[0]);
writeStringLCD(&buffer[0]);
}

/* Write a floating point number to the terminal (no exponent):
writeDoubleLCD(1234567.890, 11, 3);
*/

void writeDouble(double number, uint8_t width, uint8_t prec)
{char buffer[width + 1];
dtostrf(number, width, prec, &buffer[0]);
writeString(&buffer[0]);
}




/**************accuspannungsanzeige********/

void accuspannung(void) // accuspannung ausgeben
{
// Voltage & current sensor test:
multiio_init();
LTC2990_measure();
setCursorPosLCD(0, 0);
//writeStringLCD("BAT Current: ");
//writeDoubleLCD(cbat, 6, 1);
writeStringLCD(" accu: ");
writeDoubleLCD(vbat, 4, 1);
writeStringLCD( " V");
}

/**************accuzustand********/

void accuzustand(void) // accuspannung abfragen und signalisieren
{

LTC2990_measure();
if (vbat < 6)
{
buzzer(330);
mSleep(200);
buzzer(330);
mSleep(200);
}

}

/************************************************** ***************************/
// 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 IS: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}

/*******************LCD_heart_beat***************** *******/

void task_LCDHeartbeat(void)
{
if(getStopwatch1() > 500)
{
static uint8_t heartbeat = false;
if(heartbeat)
{
clearPosLCD(0, 15, 1);
heartbeat = false;
}
else
{
setCursorPosLCD(0, 15);
writeStringLCD_P("*");
heartbeat = true;
printAllSensorValues();
}
setStopwatch1(0);
}
}

/*********************watchdod_request************* ****/
/*
* Now we have a second "Heartbeat" display
* which shows if the Controller still reacts on
* the Watchdog requests from the Slave Controller!
* And it also shows if the slave Controller is
* still up and running.
*
* It will blink with a rate of about 2Hz when
* the watchdog requests are still active.
*/
void watchDogRequest(void)
{
static uint8_t heartbeat2 = false;
if(heartbeat2)
{
clearPosLCD(0, 14, 1);
heartbeat2 = false;
}
else
{
setCursorPosLCD(0, 14);
writeStringLCD_P("#");
heartbeat2 = true;
}
}
/*******************print_all_sensor_values******** *********/

/*
* This function prints out all ADC values and motor parameters:
* power, desired speed, measured speed and driven distance.
*
* It first calls "getAllSensors()" from the library which reads all
* the sensor values we use here from the Slave Controller.
* Then you can use just the same variables as on the RP6Base to get
* the ADC values.
*/
void printAllSensorValues(void)
{
getAllSensors();
writeString_P("\nRead Sensor Values:\n");
writeString_P("PL:");writeIntegerLength(mleft_power,DEC,3);
writeString_P(" | PR:");writeIntegerLength(mright_power,DEC,3);
writeString_P(" | VL:");writeIntegerLength(mleft_speed,DEC,3);
writeString_P(" | VR:");writeIntegerLength(mright_speed,DEC,3);
writeString_P(" | DL:");writeIntegerLength(mleft_des_speed,DEC,3);
writeString_P(" | DR:");writeIntegerLength(mright_des_speed,DEC,3);
writeChar('\n');
writeString_P("DSTL:");writeIntegerLength(mleft_dist,DEC,5);
writeString_P(" | DSTR:");writeIntegerLength(mright_dist,DEC,5);
writeChar('\n');
writeString_P("LSL:");writeIntegerLength(adcLSL,DEC,4);
writeString_P(" | LSR:");writeIntegerLength(adcLSR,DEC,4);
writeString_P(" | MCL:");writeIntegerLength(adcMotorCurrentLeft,DEC,4);
writeString_P(" | MCR:");writeIntegerLength(adcMotorCurrentRight,DEC,4);
writeString_P(" | BAT:");writeIntegerLength(adcBat,DEC,4);
writeString_P(" | AD0:");writeIntegerLength(adc0,DEC,4);
writeString_P(" | AD1:");writeIntegerLength(adc1,DEC,4);
writeChar('\n');
}



/******************acs_State_Changed*************** **************/

void acsStateChanged(void)
{
writeString_P("ACS state changed L: ");
if(obstacle_left)
{
writeChar('o');
setCursorPosLCD(1, 12);
writeStringLCD_P("LEFT");
}
else
{
writeChar(' ');
clearPosLCD(1, 12, 4);
}
writeString_P(" | R: ");
if(interrupt_status.obstacleRight)
{
writeChar('o');
setCursorPosLCD(1, 0);
writeStringLCD_P("RIGHT");
}
else
{
writeChar(' ');
clearPosLCD(1, 0, 5);
}
if(obstacle_left && obstacle_right)
{
externalPort.LEDS = 0b0110;
writeString_P(" MIDDLE!");
setCursorPosLCD(1, 7);
writeStringLCD_P("MID");
}
else
{
externalPort.LEDS = 0b0000;
clearPosLCD(1, 7, 3);
}

if(obstacle_left)
externalPort.LED1 = true;
if(obstacle_right)
externalPort.LED4 = true;
outputExt();

if(obstacle_left && obstacle_right)
{
sound(140,10,0);
}
else
{
if(obstacle_left)
sound(100,5,0);
if(obstacle_right)
sound(120,5,0);
}
writeChar('\n');
}



/*****************bumpers_state_changed************ *********/

void bumpersStateChanged(void)
{
// Bumper status changed, output current state and play sounds:
writeString_P("Bumpers changed: ");
if(bumper_right && bumper_left)
{
writeString_P("MIDDLE!");
sound(200,100,0);
}
else
{
if(bumper_left)
{
writeString_P("LEFT!");
sound(200,50,10);
sound(150,20,0);
}
else if(bumper_right)
{
writeString_P("RIGHT!");
sound(200,50,10);
sound(150,20,0);
}
else
{
writeString_P("FREE!");
}
}
writeChar('\n');
}

/**********receive_RC5_data************************ ***/
/*
void receiveRC5Data(RC5data_t rc5data)
{
// Output the received data:
writeString_P("RC5 Reception --> Toggle Bit:");
writeChar(rc5data.toggle_bit + '0');
writeString_P(" | Device Address:");
writeInteger(rc5data.device, DEC);
writeString_P(" | Key Code:");
writeInteger(rc5data.key_code, DEC);
writeChar('\n');
}
*/
/************battery_voltage_low******************* ******/

void batteryVoltageLow(uint8_t isVoltageLow)
{
if(isVoltageLow)
{
writeString_P("\nBattery Voltage low: ");
// Send Battery voltage to UART:
writeIntegerLength((((adcBat/102.4f)+0.1f)), DEC, 2);
writeChar('.');
writeIntegerLength((((adcBat/1.024f)+10)), DEC, 2);
writeString_P("V\n");
}
else
{
writeString_P("\nBattery Voltage is OK!\n");
}
}

Wsk8
04.10.2013, 15:55
das "#endif /*STANDARD_H_*/" habe ich ans programmende verschoben - das problem löst es aber nicht...
Mein Beitrag besteht aus mehr als 2 Zeilen, ja?

Den Rest mit uint8_t auch beachtet??

mfg

inka
04.10.2013, 16:07
Mein Beitrag besteht aus mehr als 2 Zeilen, ja?

Den Rest mit uint8_t auch beachtet??

mfg

ja, ist mir nicht entgangen. Unser RP6 spezialist (Dirk) hat ja schon geschrieben, dass es in diesem fall bekannt ist...

Das hauptprogramm (RP6Control_08_I2CMaster.c) ist eines der demo-programme für das M32-board des RP6. Mehrfach in seinem originalzustand kompiliert und eingesetzt. Auch mit seinen variablen. Abgesehen davon, dass ich überhaupt nicht weiss, wo überall ich es ändern müsste, nehme ich aus dem vorgenanntem an, dass es nicht funtionieren wird...

Wsk8
04.10.2013, 16:26
ja, ist mir nicht entgangen. Unser RP6 spezialist (Dirk) hat ja schon geschrieben, dass es in diesem fall bekannt ist...
Aha, also findest du es auch in Ordnung, dass die USA fast den ganzen Nahen Osten zusammenbombt. Schließlich sind sie ja die "Experten" in der Terrorismusbekämpfung.


void batteryVoltageLow(uint8_t isVoltageLow)
Du schreibst statt dem "uint8_t" einfach "unsigned char" oder von mir aus auch nur "char". Und das sowohl in der .h als auch in der .c. Und erst wenn der gleiche Fehler wieder kommt, dann, aber nur dann kannst du sagen, dass es nichts hilft.

mfg

inka
04.10.2013, 17:00
wenn schon mal einer schreibt "mach mal einfach" sträuben sich bei mir schon die nackenhaare. ich will aber keinen streit, also;

in "standarad.c" und "standard.h" geändert von: uint8_t in: char.


in der "RP6Control_I2CMasterLib.h" wird die zeile


void BATTERY_setLowVoltageHandler(void (*lowVoltageHandler)(uint8_t));

mit folgender fehlermeldung angemotzt:


../../RP6Lib/RP6control/RP6Control_I2CMasterLib.h|218|note: expected ‘void (*)(uint8_t)’ but argument is of type ‘void (*)(char)’|

hast du noch ein paar ideen? Ich würde auch einen anderen ton sehr begrüßen...

Wsk8
04.10.2013, 17:08
hast du noch ein paar ideen? Ich würde auch einen anderen ton sehr begrüßen...
Sorry, aber als langer supporter in vielen Foren macht es mich einfach wütend, wenn Leute nach Hilfe fragen und sie dann aber nicht ausprobieren sondern mit irgendeiner Ausrede daherkommen. Noch schlimmer wirds dann, wenn die Lösung auf der 1 Seite steht, aber nach 5 Seiten der TE es das erste mal probiert und feststellt dass es doch funktioniert.


in der "RP6Control_I2CMasterLib.h" wird die zeile


void BATTERY_setLowVoltageHandler(void (*lowVoltageHandler)(uint8_t));


mit folgender fehlermeldung angemotzt:


../../RP6Lib/RP6control/RP6Control_I2CMasterLib.h|218|note: expected ‘void (*)(uint8_t)’ but argument is of type ‘void (*)(char)’|


hast du noch ein paar ideen? Ich würde auch einen anderen ton sehr begrüßen...
Habe natürlich nicht gewusst, dass es hier noch abhängig ist. Hier bitte auch in "char" ändern. In der .c vermutlich auch.

mfg

inka
04.10.2013, 17:22
Sorry, aber als langer supporter in vielen Foren macht es mich einfach wütend, wenn Leute nach Hilfe fragen und sie dann aber nicht ausprobieren sondern mit irgendeiner Ausrede daherkommen. Noch schlimmer wirds dann, wenn die Lösung auf der 1 Seite steht, aber nach 5 Seiten der TE es das erste mal probiert und feststellt dass es doch funktioniert.


Habe natürlich nicht gewusst, dass es hier noch abhängig ist. Hier bitte auch in "char" ändern. In der .c vermutlich auch.

mfg

Ausrede! "natürlich nicht gewusst"!!

und an wievielen stellen soll ich sonst noch ändern? Ich werde jetzt keinen uint8_t in einen char ändern. bevor man wütend wird sollte man sich informieren. Und man sollte dort supporten, wo man sich auskennt, hier im RP6 bereich habe ich auf jeden fall noch nicht so viel von dir gehört.

Und jetzt werde ich wütend: geh aus der leitung!

Wsk8
04.10.2013, 17:30
Ok, einmal versuch ichs noch. Änder wieder alles in uint8_t.

In der standard.h nach den ersten 2 zeilen:


#ifndef STANDARD_H_
#define STANDARD_H_


#include <stdint.h>


mfg

inka
04.10.2013, 17:42
ich habe es schon geschrieben - ich will keinen streit.

Dieser vorschlag passt. Steht aber nicht auf der ersten seite (um deine worte mal zu nutzen), sondern war erst der dritte schuss. Trotzdem danke....

Evtl. in zukunft weniger aus der hüfte schiessen, mehr zuhören und in ruhe lesen was die anderen schreiben. Und nicht vergessen, es gibt viele anfänger hier, für die ist nix "einfach"....

Wsk8
04.10.2013, 18:01
Ausrede! "natürlich nicht gewusst"!!
Ich kenne weder die RP6 lib noch bin ich Gott. Ja, ich habe es nicht gewusst!


Und man sollte dort supporten, wo man sich auskennt, hier im RP6 bereich habe ich auf jeden fall noch nicht so viel von dir gehört.
Hier gehts um C. Ich kenne mich mit C aus, deshalb wüsste ich nicht warum ich mich nicht einmischen sollte.


Dieser vorschlag passt. Steht aber nicht auf der ersten seite (um deine worte mal zu nutzen), sondern war erst der dritte schuss. Trotzdem danke....
Nein, aber Peter hat zumindest schon auf der 2 Seite den Hinweis dazu gegeben, denn aber jeder ignoriert hat weil es ja ein sogenannter "RP6-Experte" aus dem RP6-Forum besser wusste.


Evtl. in zukunft weniger aus der hüfte schiessen, mehr zuhören und in ruhe lesen was die anderen schreiben. Und nicht vergessen, es gibt viele anfänger hier, für die ist nix "einfach"....
Tut mir Leid dass ich nicht Gott bin und alles beim ersten mal weiß. Ich muss auch alle möglichen Lösungen erst durchprobieren. Ein Schütze muss auch erst viele Schüsse abgeben, bevor er perfekt trifft.


UND ICH WAR HIER DER LETZTE, DER STREIT GESUCHT HAT. DAS WARST NUR DU! ICH HABE NUR VERSUCHT DIR ZU HELFEN!
ICH WAR AUCH NICHT IMMER PERFEKT, ABER ICH HABE DEN LEUTEN NICHT GESAGT, DASS SIE SICH HIER SOWIESO NICHT AUSKENNEN UND VERSCHWINDEN SOLLEN.
SOWAS IST EINFACH NUR EINE FRECHHEIT DEINERSEITS!!!!
DU BIST HIER EINFACH WIE EIN INKOMPETENTER B*ASTARD AUFGETRETEN UND GENAU DAS IST AB JETZT AUCH MEINE MEINUNG VON DIR. EINFACH UNGLAUBLICH SOWAS

Dirk
04.10.2013, 18:44
@ Peter(TOO):

Zitat von Dirk: "uint8_t kennt der Compiler in diesem Fall."

Woher ?

... aus der stdint.h, die bei den RP6 Libs immer mit eingebunden wird (in diesem Fall in der RP6Control.h).

inka
04.10.2013, 19:04
hier wäre es die frage wieso erst das includen der stdint.h in meine standard.h hier abhilfe gebracht hat? Die RP6control.h ist in meinem projekt eingebunden...

Wsk8
04.10.2013, 21:29
#include "standard.h"
#include "RP6ControlLib.h"

Vlt weil du Genie erst die standard.h eingebunden hast und dann die RP6CL.h. Das macht nämlich nen Unterschied.

mfg

fabqu
04.10.2013, 22:29
? Bombardement der USA? Ein schütze muss erst viele Schüsse abgeben? Du bist nicht Gott? Bitte mal beim Thema bleiben, nicht rum schimpfen, und schon gar nicht andere user beschimpfen mit "b*stard" oder sonst was! Ist ja nicht zu glauben!
Inka ist Anfänger (wie ich auch) und als solcher gibt es sicherlich keine blöden fragen, und es kann nie einfach genug sein.
Wenn du keine konstruktive Kritik hast, dann lass es bitte stecken.
Danke

inka
05.10.2013, 08:06
ja, die reihenfolge spielt eine rolle, danke für den hinweis...

Und - genie ist anders. Ich habe mir die bezeichnung beim avatar nicht ausgesucht...

Peter(TOO)
05.10.2013, 16:02
Hallo Wsk8,


[CODE]
Sorry, aber lern doch bitte wie man die Fehlermeldungen liest. Die sind zu 98% immer sehr genau an der entsprechenden Stelle! Nur bei fehlenden Klammern ist die Meldung verstreut, aber dafür gibts jetzt ja die Möglichkeit sie mit Autocomplete sofort zu schließen.


Da habe ich vermutlich mehr Erfahrung als du!
Ich programmiere jetzt seit 25 Jahren in C, hauptsächlich auf Microcontrollern, also ohne bestehendes Betriebssystem. Betriebssysteme habe ich auch schon ein paar geschriben. Zudem war ich an der Entwicklung mehrerer C-Compiler beteiligt.
Beruflich programmiere ich Microprozessoren seit 1976, anfangs mit einem KIM-1, alles von Hand auf Papier assembliert und Hex eingegeben. War eine heiden Arbeit!
Das waren damals Prüfprogamme, mit denen Hardware in der Fabrikation getestet wurde.

Sollte eigentlich an Erfahrung genügen.


[CODE]
Der Compiler will hinter uint8_t eine Klammer. Warum ist mir jetzt auch nicht bewusst. Evtl liegts am uint8_t.


Das ist mit Garantie so.
Der Compiler kennt uint8_t nicht, also wird es lexikalisch als Bezeichner gewertet. Bei der syntaktischen Prüfung ist dann uint8_t kein Datentyp, muss also eine Variable sein, folglich kann daruf nur ein ",", eine andere Variable oder eine ")" folgen!

Folglöich kennt der Compiler an dieser Stelle uint8_t nicht, dass hast du aber bestritten!

Ich habe nicht immer die Zeit und Lust lange Romane zu schreiben!
Deshalb meine Kurze Bemerkung, dass der Compiler uint8_t nicht kennt und der eigentliche Fehler irgendwo vorher zu suchen ist.

Ich habe es schon zur genüge erlebt, dass in Projeten ein Tippfel in eine HeaderDatei, erst viele Seiten und andere Includes später zu einem Fehler führt.
Jeder der etwas mehr Erfahrung mit C hat, kennt das eben, dass der Fehler zwischen Anfang und der gemeldeten Stelle liegt.
Das hängt halt eben auch mit der Freiheit der Sprache zusammen, je restriktiver eine Sprache ist, umso genauer kann die Syntax-Fehlerstelle angegeben werden.

MfG Peter(TOO)

Wsk8
05.10.2013, 16:32
Da habe ich vermutlich mehr Erfahrung als du!
Ich programmiere jetzt seit 25 Jahren in C, hauptsächlich auf Microcontrollern, also ohne bestehendes Betriebssystem. Betriebssysteme habe ich auch schon ein paar geschriben. Zudem war ich an der Entwicklung mehrerer C-Compiler beteiligt.
Beruflich programmiere ich Microprozessoren seit 1976, anfangs mit einem KIM-1, alles von Hand auf Papier assembliert und Hex eingegeben. War eine heiden Arbeit!
Das waren damals Prüfprogamme, mit denen Hardware in der Fabrikation getestet wurde.

Sollte eigentlich an Erfahrung genügen.
Dann frage ich mich aber, welche Compiler du verwendest?! Der GCC, den ich verwende, gibt die Fehler zu 98% sehr genau aus!! Wenns nicht so genau ist, dann liegts im Normalfall daran, dass man ein Semikolon oder eine Klammer vergessen hat. Und bei solchen Fehlern treten meistens sowieso mehrere Fehler auf, da die ganze Struktur nicht passt.

Auch frage ich mich, wie du zu der Ansicht gelangt bist, dass der Fehler wo anders als an der angegebenen Stelle liegt? Der Fehler war nämlich mitten in der Parameterliste und uint8_t ist kein selbstdefinierter Typ wo man mal ein Semikolon etc vergisst.


Folglöich kennt der Compiler an dieser Stelle uint8_t nicht, dass hast du aber bestritten!
Ich habe gar nichts bestritten :confused: Dazu kann ich mich sogar selbst zitieren:

Nein, aber Peter hat zumindest schon auf der 2 Seite den Hinweis dazu gegeben, denn aber jeder ignoriert hat weil es ja ein sogenannter "RP6-Experte" aus dem RP6-Forum besser wusste.


Deshalb meine Kurze Bemerkung, dass der Compiler uint8_t nicht kennt und der eigentliche Fehler irgendwo vorher zu suchen ist.
Du musst auch keinen langen Romane schreiben. Die einfachste Antwort war einfach: "#include <stdint.h>"

mfg

Peter(TOO)
06.10.2013, 00:22
Hallo,

Der GCC, den ich verwende, gibt die Fehler zu 98% sehr genau aus!!

Meistens trifft der Compiler auch die Stelle, aber:

1. Der Pre-Prozessor funktioniert, etwas vereinfacht, wie "suchen und ersetzen" in einen Texteditor. Fehler welche durch Macros entstehen, treten daher nicht an der Stelle wo das "#define" steht auf, sondern dort wo das Macro verwendet wird.

2. Selbiges gilt auch, wie in diesem Fall, für fehlende "typedef". Wobei ich jetzt keine Ahnung habe, wie die Definition in der verwendeten Implementierung gemacht wird. Grundsätlich ist die Verwendung von "typedef" und "#define" in diesem Fall gleichwertig.

3. Eine fehlende "}" wird oft erst bei der Definition der nächsten Funktion erkannt. Das liegt an der gültigen Syntax von C.



Auch frage ich mich, wie du zu der Ansicht gelangt bist, dass der Fehler wo anders als an der angegebenen Stelle liegt? Der Fehler war nämlich mitten in der Parameterliste und uint8_t ist kein selbstdefinierter Typ wo man mal ein Semikolon etc vergisst.

uint8_t gibt es in Standard-C erst seit C99.
Compilertechnisch, bleibt es aber ein selbst definierter Datentyp.
Das dieser in stdint.h hinterlegt ist, ist eine implementierungsspezifische Erweiterung, dieser muss nicht in einer konkreten Implementierung vorhanden sein.
Hier mal die Datentypen welche Standard-C kennt:
http://en.wikipedia.org/wiki/C_data_types

C ist wohl die am meisten falsch verstandene Sprache.
Der Compiler kennt nur um die 30-40 Schlüsselwörter und eine Hand voll Operatoren.
Der ganze Rest wie z.B. itoa();, printf(); usw., sind Funktionen welche sich in, heute standartisierten, Bibliotheken befinden und sich aber, aus Sicht des Compilers, in keiner Weise von eigenen Funktionen unterscheiden.
Ursprünglich, nach K&R, waren die ganzen Bibliothen nicht direkter Bestandteil der Sprachdefinition.

Dies mach aber die ganze Stärke von C aus!
In Pascal gab es z.B. keine Möglichkeit, Funktionen mit variabler Parameterzahl zu schreiben. Einzig write() konnte dies, weil write() ein Schlüsselwort war und der Compiler bei diesem eine Ausnahme machte. Änlich ist es bei BASIC mit PRINT.
Bei C kann ich problemlos das printf() durch eine eigene Funktion ersetzen und dann Programme, ohne Änderung, überersetzen und mit meinem printf() linken.
Auch kann man in C ein eigenes Dateisystem schreiben. Ich habe das bei vielen µP-Anwendungen gemacht. Da gab es vielleicht nur zwei Datwenstrukturen, welche als Datei angesprochen werden konnten. Das Dateisystem konnte deshalb nur mit zwei, fest vorgegebenen "Dateinamen" arbeiten, auf die konnte man dann aber über die "normalen Dateifunktionen" zugreifen. Dies hatte den Vorteil, dass der selbe Sourcecode auch auf einem PC verwendet werden konnte, auf dem µP aber kein aufwändiges Dateisysten programmiert werden musste. Zudem konnte jeder C-Programmierer erkennen, was der Code macht.



Du musst auch keinen langen Romane schreiben. Die einfachste Antwort war einfach: "#include <stdint.h>"


Dies gilt scheinbar nur bei dem verwendeten Compiler und den, bzw. die verwendeten Bibliotheken, kenne ich (noch) nicht, da ich bisher nicht mit dem AVR gearbeitet habe.
Zudem gibt es auch noch das Problem der richtigen Reihenfolge, da war der UP auch recht zurückhaltend.

MfG Peter(TOO)

inka
06.10.2013, 14:14
hallo,

eine lösung für den rücksprung aus dem jeweiligen zweig der programmstruktur - was ja der ursprung des threads war - habe ich nun für mich gefunden:


#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_MultiIOLib.h"
#include "RP6Control_I2CMasterLib.h"

#include "RP6ControlServoLib.h"
#include "RP6Control_OrientationLib.h"
#define I2C_RP6_BASE_ADR 10



/************************************************** ***************************/
// Variables:

uint8_t ch;
char item[12];
char dir[3];

/************************************************** ***************************/
/**
* Returns a 2 character string for the eighth
* parts of the direction calculated from the
* heading value.
*
* Input: heading -> Heading value [0..359]
*
*/
void calculateDir(char *dir, uint16_t heading)
{
dir[1] = ' ';
dir[2] = '\0';
if ((heading <= 22) || (heading >=338)) dir[0] = 'N';
if ((heading >= 23) && (heading <= 67)) {dir[0] = 'N'; dir[1] = 'E';}
if ((heading >= 68) && (heading <= 112)) dir[0] = 'E';
if ((heading >= 113) && (heading <= 157)) {dir[0] = 'S'; dir[1] = 'E';}
if ((heading >= 158) && (heading <= 202)) dir[0] = 'S';
if ((heading >= 203) && (heading <= 247)) {dir[0] = 'S'; dir[1] = 'W';}
if ((heading >= 248) && (heading <= 292)) dir[0] = 'W';
if ((heading >= 293) && (heading <= 337)) {dir[0] = 'N'; dir[1] = 'W';}
}

/******************Write a floating point number to the LCD and terminal***********************/

/**
*
*
* Example:
*
* // Write a floating point number to the LCD (no exponent):
* writeDoubleLCD(1234567.890, 11, 3);
*
* The value of prec (precision) defines the number of decimal places.
* For 32 bit floating point variables (float, double ...) 6 is
* the max. value for prec (7 relevant digits).
* The value of width defines the overall number of characters in the
* floating point number including the decimal point. The number of
* pre-decimal positions is: (width - prec - 1).
*/
void writeDoubleLCD(double number, uint8_t width, uint8_t prec)
{char buffer[width + 1];
dtostrf(number, width, prec, &buffer[0]);
writeStringLCD(&buffer[0]);
}

void writeDouble(double number, uint8_t width, uint8_t prec)
{char buffer[width + 1];
dtostrf(number, width, prec, &buffer[0]);
writeString(&buffer[0]);
}



/*********************I2C-fehlermeldungen******************/

void I2C_transmissionError(uint8_t errorState) //gibt I2C fehlermeldungen über LCD aus
{
clearLCD();
writeStringLCD_P("I2C ERROR -->");
setCursorPosLCD(1, 0); // line 2
writeStringLCD_P("TWI STATE: 0x");
writeIntegerLCD(errorState, HEX);
}


/*****************gyroscope***************/
void gyroscope(void) // L3GD20 gyroscope

{
mSleep(1000);
task_I2CTWI();
readL3GD20(); // Get sensor values
// normalizeL3GD20();
task_I2CTWI();
clearLCD();
setCursorPosLCD(0, 0); // line 1
writeStringLCD_P("X");
writeIntegerLCD(x_axisg, DEC);
setCursorPosLCD(0, 6); // line 1 pos 6
writeStringLCD_P("Y");
writeIntegerLCD(y_axisg, DEC);
setCursorPosLCD(0, 12); // line1 pos 12
writeStringLCD_P("Z");
writeIntegerLCD(z_axisg, DEC);

// setCursorPosLCD(1, 0); // line 2
// writeStringLCD_P("X");
writeString_P("x: ");
writeDouble(xg, 1, 1);
writeString_P("\n");
/* setCursorPosLCD(1, 6); // line 2 pos 6
writeStringLCD_P("Y");
writeIntegerLCD(yg, DEC);
setCursorPosLCD(1, 12); // line 2 pos 12
writeStringLCD_P("Z");
writeIntegerLCD(zg, DEC);*/

/*********/
/* setServoPower(1);
initSERVO(SERVO1);
setServo(1, SERVO1_LT);
mSleep(50);
setServo(1, SERVO1_RT);
mSleep(100);
setServoPower(0);
task_SERVO();

*/
/*********/

#ifdef GET_TEMP
temperatureg = calcTempL3GD20(temperatureg) + 5;
temperatureg += OFFSET_TEMP;
setCursorPosLCD(1, 8); // line 2 pos 9
writeStringLCD_P("T");
writeIntegerLCD(temperatureg, DEC);
writeStringLCD_P(" ");
#endif
mSleep(2000);//3 sec
clearLCD();
task_I2CTWI();
}

/************accelerometer****************/
void accelerometer(void) // LSM303DLHC accelerometer
{
mSleep(1000);
task_I2CTWI();
readLSM303DLHC_A(); // Get sensor values
// normalizeLSM303DLHC_A();
task_I2CTWI();
setCursorPosLCD(0, 0); // line 1
writeStringLCD_P("X");
writeIntegerLCD(x_axisa, DEC);
writeStringLCD_P(" ");
setCursorPosLCD(0, 5); // line 1 pos 6
writeStringLCD_P("Y");
writeIntegerLCD(y_axisa, DEC);
writeStringLCD_P(" ");
setCursorPosLCD(0, 10); // line 1 pos 11
writeStringLCD_P("Z");
writeIntegerLCD(z_axisa, DEC);
writeStringLCD_P(" ");
// normalizeLSM303DLHC_A(); // Normalize data
positionLSM303DLHC_A(); // Calculate position
setCursorPosLCD(1, 0); // line 2
writeStringLCD_P("P");
writeDoubleLCD(pitch, 6, 1);
writeStringLCD_P(" ");
setCursorPosLCD(1, 8); // line 2 pos 9
writeStringLCD_P("R");
writeDoubleLCD(roll, 6, 1);
writeStringLCD_P(" ");
mSleep(2000);
clearLCD();
task_I2CTWI();
}

/*****************magnetometer************/
void magnetometer(void) // LSM303DLHC magnetometer
{
mSleep(1000);
task_I2CTWI();
readLSM303DLHC_M(); // Get sensor values
// normalizeLSM303DLHC_M();
task_I2CTWI();
setCursorPosLCD(0, 0); // line 1
writeStringLCD_P("X");
writeIntegerLCD(x_axism, DEC);
writeStringLCD_P(" ");
setCursorPosLCD(0, 5); // line 1 pos 6
writeStringLCD_P("Y");
writeIntegerLCD(y_axism, DEC);
writeStringLCD_P(" ");
setCursorPosLCD(0, 10); // line 1 pos 11
#ifndef GET_TEMP_M
writeStringLCD_P(" Z");
writeIntegerLCD(z_axism, DEC);
writeStringLCD_P(" ");
#else
temperature_imu = (double) temperaturem / 8.0 + OFFSET_TEMP_M;
writeStringLCD_P("T");
writeDoubleLCD(temperature_imu, 5, 1);
#endif

// normalizeLSM303DLHC_M(); // Normalize data
headingm = headingLSM303DLHC_M(); // Calculate heading
calculateDir(dir, headingm);
setCursorPosLCD(1, 0); // line 2
writeStringLCD_P("H");
writeIntegerLengthLCD(headingm, DEC, 3);
writeStringLCD_P(" ");
writeStringLCD(dir);
headingtc = headingLSM303DLHC_TC(); // Calculate TILT COMPENSATED
calculateDir(dir, headingtc); // heading
writeStringLCD_P(" C");
writeIntegerLengthLCD(headingtc, DEC, 3);
writeStringLCD_P(" ");
writeStringLCD(dir);
writeStringLCD_P(" ");
mSleep(1000);
// clearLCD();
task_I2CTWI();
}


/*************** hauptprogramm ***********/

int main(void)
{


initRP6Control();
multiio_init();
initLCD();
//orientation_init();


setLEDs(0b1111);
mSleep(500);
setLEDs(0b0000);

I2CTWI_initMaster(100);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError); //aktiviert I2C fehlermeldungen

showScreenLCD(" RP6Control M32", " calibrate_imu");
mSleep(2500);
clearLCD();

orientation_init();

while(true)
{

/*****************anzeige gedrückter buttons****************/
clearLCD();
pressedMultiIOButtonNumber = getMultiIOPressedButtonNumber();
setCursorPosLCD(0, 0);
writeStringLCD("Button: ");
writeIntegerLCD(pressedMultiIOButtonNumber, DEC);
mSleep(500);

uint8_t key = getMultiIOPressedButtonNumber();


/********************funktion der buttons*********************/
if(key)
{
switch(key)
{
case 1://
setLEDs(0b0001);

while(true)
{
setLEDs(0b0001);
gyroscope();
mSleep(500);
clearLCD();

/**************************/
uint8_t key_1 = getMultiIOPressedButtonNumber();
key_1 = getMultiIOPressedButtonNumber();
if(key_1 != 0)
{
break;
}
/**************************/
}

break;

case 2://
setLEDs(0b0010);

while(true)
{
setLEDs(0b0010);
accelerometer();
mSleep(500);
clearLCD();

/**************************/
uint8_t key_1 = getMultiIOPressedButtonNumber();
key_1 = getMultiIOPressedButtonNumber();
if(key_1 != 0)
{
break;
}
/**************************/
}

break;

case 3://
setLEDs(0b0100);

while(true)
{
magnetometer();
mSleep(50);
clearLCD();

/**************************/
uint8_t key_1 = getMultiIOPressedButtonNumber();
key_1 = getMultiIOPressedButtonNumber();
if(key_1 != 0)
{
break;
}
/**************************/
}

break;

case 4://
setLEDs(0b1000);

while(true)
{
setLEDs(0b1000);
gyroscope();
mSleep(50);
clearLCD();
accelerometer();
mSleep(50);
clearLCD();
magnetometer();
mSleep(50);
clearLCD();

/**************************/
uint8_t key_1 = getMultiIOPressedButtonNumber();
key_1 = getMultiIOPressedButtonNumber();
if(key_1 != 0)
{
break;
}
/**************************/
}

break;

}
}


}


return 0;
}

damit kann ich jetzt z.b. den 3D-gyro (und seine einzelnen komponenten) testen und werte überprüfen ohne unnütz warten zu müssen bis nun die erwünschte einzelfunktion wiederkommt...

nochmals dank an alle die mir hierbei geholfen haben...

Wsk8
06.10.2013, 14:26
Zur Lösung willst du keine 3 Wörter schreiben, aber jetzt schreibst du doch auf einmal nen halben Roman :confused:
Besser du machst es das nächste mal gleich am Anfang mit der Lösung, dann können wir uns ein paar Seiten sparen ;)

Und was soll jetzt der Grundkurs in C?? Hab ich alles schon 100x gehört und wer es nicht weis, kann es auch schnell selbst googlen. Das ist keine Kunst, es ist eher eine Schande wenn man es als C-Programmierer nicht weiß.

Da für mich die STL zu C gehört, gehört auch uint8_t für mich dazu! Wie der implementiert ist, ist für mich relativ egal.


Dies gilt scheinbar nur bei dem verwendeten Compiler und den, bzw. die verwendeten Bibliotheken, kenne ich (noch) nicht, da ich bisher nicht mit dem AVR gearbeitet habe.
Ähm nein?! stdint.h gibts bei eigentlich jedem Compiler. Wenn man portablen Sourcecode erstellen will, sollte man sogar stdint verwenden, da ein integer je nach System anders ist.

mfg

inka
06.10.2013, 15:21
so jetzt machen wir hier schluss