Voting resources, early voting, and poll worker information - VOTE. ... Adafruit is open and shipping.
0

Convert C byte to Python string
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Convert C byte to Python string

by Seras on Mon May 25, 2020 10:32 pm

Hello, I am a beginner when it comes to Python, and I'm having some trouble working with an Adafruit 7-Segment Display.

In brief, what I am trying to do is call a C program in a function via subprocess and receive a value such as "50.55" in a variable. I want to take that number and display it on the Adafruit display, however I'm running into a problem.

The display works as intended when I create a variable teststring with a string in it and send that through "display.print(teststring)". However, when I try to use the variable I get from calling the C function I get errors. I know that the value returned from my function is first in the type of bytes, so I convert that to a string. However, that string must have a different encoding since it causes errors when placed inside display.print().

This is what I am trying at the moment to convert the bytes to a string:

Code: Select all | TOGGLE FULL SIZE
valstring = str(valbyte, 'utf-8')
display.print(valstring)


I think this is the right approach, however I don't think that utf-8 is the correct thing to convert it to. I have also seen elsewhere that another suggestion would be to use "value.decode", but I am unsure how this works or if it is the answer I am looking for. Any help would be immensely appreciated!

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Re: Convert C byte to Python string

by siddacious on Tue May 26, 2020 2:57 am

Please post your full code, or at least the sections in question as well the errors you're getting.

siddacious
 
Posts: 310
Joined: Fri Apr 21, 2017 3:09 pm

Re: Convert C byte to Python string

by Seras on Tue May 26, 2020 2:23 pm

My apologies, here is the code:

Code: Select all | TOGGLE FULL SIZE
import board
import time
import subprocess
import shlex
from adafruit_ht16k33.segments import Seg7x4

i2c = board.I2C()
display = Seg7x4(i2c)

display = Seg7x4(i2c, address=0x70)

display.fill(0)
display.brightness = 0.7

# getval
def getval():
   subprocess1 = subprocess.Popen('sudo /home/pi/GETVAL/val --b', shell=True, stdout=subprocess.PIPE)
   subprocess_return = subprocess1.stdout.read()
   return subprocess_return
   
display.fill(0)
valinit = getval()
valstr = str(valinit, 'utf-8')
print(valstr)
print(type(valstr))
display.print(valstr)


And here is the error output I am receiving:

pi@raspberrypi:~ $ python3 4DigitDisplay.py
50.5
<class 'str'>
Traceback (most recent call last):
File "4DigitDisplay.py", line 26, in <module>
display.print(valstr)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_ht16k33/segments.py", line 167, in print
self.show()
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_ht16k33/ht16k33.py", line 117, in show
self.i2c_device.write(self._buffer)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_bus_device/i2c_device.py", line 104, in write
self.i2c.writeto(self.device_address, buf, start=start, end=end, stop=stop)
File "/home/pi/.local/lib/python3.7/site-packages/busio.py", line 99, in writeto
address, memoryview(buffer)[start:end], stop=stop
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py", line 46, in writeto
self._i2c_bus.write_bytes(address, buffer[start:end])
File "/home/pi/.local/lib/python3.7/site-packages/Adafruit_PureIO/smbus.py", line 308, in write_bytes
self._device.write(buf)
OSError: [Errno 5] Input/output error

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Re: Convert C byte to Python string

by siddacious on Wed May 27, 2020 12:24 am

It's a bit strange that you would get an input/output error, as that's a pretty low level issue talking with the display. It's possible that you're ending up with extra bytes in your buffer due to encoding it as utf-8.

Here's a few ideas to try:
use ascii encoding:
valstr = str(valinit, "ascii")

set the display to not auto-write, and then print the display's buffer before writing to the display:
Code: Select all | TOGGLE FULL SIZE
display = Seg7x4(i2c, auto_write=False)
...
print(display._buffer)
display.show()

do this with both the working hardcoded value as well as the string that you're getting from the C program, compare the results.

