User avatar
scootergarrett
Posts: 55
Joined: Sat Apr 19, 2014 2:36 pm

GTK and pigpio.h level change callback

Thu Dec 26, 2019 2:02 pm

I'm working on a larger project, running into issues with changing the text on a GUI based on the state of a GPIO pin. The text on the GUI changes when the state of pin 17 changes state using the gpioSetAlertFunc to call a function. After a few pin changes (not always the same amount) I get an error and the GUI stops updating when the pin changes. I’ve boiled the code down to the simplest that has the issue.

error:

Code: Select all

(SimpleProblem:17582): GLib-CRITICAL **: 08:45:46.898: Source ID 25 was not found when attempting to remove it


SimpleProblem.h:

Code: Select all

#include <stdio.h>          /// IO functions
#include <string.h>         /// String functions
#include <math.h>           /// Math functions
#include <stdlib.h>         /// Various functions
#include <pigpio.h>         /// Raspberry pi GPIO stuff
#include <gtk/gtk.h>        /// GUI Functions

#define FloatLevelSwitchGPIO 17

GtkWidget *DisplayTextW;

/// Closes the window and program when 'X' is pressed ///
void end_program(GtkWidget *wid, gpointer ptr)
{
    gtk_main_quit();
}

/// Function get called when ever FloatLevelSwitchGPIO changes state ///
void FloatSwitchWatchF(int gpio, int level, uint32_t tick)
{
    // Change the text on the GUI based on the state of FloatLevelSwitchGPIO pin //
    if(gpioRead(FloatLevelSwitchGPIO))
        gtk_label_set_text(GTK_LABEL(DisplayTextW), "LOW LEVEL WARNING");
    else
        gtk_label_set_text(GTK_LABEL(DisplayTextW), "Level OK");
}


void main(int argc, char *argv[])
{
    GtkWidget *win, *BigButtonW, *tab;

    /// Set up the FloatLevelSwitchGPIO as an input that triggers FloatSwitchWatchF function ///
    gpioInitialise();
    gpioSetMode(FloatLevelSwitchGPIO, PI_INPUT);
    gpioSetPullUpDown(FloatLevelSwitchGPIO, PI_PUD_UP);
    gpioSetAlertFunc(FloatLevelSwitchGPIO, FloatSwitchWatchF);

    /// Sets up GTK buttons exc ///
    gtk_init(NULL, NULL);
    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    DisplayTextW = gtk_label_new("OFF");
    BigButtonW = gtk_button_new_with_label("BUTTON DOSE NOTHING");
    // Connect the buttons //
    g_signal_connect(win, "delete_event", G_CALLBACK(end_program), NULL);
    // Layout stuff //
    tab = gtk_table_new (4, 4, TRUE);
    gtk_table_attach_defaults(GTK_TABLE(tab), BigButtonW, 0, 4, 0, 1);
    gtk_table_attach_defaults(GTK_TABLE(tab), DisplayTextW, 0, 4, 1, 3);
    gtk_container_add(GTK_CONTAINER(win), tab);
    // Show gtk stuff //
    gtk_widget_show_all(win);
    gtk_main();
}
Compiled with:

Code: Select all

gcc -c ./SimpleProblem.c -o ./SimpleProblem.o `pkg-config --cflags --libs gtk+-2.0` ; g++  -o ./$var ./SimpleProblem.o  -lpthread -lpigpio -lrt `pkg-config --cflags --libs gtk+-2.0` ; sudo ./SimpleProblem
I know this is a specific problem with both GTK and pigpio stuff going on. any help is appreciated.
THANKS

User avatar
PeterO
Posts: 5467
Joined: Sun Jul 22, 2012 4:14 pm

Re: GTK and pigpio.h level change callback

Thu Dec 26, 2019 2:14 pm

My first guess wild be that the gpio callback is running in a different thread to the GTK event loop.

If I was doing this, I would make the gpio callback do as little work as possible, may be just setting a flag. Then create an event source for the gtk event loop that checks the state of the flag and then act on it.

