boomshalek
Posts: 2
Joined: Thu Aug 22, 2019 3:26 pm

Read IR Remote scancodes (no LIRC) from Waveshare ir sensor

Thu Aug 22, 2019 5:43 pm

Read IR Remote scancodes (no LIRC) from Waveshare ir sensor

Hi guys

I'm just about to start with the pi universe.
This is my first post. I hope i am asking in a accepted way.

I do have 15 years experience on linux, but not a lot in scripting/programming.
I am not at all savvy in electrical engineering.

I have a Pi Zero WH Rev. 1.1 and connected a RPi Motor Driver Board on top through the 40pin header.
I do power it through a 12V Power Adapter from an old QNAP TS209 that goes into VIN and GND on the Motor Driver Board. The Motor Driver Board powers the piz zero (through the header) and two 12V DC motors. AFAIK the motor board can do that ( Onboard 5V regulator, provides power to Raspberry Pi
There is a IR receiver on the motor board too, although i do not know which one exactly (TSOP etc.).

I have installed Raspian Lite Buster from July (this might be a source of the problem, as I do not know how the development state is for IR, Pi Zero etc. on Debian Buster)

I want to use my IR Remote to control the motors with python (but IMPORTANT:without LIRC) and i have succeeded to do so using the waveshare's example code for that HAT board.

But it seems as if only about 10% of all key-presses (scancodes) are captured by the python code. The rest is ignored. Often i can't stop the motors after one of several key-presses has started the motor(s).

If run my pre-configured ir-keytable -t I do receive a scancode for all key-presses using different remotes (NEC with Terratec Cinergy, RC-5 with Hauppauge remote, NEC with a Yamaha HiFi remote).
But when i am running the motor.py code it only captures NEC type scancodes and only about 10% of the key-presses are executed through the code.
This is the ir remote python script ( motor.py) from Waveshare demo code files i am using
What I find strange is that they already take away some parts of the scancode and only using the last bits. But I think this is not the source of the problems i am facing.

Code: Select all

import RPi.GPIO as GPIO
import time

PIN = 18
PWMA1 = 6 
PWMA2 = 13
PWMB1 = 20
PWMB2 = 21
D1 = 12
D2 = 26

PWM = 50

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(PIN,GPIO.IN,GPIO.PUD_UP)
GPIO.setup(PWMA1,GPIO.OUT)
GPIO.setup(PWMA2,GPIO.OUT)
GPIO.setup(PWMB1,GPIO.OUT)
GPIO.setup(PWMB2,GPIO.OUT)
GPIO.setup(D1,GPIO.OUT)
GPIO.setup(D2,GPIO.OUT)
p1 = GPIO.PWM(D1,500)
p2 = GPIO.PWM(D2,500)
p1.start(50)
p2.start(50)

def	set_motor(A1,A2,B1,B2):
	GPIO.output(PWMA1,A1)
	GPIO.output(PWMA2,A2)
	GPIO.output(PWMB1,B1)
	GPIO.output(PWMB2,B2)

def forward():
	GPIO.output(PWMA1,1)
	GPIO.output(PWMA2,0)
	GPIO.output(PWMB1,1)
	GPIO.output(PWMB2,0)

def stop():
	set_motor(0,0,0,0)

def reverse():
	set_motor(0,1,0,1)

def left():
	set_motor(1,0,0,0)

def right():
	set_motor(0,0,1,0)

def getkey():
	if GPIO.input(PIN) == 0:
		count = 0
		while GPIO.input(PIN) == 0 and count < 200:  #9ms
			count += 1
			time.sleep(0.00006)

		count = 0
		while GPIO.input(PIN) == 1 and count < 80:  #4.5ms
			count += 1
			time.sleep(0.00006)

		idx = 0
		cnt = 0
		data = [0,0,0,0]
		for i in range(0,32):
			count = 0
			while GPIO.input(PIN) == 0 and count < 15:    #0.56ms
				count += 1
				time.sleep(0.00006)
				
			count = 0
			while GPIO.input(PIN) == 1 and count < 40:   #0: 0.56ms
				count += 1                               #1: 1.69ms
				time.sleep(0.00006)
				
			if count > 8:
				data[idx] |= 1<<cnt
			if cnt == 7:
				cnt = 0
				idx += 1
			else:
				cnt += 1
		if data[0]+data[1] == 0xFF and data[2]+data[3] == 0xFF:  #check
			return data[2]

print('IRM Test Start ...')
stop()
try:
	while True:
		key = getkey()
		if(key != None):
			print("Get the key: 0x%02x" %key)
			if key == 0x18:
				forward()
				print("forward")
			if key == 0x08:
				left()
				print("left")
			if key == 0x1c:
				stop()
				print("stop")
			if key == 0x5a:
				right()
				print("right")
			if key == 0x52:
				reverse()		
				print("reverse")
			if key == 0x15:
				if(PWM + 10 < 101):
					PWM = PWM + 10
					p1.ChangeDutyCycle(PWM)
					p2.ChangeDutyCycle(PWM)
					print(PWM)
			if key == 0x07:
				if(PWM - 10 > -1):
					PWM = PWM - 10
					p1.ChangeDutyCycle(PWM)
					p2.ChangeDutyCycle(PWM)
					print(PWM)
except KeyboardInterrupt:
	GPIO.cleanup();

How can i test/modify the script in order to fix this?

Important side information: I have manually recompiled WebIOPi (otherwise buster issues again) and can control all python functions as used in the IR script without any delay or problems. With WebIOPi it just works.

ghp
Posts: 1399
Joined: Wed Jun 12, 2013 12:41 pm
Location: Stuttgart Germany
Contact: Website

Re: Read IR Remote scancodes (no LIRC) from Waveshare ir sensor

Fri Aug 23, 2019 6:27 am

Hello, your getkey method is matching the NEC code timings.
Found a description for NEC here: https://exploreembedded.com/wiki/NEC_IR ... _with_8051
To compare with RC5: https://en.wikipedia.org/wiki/RC-5

Your decoding logic could be improved: your code grabs logic levels and just starts to interpret them as valid codes whenever it finds a logic low. While decoding, there are good indicators that nothing valid is arriving and then an immediate restart of decoding should be performed. A good indicator is the start pulse length 9ms pulse, 4.5 ms pause which is 9ms low, 4.5 ms high.

Other things to consider:
- short timings like in your code take considerable more time than expected
- As all of your code runs in one thread, the print()-statements will delay again the execution
- the pi zero is quite slow.
Take this all together and the conclusion is that decoding a protocol with millisecond pulses is ambitious with python.

LIRC would be an option. Possibly also pigpiod.

boomshalek
Posts: 2
Joined: Thu Aug 22, 2019 3:26 pm

Re: Read IR Remote scancodes (no LIRC) from Waveshare ir sensor

Fri Aug 23, 2019 5:04 pm

Hey ghp

Thank you a lot for your answer.
I wanted to use a pi zero for this as i didn't expect to use a lot of computing power for the control of my two motors. It is used in stationary mode, meaning: No robot, but a simple control to turn on Motor A and B in both directions.
Apparently I was wrong assuming that listing on the ir remote port won't use a lot of computing power.

Also i thought that going directly on python scrypt would save ressources. Well, wrong I was.

As I will only give commands twice a day through IR I will try to migrate my script to LIRC as I already know that from other projects (VDR, MythTV).
pigpiod seems to be just another thing to dive into which might be too hard at the moment.

Thank you for directing me into hopefully the right direction for this project.

User avatar
joan
Posts: 14175
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Read IR Remote scancodes (no LIRC) from Waveshare ir sensor

Fri Aug 23, 2019 7:09 pm

Might be worth a shot at firing up this script.

http://abyz.me.uk/rpi/pigpio/examples.h ... _hasher_py

It may give a useful hash depending on the protocol your remotes use.

Return to “Python”