Hello,

I’ve come across an unexpected issue that may be hard to diagnose due to required hardware, but here goes.

I have a Raspberry Pi connected to an LCD display that I’m testing turning the screen on and off (not worrying about displaying text, I’ve previously written a program that uses a DHT22 sensor to display the temperature & humidity and external weather conditions using the Pirate Weather API).

While trying to write a simple program just to turn the display on or off, I run into an issue.

Here’s the code:

import board
import datetime
# I2C driver from:
# https://gist.github.com/vay3t/8b0577acfdb27a78101ed16dd78ecba1
import I2C_LCD_driver
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("state", help="'on' to turn on the screen, 'off' to turn off",type=str)
args = parser.parse_args()

mylcd = I2C_LCD_driver.lcd()

match args.state:
    case "on":
        power = 1
    case "off":
        power = 0
    case _:
        print("Please enter 'on' or 'off'")
        power = None

if power != None:
    print(power) # this is just to test
    mylcd.backlight(power)

What’s happening that I don’t understand is if power == None, the if statement will not trigger but the display will turn on.

The only way I’ve been able to keep the display off is if I add an else statement:

else:
    pass

This is using Python 3.10. My understanding is the else should not be needed at all. Any suggestions as to why the display might be turning on, or a better suggestion on how to handle the match statement?

–EDIT–

So it turns out initializing the display is turning it on at the same time. For a community that had no activity for ~2 years before this post, I’m pleasantly surprised with the amount of responses I’ve gotten - you all are awesome!

  • golden_zealot@lemmy.mlM
    link
    fedilink
    English
    arrow-up
    1
    ·
    2 days ago

    Wow… I’m FLOORED that this community is alive despite there basically never being posts, and am very happy to see that!

    • bravemonkeyOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      4 days ago

      Yes, just got to testing again and that was it. The mylcd = I2C_LCD_driver.lcd() line is turning it on, then I need to action after it. I had tried using ‘is not’ before posting with no effect, and now I know why.

  • CameronDev@programming.dev
    link
    fedilink
    English
    arrow-up
    4
    ·
    4 days ago

    Not sure why, but as for a code change suggestion:

    if args.state == "on":
        mylcd.backlight(1)
    else:
        mylcd.backlight(0)
    

    Does the print(power) output correctly? Also, is it possible that the initialisation of the mylcd is turning on the display, so if you dont explicitly turn it off again, the default is on?

    • bravemonkeyOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 days ago

      Yeh, that initialization was doing it. Not sure there’s a way to initialize it without powering it on, but at least I know!

      A lot of the code I posted came from both trying to get a working test showing me if it got to the place I wanted as well as wanting a third option without multiple elif statements. I’m really just learning Python so lots of ways it could be better, I’m sure.

  • MoonMelon@lemmy.ml
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    4 days ago

    I think some of the other responses about there being a hidden “on” default are probably right, but if I was writing this code I would skip using “None” completely. Seems you want it either on or off, considering your “print” statement instructing the user? So either exit the program after bad input and do nothing:

        case _:
            print("Please enter 'on' or 'off'")
            return
    

    or restrict this up front by not allowing invalid command line args in the first place:

    parser.add_argument("state", help="'on' to turn on the screen, 'off' to turn off",type=str, choices=['on','off'])

    Alternatively you could make on a flag, and when it is present you assume “on” and absent you assume “off”:

    parser.add_argument('--on', action='store_true')

    Another options is to logically default to “0” and always set to either on or off yourself. There is no need to use None:

    power = 0  # This always evaluates
    if args.state == 'on':
        power = 1
    mylcd.backlight(power)  # This always evaluates
    

    This will have the side effect of turning the light off if the user enters anything besides “on”, not just the word “off” but also “0”, “ON”, “coconut”, etc. This may or may not be desirable, it’s up to you.

    Just as side note if you do use None it’s idiomatic to use is when checking None for reasons discussed here.. This isn’t your problem just thought I would mention it.

    • bravemonkeyOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 days ago

      Reading this again too, I like the suggestion to default power to 0. A lot of this was testing to see how to do it at a dumbed-down level; the Python file I was testing in is a lot messier as is!

    • bravemonkeyOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 days ago

      Found the problem, as mentioned in another reply. I really appreciate your response here though - I’m coming from a PowerShell scripting background with my day job, and learned about arguments in Python just this morning. I didn’t know about ‘choices’, but that’s super handy.

      I had tried ‘is not None’ and didn’t have any luck so then tried == with the same outcome.

  • EmptySlime@lemmy.blahaj.zone
    link
    fedilink
    English
    arrow-up
    2
    ·
    4 days ago

    It’s been a while since I’ve done Python so I might be hazy on my syntax but that code reads to me like the if statement is only applying to the print immediately below. Especially with what you’re saying of it working properly adding that basically empty else case.

    So like if I were to add some imaginary grouping, instead of

    if power != None: {
        print(power) # this is just to test
        mylcd.backlight(power)
    }
    

    You’re getting

    if power != None: {
        print(power) # this is just to test
    }
    mylcd.backlight(power)
    

    And the mylcd.backlight(power) statement is running regardless of the state of the power variable? Again it’s been a few years since I’ve done Python so I might be misremembering the syntax rules. But that’s how it’s reading to me.

    • bravemonkeyOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      4 days ago

      The code is intended to only run mylcd.backlight(power) if the power variable was anything but 1 or 0, but the initialization was turning it on unexpectedly.

      • EmptySlime@lemmy.blahaj.zone
        link
        fedilink
        English
        arrow-up
        1
        ·
        3 days ago

        I’d think if it was related to initialization then the else statement wouldn’t result in the display staying off as you mentioned in the post though. Either way, glad you figured it out and it’s doing what you want it to now.