proposal:
example code for a Brickpi3 multithreading setup
compile/build flags:
-pthread -lwiringPi
wiringPi Installation: http://wiringpi.com/download-and-install/
share and enjoy!
/*
* example code for a Brickpi3 multithreading setup
* version 0.0.4b
*/
#include <stdbool.h> // boolean types and values
#include <stdio.h> // files, keyboard IO (getchar())
#include <termio.h> // low level XBD (termios, ioctl)
#include <unistd.h> // POSIX/LINUX symbolic constants and types
#include <string.h> // strings+arrays (memcpy())
#include <pthread.h> // multithreading
#include <wiringPi> // GPIOs, delay, millis
#include "BrickPi3.cpp" // for BrickPi3
#include <signal.h> // for catching exit signals
volatile int MT_active=1, Ts1=0, Ts2=0, Ts3=0; // semaphores to control and monitor MT
//===============================================
// create BrickPi instance
//===============================================
BrickPi3 BP;
//===============================================
// Signal handler to be called when Ctrl+C is pressed
//===============================================
void exit_signal_handler(int signo){
if(signo == SIGINT){
MT_active = 0; // signalize threads to terminate by themselves
fprintf( stdout, "\naborted by [CTRL+C]\n" ); // optional
}
}
//===============================================
// mimics conio.h kbhit()
//===============================================
bool kbhit(void)
{
struct termios original;
tcgetattr(STDIN_FILENO, &original);
struct termios term;
memcpy(&term, &original, sizeof(term));
term.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &term);
int characters_buffered = 0;
ioctl(STDIN_FILENO, FIONREAD, &characters_buffered);
tcsetattr(STDIN_FILENO, TCSANOW, &original);
bool pressed = (characters_buffered != 0);
return pressed;
}
//===============================================
// single threads & MT thread control
//===============================================
pthread_mutex_t mutexBP;
void* thread1Name(void *) {
Ts1=1; // indicate thread 1 was started
while(MT_active) {
///... (code/loop)
delay(1); // optional, arbitrarily
}
Ts1=0; // indicate thread 1 was stopped
fprintf( stdout, "\nthread 1 exit message\n" ); // optional
return NULL;
}
void* thread2Name(void *) {
Ts2=1; // indicate thread 2 was started
while(MT_active) {
///... (code/loop)
delay(10); // optional, arbitrarily
}
Ts2=0; // indicate thread 2 was stopped
fprintf( stdout, "\nthread 2 exit message\n" ); // optional
return NULL;
}
void* thread3Name(void *) {
Ts3=1; // indicate thread 3 was started
while(MT_active) {
///... (code/loop)
delay(100); // optional, arbitrarily
}
Ts3=0; // indicate thread 3 was stopped
fprintf( stdout, "\nthread 3 exit message\n" ); // optional
return NULL;
}
//===============================================
// main()
//===============================================
int main() {
signal(SIGINT, exit_signal_handler); // register the exit function for Ctrl+C
pthread_mutex_init (&mutexBP, NULL); // init a mutex for Brickpi access
//----------------------------------------
// mutex handling: lock and unlock
//----------------------------------------
pthread_mutex_lock (&mutexBP); // lock the following variable operations by the BrickPi mutex
// Make sure that the BrickPi3 is communicating and that the firmware is compatible with the drivers:
BP.detect();
// Reset the encoders:
BP.offset_motor_encoder(PORT_A, BP.get_motor_encoder(PORT_A));
BP.offset_motor_encoder(PORT_B, BP.get_motor_encoder(PORT_B));
BP.offset_motor_encoder(PORT_C, BP.get_motor_encoder(PORT_C));
BP.offset_motor_encoder(PORT_D, BP.get_motor_encoder(PORT_D));
pthread_mutex_unlock (&mutexBP); // release the mutex to write/read by different threads
//----------------------------------------
// create and start the pthread threads
//----------------------------------------
pthread_t tid1, tid2, tid3; // thread IDs
pthread_create(&tid1, NULL, thread1Name, NULL);
pthread_create(&tid2, NULL, thread2Name, NULL);
pthread_create(&tid3, NULL, thread3Name, NULL);
delay(1); // give the threads a chance to start
//----------------------------------------
// keyboard handler: terminate by ESC key
//----------------------------------------
while(MT_active) {
if ( kbhit() ) {
int key = getchar();
if (key==27) { // ESC == ASCII 27
MT_active = 0;
fprintf( stdout, "\naborted by [ESC]\n" ); // optional
break();
}
}
// optional: rest of a perpetual main() code
// instead, put BP code into a proprietary thread
delay(100); // optional
}
//----------------------------------------
// wait for threads to join before exiting
//----------------------------------------
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
//----------------------------------------
// reset and then terminate
//----------------------------------------
pthread_mutex_lock (&mutexBP); // not compellingly required here, just to demonstrate mutexes
BP.reset_all(); // Reset everything so there are no run-away motors
pthread_mutex_unlock (&mutexBP);
return 0;
}
edited, c+p mistake