Close

Manchester encoding via ICU

A project log for ViperPhoton weather station

Host webpage with weather readings from distributed sensors on a viperized Photon

andreas.betzandreas.betz 11/25/2015 at 17:140 Comments

Receiving Manchester encoded data on the Photon's Input Capture Unit is now finally up and running. Well, the data bit at least (see below). I am still struggling to sync the receiver to the incoming serial clock, though. But that's a story for another day...

Here's the code that let's me capture Manchester encoded data (sent from a Nano following closely the work done by mchr3k) on the Photon

################################################################################
# ManchesterRx_v6
#
# Created: 2015-11-20
#
# This software creates a serial code receiver on any digital pin of an MCU running VIPER python.
# Serial data needs to be Manchester encoded.
# The Manchester en/decoding works along the lines of the Atmel Application Note "Manchester Coding Basics"
# This code was developed and tested on a viperized Photon board (Particle Photon).
#
# Copyright (c) 2015 A.C. Betz.  All right reserved. Developed using the VIPER IDE. 
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
#############################################################################################################################


############
#########
# DO THESE THINGS IN THE MAIN PROGRAM
#########
############
# import the streams module for USB serial port.
import streams

# open the default serial port
streams.serial()

#import ICU library
import icu

############
#########
# end of things to do in main program
#########
############

#############################################################################################################################

############
#########
# functions
#########


#########
# convert RxBuffer to decimal
#########
def SoftRx_Bin2Dec(_BinList):
    global tmpDec
    tmpDec = 0
    for i in range(8):
        tmpDec += _BinList[i]*(2**i)
    return tmpDec
    _BinList[0:8] = []

#########
# round of values
#########
def round(_x):
    if _x - int(_x) >0.5: # int() always rounds towards zero & _x always >0
        return _x+1
    else:
        return _x

#########
# receive Manchester encoded data on the software serial port using InputCaptureUnit
#########
#
# this code is waiting for 8 bits encoded in Manchester code flanked by a start and stop signal (each a [HIGH,LOW] tuple, i.e. a Manchester 0).
# Manchester code represents logic 1/0 by rising/falling edge transition in the bit middle:
# HIGH/1    __     LOW/0 __
#        __|               |__
#
# 
#########

# receive an array of data bytes (without termination zeros in the stream!)

def receiveManByteArray(_receivepin,_baudrate,_numberOfBytes): # expects inputs of the form (D1.ICU, 600, 10)
    duration1bitMICROS = int(round((1/_baudrate)*(10**6))) # 1s = 10^6 microseconds, rounded to next integer
    global RxBuffer

    RxBufferMAN = []
    BinListMAN = []
    
    tmpICU = icu.capture(_receivepin,LOW,16*_numberOfBytes,int(round((8*_numberOfBytes+0.75)*duration1bitMICROS)),time_unit=MICROS) # start capturing on falling edge, i.e. in the middle of the start "0"
    timeValues = [int(round(2*x/duration1bitMICROS)) for x in tmpICU]
    
    if len(tmpICU) > 0:  

        BinListMAN = [] # initiate list of binary values created from the microseconds list coming from the ICU, these are "half bits" though!
        for i in range(len(tmpICU)):
            if i%2==0:
                for j in range(timeValues[i]):
                    BinListMAN.append(0)
            else:
                for j in range(timeValues[i]):
                    BinListMAN.append(1)
        BinListMAN[0:1] = [] #remove first "bit"

        for i in range(8*_numberOfBytes+1):

            if BinListMAN[2*i:2*i+2] == [1,0]:
                RxBufferMAN.append(0)
            else:
                RxBufferMAN.append(1)
        print(RxBufferMAN)
        
        for i in range(_numberOfBytes):
            RxBuffer.append(SoftRx_Bin2Dec(RxBufferMAN))

            RxBufferMAN[0:8] = []

        RxBufferMAN = []

        return RxBuffer


#############################################################################################################################

# ############
# #########
# # this section is only to test the SoftRx_ICU code
# #########
# ############


_baudrate = 500
_receivepin = D4.ICU

global RxBuffer
RxBuffer = []

sleep(3000)
print("starting")

while True:
    receiveManByteArray(D4.ICU,500,5)
    print(RxBuffer)
    RxBuffer = []
        

Discussions