With Python, how to prevent two threads from writing simultaneously to display











up vote
0
down vote

favorite












I'm working on a Raspberry Pi project where I have an OLED display that is continuously updated with information in a Python while True-loop. However, whenever I press a button (GPIO 5) I would like to display some other static information (e.g. system info) for as long as the button is depressed, or possibly for a predefined period of time. When the button is released, the "main loop" may take over again.
I have tried to implement this using RPi.GPIO and a callback function for the display of system info, but the problem is of course that even during the callback function execution, the main loop continues writing to the OLED, creating garbage on the OLED if GPIO 5 is depressed: Both "threads" are writing simultaneously to the OLED...



I assume I need a way to pause the execution of the main loop during the callback function and I have experimented with Semaphore and aquire/release but with no luck. I have also considered the possibility of having two callback functions in combination with Semaphore, but since the info displayed in the main loop should be continuously updated (e.g. not interrupt-driven) I'm not so sure that is a solution for me.



At this point I am not even sure what to google next. Perhaps someone in here can enlighten me? Is this perhaps a totally wrong way of doing this kind of thing? (Limited experience with Python...)



Below is a simplified code example that simulates what I would like to do.



import time
import Adafruit_GPIO.SPI as SPI
import RPi.GPIO as GPIO
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

# Initialize
disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
disp.begin()
disp.clear()
disp.display()
image = Image.new('1', (disp.width, disp.height))
draw = ImageDraw.Draw(image)
font = ImageFont.load_default()
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

def clear_display():
draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
disp.image(image)
disp.display()

# Callback function
def display_system_info(channel):
draw.text((0, 0), "System info displayed", font=font, fill=255)
draw.text((0, 9), "for five seconds.", font=font, fill=255)
disp.image(image)
disp.display()
time.sleep(5)
clear_display()

GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

try:
while True:
for counter in range(7):
draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
disp.image(image)
disp.display()
time.sleep(1)
clear_display()
except KeyboardInterrupt:
GPIO.cleanup() # clean up GPIO on CTRL+C exit
GPIO.cleanup() # clean up GPIO on normal exit


Many thanks for any help.



/N










