20 May, 2017

GY-MCU90614-BCC Serial IR Non-contact Module: Python code

It seems that this variant of the module, with serial interface, is not that popular or at least I could not find code that I can easily port to Raspberry Pi. One can find a Windows program that prints the values from the serial port but that is all.
Anyway, I found description of the protocol on several pages, and it looked doable. Later, I found an Arduino example code, which could have helped, but...  I start programming before I had the module, which explains the reason why I first convert the characters to hex and then decode... This way is easier to debug it... So, here is the Python code (at the end of the post) that tests the checksum, decodes and prints the values to the standard output. (by the way, I still do not know how to get negative values for the temperature...)

Example output:
$ ./IRserial.py
TO: 21.36   TA: 24.04
TO: 21.36   TA: 24.04
TO: 21.36   TA: 24.04
TO: 21.57   TA: 24.04
TO: 21.57   TA: 24.04
TO: 21.57   TA: 24.04
TO: 21.57   TA: 24.08
TO: 21.57   TA: 24.08
TO: 21.57   TA: 24.08

You might need to change the serial port device definition, baudrate etc.



#!/usr/bin/python
"""
5A5A45040C780D19A7
Express TO (There is a sign 16 bit, which represents the target temperature) :TO=0x0C78/100= 31.92C
Express TA (There is a sign 16 bit, indicates the ambient temperature)       :TA=0x0D19/100= 33.53C
"""

import serial
import re

SerPort= "/dev/ttyAMA0"

#==========================================================
def checksum(st):
  s_sum= reduce(lambda x,y: x+y, map(lambda x:int(x,16), re.findall(".{2}",st[:-2]) ) )

  #print format(s_sum,"02X")[-2:]
  if format(s_sum,"02X")[-2:] == st[-2:]:
    return True
  else:
    return False
#==========================================================

try:
  ser= serial.Serial(SerPort, timeout=1)
except:
  print "Problem opening serial port"
  exit(1)

serbuff= ".."*9
while True:
  char= ser.read()
  hexchar= format(ord(char),"02X")
  serbuff= serbuff[2:] + hexchar

  #print serbuff, hexchar
  #serbuff="..5A5A45040C780D19A7.."
  match= re.findall("5A5A4504.{10}",serbuff)

  if match:
    line= match[0]
    if checksum(line):
      TO= int(line[ 8:12],16)/100.
      TA= int(line[12:16],16)/100.
      print "TO: {0:5.2f}     TA: {1:5.2f}".format(TO,TA)
    else:
      print "Wrong checksum"






Update: Well, once I got the code running, I could not resist to remove the redundant conversions, so here a bit better version:

#!/usr/bin/python
"""
5A5A45040C780D19A7
Express TO (There is a sign 16 bit, which represents the target temperature) :TO=0x0C78/100= 31.92C
Express TA (There is a sign 16 bit, indicates the ambient temperature)       :TA=0x0D19/100= 33.53C
"""

import serial
SerPort= "/dev/ttyAMA0"

#========================================================
try:
  ser= serial.Serial(SerPort, timeout=1)
except:
  print "Problem opening serial port"
  exit(1)

serbuff= "."*9                  # Initialize string buffer
start= "5A5A4504".decode("hex") # Start mask

while True:
  char= ser.read()
  serbuff= serbuff[1:] + char;  # FIFO char buffer

  if serbuff[:4] == start:
    line= serbuff
    if sum(bytearray(line[:-1]))%256 == ord(line[-1]) :
      TO= int(line[ 4:6].encode("hex"),16)/100.
      TA= int(line[ 6:8].encode("hex"),16)/100.
      print "TO: {0:5.2f}     TA: {1:5.2f}".format(TO,TA)
    else:
      print "TO: {0:5.2f}     TA: {1:5.2f}  Wrong Checksum!".format(TO,TA)

No comments: