Python Forum

Full Version: Need help understanding the math in the code
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am a middle school technology teacher and I am creating tutorials for the Raspberry Pi. This code lights up a 7 segment display which lights up the numbers 1 - 9 then a - f and lastly a period. The code works great, but I don't understand what is happening with the math! I don't get how the writeOneByte function works. What is happening in
GPIO.output(11, val & (0x01 << 0))
? What do the dats represent mathematically?

I can't create an extension exercise or help explain the code if I can't understand this. Even a link to an explanation would help. Thank you.

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

pins = [11,12,13,15,16,18,22,7]
dats = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x80]

def setup():
	GPIO.setmode(GPIO.BOARD)
	for pin in pins:
		GPIO.setup(pin, GPIO.OUT)   # Set pin mode as output
		GPIO.output(pin, GPIO.LOW)

def writeOneByte(val):
	GPIO.output(11, val & (0x01 << 0))  
	GPIO.output(12, val & (0x01 << 1))  
	GPIO.output(13, val & (0x01 << 2))  
	GPIO.output(15, val & (0x01 << 3))  
	GPIO.output(16, val & (0x01 << 4))  
	GPIO.output(18, val & (0x01 << 5))  
	GPIO.output(22, val & (0x01 << 6))  
	GPIO.output(7,  val & (0x01 << 7)) 

def loop():
	while True:
		for dat in dats:
			writeOneByte(dat)
			time.sleep(0.5)

def destroy():
	for pin in pins:
		GPIO.output(pin, GPIO.LOW)
	GPIO.cleanup()             # Release resource

if __name__ == '__main__':     # Program start from here
	setup()
	try:
		loop()
	except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
		destroy()
GPIO.output(11, val & (0x01 << 0))
& if a logical and,
<< is shift left bytes
so it's taking a value with bit zero set, shifting it left 0 positions (a rather worthless move) and anding the results with the value of val (which masks out all but bit 0.
Essentially, using bit 0 as a flag because the mask eliminates all the other bits
Here is what I understand from your code. There is a mapping between the 8 bits of a small integer in the range 0-255 and the segments of the display. This mapping is described by the following picture
Output:
0 ----- 5 | | 1 | 6 | ----- 4 | | 2 | | ----- o 7 3
Consider the small integer 0x5e, which is equal to 94. Its binary representation is
>>> bin(0x5e)
'0b1011110'
Reading the bits from right to left, you see that the bits number 1, 2, 3, 4, 6 are on and the bits 0, 5, 7 are off. Light the segments 1, 2, 3, 4, 6 on the display, and you get the letter "d".

The writeOneByte() method sends a zero or non zero value for each of the segments depending on the value of the corresponding bit in the small integer 'val'.

Suppose I want to write the letter 'h'. I need to light the segments 2, 4, 5, 6. The interpreter tells me which integer I need to send
>>> hex(int('1110100', 2))
'0x74'
I'll use 0x74 (116 in decimal).
Never mind!! I researched it and figured it out. There are 8 locations that can be lit that can be represented in an 8 digit binary number. 1111 1111 switches on all the locations which looks like the number 8 with a period. The number 2 would be 01011011. Going backwards, the hex conversion for that is 0x5b. To make letters that are not already represented in the tutorial, students can write the binary number that lights up the right locations, find the hex equivalent and plug it into the program.

(Apr-06-2018, 10:10 PM)Gribouillis Wrote: [ -> ]Here is what I understand from your code. There is a mapping between the 8 bits of a small integer in the range 0-255 and the segments of the display. This mapping is described by the following picture
Output:
0 ----- 5 | | 1 | 6 | ----- 4 | | 2 | | ----- o 7 3
Consider the small integer 0x5e, which is equal to 94. Its binary representation is
>>> bin(0x5e)
'0b1011110'
Reading the bits from right to left, you see that the bits number 1, 2, 3, 4, 6 are on and the bits 0, 5, 7 are off. Light the segments 1, 2, 3, 4, 6 on the display, and you get the letter "d".

The writeOneByte() method sends a zero or non zero value for each of the segments depending on the value of the corresponding bit in the small integer 'val'.

YES! Thank you for the explanation. I will use this with my students.