Oh look.... I've been here before !
https://www.raspberrypi.org/forums/view ... p?t=232257

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
scootergarrett
Posts: 55
Joined: Sat Apr 19, 2014 2:36 pm

Re: GTK and pigpio.h level change callback

Thu Dec 26, 2019 4:12 pm

I made a g_thread_new that controls the display text. It updates the text every 50ms. This seems to work for longer but eventual stops working the same as before

Code: Select all

#include <stdio.h>          /// IO functions
#include <string.h>         /// String functions
#include <math.h>           /// Math functions
#include <stdlib.h>         /// Various functions
#include <stdbool.h>        /// Boolean type and values
#include <pigpio.h>         /// Raspberry pi GPIO stuff
#include <gtk/gtk.h>        /// GUI Functions

#define FloatLevelSwitchGPIO 17

bool LowLevelB;

/// Closes the window and program when 'X' is pressed ///
void end_program(GtkWidget *wid, gpointer ptr)
{
    gtk_main_quit();
}

/// Function get called when ever FloatLevelSwitchGPIO changes state ///
void FloatSwitchWatchF(int gpio, int level, uint32_t tick)
{
    if(gpioRead(FloatLevelSwitchGPIO))
        LowLevelB = false;
    else
        LowLevelB = true;
}

/// Thread running updating text WORKS FOR ~1 min then stops working correctly ///
void *DisplayControlThread(gpointer ptr)
{
    while(true)
    {
        usleep(50000);

        // Change the text on the GUI based on the state of LowLevelB //
        if(LowLevelB)
            gtk_label_set_text(GTK_LABEL(ptr), "LOW LEVEL WARNING");
        else
            gtk_label_set_text(GTK_LABEL(ptr), "Level OK");
    }
}


void main(int argc, char *argv[])
{
    GtkWidget *win, *BigButtonW, *tab;
    GtkWidget *DisplayTextW;

    LowLevelB = false;

    /// Set up the FloatLevelSwitchGPIO as an input that triggers FloatSwitchWatchF function ///
    gpioInitialise();
    gpioSetMode(FloatLevelSwitchGPIO, PI_INPUT);
    gpioSetPullUpDown(FloatLevelSwitchGPIO, PI_PUD_UP);
    gpioSetAlertFunc(FloatLevelSwitchGPIO, FloatSwitchWatchF);

    /// Sets up GTK buttons exc ///
    gtk_init(NULL, NULL);
    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    DisplayTextW = gtk_label_new("OFF");
    BigButtonW = gtk_button_new_with_label("BUTTON DOSE NOTHING");
    // Connect the buttons //
    g_signal_connect(win, "delete_event", G_CALLBACK(end_program), NULL);

    // Layout stuff //
    tab = gtk_table_new (4, 4, TRUE);
    gtk_table_attach_defaults(GTK_TABLE(tab), BigButtonW, 0, 4, 0, 1);
    gtk_table_attach_defaults(GTK_TABLE(tab), DisplayTextW, 0, 4, 1, 3);
    gtk_container_add(GTK_CONTAINER(win), tab);
    // Show gtk stuff //
    gtk_widget_show_all(win);

    g_thread_new("THREAD NAME", DisplayControlThread, DisplayTextW);

    gtk_main();
}
should I be using some 'g_signal_connect' to connect a function to the sate of LowLevelB?

User avatar
PeterO
Posts: 5467
Joined: Sun Jul 22, 2012 4:14 pm

Re: GTK and pigpio.h level change callback

Thu Dec 26, 2019 4:17 pm

The only advice I can offer is this :
GTK+, however, is not thread safe. You should only use GTK+ and GDK from the thread gtk_init() and gtk_main() were called on. This is usually referred to as the “main thread”.
taken from https://developer.gnome.org/gdk3/stable ... reads.html
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
scootergarrett
Posts: 55
Joined: Sat Apr 19, 2014 2:36 pm

Re: GTK and pigpio.h level change callback

Thu Dec 26, 2019 5:13 pm

