Reputation: 55
I've just started my first project in C language on raspberry pi 3 and I want to create my first GUI app for touch panel. My goal is to run the while(1) loop which controls the raspberry I/O and the gtk_main function to open a simple window.
After calling gtk_main(), the rest of the code doesn't work. I know it's caused by the fact that gtk_main creates it's own loop. Is there any way to run these two loops simultaneously?
#include <stdio.h> // Used for printf() statements
#include <wiringPi.h> // Include WiringPi library!
#include <gtk/gtk.h>
// Pin number declarations. We're using the Broadcom chip pin numbers.
const int pwmPin = 18; // PWM LED - Broadcom pin 18, P1 pin 12
const int ledPin = 23; // Regular LED - Broadcom pin 23, P1 pin 16
const int butPin = 21; // Active-low button - Broadcom pin 17, P1 pin 11
const int pwmValue = 0; // Use this to set an LED brightness
int main(int argc, char *argv[]){
int add = 0;
int sign = 1;
// Setup stuff:
wiringPiSetupGpio(); // Initialize wiringPi -- using Broadcom pin numbers
pinMode(pwmPin, PWM_OUTPUT); // Set PWM LED as PWM output
pinMode(ledPin, OUTPUT); // Set regular LED as output
pinMode(butPin, INPUT); // Set button as INPUT
pullUpDnControl(butPin, PUD_UP); // Enable pull-up resistor on button
GtkWidget *window;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_main ();
// Loop (while(1)):
while(1)
{
if (digitalRead(butPin)) // Button is released if this returns 1
{
pwmWrite(pwmPin, pwmValue+add); // PWM LED at bright setting
digitalWrite(ledPin, LOW); // Regular LED off
add=add+(sign*50);
if (add==1000) sign=-1;
if (add==0) sign=1;
delay(50);
}
else // If digitalRead returns 0, button is pressed
{
pwmWrite(pwmPin, 1024 - pwmValue); // PWM LED at dim setting
// Do some blinking on the ledPin:
digitalWrite(ledPin, HIGH); // Turn LED ON
delay(75); // Wait 75ms
digitalWrite(ledPin, LOW); // Turn LED OFF
delay(75); // Wait 75ms again
}
}
}
Upvotes: 1
Views: 379
Reputation: 11454
Remove your while loop and use g_idle_add
and/or g_timeout
to trigger your callbacks. This defines when your code is called. Then in your callback, do your pin I/O control stuff. Just remember that using delay
or any blocking function similar to sleep
will freeze your UI for the same amount of time. You may avoid this by using g_idle_add
or g_timeout
to trigger for changing the state again.
Upvotes: 0
Reputation: 1
gtk_main
is documented as:
Runs the main loop until
gtk_main_quit()
is called.You can nest calls to
gtk_main()
. In that casegtk_main_quit()
will make the innermost invocation of the main loop return.
So you need to have some callback explicitly invoking gtk_main_quit
(and I guess you don't).
So the behavior is expected. You may want to handle the "delete-event"
GTK signal on your window
(by having your GTK signal handler for that event calling explicitly gtk_main_quit
). You need to read much more, notably about the GTK event loop, and GObject's signals.
If you want to poll(2) and read(2) some device, you'll better do that inside the GTK event loop (e.g. by calling g_source_add_unix_fd or g_io_channel_unix_new, etc etc...).
You should spend several days reading more about Gtk, notably its Getting Started chapter.
Upvotes: 1
Reputation: 9659
I have two solution in mind to solve your problem:
butPin
value each 100ms,You could use threads:
void *start_gtk_thread(void *arg)
{
gtk_main();
return NULL;
}
void *start_pin_thread(void *arg)
{
while(1)
{
if (digitalRead(butPin)) // Button is released if this returns 1
{
....
}
return NULL;
}
}
And in your main function
gtk_widget_show (window);
/* threads id*/
pthread_t tid[2];
/* create threads */
pthread_create(&tid[0], NULL, start_gtk_thread, NULL);
pthread_create(&tid[1], NULL, start_pin_thread, NULL);
/* wait for threads (warning, they should never terminate) */
pthread_join(id[0], NULL);
pthread_join(id[1], NULL);
Upvotes: 0