I am working through a tutorial trying to learn Python. I have come across a line of code I cannot decipher.
I have asked the developer of the code and their explanation ignored my question. My question seems too basic for them to address.
I have simplified the code to the following:
GPIO.output(22,((j == 1<<i) and GPIO.HIGH or GPIO.LOW))
The index i rotates through 0 to 3
The index j rotates through 0x01, 0x02, 0x03 and 0x04
I know the code sends a "High" or "Low" to GPIO pin 22.
I do not understand the code: (j == 1<<i)
it seems to be checking for equality between a hex number "j" and "1<<i"
Questions:
1. How does this work? In other words, what is it saying?
2. Once evaluated, how does it interact with the following "and" and "or" statement?
3.Is there a simpler way to write this line of code?
Hi :)
x << y is a binary operator, which symbolises a left shift. To be a more precise, it shifts the value of x by the value of y to the left: if x is 1 it would be 0001 in binary. so if y is 1 and you have 1 << 1 it would result into 0010 (which is 2 in decimal). If y would be 2 it would result to 0100 (which is 4 in decimal). Though 0x02 is hexadecimal and the result of << would be binary it does not matter. 0x02 results to 2 and so does 1 << 1 which in comparison is True. GPIO.HIGH equals True and GPIO.LOW equals False. So the LED would only work if j == 1 << i is True. The part of the GPIO.HIGH or GPIO.LOW is completely unnecessary. I don't know why he would compare the hex number to the binary number, but your script could be made easier by doing this:
GPIO.output(22,(j == 1<<i))
without knowledge where j and i originate from I can not say how to make it more simple.
I had found the << operator but could not imagine why someone would use such complicated code. This is akin to using recursion. . .it is elegant and compact but exceedingly difficult for any subsequent programmer to maintain.
BTW, this is code to run a stepper motor. I am studying other stepper driving scheme to find one I can understand and modify to my own uses.
I just hate giving up on trying to understand something because it is hard.
Thank you for the help.
could you show me the original code, maybe I can help you with that :)
Sure. Here it is. It is from Frenove "Ultimate Starter Kit for Raspberry Pi"
#!/usr/bin/env python3
########################################################################
# Filename : SteppingMotor.py
# Description : Drive SteppingMotor
# Author : www.freenove.com
# modification: 2019/12/27
########################################################################
import RPi.GPIO as GPIO
import time
motorPins = (12, 16, 18, 22) # define pins connected to four phase ABCD of stepper motor
CCWStep = (0x01,0x02,0x04,0x08) # define power supply order for rotating anticlockwise
CWStep = (0x08,0x04,0x02,0x01) # define power supply order for rotating clockwise
def setup():
GPIO.setmode(GPIO.BOARD) # use PHYSICAL GPIO Numbering
for pin in motorPins:
GPIO.setup(pin,GPIO.OUT)
# as for four phase stepping motor, four steps is a cycle. the function is used to drive the stepping motor clockwise or anticlockwise to take four steps
def moveOnePeriod(direction,ms):
for j in range(0,4,1): # cycle for power supply order
for i in range(0,4,1): # assign to each pin
if (direction == 1):# power supply order clockwise
GPIO.output(motorPins[i],((CCWStep[j] == 1<<i) and GPIO.HIGH or GPIO.LOW))
else : # power supply order anticlockwise
GPIO.output(motorPins[i],((CWStep[j] == 1<<i) and GPIO.HIGH or GPIO.LOW))
if(ms<3): # the delay can not be less than 3ms, otherwise it will exceed speed limit of the motor
ms = 3
time.sleep(ms*0.001)
# continuous rotation function, the parameter steps specifies the rotation cycles, every four steps is a cycle
def moveSteps(direction, ms, steps):
for i in range(steps):
moveOnePeriod(direction, ms)
# function used to stop motor
def motorStop():
for i in range(0,4,1):
GPIO.output(motorPins[i],GPIO.LOW)
def loop():
while True:
moveSteps(1,3,512) # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
time.sleep(0.5)
moveSteps(0,3,512) # rotating 360 deg anticlockwise
time.sleep(0.5)
def destroy():
GPIO.cleanup() # Release resource
if __name__ == '__main__': # Program entrance
print ('Program is starting...')
setup()
try:
loop()
except KeyboardInterrupt: # Press ctrl-c to end the program.
destroy()
Trying to figure out how to attach the .py file so the indentations remain.
If you use the python tags it keeps indentation.
Bit shifting can be useful, there was a posted question here for solving 2^2^34 or something similar. Solution takes less than 1 second by taking 1<<(1<<34). Converting that integer to a string to display takes, well, months.
I just read the posts about 2^^2^^34. Impressive how very clever people approach a problem in different manners.
Reminds me of spherical math we had to use in a navigation project for a Coast Guard helicopter. Bit shifting sped everything up tremendously.
BTW: I was the hardware engineer on that project. I designed the board and how to integrate it into the bus. I hired a programmer to do the math. He created the marvelous result.