Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 60 additions & 127 deletions IRModule.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,157 +23,91 @@
"""

import RPi.GPIO as GPIO
import time, threading
import time, threading
from datetime import datetime

class IRRemote:

def __init__(self, callback = None):

self.decoding = False
self.pList = []
self.timer = time.time()
if callback == 'DECODE':
self.callback = self.print_ir_code
else:
self.callback = callback
self.checkTime = 150 # time in milliseconds
self.verbose = False
self.repeatCodeOn = True
self.lastIRCode = 0
self.maxPulseListLength = 70
#self.lastRecievedTime = None

def pWidth(self, pin):
"""pWidth, function to record the width of the highs and lows
of the IR remote signal and start the function to look for the
end of the IR remote signal"""

self.pList.append(time.time()-self.timer)
self.timer = time.time()

if self.decoding == False:
self.decoding = True
check_loop = threading.Thread(name='self.pulse_checker',target=self.pulse_checker)
check_loop = threading.Thread(name='self.pulse_checker',target=self.getData)
check_loop.start()

return

def pulse_checker(self):
"""pulse_checker, function to look for the end of the IR remote
signal and activate the signal decode function followed by
the callback function.

End of signal is determined by 1 of 2 ways
1 - if the length of the pulse list is larger than self.maxPulseListLength
- used for initial button press codes
2 - if the length of time receiving the pulse is great than self.checkTime
- used for repeat codes"""

timer = time.time()

while True:
check = (time.time()-timer)*1000
if check > self.checkTime:
print(check, len(self.pList))
break
if len(self.pList) > self.maxPulseListLength:
print(check, len(self.pList))
break
time.sleep(0.001)

if len(self.pList) > self.maxPulseListLength:
decode = self.decode_pulse(self.pList)
self.lastIRCode = decode

# if the length of self.pList is less than 10
# assume repeat code found
elif len(self.pList) < 10:
if self.repeatCodeOn == True:
decode = self.lastIRCode
else:
decode = 0
self.lastIRCode = decode
else:
decode = 0
self.lastIRCode = decode

self.pList = []
self.decoding = False

if self.callback != None:
self.callback(decode)

return

def decode_pulse(self,pList):
"""decode_pulse, function to decode the high and low
timespans captured by the pWidth function into a binary
number"""

bitList = []
sIndex = -1

# convert the timespans in seconds to milli-seconds
# look for the start of the IR remote signal
def ConvertHex(self, BinVal): #Converts binary data to hexidecimal
tmpB2 = int(str(BinVal), 2)
return hex(tmpB2)

def getData(self): #Pulls data from sensor
PinIn = 17
num1s = 0 #Number of consecutive 1s
command = [] #Pulses and their timings
binary = 1 #Decoded binary command
previousValue = 0 #The previous pin state
value = GPIO.input(PinIn) #Current pin state

for p in range(0,len(pList)):
try:
pList[p]=float(pList[p])*1000
if self.verbose == True:
print(pList[p])
if pList[p]<11:
if sIndex == -1:
sIndex = p
except:
pass

# if no acceptable start is found return -1

if sIndex == -1:
return -1

if sIndex+1 >= len(pList):
return -1
while value: #Waits until pin is pulled low
value = GPIO.input(PinIn)

#print(sIndex, pList[sIndex], pList[sIndex+1])

if (pList[sIndex]<4 or pList[sIndex]>11):
return -1
startTime = datetime.now() #Sets start time

if (pList[sIndex+1]<2 or pList[sIndex+1]>6):
return -1
while True:
if value != previousValue: #Waits until change in state occurs
now = datetime.now() #Records the current time
pulseLength = now - startTime #Calculate time in between pulses
startTime = now #Resets the start time
command.append((previousValue, pulseLength.microseconds)) #Adds pulse time to array (previous val acts as an alternating 1 / 0 to show whether time is the on time or off time)

#Interrupts code if an extended high period is detected (End Of Command)
if value:
num1s += 1
else:
num1s = 0

""" pulses are made up of 2 parts, a fixed length low (approx 0.5-0.6ms)
and a variable length high. The length of the high determines whether or
not a 0,1 or control pulse/bit is being sent. Highes of length approx 0.5-0.6ms
indicate a 0, and length of approx 1.6-1.7 ms indicate a 1"""


for i in range(sIndex+2,len(pList),2):
if i+1 < len(pList):
if pList[i+1]< 0.9:
bitList.append(0)
elif pList[i+1]< 2.5:
bitList.append(1)
elif (pList[i+1]> 2.5 and pList[i+1]< 45):
#print('end of data found')
break
if num1s > 10000:
break

#Reads values again
previousValue = value
value = GPIO.input(PinIn)

#Covers data to binary
for (typ, tme) in command:
if typ == 1:
if tme > 1000: #According to NEC protocol a gap of 1687.5 microseconds repesents a logical 1 so over 1000 should make a big enough distinction
binary = binary * 10 + 1
else:
break

if self.verbose == True:
print(bitList)

# convert the list of 1s and 0s into a
# binary number

pulse = 0
bitShift = 0

for b in bitList:
pulse = (pulse<<bitShift) + b
bitShift = 1

return pulse
binary *= 10

if len(str(binary)) > 34: #Sometimes the binary has two rouge charactes on the end
binary = int(str(binary)[:34])
#print("binary")
#print(binary)
command = self.ConvertHex(binary)
#print("hex")
#print(command)
if self.callback != None:
self.callback(command)
#self.getData()
time.sleep(0.01)
check_loop = threading.Thread(name='self.pulse_checker',target=self.getData)
check_loop.start()
return command

def set_callback(self, callback = None):
"""set_callback, function to allow the user to set
Expand All @@ -194,7 +128,8 @@ def remove_callback(self):
def print_ir_code(self, code):
"""print_ir_code, function to display IR code received"""

print(hex(code))
#print(hex(code))
print(code)

return

Expand All @@ -212,10 +147,8 @@ def set_repeat(self, repeat = True):
the IR repeat code functionality"""

self.repeatCodeOn = repeat

return


if __name__ == "__main__":

def remote_callback(code):
Expand Down