share|improve this question


























    up vote
    0
    down vote

    favorite












    I'm working on a Raspberry Pi project where I have an OLED display that is continuously updated with information in a Python while True-loop. However, whenever I press a button (GPIO 5) I would like to display some other static information (e.g. system info) for as long as the button is depressed, or possibly for a predefined period of time. When the button is released, the "main loop" may take over again.
    I have tried to implement this using RPi.GPIO and a callback function for the display of system info, but the problem is of course that even during the callback function execution, the main loop continues writing to the OLED, creating garbage on the OLED if GPIO 5 is depressed: Both "threads" are writing simultaneously to the OLED...



    I assume I need a way to pause the execution of the main loop during the callback function and I have experimented with Semaphore and aquire/release but with no luck. I have also considered the possibility of having two callback functions in combination with Semaphore, but since the info displayed in the main loop should be continuously updated (e.g. not interrupt-driven) I'm not so sure that is a solution for me.



    At this point I am not even sure what to google next. Perhaps someone in here can enlighten me? Is this perhaps a totally wrong way of doing this kind of thing? (Limited experience with Python...)



    Below is a simplified code example that simulates what I would like to do.



    import time
    import Adafruit_GPIO.SPI as SPI
    import RPi.GPIO as GPIO
    import Adafruit_SSD1306
    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageFont

    # Initialize
    disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
    disp.begin()
    disp.clear()
    disp.display()
    image = Image.new('1', (disp.width, disp.height))
    draw = ImageDraw.Draw(image)
    font = ImageFont.load_default()
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

    def clear_display():
    draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
    disp.image(image)
    disp.display()

    # Callback function
    def display_system_info(channel):
    draw.text((0, 0), "System info displayed", font=font, fill=255)
    draw.text((0, 9), "for five seconds.", font=font, fill=255)
    disp.image(image)
    disp.display()
    time.sleep(5)
    clear_display()

    GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

    try:
    while True:
    for counter in range(7):
    draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
    disp.image(image)
    disp.display()
    time.sleep(1)
    clear_display()
    except KeyboardInterrupt:
    GPIO.cleanup() # clean up GPIO on CTRL+C exit
    GPIO.cleanup() # clean up GPIO on normal exit


    Many thanks for any help.



    /N










    share|improve this question
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I'm working on a Raspberry Pi project where I have an OLED display that is continuously updated with information in a Python while True-loop. However, whenever I press a button (GPIO 5) I would like to display some other static information (e.g. system info) for as long as the button is depressed, or possibly for a predefined period of time. When the button is released, the "main loop" may take over again.
      I have tried to implement this using RPi.GPIO and a callback function for the display of system info, but the problem is of course that even during the callback function execution, the main loop continues writing to the OLED, creating garbage on the OLED if GPIO 5 is depressed: Both "threads" are writing simultaneously to the OLED...



      I assume I need a way to pause the execution of the main loop during the callback function and I have experimented with Semaphore and aquire/release but with no luck. I have also considered the possibility of having two callback functions in combination with Semaphore, but since the info displayed in the main loop should be continuously updated (e.g. not interrupt-driven) I'm not so sure that is a solution for me.



      At this point I am not even sure what to google next. Perhaps someone in here can enlighten me? Is this perhaps a totally wrong way of doing this kind of thing? (Limited experience with Python...)



      Below is a simplified code example that simulates what I would like to do.



      import time
      import Adafruit_GPIO.SPI as SPI
      import RPi.GPIO as GPIO
      import Adafruit_SSD1306
      from PIL import Image
      from PIL import ImageDraw
      from PIL import ImageFont

      # Initialize
      disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
      disp.begin()
      disp.clear()
      disp.display()
      image = Image.new('1', (disp.width, disp.height))
      draw = ImageDraw.Draw(image)
      font = ImageFont.load_default()
      GPIO.setmode(GPIO.BCM)
      GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

      def clear_display():
      draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
      disp.image(image)
      disp.display()

      # Callback function
      def display_system_info(channel):
      draw.text((0, 0), "System info displayed", font=font, fill=255)
      draw.text((0, 9), "for five seconds.", font=font, fill=255)
      disp.image(image)
      disp.display()
      time.sleep(5)
      clear_display()

      GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

      try:
      while True:
      for counter in range(7):
      draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
      disp.image(image)
      disp.display()
      time.sleep(1)
      clear_display()
      except KeyboardInterrupt:
      GPIO.cleanup() # clean up GPIO on CTRL+C exit
      GPIO.cleanup() # clean up GPIO on normal exit


      Many thanks for any help.



      /N










      share|improve this question













      I'm working on a Raspberry Pi project where I have an OLED display that is continuously updated with information in a Python while True-loop. However, whenever I press a button (GPIO 5) I would like to display some other static information (e.g. system info) for as long as the button is depressed, or possibly for a predefined period of time. When the button is released, the "main loop" may take over again.
      I have tried to implement this using RPi.GPIO and a callback function for the display of system info, but the problem is of course that even during the callback function execution, the main loop continues writing to the OLED, creating garbage on the OLED if GPIO 5 is depressed: Both "threads" are writing simultaneously to the OLED...



      I assume I need a way to pause the execution of the main loop during the callback function and I have experimented with Semaphore and aquire/release but with no luck. I have also considered the possibility of having two callback functions in combination with Semaphore, but since the info displayed in the main loop should be continuously updated (e.g. not interrupt-driven) I'm not so sure that is a solution for me.



      At this point I am not even sure what to google next. Perhaps someone in here can enlighten me? Is this perhaps a totally wrong way of doing this kind of thing? (Limited experience with Python...)



      Below is a simplified code example that simulates what I would like to do.



      import time
      import Adafruit_GPIO.SPI as SPI
      import RPi.GPIO as GPIO
      import Adafruit_SSD1306
      from PIL import Image
      from PIL import ImageDraw
      from PIL import ImageFont

      # Initialize
      disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
      disp.begin()
      disp.clear()
      disp.display()
      image = Image.new('1', (disp.width, disp.height))
      draw = ImageDraw.Draw(image)
      font = ImageFont.load_default()
      GPIO.setmode(GPIO.BCM)
      GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

      def clear_display():
      draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
      disp.image(image)
      disp.display()

      # Callback function
      def display_system_info(channel):
      draw.text((0, 0), "System info displayed", font=font, fill=255)
      draw.text((0, 9), "for five seconds.", font=font, fill=255)
      disp.image(image)
      disp.display()
      time.sleep(5)
      clear_display()

      GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

      try:
      while True:
      for counter in range(7):
      draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
      disp.image(image)
      disp.display()
      time.sleep(1)
      clear_display()
      except KeyboardInterrupt:
      GPIO.cleanup() # clean up GPIO on CTRL+C exit
      GPIO.cleanup() # clean up GPIO on normal exit


      Many thanks for any help.



      /N







      python callback interrupt






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 22 at 3:15









      Nils

      1




      1
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          0
          down vote













          I am solving situations like this with global varialbe - buttonPressed.
          When you press button (GPIO 5), buttonPressed is set to True and main loop does nothing.
          Hope it is clear for you and will help you.



          import time
          import Adafruit_GPIO.SPI as SPI
          import RPi.GPIO as GPIO
          import Adafruit_SSD1306
          from PIL import Image
          from PIL import ImageDraw
          from PIL import ImageFont

          # Initialize
          disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
          disp.begin()
          disp.clear()
          disp.display()
          image = Image.new('1', (disp.width, disp.height))
          draw = ImageDraw.Draw(image)
          font = ImageFont.load_default()
          GPIO.setmode(GPIO.BCM)
          GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

          buttonPressed = False

          def clear_display():
          draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
          disp.image(image)
          disp.display()

          # Callback function
          def display_system_info(channel):
          global buttonPressed
          buttonPressed = True
          draw.text((0, 0), "System info displayed", font=font, fill=255)
          draw.text((0, 9), "for five seconds.", font=font, fill=255)
          disp.image(image)
          disp.display()
          time.sleep(5)
          clear_display()
          buttonPressed = False

          GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

          try:
          while True:
          if(not buttonPressed):
          for counter in range(7):
          draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
          disp.image(image)
          disp.display()
          time.sleep(1)
          clear_display()
          except KeyboardInterrupt:
          GPIO.cleanup() # clean up GPIO on CTRL+C exit
          GPIO.cleanup() # clean up GPIO on normal exit


          Try and let me know.






          share|improve this answer





















          • I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
            – Nils
            Nov 22 at 14:56


















          up vote
          0
          down vote













          Depending on your application I'd avoid doing any real work inside of the callback. Instead I'd only set a flag which the main thread/loop can handle or add the events to a queue which is processed by the main thread/loop.






          share|improve this answer





















          • That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
            – Nils
            Nov 22 at 14:59










          • Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
            – katzenversteher
            Nov 28 at 5:23




















          up vote
          0
          down vote













          I realized interrupts was not a good path to walk for this particular application. Instead, I re-wrote my code so that it's only possible to push the button when the main loop is idle and waiting...which is most of the time of course. Thanks for input!






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423361%2fwith-python-how-to-prevent-two-threads-from-writing-simultaneously-to-display%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            I am solving situations like this with global varialbe - buttonPressed.
            When you press button (GPIO 5), buttonPressed is set to True and main loop does nothing.
            Hope it is clear for you and will help you.



            import time
            import Adafruit_GPIO.SPI as SPI
            import RPi.GPIO as GPIO
            import Adafruit_SSD1306
            from PIL import Image
            from PIL import ImageDraw
            from PIL import ImageFont

            # Initialize
            disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
            disp.begin()
            disp.clear()
            disp.display()
            image = Image.new('1', (disp.width, disp.height))
            draw = ImageDraw.Draw(image)
            font = ImageFont.load_default()
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

            buttonPressed = False

            def clear_display():
            draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
            disp.image(image)
            disp.display()

            # Callback function
            def display_system_info(channel):
            global buttonPressed
            buttonPressed = True
            draw.text((0, 0), "System info displayed", font=font, fill=255)
            draw.text((0, 9), "for five seconds.", font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(5)
            clear_display()
            buttonPressed = False

            GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

            try:
            while True:
            if(not buttonPressed):
            for counter in range(7):
            draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(1)
            clear_display()
            except KeyboardInterrupt:
            GPIO.cleanup() # clean up GPIO on CTRL+C exit
            GPIO.cleanup() # clean up GPIO on normal exit


            Try and let me know.






            share|improve this answer





















            • I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
              – Nils
              Nov 22 at 14:56















            up vote
            0
            down vote













            I am solving situations like this with global varialbe - buttonPressed.
            When you press button (GPIO 5), buttonPressed is set to True and main loop does nothing.
            Hope it is clear for you and will help you.



            import time
            import Adafruit_GPIO.SPI as SPI
            import RPi.GPIO as GPIO
            import Adafruit_SSD1306
            from PIL import Image
            from PIL import ImageDraw
            from PIL import ImageFont

            # Initialize
            disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
            disp.begin()
            disp.clear()
            disp.display()
            image = Image.new('1', (disp.width, disp.height))
            draw = ImageDraw.Draw(image)
            font = ImageFont.load_default()
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

            buttonPressed = False

            def clear_display():
            draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
            disp.image(image)
            disp.display()

            # Callback function
            def display_system_info(channel):
            global buttonPressed
            buttonPressed = True
            draw.text((0, 0), "System info displayed", font=font, fill=255)
            draw.text((0, 9), "for five seconds.", font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(5)
            clear_display()
            buttonPressed = False

            GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

            try:
            while True:
            if(not buttonPressed):
            for counter in range(7):
            draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(1)
            clear_display()
            except KeyboardInterrupt:
            GPIO.cleanup() # clean up GPIO on CTRL+C exit
            GPIO.cleanup() # clean up GPIO on normal exit


            Try and let me know.






            share|improve this answer





















            • I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
              – Nils
              Nov 22 at 14:56













            up vote
            0
            down vote










            up vote
            0
            down vote









            I am solving situations like this with global varialbe - buttonPressed.
            When you press button (GPIO 5), buttonPressed is set to True and main loop does nothing.
            Hope it is clear for you and will help you.



            import time
            import Adafruit_GPIO.SPI as SPI
            import RPi.GPIO as GPIO
            import Adafruit_SSD1306
            from PIL import Image
            from PIL import ImageDraw
            from PIL import ImageFont

            # Initialize
            disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
            disp.begin()
            disp.clear()
            disp.display()
            image = Image.new('1', (disp.width, disp.height))
            draw = ImageDraw.Draw(image)
            font = ImageFont.load_default()
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

            buttonPressed = False

            def clear_display():
            draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
            disp.image(image)
            disp.display()

            # Callback function
            def display_system_info(channel):
            global buttonPressed
            buttonPressed = True
            draw.text((0, 0), "System info displayed", font=font, fill=255)
            draw.text((0, 9), "for five seconds.", font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(5)
            clear_display()
            buttonPressed = False

            GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

            try:
            while True:
            if(not buttonPressed):
            for counter in range(7):
            draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(1)
            clear_display()
            except KeyboardInterrupt:
            GPIO.cleanup() # clean up GPIO on CTRL+C exit
            GPIO.cleanup() # clean up GPIO on normal exit


            Try and let me know.






            share|improve this answer












            I am solving situations like this with global varialbe - buttonPressed.
            When you press button (GPIO 5), buttonPressed is set to True and main loop does nothing.
            Hope it is clear for you and will help you.



            import time
            import Adafruit_GPIO.SPI as SPI
            import RPi.GPIO as GPIO
            import Adafruit_SSD1306
            from PIL import Image
            from PIL import ImageDraw
            from PIL import ImageFont

            # Initialize
            disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
            disp.begin()
            disp.clear()
            disp.display()
            image = Image.new('1', (disp.width, disp.height))
            draw = ImageDraw.Draw(image)
            font = ImageFont.load_default()
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up

            buttonPressed = False

            def clear_display():
            draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
            disp.image(image)
            disp.display()

            # Callback function
            def display_system_info(channel):
            global buttonPressed
            buttonPressed = True
            draw.text((0, 0), "System info displayed", font=font, fill=255)
            draw.text((0, 9), "for five seconds.", font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(5)
            clear_display()
            buttonPressed = False

            GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)

            try:
            while True:
            if(not buttonPressed):
            for counter in range(7):
            draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
            disp.image(image)
            disp.display()
            time.sleep(1)
            clear_display()
            except KeyboardInterrupt:
            GPIO.cleanup() # clean up GPIO on CTRL+C exit
            GPIO.cleanup() # clean up GPIO on normal exit


            Try and let me know.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 22 at 8:23









            Koxo

            694




            694












            • I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
              – Nils
              Nov 22 at 14:56


















            • I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
              – Nils
              Nov 22 at 14:56
















            I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
            – Nils
            Nov 22 at 14:56




            I played around with your suggestion but the strange thing is that if I add print commands to verify whether I am inside the callback function or not, I can see that even if I am inside the function, the main loop keeps printing tings to my OLED despite the fact that I added the "if not buttonPressed" check. Probably because the add_event_detect looks for edges.
            – Nils
            Nov 22 at 14:56












            up vote
            0
            down vote













            Depending on your application I'd avoid doing any real work inside of the callback. Instead I'd only set a flag which the main thread/loop can handle or add the events to a queue which is processed by the main thread/loop.






            share|improve this answer





















            • That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
              – Nils
              Nov 22 at 14:59










            • Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
              – katzenversteher
              Nov 28 at 5:23

















            up vote
            0
            down vote













            Depending on your application I'd avoid doing any real work inside of the callback. Instead I'd only set a flag which the main thread/loop can handle or add the events to a queue which is processed by the main thread/loop.






            share|improve this answer





















            • That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
              – Nils
              Nov 22 at 14:59










            • Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
              – katzenversteher
              Nov 28 at 5:23















            up vote
            0
            down vote










            up vote
            0
            down vote









            Depending on your application I'd avoid doing any real work inside of the callback. Instead I'd only set a flag which the main thread/loop can handle or add the events to a queue which is processed by the main thread/loop.






            share|improve this answer












            Depending on your application I'd avoid doing any real work inside of the callback. Instead I'd only set a flag which the main thread/loop can handle or add the events to a queue which is processed by the main thread/loop.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 22 at 9:28









            katzenversteher

            583210




            583210












            • That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
              – Nils
              Nov 22 at 14:59










            • Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
              – katzenversteher
              Nov 28 at 5:23




















            • That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
              – Nils
              Nov 22 at 14:59










            • Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
              – katzenversteher
              Nov 28 at 5:23


















            That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
            – Nils
            Nov 22 at 14:59




            That is a plausible solution. However, I assume I then have to constantly check whether this flag is 1/0...and then I could just as well constantly check if the button is pressed. Or did I perhaps misunderstand your suggestion?
            – Nils
            Nov 22 at 14:59












            Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
            – katzenversteher
            Nov 28 at 5:23






            Constant checking if the button is pressed (polling) might be even better. I'm not sure how the event is implemented, but if it is an interrupt you could cause all kinds of strange (timing) issues by constantly pressing the button (whatever your application is doing, it will be interrupted). Some buttons/switches also suffer from bouncing contacts, so even if you think you pressed it only once it might be detected as several very quick presses.
            – katzenversteher
            Nov 28 at 5:23












            up vote
            0
            down vote













            I realized interrupts was not a good path to walk for this particular application. Instead, I re-wrote my code so that it's only possible to push the button when the main loop is idle and waiting...which is most of the time of course. Thanks for input!






            share|improve this answer

























              up vote
              0
              down vote













              I realized interrupts was not a good path to walk for this particular application. Instead, I re-wrote my code so that it's only possible to push the button when the main loop is idle and waiting...which is most of the time of course. Thanks for input!






              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                I realized interrupts was not a good path to walk for this particular application. Instead, I re-wrote my code so that it's only possible to push the button when the main loop is idle and waiting...which is most of the time of course. Thanks for input!






                share|improve this answer












                I realized interrupts was not a good path to walk for this particular application. Instead, I re-wrote my code so that it's only possible to push the button when the main loop is idle and waiting...which is most of the time of course. Thanks for input!







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 29 at 11:33









                Nils

                1




                1






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423361%2fwith-python-how-to-prevent-two-threads-from-writing-simultaneously-to-display%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Berounka

                    Sphinx de Gizeh

                    Different font size/position of beamer's navigation symbols template's content depending on regular/plain...