Since the Photon is now running Python, which can do multi-threading, it's not necessarily the best idea to "interrupt & delay". That could grind everything to a halt. Not what we want...
So instead I've been working on reading the incoming serial from the Photon's Input Capture Unit. Most of the Photon's digital pins are enabled for that and since it's a hardware (!) feature it means the rest of the code can continue to run (Provided the different parts are in different threads).
So here's the code:
################################################################################
# SoftRx_ICU
#
# Created: 2015-11-06 16:31:10
#
# This software creates a serial code receiver on any digital pin of an MCU running VIPER python.
# It 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 necessary libraries
import timers
import pwm #needed to enable hwtimers to run (?)
import hwtimers
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 off 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 data on the software serial port using InputCaptureUnit
#########
#
# this code is waiting for an 8bit number flanked by a 2bit start and stop signal (each a [1,0] tuple)
# so it's looking for this kind of signal:
# __ __
# |__--|--|--|--|--|--|--|--| |__
#
# start| 8 bit binary |stop
#
# as far as I'm aware the arduino SoftSerial library only sends a LOW start bit and a HIGH stop bit.
# The start bit would be OK for this code (it's looking for a falling edge to start capture), but it doesn't cope well with just a HIGH stop bit.
#########
def receive1byteICU(_receivepin,_baudrate): # _receivepin must be DigPin.ICU
global RxBuffer
duration1bitMICROS = int(round((1/_baudrate)*(10**6))) # 1s = 10^6 microseconds, rounded to next integer
#wait for a falling edge to start capturing
tmpICU = icu.capture(_receivepin,LOW,8,int(10*(round(1/_baudrate))*(10**6)),time_unit=MICROS)#returns a list of microseconds
#create binary list from tmpICU
timeListICU = [int(round(x/duration1bitMICROS)) for x in tmpICU] #list of times in units of bit duration
BinListICU = [] # initiate list of binary values created from the microseconds list coming from the ICU
for i in range(len(tmpICU)):
if i%2==0:
for j in range(timeListICU[i]):
BinListICU.append(0)
else:
for j in range(timeListICU[i]):
BinListICU.append(1)
BinListICU[0:1] = [] #remove start bit
if len(BinListICU) < 8: #fill up all 8 bits
for i in range(8-len(BinListICU)):
BinListICU.append(0)
RxBuffer.append(SoftRx_Bin2Dec(BinListICU)) # add received decimal to buffer
return RxBuffer # hand the buffer back to the thread/main program
#########
# start up serial port using InputCaptureUnit
#########
def SoftRx_startICU(_rxpin,_baudrate):
global RxBuffer # any thread/program that wants to modify (!) the buffer needs to declare it global
RxBuffer = []
while True:
receive1byteICU(_rxpin,_baudrate) # now we're receiving decimal serial data
#############################################################################################################################
############
#########
# this section is only to test the SoftRx_ICU code
#########
############
def threadFct2():
while True:
#testing
sleep(10) # give the buffer time to fill
if len(RxBuffer)>9:
print(RxBuffer)
RxBuffer = []
sleep(1000)
print("starting")
sleep(500)
thread(SoftRx_startICU,D4.ICU,400) #start listening on the SoftSerial port
thread(threadFct2)
And a screenshot of the SoftRx_ICU in action:
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.