Thanks a lot. I think I have the solution (still stress testing program, but its running strong for 10+ minutes). I'm using a timed callback g_timeout_add, to call a function on a time schedule, and updating the text from there. I think this keeps it in the GTK thread 'scope' (may be wrong use of scope). also need to add time_handler(win); before gtk_main();

Code: Select all

#include <stdio.h>          /// IO functions
#include <string.h>         /// String functions
#include <math.h>           /// Math functions
#include <stdlib.h>         /// Various functions
#include <stdbool.h>        /// Boolean type and values
#include <pigpio.h>         /// Raspberry pi GPIO stuff
#include <gtk/gtk.h>        /// GUI Functions

#define FloatLevelSwitchGPIO 17

bool LowLevelB;
    GtkWidget *DisplayTextW;

/// Closes the window and program when 'X' is pressed ///
void end_program(GtkWidget *wid, gpointer ptr)
{
    gtk_main_quit();
}

/// Function gets called when ever FloatLevelSwitchGPIO changes state ///
void FloatSwitchWatchF(int gpio, int level, uint32_t tick)
{
    if(gpioRead(FloatLevelSwitchGPIO))
        LowLevelB = false;
    else
        LowLevelB = true;
}

/// Function gets called by g_timeout_add on schedule ///
gboolean time_handler(GtkWidget *ptr)
{
    // Change the text on the GUI based on the state of LowLevelB //
    if(LowLevelB)
        gtk_label_set_text(GTK_LABEL(DisplayTextW), "LOW LEVEL WARNING");
    else
        gtk_label_set_text(GTK_LABEL(DisplayTextW), "Level OK");

    return true;
}


void main(int argc, char *argv[])
{
    GtkWidget *win, *BigButtonW, *tab;
    LowLevelB = false;

    /// Set up the FloatLevelSwitchGPIO as an input that triggers FloatSwitchWatchF function ///
    gpioInitialise();
    gpioSetMode(FloatLevelSwitchGPIO, PI_INPUT);
    gpioSetPullUpDown(FloatLevelSwitchGPIO, PI_PUD_UP);
    gpioSetAlertFunc(FloatLevelSwitchGPIO, FloatSwitchWatchF);

    /// Sets up GTK buttons exc ///
    gdk_threads_enter();
    gtk_init(NULL, NULL);
    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    DisplayTextW = gtk_label_new("OFF");
    BigButtonW = gtk_button_new_with_label("BUTTON DOSE NOTHING");
    // Connect the buttons //
    g_signal_connect(win, "delete_event", G_CALLBACK(end_program), NULL);
    // Set up timer with time_handler function //
    g_timeout_add(50, (GSourceFunc) time_handler, (gpointer) win);

    // Layout stuff //
    tab = gtk_table_new (4, 4, TRUE);
    gtk_table_attach_defaults(GTK_TABLE(tab), BigButtonW, 0, 4, 0, 1);
    gtk_table_attach_defaults(GTK_TABLE(tab), DisplayTextW, 0, 4, 1, 3);
    gtk_container_add(GTK_CONTAINER(win), tab);
    // Show gtk stuff //
    gtk_widget_show_all(win);

    time_handler(win);

    gtk_main();
}
Need to scale back up to my more complex program and see what happens. Thanks again

User avatar
joan
Posts: 14695
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: GTK and pigpio.h level change callback

Thu Dec 26, 2019 6:09 pm

piscope is a C GTK application which uses pigpio and the GPIO.

Code at http://abyz.me.uk/rpi/pigpio/piscope.html or https://github.com/joan2937/piscope

User avatar
PeterO
Posts: 5467
Joined: Sun Jul 22, 2012 4:14 pm

Re: GTK and pigpio.h level change callback

Thu Dec 26, 2019 6:47 pm

joan wrote:
Thu Dec 26, 2019 6:09 pm
piscope is a C GTK application which uses pigpio and the GPIO.

Code at http://abyz.me.uk/rpi/pigpio/piscope.html or https://github.com/joan2937/piscope
So where in the 3300 lines of C code (not counting the demon code) is the solution to the OP's problem ? :roll:
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Return to “C/C++”