Hi,
die erste Frage hast du dir schon selbst beantwortet. Den Dereferenzierungsoperator "->" brauchst du nicht mehr, wenn du mit dem Array von Strukturen arbeitest. Du musst nur den Index für einen Motor als Parameter in die Thread-Main bekommen, indem deine PID-Kalkulationen sind.
Zu deiner zweiten Frage: das Element kannst du weglassen denn wir werden diese id als index übergeben.
Zu deiner letzten Frage:
schau mal die Signatur der pthread_create genau an (mit "$> man pthread_create" in 'nem Terminal unter Linux gibt's die Erklärungsseite zu sehen):
Code:
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
Parameter eins ist ein Zeiger auf das pthread Handle. So wie in deinem RotatePID-Beispiel passt das schon mal.
Parameter zwei ist ein unveränderlicher Zeiger auf eine Attributstruktur. Es gibt paar, das wichtigste ist das deine Threads mit pthread_cancel sich unterbrechen liessen. Da das ein Default-Wert ist und die anderen Attribute erstmal nicht wichtig sind, kannst du hier eine 0 oder NULL reingeben, was heist, das die Defaults verwendet werden.
Parameter drei ist jetzt der Zeiger auf die Funktion, welche die Thread-Main sein soll. In deinem Fall gibst du da einfach den Namen der PID-Kalkulationsroutine an (die ist ja wohl für alle gleich?).
Parameter vier ist ein Zeiger ohne konkreten Datentypen, also void. Da Zeiger in C immer vorzeichenlose, integrale Datentypen sind können wir hier ausnahmsweise den Wert des Zeigers als unsigned int für den Index in das Array missbrauchen und so sicherstellen, das ein Thread immer nur auf ein bestimmtest Element des Arrays zurgreifen wird.
Der Erzeugungsaufruf in RotatePID sähe also so aus:
Code:
pthread_create( &motor[port].tid, // id speichern in dem dazugehörigen Array-Element
0, // Default Attribute (threads cancelbar)
pid_calc, // Name der PID-Kalkulationsroutinge
(void*)port); // der Index des Array-Elements für eine PID Struktur, die mit dem Motorindex gleich ist.
// Der cast ist notwendig, sonst meckert der Compiler.
in der "pid_calc" müssen wir dann den Wert des Zeigers einmal am Anfang in einen "unsigned int" casten und diese Variable verwendest du bei den Arrayzugriffen und in deinen Unterfunktionen als Wert für den port Parameter.
Die Signatur ist bindend!:
Code:
void *pid_calc(void *arg) {
// Was immer du für Variablen brauchst
// Zeigerwert in Arrayindex wandeln.
unsigned port = (unsigned)arg;
// Nur als sinnloses Bsp.
motor[port].P = 0.4;
// Was immer du rechnen magst.
pthread_exit(0);
}
Wenn du einen anderen Namen verwenden willst, musst du nur darauf achten das die Routine "void*" als Rückgabewert hat und es genau einen Parameter gibt mit "void*" als Typ.
Code:
void* welcher_name_auch_immer(void *arg) { ... }
Das war's.
Gruss
botty
P.S. leider sind die Formatierungen in den code-Tags verrutscht, hoffe es ist trotzdem lesbar.
Lesezeichen