print out the raw output from getval() and check it's type. It should be bytes:
print("valinit:", valinit, "type(valinit)", type(valinit))
and then compare that to the buffer, as well as trying to convert the string back to bytes using bytes(valstr, "utf-8') and/or with 'ascii'

lastly, you may try using subprocess.check_output() instead:

subprocess.check_output(['echo 5.5'])

In short, if a hardcoded string is working and the output from the subprocess is not, there's going to be a difference between the two

siddacious
 
Posts: 310
Joined: Fri Apr 21, 2017 3:09 pm

Re: Convert C byte to Python string

by Seras on Wed May 27, 2020 4:26 pm

Thank you for your input. I've tried all of what you have suggested, however I am still running into the same error.

This is what my code now currently looks like:

Code: Select all | TOGGLE FULL SIZE
import board
import time
import subprocess
import shlex
from adafruit_ht16k33.segments import Seg7x4
i2c = board.I2C()
display = Seg7x4(i2c)
display = Seg7x4(i2c, address=0x70)
display.fill(0)
display.brightness = 0.7
# getval
def getval():
        #subprocess1 = subprocess.Popen('echo \"5.5\c\"', shell=True, stdout=subprocess.PIPE)
        subprocess1 = subprocess.Popen('sudo /home/pi/cprog', shell=True, stdout=subprocess.PIPE)
        subprocess_return = subprocess1.stdout.read()
        return subprocess_return

#hardtest = 55
curtemp = getval()
print (curtemp)
curtemp = curtemp.decode("ascii")
print (curtemp)
display.print(curtemp)


Which looks like this when run. The same error as last time:

python3 test4digit.py
b'5.2'
5.2
Traceback (most recent call last):
File "test4digit.py", line 23, in <module>
display.print(curtemp)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_ht16k33/segments.py", line 167, in print
self.show()
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_ht16k33/ht16k33.py", line 117, in show
self.i2c_device.write(self._buffer)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_bus_device/i2c_device.py", line 104, in write
self.i2c.writeto(self.device_address, buf, start=start, end=end, stop=stop)
File "/home/pi/.local/lib/python3.7/site-packages/busio.py", line 99, in writeto
address, memoryview(buffer)[start:end], stop=stop
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py", line 46, in writeto
self._i2c_bus.write_bytes(address, buffer[start:end])
File "/home/pi/.local/lib/python3.7/site-packages/Adafruit_PureIO/smbus.py", line 308, in write_bytes
self._device.write(buf)
OSError: [Errno 5] Input/output error

The subprocess that is commented out in my code which you provided for me worked as intended with no issues. However, as I've shown, my subprocess still does not.

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Re: Convert C byte to Python string

by siddacious on Wed May 27, 2020 10:20 pm

If you have a subprocess that is working and one that is not, you'll want to dig into what the differences are in what is being passed along from the subprocess to the display call. There is obviously a difference somewhere, otherwise they'd both the working the same. Maybe try doing both the working and non-working versions of the subprocess call simultaneously, performing the same operations (encoding, printing values, etc) on both pieces of output.

Good luck

siddacious
 
Posts: 310
Joined: Fri Apr 21, 2017 3:09 pm

Re: Convert C byte to Python string

by MakerMelissa on Thu May 28, 2020 11:49 am

Hi Seras,

The only idea I have on this is to maybe try converting the string to a float and pass that to the segmented display.

Melissa

MakerMelissa
 
Posts: 176
Joined: Wed Jun 05, 2013 2:10 am

Re: Convert C byte to Python string

by Seras on Thu May 28, 2020 1:06 pm

Hi Melissa,

Thank you for replying to my issue. I have tried doing what you suggested, however ran into the same input/output error as before. Below is the code I used:

Code: Select all | TOGGLE FULL SIZE
import board
import time
import subprocess
import shlex
from adafruit_ht16k33.segments import Seg7x4
i2c = board.I2C()
display = Seg7x4(i2c)
display = Seg7x4(i2c, address=0x70)
display.fill(0)
display.brightness = 0.7
# getval
def getval():
        #subprocess1 = subprocess.Popen('echo \"5.5\c\"', shell=True, stdout=subprocess.PIPE)
        subprocess1 = subprocess.Popen('sudo /home/pi/E2EFev/Temp --b', shell=True, stdout=subprocess.PIPE)
        subprocess_return = subprocess1.stdout.read()
        return subprocess_return

#hardtest = 55
curtemp = getval()
print (curtemp)
#curtemps = curtemp.decode("ascii")
curtempf = float(curtemp)
print (curtempf)
print (type(curtempf))
display.print(curtempf)


And here was the output:

pi@raspberrypi:~ $ python3 test4digit.py
b'5.5'
5.5
<class 'float'>
Traceback (most recent call last):
File "test4digit.py", line 25, in <module>
display.print(curtempf)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_ht16k33/segments.py", line 167, in print
self.show()
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_ht16k33/ht16k33.py", line 117, in show
self.i2c_device.write(self._buffer)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_bus_device/i2c_device.py", line 104, in write
self.i2c.writeto(self.device_address, buf, start=start, end=end, stop=stop)
File "/home/pi/.local/lib/python3.7/site-packages/busio.py", line 99, in writeto
address, memoryview(buffer)[start:end], stop=stop
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py", line 46, in writeto
self._i2c_bus.write_bytes(address, buffer[start:end])
File "/home/pi/.local/lib/python3.7/site-packages/Adafruit_PureIO/smbus.py", line 308, in write_bytes
self._device.write(buf)
OSError: [Errno 5] Input/output error

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Re: Convert C byte to Python string

by MakerMelissa on Thu May 28, 2020 1:27 pm

What is the subprocess doing? I'm wondering if maybe it's taking over the I2C bus and that's what is causing issues.

MakerMelissa
 
Posts: 176
Joined: Wed Jun 05, 2013 2:10 am

Re: Convert C byte to Python string

by Seras on Thu May 28, 2020 1:31 pm

It's using the SDA and SCL. Is there something I should be doing in between the subprocess call and the display.print?

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Re: Convert C byte to Python string

by MakerMelissa on Thu May 28, 2020 1:36 pm

Ok, that's what the issue is.

What is happening is that the subprocess is changing the state of I2C (which uses the SDA and SCL pins) and then it gets confused. You will likely need to reinitialize I2C every time after the subprocess gets called or look into using a second I2C bus to communicate with the segmented display.

Melissa

MakerMelissa
 
Posts: 176
Joined: Wed Jun 05, 2013 2:10 am

Re: Convert C byte to Python string

by Seras on Thu May 28, 2020 1:41 pm

I'm sorry, I'm quite a newbie when it comes to this. How can I reinitialize I2C without rebooting?

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Re: Convert C byte to Python string

by MakerMelissa on Thu May 28, 2020 1:46 pm

I think it would probably be enough to reinitialize the display objects as I think that will send and set all the necessary bits.

MakerMelissa
 
Posts: 176
Joined: Wed Jun 05, 2013 2:10 am

Re: Convert C byte to Python string

by MakerMelissa on Thu May 28, 2020 1:54 pm

Another option may be to use bitbangio I2C using https://github.com/adafruit/Adafruit_Ci ... _BitbangIO. It's not as fast as hardware I2C, but for the LED segmented display, it will probably be fast enough and you can use whichever GPIO pins aren't in use.

MakerMelissa
 
Posts: 176
Joined: Wed Jun 05, 2013 2:10 am

Re: Convert C byte to Python string

by Seras on Thu May 28, 2020 2:16 pm

Alright, reinitializing I2C worked! I am finally getting the subprocess value to print out on the display. Thank you so much for your help! I have a new question now, however. I can't seem to get the float to print fully/correctly onto the display. Here is my code once again:

Code: Select all | TOGGLE FULL SIZE
curtemp = getval()
print (curtemp)
curtempf = float(curtemp)
print (curtempf)
print (type(curtempf))

i2c = board.I2C()
display = Seg7x4(i2c)
display = Seg7x4(i2c, address=0x70)

display.print(curtempf)


Which outputs:

pi@raspberrypi:~ $ python3 newDisplayTest.py
b'120.1'
120.1
<class 'float'>

However, on the display it only prints "120". I tried converting it to a string instead of a float, but the result was even funkier, with "20." appearing on the left side of the display.

Seras
 
Posts: 8
Joined: Mon May 25, 2020 10:14 pm

Please be positive and constructive with your questions and comments.