::::::::::textpak=>_Desc_adcRead_pkg.py.txt *********************************** adcRead_pkg.py Description (simple) *********************************** adcRead_pkg.py # function Package adcRead_pkg.py # contains # various functions needed by adcRead() # adcRead() itself # adcReadInit() which must be run before adcRead # see test_adcRead.py for main program setup import cmd, time, logging, smbus, RPi.GPIO as GPIO for Rpi 5B will need RPi5GPIO to use gpiozero ************************************************************************************ FROM smartyPies.com welcome projects misc imprint - legal - GDPR ADS1115Runner.py Mark©&paste the code into a file named "ADS1115Runner.py". Thanks to the guys from GeSHi and Curt, who made me revise the code. Created with GeSHi http://qbnz.com/highlighter/ ************************************************************************************ /_Desc_adcRead_pkg.py.txt ::::::::::textpak=>_Desc_ambRead_pkg.py.txt *********************************** ambRead_pkg.py Description (Simple) *********************************** This package contains functions that measure ambient parameters. /_Desc_ambRead_pkg.py.txt ::::::::::textpak=>_Desc_functionList_pkg.py.txt *********************************************************************** functionList_pkg.py Description (simple) *********************************************************************** This package is used by n_v04.py *********************************************************************** retrieved from Seagate 3T2021 BUs_ByH/2022/2022HAug23/_Fla58D064G/ BUs_byHand/2022DApr02Fla53S032G/functionList_pkg.py dated 4/2/2022 38 KB *********************************************************************** /_Desc_functionList_pkg.py.txt ::::::::::textpak=>_Desc_ix~ix_pkg.py.txt ix/ix_pkg.py.txt by D@CC on 2024BFeb09 This is the main pkg of general-purpose IX Python functions. It contains the most-used functions in the IX software library such as: f3() inputWTO() show() It is stored in Desktop/IX_assets/ /_Desc_ix~ix_pkg.py.txt ::::::::::textpak=>_Desc_textpack_pkg.py.txt ************************************ textpack_pkg.py Description (simple) ************************************ this package is quite stable it allows pack and unpack of code into a package It works with n.py textpack.py textunpack.py etc The latest version v04 of n.py display much info about the files in a package. *********************************** /_Desc_textpack_pkg.py.txt ::::::::::textpak=>_mod8.py.txt # store this in Desktop/mod6 as _mod8.py # point Files to /home/pi/Desktop # then run this with # >>>import mod6 # >>>mod8.hello() # This worked on 2021EMay28 by D@CC using Python3 # and with MicroPython in a package folder w/o __init__.py # Source: https://wiki.micropython.org/Importing-Modules def hello(): print('hello from mod8') hello() #/mod8.py ::::::::::textpak=>1Char_py.py.txt def bChar(strB): # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] print("b:"+b) c=b[0] #c="zz" print("bChar("+'"'+strB+ '"):'+c) return c #end def while True: print(bChar(input("eg b'h' :"))) #end while ::::::::::textpak=>adcRead_pkg.py.txt #::::::::::textpak=>adcRead_pkg.py # function Package adcRead_pkg.py # contains # various functions needed by adcRead() # adcRead() itself # adcReadInit() which must be run before adcRead # see test_adcRead.py for main program setup import cmd, time, logging, smbus, RPi.GPIO as GPIO #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F # Usage once: # define adcRead constants # see the main program test_adcRead.py # BUS = adcReadInit(I2C_BUS,icNumber) # create BUS class object # BUS.open(I2C_BUS) # . . . then repeatedly # value = adcRead(nChannel) # read nChannel of the ADS1115 once # # no other functions need to be called # # the only externally callable functions are # adcReadInit() # adcRead() # # stop this program using ctrl+c # how to stop the test def MUX(n): if n==0: m="00" if n==1: m="01" if n==2: m="10" if n==3: m="11" return m #def end def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF #def end def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) #def end def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c #def end def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) #def end def resetChip(RESET_ADDRESS, RESET_COMMAND): #BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return #def end class ADS1115Runner(cmd.Cmd): # this is the entry-point for Runner.cmdloop() # NB cmd.Cmd has been deprecated # cmd.Cmd will cause the self.cmdLoop() to return to the object's main method. # the ''' permits the definition of a string variable containing LFs #intro = '''usage: type following commands # 1 - one-shot measurement mode, timed # 2 - one-shot measurement mode, alerted through GPIO # 3 - continuous measurment mode, alerted through GPIO # 4 low high - continuous mode, alerted when value out of range [low, high] # q (quit) # just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' #prompt = 'Enter 1,2,3,4 or q >>' # if you enter 1 it will run do_1(), 2 . . . do_2() etc file = None __logfile = None def alerted(self, arg): # deprecated data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return #def end alerted() def do_q(self, arg): exit #def end do_q() def mydo_1(self,BUS,AINn): RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip # replaces do_1 routine #print("into do_1 arg:",arg) #print("into do_1") '''One-shot, Read value from channel AINn with wait time''' #resetChip(RESET_ADDRESS, RESET_COMMAND) #deprecated BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # compare with configuration settings from ADS1115 datasheet #DC # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator # conf = prepareLEconf('1-110-001-1-000-0-0-0-11') #DC # AINn = 2 arg1 is AINn the nChannel to read ADSn = MUX(AINn) #e.g. AINn=2 read AIN2 ( AIN2 to GND*) #DC conf = prepareLEconf('1-1'+ADSn+'-001-1-000-0-0-0-11') #DC go = 'y' #while True and go in ['y','Y']: if True : #only do this once BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) #print("mid do_1") global g_adcValue g_adcValue = value # so adcRead() can see it #print(value) # test_adcRead() will print it #enter to break, repeat with 'y' if False : # deprecated go= input('continue: n/y') if (len(go)==0): go='n' #time.sleep(sleepTime) #if end return value #def end mydo_1() def shutdown(self): #GPIO.cleanup() #BUS.close() pass #def end shutdown() #class end ADS1115Runner() def adcRead(BUS,nChannel=0) : # nChannel is the number of the analog input to read i.e. 0 = AIN0 # adcRead returns value 0 to ~11000 as the actual reading #by D@CC on 202CMar16 DC #must be preceded by # BUS.adcReadInit(I2C_BUS,icNumber) # BUS.open(I2C_BUS) #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F #Jumper S of KY-18 photo-cell to AIN2 # invert the KY-18 3v3 and GND to measure the opposite [ light (not dark) ] # terminal strip is L-R on the ADS1115 for RPi from SeeedStudios # 3V3,AIN3,AIN2,AIN1,AIN0,GND # Uses 3 objects:BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # Runner. for ADS1115 ADC # BUS. for ADS11#Jumper S of KY-18 photo-cell to AIN2 #DC # GPIO. for ALERTPIN class is not used #DC try: # I (D@CC) do not know anything about the logging logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') #print("logger:",logger) #AINn=2 # AINn=2 to read AIN2 Runner = ADS1115Runner() # create object Runner #print("before .cmdloop") Runner.mydo_1(BUS,nChannel) # nChannel is 2 to read AIN2 #Runner.cmdloop() # will run the main Runner.method (cmd.Cmd) # which prompts for a response & invokes do_r(arg) # for a response of "r arg" #print("after .cmdloop") global g_adcValue returnValue = g_adcValue # from mydo_1 return returnValue finally: Runner.shutdown() #release this object #BUS.close() #release this object #if end adcRead() def adcReadInit(I2C_BUS=1,icNumber="ADS1115") : # arg1 is the BUS number used by the IC chip # arg2 is the number of the IC chip used on the Seeed ADS1115 4 channel RPi board # usage of global variables # global g_adcValue if icNumber=="ADS1115" : BUS=smbus.SMBus(I2C_BUS) #returns the BUS object , (usually BUS=smbus.SMBus(I2C_BUS) ) # Open I2C device # I2C_BUS = 1 # DEVICE_ADDRESS = 0x48 return BUS else: print('ERROR025: ic supported is "ADS1115"') exit #def end adcReadInit() # 9 constants included in adcRead_Pkg.py RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip icNumber = "ADS1115" # IC chip used I2C_BUS = 1 # BUS number used by the IC chip # end of adcRead_pkg.py ::::::::::textpak=>adcRead_pkg_bu.py.txt #::::::::::textpak=>adcRead_pkg.py # function Package adcRead_pkg.py # contains # various functions needed by adcRead() # adcRead() itself # adcReadInit() which must be run before adcRead # see test_adcRead.py for main program setup import cmd, time, logging, smbus, RPi.GPIO as GPIO #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F # Usage once: # define adcRead constants # see the main program test_adcRead.py # BUS = adcReadInit(I2C_BUS,icNumber) # create BUS class object # BUS.open(I2C_BUS) # . . . then repeatedly # value = adcRead(nChannel) # read nChannel of the ADS1115 once # # no other functions need to be called # # the only externally callable functions are # adcReadInit() # adcRead() # # stop this program using ctrl+c # how to stop the test def MUX(n): if n==0: m="00" if n==1: m="01" if n==2: m="10" if n==3: m="11" return m #def end def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF #def end def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) #def end def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c #def end def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) #def end def resetChip(RESET_ADDRESS, RESET_COMMAND): #BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return #def end class ADS1115Runner(cmd.Cmd): # this is the entry-point for Runner.cmdloop() # NB cmd.Cmd has been deprecated # cmd.Cmd will cause the self.cmdLoop() to return to the object's main method. # the ''' permits the definition of a string variable containing LFs #intro = '''usage: type following commands # 1 - one-shot measurement mode, timed # 2 - one-shot measurement mode, alerted through GPIO # 3 - continuous measurment mode, alerted through GPIO # 4 low high - continuous mode, alerted when value out of range [low, high] # q (quit) # just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' #prompt = 'Enter 1,2,3,4 or q >>' # if you enter 1 it will run do_1(), 2 . . . do_2() etc file = None __logfile = None def alerted(self, arg): # deprecated data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return #def end alerted() def do_q(self, arg): exit #def end do_q() def mydo_1(self,BUS,AINn): RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip # replaces do_1 routine #print("into do_1 arg:",arg) #print("into do_1") '''One-shot, Read value from channel AINn with wait time''' #resetChip(RESET_ADDRESS, RESET_COMMAND) #deprecated BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # compare with configuration settings from ADS1115 datasheet #DC # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator # conf = prepareLEconf('1-110-001-1-000-0-0-0-11') #DC # AINn = 2 arg1 is AINn the nChannel to read ADSn = MUX(AINn) #e.g. AINn=2 read AIN2 ( AIN2 to GND*) #DC conf = prepareLEconf('1-1'+ADSn+'-001-1-000-0-0-0-11') #DC go = 'y' #while True and go in ['y','Y']: if True : #only do this once BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) #print("mid do_1") global g_adcValue g_adcValue = value # so adcRead() can see it #print(value) # test_adcRead() will print it #enter to break, repeat with 'y' if False : # deprecated go= input('continue: n/y') if (len(go)==0): go='n' #time.sleep(sleepTime) #if end return value #def end mydo_1() def shutdown(self): #GPIO.cleanup() #BUS.close() pass #def end shutdown() #class end ADS1115Runner() def adcRead(BUS,nChannel=0) : # nChannel is the number of the analog input to read i.e. 0 = AIN0 # adcRead returns value 0 to ~11000 as the actual reading #by D@CC on 202CMar16 DC #must be preceded by # BUS.adcReadInit(I2C_BUS,icNumber) # BUS.open(I2C_BUS) #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F #Jumper S of KY-18 photo-cell to AIN2 # invert the KY-18 3v3 and GND to measure the opposite [ light (not dark) ] # terminal strip is L-R on the ADS1115 for RPi from SeeedStudios # 3V3,AIN3,AIN2,AIN1,AIN0,GND # Uses 3 objects:BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # Runner. for ADS1115 ADC # BUS. for ADS11#Jumper S of KY-18 photo-cell to AIN2 #DC # GPIO. for ALERTPIN class is not used #DC try: # I (D@CC) do not know anything about the logging logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') #print("logger:",logger) #AINn=2 # AINn=2 to read AIN2 Runner = ADS1115Runner() # create object Runner #print("before .cmdloop") Runner.mydo_1(BUS,nChannel) # nChannel is 2 to read AIN2 #Runner.cmdloop() # will run the main Runner.method (cmd.Cmd) # which prompts for a response & invokes do_r(arg) # for a response of "r arg" #print("after .cmdloop") global g_adcValue returnValue = g_adcValue # from mydo_1 return returnValue finally: Runner.shutdown() #release this object #BUS.close() #release this object #if end adcRead() def adcReadInit(I2C_BUS=1,icNumber="ADS1115") : # arg1 is the BUS number used by the IC chip # arg2 is the number of the IC chip used on the Seeed ADS1115 4 channel RPi board # usage of global variables # global g_adcValue if icNumber=="ADS1115" : BUS=smbus.SMBus(I2C_BUS) #returns the BUS object , (usually BUS=smbus.SMBus(I2C_BUS) ) # Open I2C device # I2C_BUS = 1 # DEVICE_ADDRESS = 0x48 return BUS else: print('ERROR025: ic supported is "ADS1115"') exit #def end adcReadInit() # 9 constants included in adcRead_Pkg.py RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip icNumber = "ADS1115" # IC chip used I2C_BUS = 1 # BUS number used by the IC chip # end of adcRead_pkg_bu.py ::::::::::textpak=>adcRead_pkg_v01.py.txt #::::::::::textpak=>ADS1115Runner_wComments.txt smartyPies.com welcome projects misc imprint - legal - GDPR ADS1115Runner.py Mark©&paste the code into a file named "ADS1115Runner.py". Thanks to the guys from GeSHi and Curt, who made me revise the code. Created with GeSHi http://qbnz.com/highlighter/ #!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' @author: guido lutterbach @contact: guido@smartypies.com @version: 1.1 @licence: Public Domain This program implements 4 cases for ADS1115 on raspberry pi with default libraries. 1) single-shot - open drain - timed 2) single-shot - open drain - GPIO alert 3) continuous mode - differential - GPIO alert 4) continuous mode - differential - GPIO alert when value leaves high/low threshold range Please check the electric circuit that goes with it at www.smartypies.com (ADS1115 project) For testing 1) + 2) use potentiometer 1 For testing 3) + 4) use potentiometer 2 Enjoy! ''' import cmd, time, logging, smbus, RPi.GPIO as GPIO # ADS1115 + hardware constants I2C_BUS = 1 DEVICE_ADDRESS = 0x4B POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 # Open I2C device BUS = smbus.SMBus(I2C_BUS) BUS.open(I2C_BUS) ALERTPIN = 27 def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) def resetChip(): BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return # Use BCM GPIO references GPIO.setmode(GPIO.BCM) GPIO.setup(ALERTPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## read mode, pull up resistor class ADS1115Runner(cmd.Cmd): intro = '''usage: type following commands 1 - one-shot measurement mode, timed 2 - one-shot measurement mode, alerted through GPIO 3 - continuous measurment mode, alerted through GPIO 4 low high - continuous mode, alerted when value out of range [low, high] q (quit) just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' prompt = 'Enter 1,2,3,4 or q >>' file = None # __logfile = None def alerted(self, arg): data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return def do_1(self, arg): '''One-shot, Read value from channel 0 with wait time''' resetChip() # compare with configuration settings from ADS115 datasheet # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator conf = prepareLEconf('1-110-001-1-000-0-0-0-11') go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) print(value) #enter to break, repeat with 'y' go= input('continue: n/y') if (len(go)==0): go='n' return def do_2(self, arg): '''One-shot with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet: # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - # trad. comparator - active high - latching - assert after one conversion conf = prepareLEconf('1-110-001-1-000-0-1-1-00') BUS.write_byte(0b0000000,0b00000110) # reset call # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) #enter to break, repeat with 'y' go= input('continue: n/y\n') # remove event listener GPIO.remove_event_detect(ALERTPIN) return def do_3(self, arg): '''Continuous mode with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 64SPS - # window comparator - active high - nonlatching - assert after one conversion conf = prepareLEconf('0-000-010-0-011-1-1-0-00') # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_4(self, arg): ''' Continuous measurements with latch and allowable data range''' largs = tuple(map(int, arg.split())) if len(largs) != 2: print('please call with exactly 2 integer arguments') return # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 8SPS - # window comparator - active high - latching - assert after one conversion conf = prepareLEconf('0-000-010-0-000-1-1-1-00') # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # prepare for ALERT pin mode - define window low = min(largs) # Python BigEndian - RaspberryPi LittleEndian high = max(largs) low_val = BEtoLE(low) high_val = BEtoLE(high) logger.debug( "{:04X} {:04x} {:04x} {:04x} ".format(low, low_val, high, high_val)) BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, low_val) BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, high_val) # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_q(self, arg): '''Quit.''' return True def default(self, line): print('undefined key') def shutdown(self): GPIO.cleanup() BUS.close() pass if __name__ == "__main__": try: logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') Runner = ADS1115Runner() Runner.cmdloop() finally: Runner.shutdown() # © Copyright 2017-20 by Guido Lutterbach # guido@smartypies.com # / ADS1115Runner.p #::::::::::textpak=>ADS1115Runner_pgmOnly.py import cmd, time, logging, smbus, RPi.GPIO as GPIO # ADS1115 + hardware constants I2C_BUS = 1 #DEVICE_ADDRESS = 0x4B #DC DEVICE_ADDRESS = 0x48 #DC POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 # Open I2C device BUS = smbus.SMBus(I2C_BUS) BUS.open(I2C_BUS) ALERTPIN = 27 #GPIO27 #DC def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) def resetChip(): BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return # Use BCM GPIO references GPIO.setmode(GPIO.BCM) GPIO.setup(ALERTPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## read mode, pull up resistor class ADS1115Runner(cmd.Cmd): intro = '''usage: type following commands 1 - one-shot measurement mode, timed 2 - one-shot measurement mode, alerted through GPIO 3 - continuous measurment mode, alerted through GPIO 4 low high - continuous mode, alerted when value out of range [low, high] q (quit) just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' prompt = 'Enter 1,2,3,4 or q >>' file = None # __logfile = None def alerted(self, arg): data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return def do_1(self, arg): '''One-shot, Read value from channel 0 with wait time''' resetChip() # compare with configuration settings from ADS115 datasheet # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator conf = prepareLEconf('1-110-001-1-000-0-0-0-11') go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) print(value) #enter to break, repeat with 'y' go= input('continue: n/y') if (len(go)==0): go='n' return def do_2(self, arg): '''One-shot with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet: # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - # trad. comparator - active high - latching - assert after one conversion conf = prepareLEconf('1-110-001-1-000-0-1-1-00') BUS.write_byte(0b0000000,0b00000110) # reset call # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) #enter to break, repeat with 'y' go= input('continue: n/y\n') # remove event listener GPIO.remove_event_detect(ALERTPIN) return def do_3(self, arg): '''Continuous mode with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 64SPS - # window comparator - active high - nonlatching - assert after one conversion conf = prepareLEconf('0-000-010-0-011-1-1-0-00') # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_4(self, arg): ''' Continuous measurements with latch and allowable data range''' largs = tuple(map(int, arg.split())) if len(largs) != 2: print('please call with exactly 2 integer arguments') return # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 8SPS - # window comparator - active high - latching - assert after one conversion conf = prepareLEconf('0-000-010-0-000-1-1-1-00') # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # prepare for ALERT pin mode - define window low = min(largs) # Python BigEndian - RaspberryPi LittleEndian high = max(largs) low_val = BEtoLE(low) high_val = BEtoLE(high) logger.debug( "{:04X} {:04x} {:04x} {:04x} ".format(low, low_val, high, high_val)) BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, low_val) BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, high_val) # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_q(self, arg): '''Quit.''' return True def default(self, line): print('undefined key') def shutdown(self): GPIO.cleanup() BUS.close() pass if __name__ == "__main__": try: logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') Runner = ADS1115Runner() Runner.cmdloop() finally: Runner.shutdown() # © Copyright 2017-20 by Guido Lutterbach # guido@smartypies.com # / ADS1115Runner_pgmOnly.p #::::::::::textpak=>adcRead_Pkg.py # function Package adcRead_Pkg.py import cmd, time, logging, smbus, RPi.GPIO as GPIO #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F # Usage once: # define adcRead constants # see the main program test_adcRead.py # BUS = adcReadInit(I2C_BUS,icNumber) # create BUS class object # BUS.open(I2C_BUS) # . . . then repeatedly # value = adcRead(nChannel) # read nChannel of the ADS1115 once # # no other functions need to be called # # the only externally callable functions are # adcReadInit() # adcRead() # # stop this program using ctrl+c # how to stop the test def MUX(n): if n==0: m="00" if n==1: m="01" if n==2: m="10" if n==3: m="11" return m #def end def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF #def end def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) #def end def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c #def end def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) #def end def resetChip(RESET_ADDRESS, RESET_COMMAND): #BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return #def end class ADS1115Runner(cmd.Cmd): # this is the entry-point for Runner.cmdloop() # NB cmd.Cmd has been deprecated # cmd.Cmd will cause the self.cmdLoop() to return to the object's main method. # the ''' permits the definition of a string variable containing LFs #intro = '''usage: type following commands # 1 - one-shot measurement mode, timed # 2 - one-shot measurement mode, alerted through GPIO # 3 - continuous measurment mode, alerted through GPIO # 4 low high - continuous mode, alerted when value out of range [low, high] # q (quit) # just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' #prompt = 'Enter 1,2,3,4 or q >>' # if you enter 1 it will run do_1(), 2 . . . do_2() etc file = None __logfile = None def alerted(self, arg): # deprecated data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return #def end alerted() def do_q(self, arg): exit #def end do_q() def mydo_1(self,BUS,AINn): RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip # replaces do_1 routine #print("into do_1 arg:",arg) #print("into do_1") '''One-shot, Read value from channel AINn with wait time''' #resetChip(RESET_ADDRESS, RESET_COMMAND) #deprecated BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # compare with configuration settings from ADS1115 datasheet #DC # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator # conf = prepareLEconf('1-110-001-1-000-0-0-0-11') #DC # AINn = 2 arg1 is AINn the nChannel to read ADSn = MUX(AINn) #e.g. AINn=2 read AIN2 ( AIN2 to GND*) #DC conf = prepareLEconf('1-1'+ADSn+'-001-1-000-0-0-0-11') #DC go = 'y' #while True and go in ['y','Y']: if True : #only do this once BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) #print("mid do_1") global g_adcValue g_adcValue = value # so adcRead() can see it #print(value) # test_adcRead() will print it #enter to break, repeat with 'y' if False : # deprecated go= input('continue: n/y') if (len(go)==0): go='n' #time.sleep(sleepTime) #if end return value #def end mydo_1() def shutdown(self): #GPIO.cleanup() #BUS.close() pass #def end shutdown() #class end ADS1115Runner() def adcRead(BUS,nChannel=0) : # nChannel is the number of the analog input to read i.e. 0 = AIN0 # adcRead returns value 0 to ~11000 as the actual reading #by D@CC on 202CMar16 DC #must be preceded by # BUS.adcReadInit(I2C_BUS,icNumber) # BUS.open(I2C_BUS) #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F #Jumper S of KY-18 photo-cell to AIN2 # invert the KY-18 3v3 and GND to measure the opposite [ light (not dark) ] # terminal strip is L-R on the ADS1115 for RPi from SeeedStudios # 3V3,AIN3,AIN2,AIN1,AIN0,GND # Uses 3 objects:BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # Runner. for ADS1115 ADC # BUS. for ADS11#Jumper S of KY-18 photo-cell to AIN2 #DC # GPIO. for ALERTPIN class is not used #DC try: # I (D@CC) do not know anything about the logging logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') #print("logger:",logger) #AINn=2 # AINn=2 to read AIN2 Runner = ADS1115Runner() # create object Runner #print("before .cmdloop") Runner.mydo_1(BUS,nChannel) # nChannel is 2 to read AIN2 #Runner.cmdloop() # will run the main Runner.method (cmd.Cmd) # which prompts for a response & invokes do_r(arg) # for a response of "r arg" #print("after .cmdloop") global g_adcValue returnValue = g_adcValue # from mydo_1 return returnValue finally: Runner.shutdown() #release this object #BUS.close() #release this object #if end adcRead() def adcReadInit(I2C_BUS=1,icNumber="ADS1115") : # arg1 is the BUS number used by the IC chip # arg2 is the number of the IC chip used on the Seeed ADS1115 4 channel RPi board # usage of global variables # global g_adcValue if icNumber=="ADS1115" : BUS=smbus.SMBus(I2C_BUS) #returns the BUS object , (usually BUS=smbus.SMBus(I2C_BUS) ) # Open I2C device # I2C_BUS = 1 # DEVICE_ADDRESS = 0x48 return BUS else: print('ERROR025: ic supported is "ADS1115"') exit #def end adcReadInit() # 9 constants included in adcRead_Pkg.py RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip icNumber = "ADS1115" # IC chip used I2C_BUS = 1 # BUS number used by the IC chip # end of adcRead_pkg.p #::::::::::textpak=>test_adcRead.py # test_adcRead.py # program to test adcRead() to read nChannel on the ADS1115 ADC RPi module from SeeedStuios # by D@CC on 2022CMar16 # needs to have adcRead_Pkg.py in the same folder as test_adcRead.py # needs import time import time # needs from adcRead_Pkg import adcRead,adcReadInit from adcRead_Pkg import adcRead,adcReadInit #needs to be run as >$ python3 test_adcRead.py if __name__ == "__main__": # import adcRead_pkg.py # is needed progName="test_adcRead.py" #this is the main program to test adcRead() print("starting:"+progName) # These 9 parameters are also defined in # adcRead_pkg.py: # mydo_1() RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip icNumber = "ADS1115" # IC chip used I2C_BUS = 1 # BUS number used by the IC chip # above constants are used with the ADS1115 IC chip: # [they could be defined as global variables in adcRead_init() instead] # These 2 constants must be defined in the test_adcRead.py program dT = 1 # sleep time between readings (set by the user of this program) nChannel = 2 # AINn is the analog pin # to read on the ADS1115 IC chip # # more than 1 channel can be read by the program # # simply use adcRead(nChannel) where nChannel is the channel to read # usage of global variables # global g_adcValue # this variable can be referenced (seen) by any program using adcRead() # it always contains the most-recent-value read by adcRead() #create the BUS object BUS = adcReadInit(I2C_BUS,icNumber) BUS.open(I2C_BUS) while True : # loop value = adcRead(BUS,nChannel) # reading nChannel of the ADS1115 once AINn="AIN"+str(nChannel) AINn=AINn.strip(" ") print ("value of "+AINn+" reading:", value) if dT==0 : break #out of while loop # dT=0 will only read it once else: time.sleep(dT) # dT>0 will read it continuously #if end #while end #end test_adcRead.py /adcRead_pkg_v01.py ::::::::::textpak=>adcRead_pkg_v02.py.txt #::::::::::textpak=>ADS1115Runner_wComments.txt smartyPies.com welcome projects misc imprint - legal - GDPR ADS1115Runner.py Mark©&paste the code into a file named "ADS1115Runner.py". Thanks to the guys from GeSHi and Curt, who made me revise the code. Created with GeSHi http://qbnz.com/highlighter/ #!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' @author: guido lutterbach @contact: guido@smartypies.com @version: 1.1 @licence: Public Domain This program implements 4 cases for ADS1115 on raspberry pi with default libraries. 1) single-shot - open drain - timed 2) single-shot - open drain - GPIO alert 3) continuous mode - differential - GPIO alert 4) continuous mode - differential - GPIO alert when value leaves high/low threshold range Please check the electric circuit that goes with it at www.smartypies.com (ADS1115 project) For testing 1) + 2) use potentiometer 1 For testing 3) + 4) use potentiometer 2 Enjoy! ''' import cmd, time, logging, smbus, RPi.GPIO as GPIO # ADS1115 + hardware constants I2C_BUS = 1 DEVICE_ADDRESS = 0x4B POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 # Open I2C device BUS = smbus.SMBus(I2C_BUS) BUS.open(I2C_BUS) ALERTPIN = 27 def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) def resetChip(): BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return # Use BCM GPIO references GPIO.setmode(GPIO.BCM) GPIO.setup(ALERTPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## read mode, pull up resistor class ADS1115Runner(cmd.Cmd): intro = '''usage: type following commands 1 - one-shot measurement mode, timed 2 - one-shot measurement mode, alerted through GPIO 3 - continuous measurment mode, alerted through GPIO 4 low high - continuous mode, alerted when value out of range [low, high] q (quit) just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' prompt = 'Enter 1,2,3,4 or q >>' file = None # __logfile = None def alerted(self, arg): data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return def do_1(self, arg): '''One-shot, Read value from channel 0 with wait time''' resetChip() # compare with configuration settings from ADS115 datasheet # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator conf = prepareLEconf('1-110-001-1-000-0-0-0-11') go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) print(value) #enter to break, repeat with 'y' go= input('continue: n/y') if (len(go)==0): go='n' return def do_2(self, arg): '''One-shot with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet: # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - # trad. comparator - active high - latching - assert after one conversion conf = prepareLEconf('1-110-001-1-000-0-1-1-00') BUS.write_byte(0b0000000,0b00000110) # reset call # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) #enter to break, repeat with 'y' go= input('continue: n/y\n') # remove event listener GPIO.remove_event_detect(ALERTPIN) return def do_3(self, arg): '''Continuous mode with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 64SPS - # window comparator - active high - nonlatching - assert after one conversion conf = prepareLEconf('0-000-010-0-011-1-1-0-00') # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_4(self, arg): ''' Continuous measurements with latch and allowable data range''' largs = tuple(map(int, arg.split())) if len(largs) != 2: print('please call with exactly 2 integer arguments') return # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 8SPS - # window comparator - active high - latching - assert after one conversion conf = prepareLEconf('0-000-010-0-000-1-1-1-00') # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # prepare for ALERT pin mode - define window low = min(largs) # Python BigEndian - RaspberryPi LittleEndian high = max(largs) low_val = BEtoLE(low) high_val = BEtoLE(high) logger.debug( "{:04X} {:04x} {:04x} {:04x} ".format(low, low_val, high, high_val)) BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, low_val) BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, high_val) # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_q(self, arg): '''Quit.''' return True def default(self, line): print('undefined key') def shutdown(self): GPIO.cleanup() BUS.close() pass if __name__ == "__main__": try: logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') Runner = ADS1115Runner() Runner.cmdloop() finally: Runner.shutdown() # © Copyright 2017-20 by Guido Lutterbach # guido@smartypies.com # / ADS1115Runner.p #::::::::::textpak=>ADS1115Runner_pgmOnly.py import cmd, time, logging, smbus, RPi.GPIO as GPIO # ADS1115 + hardware constants I2C_BUS = 1 #DEVICE_ADDRESS = 0x4B #DC DEVICE_ADDRESS = 0x48 #DC POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 # Open I2C device BUS = smbus.SMBus(I2C_BUS) BUS.open(I2C_BUS) ALERTPIN = 27 #GPIO27 #DC def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) def resetChip(): BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return # Use BCM GPIO references GPIO.setmode(GPIO.BCM) GPIO.setup(ALERTPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## read mode, pull up resistor class ADS1115Runner(cmd.Cmd): intro = '''usage: type following commands 1 - one-shot measurement mode, timed 2 - one-shot measurement mode, alerted through GPIO 3 - continuous measurment mode, alerted through GPIO 4 low high - continuous mode, alerted when value out of range [low, high] q (quit) just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' prompt = 'Enter 1,2,3,4 or q >>' file = None # __logfile = None def alerted(self, arg): data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return def do_1(self, arg): '''One-shot, Read value from channel 0 with wait time''' resetChip() # compare with configuration settings from ADS115 datasheet # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator conf = prepareLEconf('1-110-001-1-000-0-0-0-11') go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) print(value) #enter to break, repeat with 'y' go= input('continue: n/y') if (len(go)==0): go='n' return def do_2(self, arg): '''One-shot with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet: # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - # trad. comparator - active high - latching - assert after one conversion conf = prepareLEconf('1-110-001-1-000-0-1-1-00') BUS.write_byte(0b0000000,0b00000110) # reset call # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian go = 'y' while True and go in ['y','Y']: BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) #enter to break, repeat with 'y' go= input('continue: n/y\n') # remove event listener GPIO.remove_event_detect(ALERTPIN) return def do_3(self, arg): '''Continuous mode with GPIO alert''' # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 64SPS - # window comparator - active high - nonlatching - assert after one conversion conf = prepareLEconf('0-000-010-0-011-1-1-0-00') # set High and Low threshold for ALERT pin mode BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, 0xFF7F) # 0x7FFF in BigEndian BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, 0x0080) # 0x8000 in BigEndian # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_4(self, arg): ''' Continuous measurements with latch and allowable data range''' largs = tuple(map(int, arg.split())) if len(largs) != 2: print('please call with exactly 2 integer arguments') return # reset call resetChip() # compare with configuration settings from ADS115 datasheet # X - AIN0/AIN1 - 2.048V - continuous mode - 8SPS - # window comparator - active high - latching - assert after one conversion conf = prepareLEconf('0-000-010-0-000-1-1-1-00') # register callback for alerts GPIO.add_event_detect(ALERTPIN, GPIO.RISING, callback=self.alerted) # prepare for ALERT pin mode - define window low = min(largs) # Python BigEndian - RaspberryPi LittleEndian high = max(largs) low_val = BEtoLE(low) high_val = BEtoLE(high) logger.debug( "{:04X} {:04x} {:04x} {:04x} ".format(low, low_val, high, high_val)) BUS.write_word_data(DEVICE_ADDRESS, POINTER_LOW_THRESHOLD, low_val) BUS.write_word_data(DEVICE_ADDRESS, POINTER_HIGH_THRESHOLD, high_val) # write configuration ONCE BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # wait for input(), enter to break input('enter to stop\n' ) # remove event listener to stop execution GPIO.remove_event_detect(ALERTPIN) return def do_q(self, arg): '''Quit.''' return True def default(self, line): print('undefined key') def shutdown(self): GPIO.cleanup() BUS.close() pass if __name__ == "__main__": try: logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') Runner = ADS1115Runner() Runner.cmdloop() finally: Runner.shutdown() # © Copyright 2017-20 by Guido Lutterbach # guido@smartypies.com # / ADS1115Runner_pgmOnly.p #::::::::::textpak=>adcRead_Pkg.py # function Package adcRead_Pkg.py import cmd, time, logging, smbus, RPi.GPIO as GPIO #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F # Usage once: # define adcRead constants # see the main program test_adcRead.py # BUS = adcReadInit(I2C_BUS,icNumber) # create BUS class object # BUS.open(I2C_BUS) # . . . then repeatedly # value = adcRead(nChannel) # read nChannel of the ADS1115 once # # no other functions need to be called # # the only externally callable functions are # adcReadInit() # adcRead() # # stop this program using ctrl+c # how to stop the test def MUX(n): if n==0: m="00" if n==1: m="01" if n==2: m="10" if n==3: m="11" return m #def end def swap2Bytes(c): '''Revert Byte order for Words (2 Bytes, 16 Bit).''' return (c>>8 |c<<8)&0xFFFF #def end def prepareLEconf(BEconf): '''Prepare LittleEndian Byte pattern from BigEndian configuration string, with separators.''' c = int(BEconf.replace('-',''), base=2) return swap2Bytes(c) #def end def LEtoBE(c): '''Little Endian to BigEndian conversion for signed 2Byte integers (2 complement).''' c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c #def end def BEtoLE(c): '''BigEndian to LittleEndian conversion for signed 2 Byte integers (2 complement).''' if(c < 0): c= 2**16 + c return swap2Bytes(c) #def end def resetChip(RESET_ADDRESS, RESET_COMMAND): #BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) return #def end class ADS1115Runner(cmd.Cmd): # this is the entry-point for Runner.cmdloop() # NB cmd.Cmd has been deprecated # cmd.Cmd will cause the self.cmdLoop() to return to the object's main method. # the ''' permits the definition of a string variable containing LFs #intro = '''usage: type following commands # 1 - one-shot measurement mode, timed # 2 - one-shot measurement mode, alerted through GPIO # 3 - continuous measurment mode, alerted through GPIO # 4 low high - continuous mode, alerted when value out of range [low, high] # q (quit) # just hitting enter quits any mode 1-4. Enter 'y' to continue in modes 1 and 2.''' #prompt = 'Enter 1,2,3,4 or q >>' # if you enter 1 it will run do_1(), 2 . . . do_2() etc file = None __logfile = None def alerted(self, arg): # deprecated data_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) print('alerted:' + str(LEtoBE(data_raw))) return #def end alerted() def do_q(self, arg): exit #def end do_q() def mydo_1(self,BUS,AINn): RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip # replaces do_1 routine #print("into do_1 arg:",arg) #print("into do_1") '''One-shot, Read value from channel AINn with wait time''' #resetChip(RESET_ADDRESS, RESET_COMMAND) #deprecated BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # compare with configuration settings from ADS1115 datasheet #DC # start single conversion - AIN2/GND - 4.096V - single shot - 8SPS - X # - X - X - disable comparator # conf = prepareLEconf('1-110-001-1-000-0-0-0-11') #DC # AINn = 2 arg1 is AINn the nChannel to read ADSn = MUX(AINn) #e.g. AINn=2 read AIN2 ( AIN2 to GND*) #DC conf = prepareLEconf('1-1'+ADSn+'-001-1-000-0-0-0-11') #DC go = 'y' #while True and go in ['y','Y']: if True : #only do this once BUS.write_word_data(DEVICE_ADDRESS, POINTER_CONFIGURATION, conf) # long enough to be safe that data acquisition (conversion) has completed # may be calculated from data rate + some extra time for safety. # check accuracy in any case. time.sleep(0.2) value_raw = BUS.read_word_data(DEVICE_ADDRESS, POINTER_CONVERSION) value = LEtoBE(value_raw) #print("mid do_1") global g_adcValue g_adcValue = value # so adcRead() can see it #print(value) # test_adcRead() will print it #enter to break, repeat with 'y' if False : # deprecated go= input('continue: n/y') if (len(go)==0): go='n' #time.sleep(sleepTime) #if end return value #def end mydo_1() def shutdown(self): #GPIO.cleanup() #BUS.close() pass #def end shutdown() #class end ADS1115Runner() def adcRead(BUS,nChannel=0) : # nChannel is the number of the analog input to read i.e. 0 = AIN0 # adcRead returns value 0 to ~11000 as the actual reading #by D@CC on 202CMar16 DC #must be preceded by # BUS.adcReadInit(I2C_BUS,icNumber) # BUS.open(I2C_BUS) #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC #ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1647366695082&ref_url=https%253A%252F%252Fwww.digchip.com%252F #Jumper S of KY-18 photo-cell to AIN2 # invert the KY-18 3v3 and GND to measure the opposite [ light (not dark) ] # terminal strip is L-R on the ADS1115 for RPi from SeeedStudios # 3V3,AIN3,AIN2,AIN1,AIN0,GND # Uses 3 objects:BUS.write_byte(RESET_ADDRESS, RESET_COMMAND) #replace # Runner. for ADS1115 ADC # BUS. for ADS11#Jumper S of KY-18 photo-cell to AIN2 #DC # GPIO. for ALERTPIN class is not used #DC try: # I (D@CC) do not know anything about the logging logging.basicConfig( level=logging.DEBUG, #format='%(name)-12s: %(levelname)-8s %(message)s') format='%(message)s') logger = logging.getLogger('ADS1115Runner') #print("logger:",logger) #AINn=2 # AINn=2 to read AIN2 Runner = ADS1115Runner() # create object Runner #print("before .cmdloop") Runner.mydo_1(BUS,nChannel) # nChannel is 2 to read AIN2 #Runner.cmdloop() # will run the main Runner.method (cmd.Cmd) # which prompts for a response & invokes do_r(arg) # for a response of "r arg" #print("after .cmdloop") global g_adcValue returnValue = g_adcValue # from mydo_1 return returnValue finally: Runner.shutdown() #release this object #BUS.close() #release this object #if end adcRead() def adcReadInit(I2C_BUS=1,icNumber="ADS1115") : # arg1 is the BUS number used by the IC chip # arg2 is the number of the IC chip used on the Seeed ADS1115 4 channel RPi board # usage of global variables # global g_adcValue if icNumber=="ADS1115" : BUS=smbus.SMBus(I2C_BUS) #returns the BUS object , (usually BUS=smbus.SMBus(I2C_BUS) ) # Open I2C device # I2C_BUS = 1 # DEVICE_ADDRESS = 0x48 return BUS else: print('ERROR025: ic supported is "ADS1115"') exit #def end adcReadInit() # 9 constants included in adcRead_Pkg.py RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip icNumber = "ADS1115" # IC chip used I2C_BUS = 1 # BUS number used by the IC chip # end of adcRead_pkg.p #::::::::::textpak=>test_adcRead.py # test_adcRead.py # program to test adcRead() to read nChannel on the ADS1115 ADC RPi module from SeeedStuios # by D@CC on 2022CMar16 # needs to have adcRead_Pkg.py in the same folder as test_adcRead.py # needs import time import time # needs from adcRead_Pkg import adcRead,adcReadInit from adcRead_Pkg import adcRead,adcReadInit #needs to be run as >$ python3 test_adcRead.py if __name__ == "__main__": # import adcRead_pkg.py # is needed progName="test_adcRead.py" #this is the main program to test adcRead() print("starting:"+progName) # These 9 parameters are also defined in # adcRead_pkg.py: # mydo_1() RESET_ADDRESS = 0b0000000 RESET_COMMAND = 0b00000110 POINTER_CONVERSION = 0x0 POINTER_CONFIGURATION = 0x1 POINTER_LOW_THRESHOLD = 0x2 POINTER_HIGH_THRESHOLD = 0x3 DEVICE_ADDRESS = 0x48 # device address selected on the IC chip icNumber = "ADS1115" # IC chip used I2C_BUS = 1 # BUS number used by the IC chip # above constants are used with the ADS1115 IC chip: # [they could be defined as global variables in adcRead_init() instead] # These 2 constants must be defined in the test_adcRead.py program dT = 1 # sleep time between readings (set by the user of this program) nChannel = 2 # AINn is the analog pin # to read on the ADS1115 IC chip # # more than 1 channel can be read by the program # # simply use adcRead(nChannel) where nChannel is the channel to read # usage of global variables # global g_adcValue # this variable can be referenced (seen) by any program using adcRead() # it always contains the most-recent-value read by adcRead() #create the BUS object BUS = adcReadInit(I2C_BUS,icNumber) BUS.open(I2C_BUS) while True : # loop value = adcRead(BUS,nChannel) # reading nChannel of the ADS1115 once AINn="AIN"+str(nChannel) AINn=AINn.strip(" ") print ("value of "+AINn+" reading:", value) if dT==0 : break #out of while loop # dT=0 will only read it once else: time.sleep(dT) # dT>0 will read it continuously #if end #while end #end test_adcRead.p ::::::::::textpak=>adcValue.py.txt ************************* adcValue.py ************************* Date: 2022FJun10 adcValue variable is used in vMeterIXA_pico.py to read the voltage also used: RAPasc() readADC_pico(nn,cnvrt=5.035477e-05): stored in Raspberry Pi Pico & pi/pico_4f31_on_Fla53 also see readADC_pico.py in 164.html also see g_adcValue in 174.html also see n.py -a < adcRead_pkg.py # 1 m adcRead_pkg.py # 9 import cmd, time, logging, smbus, RPi.GPIO as GPIO # 11 #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC # 16 # BUS = adcReadInit(I2C_BUS,icNumber) # create BUS class object # 26 def MUX(n): # 34 def swap2Bytes(c): # 39 def prepareLEconf(BEconf): # 45 def LEtoBE(c): # 53 def BEtoLE(c): # 60 def resetChip(RESET_ADDRESS, RESET_COMMAND): # 65 class ADS1115Runner(cmd.Cmd): # 83 def alerted(self, arg): # 90 def do_q(self, arg): # 94 def mydo_1(self,BUS,AINn): # 129 global g_adcValue # 143 def shutdown(self): # 149 #class end ADS1115Runner() # 151 def adcRead(BUS,nChannel=0) : # 162 #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/ #DC # 173 # GPIO. for ALERTPIN class is not used #DC # 192 global g_adcValue # 200 def adcReadInit(I2C_BUS=1,icNumber="ADS1115") : # 203 # usage of global variables # 204 # global g_adcValue ************************* /adcValue.py.txt ::::::::::textpak=>ambLight_v00.py.txt def ambLight(a,b,c): # Purpose: returns ambient light (measured by adc) #line 1 #line 2 return a*0 #def end /ambLight_v00.py ::::::::::textpak=>ambLight_v01.py.txt def ambLight(a,b,c): # Purpose: returns ambient light (measured by adc) #line 1 #line 2 return a*1 #def end /ambLight_v01.py ::::::::::textpak=>ambLightB_v00.py.txt def ambLightB(a,b,c): # Purpose: returns ambient light (measured by adc) #line 1 #line 2 return a*0+b #def end /ambLightB_v00.py ::::::::::textpak=>ambLightB_v01.py.txt def ambLightB(a,b,c): # Purpose: returns ambient light (measured by adc) #line 1 #line 2 return a*1+b #def end /ambLightB_v01.py ::::::::::textpak=>ambLightB_v02.py.txt def ambLightB(a,b,c): # Purpose: returns ambient light (measured by adc) #line 1 #line 2 return a*1+b #def end /ambLightB_v01.py ::::::::::textpak=>bChar_py.py.txt def bChar(strB): # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] print("b:"+b) c=b[0] #c="zz" print("bChar("+'"'+strB+ '"):'+c) return c #end def while True: print(bChar(input("eg b'h' :"))) #end while ::::::::::textpak=>buttonAction_pico.py.txt # IX_libr_pico.py # This example works with Maker Pi Pico # buttonAction() # returns True when button Action is down i.e. pressed within 10 seconds # else returns False. #imports for buttonAction import machine import utime def buttonAction(gPnn,withinTime): if gPnn <0 or gPnn>25: print("Error in buttonAction: pin # is out of range") return #end if if withinTime <0 or withinTime>180: print("Error in buttonAction: withinTime is out of range") return #end if button = machine.Pin(gPnn, machine.Pin.IN) t0=utime.time() #print("t0:",t0) tDelta=0 isDown=False while tDeltadeviceReset_pico.py.txt # This example uses Maker Pi Pico import machine import utime from machine import Pin #by PicoLe-22 #on 2021EMay24 progName="deviceReset_pico.py" print(progName) print("Reset: program blinks leds 0- 25 on, then off") print(" then sets every pin as input") for GPnn in range(0,26): #except 26 ledPin = machine.Pin(GPnn, machine.Pin.OUT) ledPin.value(1) utime.sleep(.2) ledPin.value(0) ledPin = machine.Pin(GPnn, machine.Pin.IN) #end for print("after setting GP25 as IN") for GPnn in range(26,30): #except 31 print("GP",GPnn," setting to IN") ledPin = machine.Pin(GPnn, machine.Pin.IN) #end for print(" Now GP20,21,22 LEDs all ON, ADC0(GP26) might be ON") # deviceReset_pico.py # source: none # date: 2021EMay24 ::::::::::textpak=>f3.py.txt # f3() formats as f999999.999 where f means float (See endnotes) # MicroPython doesn't process complex numbers import re # to check for regular expressions in a string def f3(x): isDone=False xFloat=3.14159 xType="q" xReturn="" #print("into f3 xReturn:"+xReturn) # process a string #if isinstance(x,(float,int,str,list,dict,tuple)): if isinstance(x,(float,int,str)): if isinstance(x,str): if x.endswith("jJ"): isJend=True else: isJend=False #print("isJend:",isJend) #if(x.endswith("j)") or (x.endswith("J)"): #if((x.endswith("j")) or ((x.endswith("J")): if isJend: #almost complex but without the "(" and ")" xReturn="c" + "("+c+")" xType="c" isDone=True else: #not complex try: xFloat=float(x) xType="f" isDone=True except: xReturn="s"+x isDone=True #end try #end if # process an integer value elif isinstance(x,int): xFloat=float(x) xType="i" isDone=True # process a float value elif isinstance(x,float): xFloat=x xType="f" isDone=True #end if instances of int,float,str, else: #presume boolean if(bool(x)==1): xFloat=float(1) xType="b" isDone=True #end if if(bool(x)==0): xFloat=float(0) xType="b" isDone=True #end if #end of bool processing #end if #process unknown type if isDone==False: #nothing was recognized xReturn="u??????.???" else: if xReturn=="": #create something to return xReturn=xType + str(xFloat) else: #something was created to be returned #doh="doh" pass #end if #end if #print("xReturn:"+xReturn) return xReturn #end def #returns in format f6.3 preceeded by a type character # "b 1.000" # "???????.???" # "s . " # "r 99.00 " # f3(x) # test_f3.py print("progName:test_f3.py") print("Click in run window below, then:") while True: strIn=input("input a number:") print("strIn:",strIn,f3(strIn)) #end while #/f3.py.txt ::::::::::textpak=>f3_pyD.py.txt # pi_IX_function_library (piIX_libr.py) # by D@CC on 2021BFeb12 # ver f3_pyD uses isDone() not isNotDone() # # f3(x) converts the numerical variable to a f6.3 string #for printing. Note: decimal points should ALL line up # resolution of int, float are limited by device & Python vsn # by D@CC 2021EMay31 (c)ich180r2 # # f"abc{floatA}." works in 3.7 but not yet in MicroPython # print(("hi {floatA} bye")) # strLine="hi %a. bye" % (floatA) #python function l def f3(x): # prepares to print all numbers using format "-99999.999" i.e. 6f3 # accepts types:int,str,float,complex,bool # requires strToComplex(xStr) # inspiration is to not print out more than 3 digits to the right of the decimal point # returns S999999.999 after chopping off extra left and extra right digits # stored in pi_IX_library.py IX means "DC" if you connect the top & bottom serifs of the font letters # errors appear as "??????.???" or ">999999.999" or "<-999999.999" # by D@CC on 2021BFeb12 (c) ich180r2 print("debug: starting f3",x) isError= False isDone=True floatX=x strFloatX=str(floatX) # #strFloat= f"abc{floatA}." works in 3.7 but not in MicroPython print(" cb means { c means , P means pc sign") print("f 1. strFloatX:",strFloatX," bye") print((" 2. cb floatX cb bye")) strFloat="hi %s. bye" % (floatX) print(" strFloat= q hi pc s. bye q pc (floatX)") print("P 3. strFloat: c strFloat c bye") pyVer="MPg" #MicroPython generic" code C testing #pyVer="Py3" #Python version 3 code B works #returns complex numbers as type "u" for sample & time # where "u" means u16 x1000 # Note u12 with 4 bits of 0 on right = u16 # u16 can even have more digits to the left # type "u" is compatible with Pico ADC raw readings # even allowing for more precision in the future. # To get Pico ADC reading; divide "u" value by 16000 # i.e. lowest non-zero Pico ADC reading is 16000 in "u" # which converts to the actual ADC reading of "1" # this will work with future "16 bit" ADC on any device # & allowing more bits to the right of the decimal pnt. # #test complex if type(x)=="complex" : xUse=x isDone=True #end if xInt=int(x) print("at error, xInt:",xInt) if (abs(xInt)>999999) : isError=True str_floatX = ">999999.999" #print("line 27: strFloatX",strFloatX) else: #print("xInt:",xInt) floatX = 1.0 * xInt #strFloatX=f'{floatX:.3f}' #if pyVer=="Py3":strFloatX=f"{floatX:.3f}" if pyVer=="MPg":strFloatX="%s" % floatX print("line 54: strFloatX",strFloatX) #end if isDone=True #fix too big but negative if (abs(xInt)>999999) : isError=True str_floatX="<-999999.999" else: floatX= 1.0*xInt #if pyVer="Py3": strFloatX=f'{floatX:.3f}' if pyVer=="MPg": strFloat="%s" % floatX #end if isDone=True #float, str and int print("at 85: before xUse=0") xUse=x #to define it print("type(x),x is",type(x),"=",x) # check if Float if (isDone==False): print("76: check if Float") isFloat=False isFloat=isinstance(x,float) #strType=type(x) print("isFloat?",isFloat) if (isFloat): print("82: x is type float") print("before xUse=x") xUse=x elif (type(x)=="str") : print("86 x is type str") print("should call strToComplex here") #xUse=parseFloat(x) xUse=float(x) print("str") elif (type(x)=="int") : print("92: x is type int") xUse=1.0*x print("int") #end if # fix magnitude of xUse print("xUse:",xUse) print("x type is known, test magnitude of xUse which is x") absX=abs(xUse) print("absX:",absX) if (abs(xUse)>999999.) and (xUse>0) : print("103: too big") isError=True str_floatX="> 999999.000" else: floatX= 1.0*xUse strFloatX=str(floatX) print("strFloatX:",strFloatX) #test too low and negative isDone=False if (abs(xUse)>999999) and (xUse<0.) : isError=True str_floatX="<-999999.000" else: floatX= 1.0*xUse isDone=True #isDone=True #if end str_floatX=str(floatX) print("str_floatX:",str_floatX) #print("test bool") #bool #str_floatX=str(1.) # assign it print("isDone:",isDone) if (isDone==False) : print("check if bool") if(x==True): str_floatX="b 1.000" else: str_floatX="b 0.000" isDone=True else: print("not bool") #if end # final error and finish the function if (isDone==False): str_floatX="??????.???" #output that indicates an error (bad type) #if end print("debug: f3 of floatX: returning",str_floatX) return str_floatX #end def f3 #end f3 #/f3_py.txt print("start of test_f3.py") while True: print("click into the 'execution window' below, then:") inNumb=input("type in something") print("inStr:",inNumb) oTxt=str(f3(inNumb)) print("in f3 format:",inNumb) #end while #source:https://realpython.com/python-f-strings/ # test_f3_pyD.py ::::::::::textpak=>f3_v00.py.txt # f3() formats as f999999.999 where f means float (See endnotes) # MicroPython doesn't process complex numbers # described in 155.html import re # to check for regular expressions in a string def f3(x): isDone=False xFloat=3.14159 xType="q" xReturn="" #print("into f3 xReturn:"+xReturn) # process a string #if isinstance(x,(float,int,str,list,dict,tuple)): if isinstance(x,(float,int,str)): if isinstance(x,str): if x.endswith("jJ"): isJend=True else: isJend=False #print("isJend:",isJend) #if(x.endswith("j)") or (x.endswith("J)"): #if((x.endswith("j")) or ((x.endswith("J")): if isJend: #almost complex but without the "(" and ")" xReturn="c" + "("+c+")" xType="c" isDone=True else: #not complex try: xFloat=float(x) xType="f" isDone=True except: xReturn="s"+x isDone=True #end try #end if # process an integer value elif isinstance(x,int): xFloat=float(x) xType="i" isDone=True # process a float value elif isinstance(x,float): xFloat=x xType="f" isDone=True #end if instances of int,float,str, else: #presume boolean if(bool(x)==1): xFloat=float(1) xType="b" isDone=True #end if if(bool(x)==0): xFloat=float(0) xType="b" isDone=True #end if #end of bool processing #end if #process unknown type if isDone==False: #nothing was recognized xReturn="u??????.???" else: if xReturn=="": #create something to return xReturn=xType + str(xFloat) else: #something was created to be returned #doh="doh" pass #end if #end if #print("xReturn:"+xReturn) return xReturn #end def f3 #/f3_v00.py.txt ::::::::::textpak=>fadeLed_pico.py.txt # Example of using PIO for PWM, and fading the brightness of an LED from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep progName="fadeLed_pico.py" print(progName) #first example of PIO code @asm_pio(sideset_init=PIO.OUT_LOW) def pwm_prog(): pull(noblock) .side(0) mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock mov(y, isr) # ISR must be preloaded with PWM count max label("pwmloop") jmp(x_not_y, "skip") nop() .side(1) label("skip") jmp(y_dec, "pwmloop") class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) # Pin 25 is LED on Pico boards pwm = PIOPWM(0, 25, max_count=(1 << 16) - 1, count_freq=10_000_000) while True: for i in range(256): pwm.set(i ** 2) sleep(0.01) #end program #class PIOPWM pio_dac.py mod by William ::::::::::textpak=>functionList_pkg.py.txt # ToC of functionList_pkg.py # by D@CC on 2022CMar28 Use cmd -md to create ToC, suffix . to defs # 30 m posNxFnUsed.py # 32 def. posNxFnUsed(inStr,posIn0) : # 35 def. posNxFnUsed_v1(inStr,posIn0,v="v03") : # 128 m functionList.py # 129 def. functionList(testStr) : # 132 def. functionList_v1(testStr) : # 196 m posNxFnUsed.py # 199 def. posNxFnUsed(inStr,posIn0) : # 202 def. posNxFnUsed_v2(inStr,posIn0) : # 342 m posNxFnUsed_test.py # 343 def. t2() : # 425 m functionList.py # 427 def. functionList(testStr="#:::",v="v02") : # 431 def. functionList_v02(testStr,v) : # 474 m functionList_test.py # 475 def. mainroutine() : # 504 m posNxFnUsed.py # 506 def. posNxFnUsed(inStr,posIn0,v=3) : # 510 def. posNxFnUsed_v3(inStr,posIn0,v) : # 616 m t03.py # 617 def. mainroutine() : # 669 m t16.py # 683 def. mainroutine() : # 702 eof #::: end of list by n.py v03 #::::::::::textpak=>posNxFnUsed.py def posNxFnUsed(inStr,posIn0) : return posNxFnUsed_v1(inStr,posIn0) def posNxFnUsed_v1(inStr,posIn0,v="v03") : # by D@CC on 2022CMar15 print("posNxFnUsed_v02 on line 24 in ...._pkg.py") # beginning of def. posNxFnUsed() definition import re #print("into posNFU") #print("posIn0:",posIn0) # globals: uses globals List, bList # import re # parameters # arg1: statement to be anayzed # arg2: position of previous function name -1 (or 0 to initialize) # find the pos of the first char ( less 1) of the next function used in the inStr # returns the pos of the next function name (less 1) in the inStr statement # WARNING: does NOT find any function name beginning in first char of the statement # FIX: call it by preceding the statement with a space. # start searching at position # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b() should return 15 pos of "str4(" # 012345678901234567890123 # +0+(0+$$$+0+00+$$0$0( # 00+++$0$$(00+$++00$(+ # ( +$$0$0( +$0$$( ( # valid regular pattern is "+$" any "0" ???????????????? # globals: uses globals List, bList # import re # if posIn0==0 : v1Patt="[_a-zA-Z]" #"!" # valid first letter of a variable v2Patt="[_a-zA-Z0-9]" #"0" # valid subseq. letter of a variable vxPatt="[^_a-zA-Z0-9(!]" #";" # invalid char. of a function name incl. "(" # the above vxPatt"-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" # matches all char except those listed, I think vFPatt=";\$[0\$]\(" #print(" ;!!0!0( ;!0!!( ;!( ") #print("inStr : "+inStr) pattStr=inStr pattStr=re.sub(v1Patt,"!",pattStr) #print("pattStr: "+pattStr) pattStr=re.sub(v2Patt,"0",pattStr) #print("pattStr: "+pattStr) pattStr=re.sub(vxPatt,";",pattStr) #print("pattStr: "+pattStr) #print(" -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()") #print(" ;!!0!0( ;!0!!( ;!( ") #print(" 0123456789012345678901234567890123456789012345") #print(" 1 2 3 4") findPatt=";!{1}[!0]*\(" # find +$s where s is any number of 0 or $ followed by ( iter=re.finditer(findPatt,pattStr) global List List=[m.start(0) for m in iter] #print("List: ", List) global bList bList=[] #if end #print("b4 List") #print("List:",List) for n in List : #print("n:",n) item=testStr[n:].find("(") + n bList.append( item ) #for end #print("bList:",bList) #print("posIn0:",posIn0) # OK to here #for end -------------------------------- for n in List : #print("n:",n) thisPos=n if posIn0==0: return thisPos #returns and re-enters here else: if thisPos>posIn0: return thisPos else: continueDoh=True #keep looping #if end #if end #for end thisPos=-1 #print("thisPos:",thisPos) return thisPos #end def posNxFnUsed_v2 # ####################################### #::::::::::textpak=>functionList.py def functionList(testStr) : return functionList_v1(testStr) def functionList_v1(testStr) : # by D@CC on 2022CMar14 # beginning of def. functionList.py definition in posNxFnUsed_test.py print("functionList on line 119 in ...._pkg.py") # or "$" "(" which is '+$[0$](' # Use List=re.findall("+$[0functionList_test.py # Use List=re.search("+$[0$](", pattStr).start() # will search for each matching pattern in the pattStr # and return a list of the def. posNxFnUsed starting positions #procedure # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv # replace "_a-ZA-Z" with "_" wher e "_" is in "_a-ZA-Z" ie valid first char equiv # L-R find pos of first "0(""-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" # discard all to the right of "(" # R-L find pos of first "_" # discard all to the left of "_" # fin what remains (it begins with a "_" first char equiv and ends with a "(" # return the pos of what is found # beginning of def. functionList() definition # returns the next function name in an iteration list # of function calls in the given statment in arg1: testStr # calls posNxFnUsed() functionList=[] nPos=0 many0s="000000000000000000000000000000" while nPos>=0 : #print("in main while") v="unknown" nex = posNxFnUsed(testStr, nPos,v) nextPos=int(nex) #convert list element to string #print("in main af nextPos:",nextPos) if nextPos==-1 : # no more fNames found continueDoh=True break #out of while loop else : textStr=testStr[0:] #print("textStr: "+textStr) #textStr=testStr[0:] #print("textStr: "+textStr) #print(" 0123456789012345678901234567890123456789012345") nextFnPos =nextPos # ok to here -------------------------- #print("nextFnPos: ",nextFnPos) nextParPos = testStr[nextFnPos:].find("(")+nextFnPos #print("nextParPos: posNxFnUsed_test.py",nextParPos) fName=testStr[nextFnPos+1:nextParPos] functionList.append(fName) #print("fName:"+fName) nPos= nextParPos yield(fName) #if end #keep looping #while end #def end functionList_v1 # ########################################### #::::::::::textpak=>posNxFnUsed.py # originally was included in posNxFnUsed_test.py def posNxFnUsed(inStr,posIn0) : return posNxFnUsed_v2(inStr,posIn0) def posNxFnUsed_v2(inStr,posIn0) : import re print("posNxFnUsed_v2 on line 179 in ...._pkg.py") # by D@CC on 2022CMar15 # find the pos of the first char of the next function used in the inStr # start searching at position # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b() should return 15 pos of "str4(" # 012345678901234567890123 # +0+(0+$$$+0+00+$$0$0( # 00+++$0$$(00+$++00$(+ # ( +$$0$0( +$0$$( ( # valid regular pattern is "+$" any "0" ???????????????? v1Patt="[_a-zA-Z]" #"$" # valid first letter of a variable v2Patt="[_a-zA-Z0-9]" #"0" # valid subseq. letter of a variable vxPatt="[^_a-zA-Z0-9($]" #";" # invalid char. of a function name incl. "(" # the above vxPatt # matches all char except those listed, I think vFPatt=";\$[0\$]*\(" # or "$" "(" which is '+$[0$](' # Use List=re.findall("+$[0$](") # Use List=re.search("+$[0$](", pattStr).start() # will search for each matching pattern in the pattStr # and return a list of the starting positions #procedure # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv # replace "_a-ZA-Z" with "_" wher e "_" is in "_a-ZA-Z" ie valid first char equiv # L-R find pos of first "0(" # discard all to the right of "(" # R-L find pos of first "_" # discard all to the left of "_" # fin what remains (it begins with a "_" first char equiv and ends with a "(" # return the pos of what is found # # ( 2022CMar22 D@CC needs to test the above pattern matches. ) outPos=-1 pos0=posIn0 if pos0>len(inStr): return outPos tStr=inStr[pos0:] print("tStr:"+tStr) if tStr.find('(')>-1 : print("found another (") isFn=True parPos=inStr[pos0:].find("(") #parenthesis Position print("parPos:",parPos) while parPos > -1 : print("into while") isFn=False if parPos==-1 : print("no (") print("returning outPos:",outPos) return outPos else: #do the work pattStr=inStr[pos0:pos0+parPos+1] #::::::::::textpak=>functionList.py print("b4 pattStr:"+pattStr) pattStr=re.sub(v1Patt,"$",pattStr) print("md1 pattStr:"+pattStr) pattStr=re.sub(v2Patt,"0",pattStr) print("md2 pattStr:"+pattStr) pattStr=re.sub(vxPatt,";",pattStr) print("af pattStr:"+pattStr) findPatt=";\$[0\$]*\(" print("findPatt:"+findPatt) try: #fix DC #List=re.findall(findPatt, pattStr) #fix DC List=re.search(findPatt, pattStr).start() #fix DC except: #fix DC print("exception occurred during .search") #fix DC List=None #fix DC finally: continueDoh=True #fix DC #try end if List==None : print("parPos: ",parPos) #parPos is parentheses Position print("List=None") print("breaking out of while loop") break # out of while loop print("List:", List) posFromList=List smallStr=pattStr[posFromList:] print("smallStr: "+smallStr) pInSmallPos= smallStr.find("(") print("pInSmallPos: ",pInSmallPos) zparPos= posFromList+pInSmallPos print("zparPos: ",zparPos) if zparPos >-1 : # #working here # was ("0$") findNonRePatt=";\$[0\$]*\(" print("in nonPosNx.... zparPos>-1") print("findNonRePatt: "+findNonRePatt) v1Pos =pattStr.find("0$") #finds leftmost but # need to search R-L print("v1Pos:",v1Pos) if v1Pos> -1 : isFn=True print ("Fn found ") outPos=pos0+parPos-zparPos+v1Pos+1 FnStr=inStr[outPos:outPos+2] print("FnStr:"+FnStr) return outPos #if end else: print("zparPos:",zparPos) isFn=False #if end if isFn==False : # still not found, loop to try again print("checked FN:"+pattStr[0:parPos+1]) print("of inStr :"+inStr[pos0:pos0+parPos+1]) # new parPos will be parPos=pos0+parPos deltaparPos=inStr[pos0+parPos+1:].find("(") #parenthesis Position if deltaparPos>-1: # keep looping newparPos=pos0+parPos+1+deltaparPos print("inStr[parPos:]:"+inStr[0:newparPos+1]) parPos=newparPos print("parPos:",parPos) else: parPos=-1 # stop the while loop #if end #if end print("while end loop to try again") #while end else: return outPos #if end #def end posNxFnUsed_v2 # ############################## #::::::::::textpak=>posNxFnUsed_test.py def t2() : # beginning of actual posNxFnUsed_test.py # this is t2.py import re # body of t2 is missing doh! n=0 testStr="-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" v1Patt="[_a-zA-Z]" #"$" # valid first letter of a variable v2Patt="[_a-zA-Z0-9]" #"0" # valid subseq. letter of a variable vxPatt="[^_a-zA-Z0-9($!]" #";" # invalid char. of a function name incl. "(" # the above vxPatt # matches all char except those listed, I think vFPatt=";\$[0\$]\(" # 012345678901234567890123 while n>-1 : if False : # start with string pos 0 m=posNxFnUsed(testStr,n) print ("m:",m) if m>-1 : bracPos=testStr[m:].find("(") print("bracPos:",bracPos) FnStr=testStr[m:m+bracPos] print("FnStr:"+FnStr+":") n=bracPos #if end #if end pattStr=testStr print("b4 pattStr: "+pattStr) pattStr=re.sub(v1Patt,"!",pattStr) print("md1 pattStr: "+pattStr) pattStr=re.sub(v2Patt,"0",pattStr) print("md2 pattStr: "+pattStr) pattStr=re.sub(vxPatt,";",pattStr) print("af pattStr: af"+pattStr) print(" ;!!0!0( ;!0!!( ;!( ") print(" 0123456789012345678901234567890123456789012345") print(" 1 2 3 4") #findPatt="+$[0$](" findPatt="\+[0\$]\(" findPatt="0.0" #finds 0c0 #::::::::::textpak=>posNxFnUsed.py # originally was included in posNxFnUsed_test.py def posNxFnUsedZZ(inStr,posIn0) : return posNxFnUsed_v2(inStr,posIn0) def posNxFnUsed_v2(inStr,posIn0) : import re print("posNxFnUsed_v2 on line 179 in ...._pkg.py") # by D@CC on 2022CMar15 # find the pos of the first char of the next function used in the inStr # start searching at position # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b() should return 15 pos of "str4(" # 012345678901234567890123 # +0+(0+$$$+0+00+$$0$0( # 00+++$0$$(00+$++00$(+ # ( +$$0$0( +$0$$( ( # valid regular pattern is "+$" any "0" ???????????????? v1Patt="[_a-zA-Z]" #"$" # valid first letter of a variable v2Patt="[_a-zA-Z0-9]" #"0" # valid subseq. letter of a variable vxPatt="[^_a-zA-Z0-9($]" #";" # invalid char. of a function name incl. "(" # the above vxPatt # matches all char except those listed, I think vFPatt=";\$[0\$]*\(" # or "$" "(" which is '+$[0$](' # Use List=re.findall("+$[0$](") # Use List=re.search("+$[0$](", pattStr).start() # will search for each matching pattern in the pattStr # and return a list of the starting positions #procedure # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv # replace "_a-ZA-Z" with "_" wher e "_" is in "_a-ZA-Z" ie valid first char equiv # L-R find pos of first "0(" # discard all to the right of "(" # R-L find pos of first "_" # discard all to the left of "_" # fin what remains (it begins with a "_" first char equiv and ends with a "(" # return the pos of what is found # # ( 2022CMar22 D@CC needs to test the above pattern matches. ) outPos=-1 pos0=posIn0 if pos0>len(inStr): return outPos tStr=inStr[pos0:] print("tStr:"+tStr) if tStr.find('(')>-1 : print("found another (") isFn=True parPos=inStr[pos0:].find("(") #parenthesis Position print("parPos:",parPos) while parPos > -1 : print("into while") isFn=False if parPos==-1 : print("no (") print("returning outPos:",outPos) return outPos else: #do the work pattStr=inStr[pos0:pos0+parPos+1] #::::::::::textpak=>functionList.py print("b4 pattStr:"+pattStr) pattStr=re.sub(v1Patt,"$",pattStr) print("md1 pattStr:"+pattStr) pattStr=re.sub(v2Patt,"0",pattStr) print("md2 pattStr:"+pattStr) pattStr=re.sub(vxPatt,";",pattStr) print("af pattStr:"+pattStr) findPatt=";\$[0\$]*\(" print("findPatt:"+findPatt) try: #fix DC #List=re.findall(findPatt, pattStr) #fix DC List=re.search(findPatt, pattStr).start() #fix DC except: #fix DC print("exception occurred during .search") #fix DC List=None #fix DC finally: continueDoh=True #fix DC #try end if List==None : print("parPos: ",parPos) #parPos is parentheses Position print("List=None") print("breaking out of while loop") break # out of while loop print("List:", List) posFromList=List smallStr=pattStr[posFromList:] print("smallStr: "+smallStr) pInSmallPos= smallStr.find("(") print("pInSmallPos: ",pInSmallPos) zparPos= posFromList+pInSmallPos print("zparPos: ",zparPos) if zparPos >-1 : # #working here # was ("0$") findNonRePatt=";\$[0\$]*\(" print("in nonPosNx.... zparPos>-1") print("findNonRePatt: "+findNonRePatt) v1Pos =pattStr.find("0$") #finds leftmost but # need to search R-L print("v1Pos:",v1Pos) if v1Pos> -1 : isFn=True print ("Fn found ") outPos=pos0+parPos-zparPos+v1Pos+1 FnStr=inStr[outPos:outPos+2] print("FnStr:"+FnStr) return outPos #if end else: print("zparPos:",zparPos) isFn=False #if end if isFn==False : # still not found, loop to try again print("checked FN:"+pattStr[0:parPos+1]) print("of inStr :"+inStr[pos0:pos0+parPos+1]) # new parPos will be parPos=pos0+parPos deltaparPos=inStr[pos0+parPos+1:].find("(") #parenthesis Position if deltaparPos>-1: # keep looping newparPos=pos0+parPos+1+deltaparPos print("inStr[parPos:]:"+inStr[0:newparPos+1]) parPos=newparPos print("parPos:",parPos) else: parPos=-1 # stop the while loop #if end #if end print("while end loop to try again") #while end else: return outPos #if end #def end posNxFnUsed_v2 #::::::::::textpak=>t2.py def t2() : while False : #where c is any character findPatt="\+\$\$0\$0\(" # finds +$$0$0( findPatt="\+[\$]" # finds +$ +$$ etc findPatt="\+[\$]\+" # finds +$+ findPatt="\+[0\$]\+" # finds +c+ where c must be either 0 or $ findPatt="\+\$[\$0][\$0][\$0][\$0]\(" # finds +$ssss( where s must be either $ or 0 findPatt="\+\$+\+" # finds +$+ where s must be any number(>0) of $ findPatt="\+[\$0]+\+" # finds +$+ where s must be any number(>0) of $ or 0 # # but not a mixture of $ and 0 findPatt="\+\${1}" # find +$ where there is only 1$ findPatt=";!{1}[!0]*\(" # find +$s where s is any number of 0 or $ followed by ( # \+ is "+" ! is "!" [\!0] is either ! or 0 # af [\!0]* is any number (0 or >0) of "!" or "0" in any order # \( is "(" # So this matches "+!sssss(" where s is ! or 0 in any order # #List=re.search(findPatt, pattStr).start() #findPatt="" # can find 0 but not $ nor ( returns len+1 #pattStr="This was this is" iter=re.finditer(findPatt,pattStr) indices=[m.start(0) for m in iter] print("List: ", indices) bList=[] for n in indices : #print("n:",n) item=testStr[n:].find("(")+n bList.append( item ) #for end print("bList:",bList) break #while end print("done") # end of t2.py #def end t2 if __name__ == '__main__' : t2( ) # end of actual posNxFnUsed_test.py # -------------------------------- #::::::::::textpak=>functionList.py # beginning of def. functionList.py definition from functionList_test.py def functionList(testStr="#:::",v="v02") : if v=="?" : return "v02" return functionList_v02(testStr,v="v02") def functionList_v02(testStr,v) : # by D@CC on 2022CMar28 # returns a list of function calls in the input statment: inStr #print("functionList on line 416 in ...._pkg.py") functionList=[] nPos=0 many0s="000000000000000000000000000000" while nPos>=0 : #print("in main while") nex = posNxFnUsed(testStr, nPos) nextPos=nex #convert list element to string #print("in fList af nextPos:",nextPos) isNextPosGood=True if nextPos==-1 : isNextPosGood=False if nextPos==None : isNextPosGood=False if isNextPosGood==False : # no more fNames found continueDoh=True break #out of while loop else : textStr=testStr[0:] #print("textStr: "+textStr) #textStr=testStr[0:] #print("textStr: "+textStr) #print(" 0123456789012345678901234567890123456789012345") nextFnPos =nextPos # ok to here -------------------------- #print("nextFnPos: ",nextFnPos) nextParPos = testStr[nextFnPos:].find("(")+nextFnPos #print("nextParPos: ",nextParPos) fName=testStr[nextFnPos+1:nextParPos] functionList.append(fName) #print("fName:"+fName) nPos= nextParPos yield(fName) #if end #keep looping #while end #def end functionList_v02.py definition #::::::::::textpak=>functionList_test.py def mainroutine() : # by D@CC on 2022CMar26 # functionList_test.py from functionList_pkg import functionList, functionList_v from functionList_pkg import posNxFnUsed, posNxFnUsed_v progName="functionList_test.py" #main program starts here # calls:functionList.( # imports both functionList and posNxFnUsed from functionList_pkg.py print(" fL v: "+functionList_v() ) print(" pos v: "+posNxFnUsed_v() ) testStr="-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" print("testStr1:",testStr) for fName in functionList(testStr) : print("fName: "+fName) #for end #print(" 012345678901234567890123456789012345678901234") # print("end of functionList_test.py v4") return #def end mainroutine() if __name__ == '__main__' : mainroutine( ) # end of functionList_test.py #::::::::::textpak=>posNxFnUsed.py def posNxFnUsed(inStr,posIn0,v=3) : if v=="?" : return 3 return posNxFnUsed_v3(inStr,posIn0,v=3) def posNxFnUsed_v3(inStr,posIn0,v) : import re #if v=="?" : return 3 # by D@CC on 2022CMar25 #print("posNxFnUsed_v03 on line 501 in ...._pkg.py v03") #print("into posNFU v03") #print("posIn0:",posIn0) # find the pos of the first char of the next function used in the inStr # start searching at position # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b() should return 15 pos of "str4(" # 012345678901234567890123 # +0+(0+$$$+0+00+$$0$0( # 00+++$0$$(00+$++00$(+ # ( +$$0$0( +$0$$( ( # valid regular pattern is "+$" any "0" ???????????????? if posIn0==0 : v1Patt="[_a-zA-Z]" #"!" # valid first letter of a variable v2Patt="[_a-zA-Z0-9]" #"0" # valid subseq. letter of a variable vxPatt="[^_a-zA-Z0-9(!]" #";" # invalid char. of a function name incl. "(" # the above vxPatt"-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" # matches all char except those listed, I think vFPatt="+$[0$](" #print(" ;!!0!0( ;!0!!( ;!( ") #print("inStr : "+inStr) pattStr=inStr pattStr=re.sub(v1Patt,"!",pattStr) #print("pattStr: "+pattStr) pattStr=re.sub(v2Patt,"0",pattStr) #print("pattStr: "+pattStr) pattStr=re.sub(vxPatt,";",pattStr) #print("pattStr: "+pattStr) #print(" -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()") #print(" ;!!0!0( ;!0!!( ;!( ") #print(" 0123456789012345678901234567890123456789012345") #print(" 1 2 3 4") findPatt=";!{1}[!0]*\(" # find +$s where s is any number of 0 or $ followed by ( iter=re.finditer(findPatt,pattStr) global List List=[m.start(0) for m in iter] #print("List: ", List) global bList bList=[] #print("bList before gen") for n in List : #print("n:",n) #item=testStr[n:].find("(") + n # BAD item=inStr[n:].find("(") + n bList.append( item ) #for end #print("posIn0:",posIn0) # OK to here #for end #print("bList:",bList) #if end #print("b4 List") #print("List:",List) for n in List : #print("n:",n) thisPos=n if posIn0==0: return thisPos #returns and re-enters here else: if thisPos>posIn0: return thisPos else: continueDoh=True #keep looping #if end #if end #for end thisPos=-1 #print("thisPos:",thisPos) return thisPos # or "$" "(" which is '+$[0$](' # Use List=re.findall("+$[0$](") # Use List=re.search("+$[0$](", pattStr).start() # will search for each matching pattern in the pattStr # and return a list of the starting positions #procedure # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv # replace "_a-ZA-Z" with "_" wher e "_" is in "_a-ZA-Z" ie valid first char equiv # L-R find pos of first "0(""-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" # discard all to the right of "(" # R-L find pos of first "_" # discard all to the left of "_" # fin what remains (it begins with a "_" first char equiv and ends with a "(" # return the pos of what is found #def end posNxFnUsed_v03() #::::::::::textpak=>t03.py def mainroutine() : from functionList_pkg import posNxFnUsed #Purpose to test posNxFnUsed.py v04 #Then I created functionList.py # (which contains all this code and calls posNxFnUsed() ) # by D@CC on 2022CMar25 #main program t03.py starts here testStr="-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" print("testStr1:",testStr) print(" 012345678901234567890123456789012345678901234") # print(" 1 2 3 4 ") nPos=0 many0s="000000000000000000000000000000" while nPos>=0 : #print("in main while") nex = posNxFnUsed(testStr, nPos) nextPos=int(nex) #convert list element to string #print("in main af nextPos:",nextPos) if nextPos==-1 : continueDoh=True break #out of while loop else : textStr=testStr[0:] #print("textStr: "+textStr) #textStr=testStr[0:] #print("textStr: "+textStr) nextFnPos =nextPos # ok to here -------------------------- #print("nextFnPos: ",nextFnPos) nextParPos = testStr[nextFnPos:].find("(")+nextFnPos #print("nextParPos: ",nextParPos) fName=testStr[nextFnPos+1:nextParPos] print("fName:"+fName) nPos= nextParPos #if end #keep looping #while end print("end of t3.py") print("done") # end of t3 #end def mainroutine() if __name__ == '__main__' : mainroutine( ) #end def t03.py #end of pkg on 2022CMar25 #::::::::::textpak=>t16.py #def functionList(testStr="",v="v02") : #if v=="?" : return "v02" #return functionList_v02(testStr,v) #def end #def functionList_v02(testStr, v) : # by D@CC on 2022CMar26 #. . . . #. . . . function definition statements go here # . . . . #return anyValue #def end functionList def mainroutine() : #main program used to test the functionList function from functionList_pkg import functionList, posNxFnUsed line="abc = aStr(1000*unixTime() ) + bigI(333)" print("line:"+line+":") fList=functionList(line) for x in fList : print(x, end=" " ) #for end print() vsnStr=str( functionList("","?") ) print( "vsn of functionList: "+ vsnStr ) vsnStr=str( posNxFnUsed("",0,"?") ) print( "vsn of posNxFnUsed: "+ vsnStr ) return #def end if __name__ == '__main__' : mainroutine() #end of t.py v16 #::::::::::textpak=>posNxFnUsed.py def posNxFnUsed(inStr,posIn0,v=4) : pass; vv=4 returnValue = posNxFnUsed_v4(inStr,posIn0) # only need to edit the vsn # in 4 places (& at the end if desired) if v=="?" : return returnValue,vv else : return returnValue #if end def posNxFnUsed_v4(inStr,posIn0) : import re # by D@CC on 2022DApr02 #print("posNxFnUsed_v04 on line 867 in ...._pkg.py v04") #print("into posNFU v04") #print("posIn0:",posIn0) # find the pos of the first char of the next function used in the inStr # start searching at position # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b() should return 15 pos of "str4(" # 012345678901234567890123 # +0+(0+$$$+0+00+$$0$0( # 00+++$0$$(00+$++00$(+ # ( +$$0$0( +$0$$( ( # valid regular pattern is "+$" any "0" ???????????????? if posIn0==0 : v1Patt="[_a-zA-Z]" #"!" # valid first letter of a variable v2Patt="[_a-zA-Z0-9]" #"0" # valid subseq. letter of a variable vxPatt="[^_a-zA-Z0-9(!]" #";" # invalid char. of a function name incl. "(" # the above vxPatt"-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" # matches all char except those listed, I think vFPatt="+$[0$](" #print(" ;!!0!0( ;!0!!( ;!( ") #print("inStr : "+inStr) pattStr=inStr pattStr=re.sub(v1Patt,"!",pattStr) #print("pattStr: "+pattStr) pattStr=re.sub(v2Patt,"0",pattStr) #print("pattStr: "+pattStr) pattStr=re.sub(vxPatt,";",pattStr) #print("pattStr: "+pattStr) #print(" -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()") #print(" ;!!0!0( ;!0!!( ;!( ") #print(" 0123456789012345678901234567890123456789012345") #print(" 1 2 3 4") findPatt=";!{1}[!0]*\(" # find +$s where s is any number of 0 or $ followed by ( iter=re.finditer(findPatt,pattStr) global List List=[m.start(0) for m in iter] #print("List: ", List) global bList bList=[] #print("bList before gen") for n in List : #print("n:",n) #item=testStr[n:].find("(") + n # BAD item=inStr[n:].find("(") + n bList.append( item ) #for end #print("posIn0:",posIn0) # OK to here #for end #print("bList:",bList) #if end #print("b4 List") #print("List:",List) for n in List : #print("n:",n) thisPos=n if posIn0==0: return thisPos #returns and re-enters here else: if thisPos>posIn0: return thisPos else: continueDoh=True #keep looping #if end #if end #for end thisPos=-1 #print("thisPos:",thisPos) return thisPos # or "$" "(" which is '+$[0$](' # Use List=re.findall("+$[0$](") # Use List=re.search("+$[0$](", pattStr).start() # will search for each matching pattern in the pattStr # and return a list of the starting positions #procedure # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv # replace "_a-ZA-Z" with "_" wher e "_" is in "_a-ZA-Z" ie valid first char equiv # L-R find pos of first "0(""-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()" # discard all to the right of "(" # R-L find pos of first "_" # discard all to the left of "_" # fin what remains (it begins with a "_" first char equiv and ends with a "(" # return the pos of what is found #def end posNxFnUsed_v4() #::::::::::textpak=>t17.py #def functionList(testStr="",v="v02") : #if v=="?" : return "v02" #return functionList_v02(testStr,v) #def end #def functionList_v02(testStr, v) : # by D@CC on 2022CMar26 #. . . . #. . . . function definition statements go here # . . . . #return anyValue #def end functionList def mainroutine() : #main program used to test the functionList function from functionList_pkg import functionList, posNxFnUsed line="abc = aStr(1000*unixTime() ) + bigI(333)" print("line:"+line+":") fList=functionList(line) for x in fList : print(x, end=" " ) #for end print() vMain=17 print("vsn of t.py: ",vMain) vsnStr=str( functionList("","?") ) print( "vsn of functionList: "+ vsnStr ) vsnStr=str( posNxFnUsed("",0,"?")[1] ) print( "vsn of posNxFnUsed: "+ vsnStr ) return #def end if __name__ == '__main__' : mainroutine() #end of t17.py # -------------------------------- #::::::::::textpak=>functionList.py # beginning of def. functionList.py definition def functionList(testStr="#:::",v=3) : pass; vv=3 returnValue = functionList_v03(testStr) if v=="?" : return returnValue,vv else : return returnValue #if end def functionList_v03(testStr) : # by D@CC on 2022DApr02 # returns a list of function calls in the input statment: inStr #print("functionList v03 on line 1017 in ...._pkg.py") functionList=[] nPos=0 many0s="000000000000000000000000000000" while nPos>=0 : #print("in main while") nex = posNxFnUsed(testStr, nPos) nextPos=nex #convert list element to string #print("in fList af nextPos:",nextPos) isNextPosGood=True if nextPos==-1 : isNextPosGood=False if nextPos==None : isNextPosGood=False if isNextPosGood==False : # no more fNames found continueDoh=True break #out of while loop else : textStr=testStr[0:] #print("textStr: "+textStr) #textStr=testStr[0:] #print("textStr: "+textStr) #print(" 0123456789012345678901234567890123456789012345") nextFnPos =nextPos # ok to here -------------------------- #print("nextFnPos: ",nextFnPos) nextParPos = testStr[nextFnPos:].find("(")+nextFnPos #print("nextParPos: ",nextParPos) fName=testStr[nextFnPos+1:nextParPos] functionList.append(fName) #print("fName:"+fName) nPos= nextParPos yield(fName) #if end #keep looping #while end #def end functionList_v03.py definition ::::::::::textpak=>intRed_pico.py.txt import machine import utime #program "intRed_pico.py" toggles the pico's main green LED # every 2 seconds using an interrupt routine # (not using an loop with a counter). # press button 21 to # turn ON led GP5 and to "interrupt" # the green LED's blinking for 4 sec # external set up of GP Pins # GP15 to red (n.o.) button to 3v3 # GP10 to 330 ohm resistor to greenLED anode from cathode to GND Pin phys 23 # GP11 to 330 ohm resistor to redLED anode from cathode to GND Pin phys 23 # tested OK on 2021FJun15 with MPA by D@CC progName="intRed_pico.py" print("progName:"+progName) bRedGP=18 #button_red = machine.Pin(bRedGP, machine.Pin.IN, machine.Pin.PULL_DOWN) button_red = machine.Pin(bRedGP, machine.Pin.IN, machine.Pin.PULL_DOWN) #?no PULL_DOWN for MPA ADC0 to GP18 led_red = machine.Pin(5, machine.Pin.OUT) led_green = machine.Pin(25, machine.Pin.OUT) # inititialize red and green LEDs led_red.value(0) led_green.value(0) print("waiting for press of button",bRedGP) def int_handler(pin): button_red.irq(handler=None) print("Interrupt Detected! at time:",utime.time()) led_red.value(1) led_green.value(0) print("sleeping for 4 secs") utime.sleep(4) # seconds led_red.value(0) print("waiting for press of button",bRedGP) button_red.irq(handler=int_handler) #end def button_red.irq(trigger=machine.Pin.IRQ_RISING, handler=int_handler) while True: led_green.toggle() utime.sleep(2) # seconds #while end # source: https://www.youtube.com/watch?v=Zy64kZEM_bg #/intRed.py stored as intRed_pico.py ::::::::::textpak=>maker-pi-pico-rgb-led_pico.py.txt # This example uses Maker Pi Pico # Reference: https://www.cytron.io/p-maker-pi-pico # ----- # to stop it completely RESET is useless, unplug from Pi instead import array, time from machine import Pin import rp2 from rp2 import PIO, StateMachine, asm_pio # Configure the number of WS2812 LEDs # - There's 1x built-in RGB LED on Maker Pi Pico board NUM_LEDS = 1 @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] # Create the StateMachine with the ws2812 program, outputting on pin GP28 (Maker Pi Pico). sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(28)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) # Display a pattern on the LEDs via an array of LED RGB values. ar = array.array("I", [0 for _ in range(NUM_LEDS)]) while True: print("blue") for i in range(NUM_LEDS): ar[i] = 255 sm.put(ar,8) time.sleep_ms(1000) print("red") for i in range(NUM_LEDS): ar[i] = 255<<8 # shift 8 bits to the left sm.put(ar,8) time.sleep_ms(1000) print("green") for i in range(NUM_LEDS): ar[i] = 255<<16 # shift 16 bits to the left sm.put(ar,8) time.sleep_ms(1000) print("white") for i in range(NUM_LEDS): ar[i] = 0xFFFFFF sm.put(ar,8) time.sleep_ms(1000) # maker-pi-pico-rgb-led.py # source: https://github.com/CytronTechnologies/MAKER-PI-PICO/blob/main/Example%20Code/MicroPython/maker-pi-pico-rgb-led.py # date: 2021EMay24 #/maker-pi-pico-rgb-led_pico.py.txt ::::::::::textpak=>mid.py.txt def mid(strIn,iFrom,iTo): # by D@CC # created on 2022EMay30 # improved on 2024BFeb12 # Purpose: BASIC-like mid probably for pico # returns strType, midStr # Comment: similar to Mid(strA,2,3) in BASIC # col:2,len:3 # Issue: NOT YET FULLY TESTED # BUT READY FOR TESTING # example of use: mid(strA,2,3) # mid returns same characters as # the string splice of str(x)[1:4] # parmIn 01 strA str eg "abcdef" # parmIn 02 iFrom int eg 2 # parmIn 03 iTo int eg 4 # returns # parmOut 01 str strType eg "s" or "f" etc # parmOut 02 str strA eg "bcd" # accepts types # type strA print(Mid(strA,2,3) BASIC # print(Mid(strA,a,b) BASIC # print(mid(strA,a,b) Python IX function # print(str(strA)[a-1:a+b-1] ) equivalent Python # bool "True" "rue" # Complex "(-1+2j)" "-1+" # int 12345 "234" # float 12.34 "2.3" # str "abcdef" "bcd" # # used in article 174 # called by f3() # # Functions used: # isinstance() # Issue: maybe "isInstance" instead # endswith() # float() # str() # bool() x=strIn if x == True: x="True" if x ==False: x="False" #if end if isinstance(x,(float,int,str)): #print("at 49 x:",x) if isinstance(x,str): #print("51 checking if complex") #print("at 52 x:",x) if x.endswith(("j","J")): isJend=True else: isJend=False #print("57 isJend:",isJend) #if(x.endswith("j)") or (x.endswith("J)"): #if((x.endswith("j")) or ((x.endswith("J")): if isJend: #if x is probably complex print("Issue: Must check syntax of complex") print("complex is barely usable on pico") #almost complex but without the "(" and ")" xReturn="("+x+")" xType="sc" #print("66 xType:",xType) isDone=True else: #not complex, must be str #print("70 not complex, must be str or bool") if strIn in [True,False]: print("72 is bool") xType="b" xReturn=x else: #print("76 is str") xType="s" xReturn=x #if end #print("80 xReturn:",xReturn) return xType,str(xReturn)[iFrom-1:iFrom+iTo-1] #end if # process an integer value elif isinstance(x,int): print("87 saw int x",x) xType="i" xReturn=str(x) isDone=True elif isinstance(x,float): print("at 92, float x",x) xFloat=x xReturn=str(xFloat) xType="f" isDone=True elif isinstance(x,int): print("at 100 after elif x:",x) #xInt=int(x) xReturn=str(xInt) xType="i" isDone=True # process a float value #end if instances of int,float,str, else: #presume boolean, not complex print("at 115 test Bool") if(bool(x)==1): xFloat=float(1) xReturn=str(xFloat) xType="b" isDone=True #end if if(bool(x)==0): xFloat=float(0) xReturn=str(xFloat) xType="b" isDone=True #end if #end of bool processing #end if if isDone: if False: y="abcdef" strY=str(y)[2:3] print("at 135 should be returning a value") print("136 iFrom:",iFrom) print("137 iLen:",iTo) print("138 y:",y) print("139 str(y)[2:3]:",str(y)[2:3]) #if end #print("142 iFrom:",iFrom) #print("143 iLen:",iTo) #print("144 xType:",xType) #print("145 xReturn:",xReturn) return xType,str(xReturn)[iFrom-1:iFrom+iTo-1] else: print("unknown type, presume s") #if end print("155 x:",x) xReturn=str(x)[a-1,a+b-1] print("157,xReturn:",xReturn) xType="s" print("at 161") return xType,str(xReturn)[iFrom-1:iFrom+iTo-1] #if end #def end #/mid_pico.py.txt ::::::::::textpak=>mid_old.py.txt def mid_old(x,): #Issue: returnx xType,xFloat #Issue: xFloat is NOT a mid-string #WARNING: 2024BF11 D@CC improved this a little if isinstance(x,(float,int,str)): if isinstance(x,str): if x.endswith("jJ"): isJend==True else: isJend==False print("isJend:",isJend) #if(x.endswith("j)") or (x.endswith("J)"): #if((x.endswith("j")) or ((x.endswith("J")): if isJend: #almost complex but without the "(" and ")" xReturn="c" + "("+c+")" xType="cs" isDone=True return xType,xReturn else: #not complex try: xFloat=float(x) xType="f" isDone=True except: xReturn=x xType="s" isDone=True #end try #end if # process an integer value elif isinstance(x,int): xFloat=float(x) xType="i" isDone=True # process a float value elif isinstance(x,float): xFloat=x xType="f" isDone=True #end if instances of int,float,str, else: #presume boolean if(bool(x)==1): xFloat=float(1) xType="b" isDone=True #end if if(bool(x)==0): xFloat=float(0) xType="b" isDone=True #end if #end of bool processing return xType,xFloat #end if ::::::::::textpak=>mid_test.py.txt def mid(strIn,iFrom,iTo): # by D@CC # created on 2022EMay30 # improved on 2024BFeb12 # Purpose: BASIC-like mid probably for pico # returns strType, midStr # Comment: similar to Mid(strA,2,3) in BASIC # col:2,len:3 # Issue: NOT YET FULLY TESTED # BUT READY FOR TESTING # example of use: mid(strA,2,3) # mid returns same characters as # the string splice of str(x)[1:4] # parmIn 01 strA str eg "abcdef" # parmIn 02 iFrom int eg 2 # parmIn 03 iTo int eg 4 # returns # parmOut 01 str strType eg "s" or "f" etc # parmOut 02 str strA eg "bcd" # accepts types # type strA print(Mid(strA,2,3) BASIC # print(Mid(strA,a,b) BASIC # print(mid(strA,a,b) Python IX function # print(str(strA)[a-1:a+b-1] ) equivalent Python # bool "True" "rue" # Complex "(-1+2j)" "-1+" # int 12345 "234" # float 12.34 "2.3" # str "abcdef" "bcd" # # used in article 174 # called by f3() # # Functions used: # isinstance() # Issue: maybe "isInstance" instead # endswith() # float() # str() # bool() x=strIn if x == True: x="True" if x ==False: x="False" #if end if isinstance(x,(float,int,str)): #print("at 49 x:",x) if isinstance(x,str): #print("51 checking if complex") #print("at 52 x:",x) if x.endswith(("j","J")): isJend=True else: isJend=False #print("57 isJend:",isJend) #if(x.endswith("j)") or (x.endswith("J)"): #if((x.endswith("j")) or ((x.endswith("J")): if isJend: #if x is probably complex print("Issue: Must check syntax of complex") print("complex is barely usable on pico") #almost complex but without the "(" and ")" xReturn="("+x+")" xType="sc" #print("66 xType:",xType) isDone=True else: #not complex, must be str #print("70 not complex, must be str or bool") if strIn in [True,False]: print("72 is bool") xType="b" xReturn=x else: #print("76 is str") xType="s" xReturn=x #if end #print("80 xReturn:",xReturn) return xType,str(xReturn)[iFrom-1:iFrom+iTo-1] #end if # process an integer value elif isinstance(x,int): print("87 saw int x",x) xType="i" xReturn=str(x) isDone=True elif isinstance(x,float): print("at 92, float x",x) xFloat=x xReturn=str(xFloat) xType="f" isDone=True elif isinstance(x,int): print("at 100 after elif x:",x) #xInt=int(x) xReturn=str(xInt) xType="i" isDone=True # process a float value #end if instances of int,float,str, else: #presume boolean, not complex print("at 115 test Bool") if(bool(x)==1): xFloat=float(1) xReturn=str(xFloat) xType="b" isDone=True #end if if(bool(x)==0): xFloat=float(0) xReturn=str(xFloat) xType="b" isDone=True #end if #end of bool processing #end if if isDone: if False: y="abcdef" strY=str(y)[2:3] print("at 135 should be returning a value") print("136 iFrom:",iFrom) print("137 iLen:",iTo) print("138 y:",y) print("139 str(y)[2:3]:",str(y)[2:3]) #if end #print("142 iFrom:",iFrom) #print("143 iLen:",iTo) #print("144 xType:",xType) #print("145 xReturn:",xReturn) return xType,str(xReturn)[iFrom-1:iFrom+iTo-1] else: print("unknown type, presume s") #if end print("155 x:",x) xReturn=str(x)[a-1,a+b-1] print("157,xReturn:",xReturn) xType="s" print("at 161") return xType,str(xReturn)[iFrom-1:iFrom+iTo-1] #if end #def end def go(): progName="mid_test.py" print("progName:",progName) print("test mid( ... ,2,3)") print("Issues:1") while True: strA=input("mid string?") #strA="1+23j" #for testing #print("at 176 strA:",strA) strKeep=strA #if strA in : #if isinstance(strA,("True","False")): #print("at 181 strKeep:",strKeep) strB,strC = mid(strKeep,2,3) #print("at 183") print("184 strB,strC:",strB,strC) #while end #def end go() #if __name__ == __main__ : # go() #if end #/mid_pico.py.txt ::::::::::textpak=>mod5.py.txt # store this in Desktop/mod5 as __init__.py # don't do sys.path.append('home/pi/Desktop/mod5') # point Files to /home/pi/Desktop # then run this with # >>>import mod5 # >>>mod5.hello() # This worked on 2021EMay28 by D@CC using Python3 # but not with microPython doh! # Source: https://wiki.micropython.org/Importing-Modules def hello(): print('hello from mod5') #end def hello() ::::::::::textpak=>mpy_uart_pico.py.txt import os import utime from machine import UART, Pin progName="mpy_uart_pico.py" print(progName) print("Jumper GP04 to GP05") #print sys info print(os.uname()) #indicate program started visually led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) # speed of 400 only reads 4 bytes . . Doh? uart = machine.UART(1,600, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) #print uart info #uart = machine.UART(1) print(uart) uart.write("hello") utime.sleep(0.1) while uart.any(): print(uart.read(1)) #end while print() print("- bye -") #Source:http://helloraspberrypi.blogspot.com/2021/01/raspberry-pi-picomicropython-simple.html #program end #/mpy_uart_pico.py.txt ::::::::::textpak=>n_v02.py.txt #! /usr/bin/python3 # !/usr/local/bin/python deprecated for Raspberry Pi # IX_textnames.py renamed and enhanced to n.py # by D@CC on 2022CMar22 #################################################################### # first line (shebang) must be #! /usr/bin/python3 # # place the n.py and the package into Desktop # # # # Usage: >$ cd Desktop/ # # >sudo chmod +x n.py # # >$ python3 ../n.py < ../adcRead_pkg.py # # or: >$ cd Desktop # # >$ ./n.py --acdhimgs < adcRead_pkg.py # # NB In terminal, the above should list the names of the # # files that exist in the package named in stdin. # # # # but due to the Unix trick line 1 "#!/usr... # # and the last line if __name__ ... # # the command line below works (afer chmod ...): # # >$ ./n.py ' # the IX Marker is different mlen = len(marker) # file names appear after markers def names(): cmdList0="[n]" #default value argStr=str(sys.argv[1:]) #print("argStr1:"+argStr) alen=len(argStr) argExt=argStr[alen-5:alen-2] #print("argExt:"+argExt) isBadArg=False if argExt==".py": isBadArg=True #flag a Bad Argument if argExt.find("pkg")>-1 : isBadArg=True #flag a Bad Argument #if end if isBadArg==True: continueDoh=True print('#::: Be sure to precede the Pkg name with a "<".') return #from names else: #print("argStr2:"+argStr) #print("cmdList02:"+cmdList0) if False: continueDoh=True else: #print("argStr3:"+argStr) #for cmdList in sys.argv[1:]: if argStr=="[]": cmdList=cmdList0 else: cmdList=argStr #if end #print("cmdList3:"+cmdList) if cmdList.find("h")>-1 : print("#:::: Help for python n.py [IX pkg names list pgm]") print("#:::: Syntax: ./n.py [args] "') print("#:::: (Cudos to:O'Reilly for textpack.py)") return #from names #if end if cmdList.find("a")>-1 : cmdList="-cdings" #a means list all #endif if cmdList.find("<")>-1 : print("#:::: ERROR precede the < with a space") return #from names #if end print("#::: Enhanced n.py [IX pkg names list prg -h for help]:") if True: markCnt=0 for line in sys.stdin.readlines( ): # for all input lines #print("before first line") #if line=="": break #if line==None: break markIn=line[0:mlen] #if cmdList.find("m")>-1 : # always show markers if(line[:mlen]== marker): # is it a marker line markCnt+=1 llen=len(line) filename=line[mlen:llen-1] # get filename without LF print(filename) #if end ##if end isY=False if cmdList.find("c")>-1 : if line.find("class ")>-1: isY=True # is it an class line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print(pline) #if end #if end isY=False if cmdList.find("i")>-1 : if line.find("import ")>-1: isY=True # is it an import line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print(pline) #if end #if end isY=False if cmdList.find("g")>-1 : if line.find("global ")>-1: isY=True # is it a global line if line.find("global(")>-1: isY=True # is it a global line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print(pline) #if end #if end isY=False if cmdList.find("s")>-1 : if line.find("source:")>-1: isY=True # is it a source line if line.find("Source:")>-1: isY=True # is it a Source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print(pline) #if end #if end isY=False if cmdList.find("d")>-1 : if line.find("def " )>-1: isY=True # is it a def line if line.find("#def ")>-1: isY=False if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print(pline) #if end #if end #for end if markCnt==0 : print("#::: WARNING: pkg has no markers") print("#::: end of list by n.py") #if end #if end #def end names if __name__ == '__main__' : names( ) #end of n.py ::::::::::textpak=>n_v03.py.txt #! /usr/bin/python3 # !/usr/local/bin/python deprecated for Raspberry Pi # IX_textnames.py renamed and enhanced to n.py vsn # by D@CC on 2022CMar26 # 2022CMar25 added lNo (input line numbers) & function uses: "calls" #################################################################### # first line (shebang) must be #! /usr/bin/python3 # # place the n.py and the package into Desktop and Sandbox # # # # Usage: >$ cd Desktop/ # # >sudo chmod +x n.py # # >$ python3 ../n.py < ../adcRead_pkg.py # # or: >$ cd Desktop # # >$ ./n.py -acdghimosu < adcRead_pkg.py # # NB In terminal, the above should list the names of the # # files that exist in the package or file named in stdin. # # NB recently added is the listing of used-functions i.e. "calls" # # NB now, can also list packages using true O'Reilly markers # # but excluding many std python functions # # Due to the Unix trick line 1 "#!/usr... # # and the last line if __name__ ... mainroutine() # # the command line below works (afer chmod ...): # # >$ ./n.py -all ' # the IX Marker is different omarker = ':'*10 + 'textpak=>' # the original O'Reilly Marker mlen = len(marker) # file names appear after markers olen = len(omarker) cmdList0="[n]" #default value argStr=str(sys.argv[1:]) #print("argStr1:"+argStr) alen=len(argStr) argExt=argStr[alen-5:alen-2] #print("argExt:"+argExt) isBadArg=False if argExt==".py": isBadArg=True #flag a Bad Argument if argExt.find("pkg")>-1 : isBadArg=True #flag a Bad Argument #if end if isBadArg==True: continueDoh=True print('#::: Be sure to precede the Pkg name with a "<".') return #from names else: #print("argStr2:"+argStr) #print("cmdList02:"+cmdList0) if False: continueDoh=True else: #print("argStr3:"+argStr) #for cmdList in sys.argv[1:]: if argStr=="[]": cmdList=cmdList0 else: cmdList=argStr #if end #print("cmdList3:"+cmdList) if cmdList.find("h")>-1 : uS="_" print("#:::: Help for python n.py "+vsn+" [IX pkg names list pgm]") print("#:::: Syntax: ./n.py [args] "') print("#:::: (Cudos to:O'Reilly for textpack.py)") print("#:::: Source: http://index-of.es/Programming/Python/O'Reilly%20-%20Programming%20Python,%203rd%20Ed%20Aug2006.pdf") print("#:::: NB not to be confused with the Textpack pkg") v="unknown" print("#:::: mainroutine:n.py: "+vsn) print("#:::: posNxFnUsed vsn: v",posNxFnUsed("",0,"?") ) print("#:::: functionList vsn: "+functionList("","?") ) return #from names #if end if cmdList.find("all")>-1 : cmdList="-cdimogsu" #all means list all (except h_) #endif if cmdList.find("a")>-1 : cmdList="-cdimogs" #a means list all (except hu) #endif if cmdList.find("<")>-1 : print("#:::: ERROR precede the < with a space") return #from names #if end print("#::: Enhanced n.py "+vsn+" [IX pkg names list prg -h for help]:") if True: lNo=0 markCnt=0 for line in sys.stdin.readlines( ): # for all input lines lNo=lNo+1 #print("before first line") #if line=="": break #if line==None: break markIn=line[0:mlen] #if cmdList.find("m")>-1 : # always show markers #if markCnt==0: if False : print("mlen:",mlen) print("line.mlen:"+line[:mlen]) print("mkr:"+marker) #if end if(line[:mlen]== marker): # is it a marker line markCnt+=1 llen=len(line) filename=line[mlen:llen-1] # get filename without LF print("#",lNo, "m "+filename) #if end #if cmdList.find("o")>-1 functionList on line: # also show oreilly markers if(line[:olen]== omarker): # is it a o-marker line markCnt+=1 llen=len(line) filename=line[olen:llen-1] # get filename without LF print() print("#",lNo, "o "+filename+" oooooooo Oreilly marker oooooooo") print() #if end ##if end isY=False if cmdList.find("c")>-1 : if line.find("class ")>-1: isY=True # is it an class line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("i")>-1 : if line.find("import ")>-1: isY=True # is it an import line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("g")>-1 : if line.find("global ")>-1: isY=True # is it a global line if line.find("global(")>-1: isY=True # is it a global line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("s")>-1 : if line.find("source:" )>-1: isY=True # is it a source line if line.find("Source:" )>-1: isY=True # is it a Source line if line.find("Web Source M")>-1: isY=True # is it a Source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False uS="_" if cmdList.find("_")>-1 : if line.find(uS+uS)>-1: isY=True # is it a source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("u")>-1 : #print("in n.py before calling functionListNew") for fName in functionList(line,0): isY=True # default is to print the function name # # but don't print std python function names pyL= ",if,append,close,cleanup,exit,fltest,find,findall,finditer" pyL=pyL+",globals,imorts,input,int,len,lstrip" pyL=pyL+",names,number,not,open" pyL=pyL+",output,pac,print,read,range,read,readline,readlines" pyL=pyL+",remove,replace,rstrip,search,sleep,start,split,str" pyL=pyL+",strip,system,time,type,sub,write,yield," if fName in pyL: isY=False if False : if fName=="if" :isY=False # bad #if fName=="functionList" :isY=False #in IX if fName=="globals" :isY=False #IX main test if fName=="imports" :isY=False #IX main test if fName=="mainroutine" :isY=False #IX main test if fName=="names" :isY=False #IX main test #if fName=="output" :isY=False #if fName=="posNFnUsed" :isY=False #in IX #if fName=="setup" :isY=False #if fName=="setmode" :isY=False #if fName=="SMBus" :isY=False #in IX #if end if cmdList.find("d")>-1 : if line.find("def ") >-1 : #so "d" will also print it out isY=False #so don't print it twice #if end #if end if isY : print("#",lNo," "+fName+"()") #print("#",lNo,line) #if end #for end #if end isY=False if cmdList.find("d")>-1 : if line.find("def " )>-1: isY=True # is it a def line #defList=defList+[1] if line.find("#def ")>-1: isY=False if line.find("#end def ")>-1: isY=False if line.find("#def end ")>-1: isY=False if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end #for end if markCnt==0 : print("#::: WARNING: pkg has no markers") print("#",lNo,"eof") print("#::: end of list by n.py "+vsn) #if end #if end #def end mainroutine if __name__ == '__main__' : mainroutine( ) #end of n.py ::::::::::textpak=>n_v04.py.txt #! /usr/bin/python3 # !/usr/local/bin/python deprecated for Raspberry Pi # IX_textnames.py renamed and enhanced to n.py vsn # by D@CC on 2022CMar26 # 2022CMar25 added lNo (input line numbers) & function uses: "calls" #################################################################### # first line (shebang) must be #! /usr/bin/python3 # # place the n.py and the package into Desktop and Sandbox # # # # Usage: >$ cd Desktop/ # # >sudo chmod +x n.py # # >$ python3 ../n.py < ../adcRead_pkg.py # # or: >$ cd Desktop # # >$ ./n.py -acdghimosu < adcRead_pkg.py # # NB In terminal, the above should list the names of the # # files that exist in the package or file named in stdin. # # NB recently added is the listing of used-functions i.e. "calls" # # NB now, can also list packages using true O'Reilly markers # # but excluding many std python functions # # Due to the Unix trick line 1 "#!/usr... # # and the last line if __name__ ... mainroutine() # # the command line below works (afer chmod ...): # # >$ ./n.py -all ' # the IX Marker is different omarker = ':'*10 + 'textpak=>' # the original O'Reilly Marker mlen = len(marker) # file names appear after markers olen = len(omarker) cmdList0="[n]" #default value argStr=str(sys.argv[1:]) #print("argStr1:"+argStr) alen=len(argStr) argExt=argStr[alen-5:alen-2] #print("argExt:"+argExt) isBadArg=False if argExt==".py": isBadArg=True #flag a Bad Argument if argExt.find("pkg")>-1 : isBadArg=True #flag a Bad Argument #if end if isBadArg==True: continueDoh=True print('#::: Be sure to precede the Pkg name with a "<".') return #from names else: #print("argStr2:"+argStr) #print("cmdList02:"+cmdList0) if False: continueDoh=True else: #print("argStr3:"+argStr) #for cmdList in sys.argv[1:]: if argStr=="[]": cmdList=cmdList0 else: cmdList=argStr #if end #print("cmdList3:"+cmdList) if cmdList.find("h")>-1 : uS="_" print("#:::: Help for python n.py "+vsn+" [IX pkg names list pgm]") print("#:::: Syntax: ./n.py [args] "') print("#:::: (Cudos to:O'Reilly for textpack.py)") print("#:::: Source: http://index-of.es/Programming/Python/O'Reilly%20-%20Programming%20Python,%203rd%20Ed%20Aug2006.pdf") print("#:::: NB not to be confused with the Textpack pkg") v="unknown" print("#:::: mainroutine:n.py: "+vsn) print("#:::: posNxFnUsed vsn: v",posNxFnUsed("",0,"?") ) print("#:::: functionList vsn: "+functionList("","?") ) return #from names #if end if cmdList.find("all")>-1 : cmdList="-cdimogsu" #all means list all (except h_) #endif if cmdList.find("a")>-1 : cmdList="-cdimogs" #a means list all (except hu) #endif if cmdList.find("<")>-1 : print("#:::: ERROR precede the < with a space") return #from names #if end print("#::: Enhanced n.py "+vsn+" [IX pkg names list prg -h for help]:") if True: lNo=0 markCnt=0 for line in sys.stdin.readlines( ): # for all input lines lNo=lNo+1 #print("before first line") #if line=="": break #if line==None: break markIn=line[0:mlen] #if cmdList.find("m")>-1 : # always show markers #if markCnt==0: if False : print("mlen:",mlen) print("line.mlen:"+line[:mlen]) print("mkr:"+marker) #if end if(line[:mlen]== marker): # is it a marker line markCnt+=1 llen=len(line) filename=line[mlen:llen-1] # get filename without LF print("#",lNo, "m "+filename) #if end #if cmdList.find("o")>-1 functionList on line: # also show oreilly markers if(line[:olen]== omarker): # is it a o-marker line markCnt+=1 llen=len(line) filename=line[olen:llen-1] # get filename without LF print() print("#",lNo, "o "+filename+" oooooooo Oreilly marker oooooooo") print() #if end ##if end isY=False if cmdList.find("c")>-1 : if line.find("class ")>-1: isY=True # is it an class line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("i")>-1 : if line.find("import ")>-1: isY=True # is it an import line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("g")>-1 : if line.find("global ")>-1: isY=True # is it a global line if line.find("global(")>-1: isY=True # is it a global line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("s")>-1 : if line.find("source:" )>-1: isY=True # is it a source line if line.find("Source:" )>-1: isY=True # is it a Source line if line.find("Web Source M")>-1: isY=True # is it a Source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False uS="_" if cmdList.find("_")>-1 : if line.find(uS+uS)>-1: isY=True # is it a source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("u")>-1 : #print("in n.py before calling functionListNew") for fName in functionList(line,0): isY=True # default is to print the function name # # but don't print std python function names pyL= ",if,append,close,cleanup,exit,fltest,find,findall,finditer" pyL=pyL+",globals,imorts,input,int,len,lstrip" pyL=pyL+",names,number,not,open" pyL=pyL+",output,pac,print,read,range,read,readline,readlines" pyL=pyL+",remove,replace,rstrip,search,sleep,start,split,str" pyL=pyL+",strip,system,time,type,sub,write,yield," if fName in pyL: isY=False if False : if fName=="if" :isY=False # bad #if fName=="functionList" :isY=False #in IX if fName=="globals" :isY=False #IX main test if fName=="imports" :isY=False #IX main test if fName=="mainroutine" :isY=False #IX main test if fName=="names" :isY=False #IX main test #if fName=="output" :isY=False #if fName=="posNFnUsed" :isY=False #in IX #if fName=="setup" :isY=False #if fName=="setmode" :isY=False #if fName=="SMBus" :isY=False #in IX #if end if cmdList.find("d")>-1 : if line.find("def ") >-1 : #so "d" will also print it out isY=False #so don't print it twice #if end #if end if isY : print("#",lNo," "+fName+"()") #print("#",lNo,line) #if end #for end #if end isY=False if cmdList.find("d")>-1 : if line.find("def " )>-1: isY=True # is it a def line #defList=defList+[1] if line.find("#def ")>-1: isY=False if line.find("#end def ")>-1: isY=False if line.find("#def end ")>-1: isY=False if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end #for end if markCnt==0 : print("#::: WARNING: pkg has no markers") print("#",lNo,"eof") print("#::: end of list by n.py "+vsn) #if end #if end #def end mainroutine if __name__ == '__main__' : mainroutine( ) #end of n.py ::::::::::textpak=>n_v05.py.txt #! /usr/bin/python3 # !/usr/local/bin/python deprecated for Raspberry Pi # IX_textnames.py renamed and enhanced to n.py vsn # by D@CC on 2022CMar26 # 2022CMar25 added lNo (input line numbers) & function uses: "calls" #################################################################### # first line (shebang) must be #! /usr/bin/python3 # # place the n.py and the package into Desktop and Sandbox # # Version: v05 by D@CC on 2024BFeb08 2 edits # # # # Usage: >$ cd Desktop/ # # >sudo chmod +x n.py # # >$ python3 ../n.py < ../adcRead_pkg.py # # or: >$ cd Desktop # # >$ ./n.py -acdghimosu < adcRead_pkg.py # # NB In terminal, the above should list the names of the # # files that exist in the package or file named in stdin. # # NB recently added is the listing of used-functions i.e. "calls" # # NB now, can also list packages using true O'Reilly markers # # but excluding many std python functions # # Due to the Unix trick line 1 "#!/usr... # # and the last line if __name__ ... mainroutine() # # the command line below works (afer chmod ...): # # >$ ./n.py -all ' # the IX Marker is different omarker = ':'*10 + 'textpak=>' # the original O'Reilly Marker mlen = len(marker) # file names appear after markers olen = len(omarker) cmdList0="[n]" #default value argStr=str(sys.argv[1:]) #print("argStr1:"+argStr) alen=len(argStr) argExt=argStr[alen-5:alen-2] #print("argExt:"+argExt) isBadArg=False if argExt==".py": isBadArg=True #flag a Bad Argument if argExt.find("pkg")>-1 : isBadArg=True #flag a Bad Argument #if end if isBadArg==True: continueDoh=True print('#::: Be sure to precede the Pkg name with a "<".') return #from names else: #print("argStr2:"+argStr) #print("cmdList02:"+cmdList0) if False: continueDoh=True else: #print("argStr3:"+argStr) #for cmdList in sys.argv[1:]: if argStr=="[]": cmdList=cmdList0 else: cmdList=argStr #if end #print("cmdList3:"+cmdList) if cmdList.find("h")>-1 : uS="_" print("#:::: Help for python n.py "+vsn+" [IX pkg names list pgm]") print("#:::: Syntax: ./n.py [args] "') print("#:::: (Cudos to:O'Reilly for textpack.py)") print("#:::: Source: http://index-of.es/Programming/Python/O'Reilly%20-%20Programming%20Python,%203rd%20Ed%20Aug2006.pdf") print("#:::: NB not to be confused with the Textpack pkg") v="unknown" print("#:::: mainroutine:n.py: "+vsn) print("#:::: posNxFnUsed vsn: v",posNxFnUsed("",0,"?") ) print("#:::: functionList vsn: "+str(functionList("","?") )) #v05 return #from names #if end if cmdList.find("all")>-1 : cmdList="-cdimogsu" #all means list all (except h_) #endif if cmdList.find("a")>-1 : cmdList="-cdimogs" #a means list all (except hu) #endif if cmdList.find("<")>-1 : print("#:::: ERROR precede the < with a space") return #from names #if end print("#::: Enhanced n.py "+vsn+" [IX pkg names list prg -h for help]:") if True: lNo=0 markCnt=0 for line in sys.stdin.readlines( ): # for all input lines lNo=lNo+1 #print("before first line") #if line=="": break #if line==None: break markIn=line[0:mlen] #if cmdList.find("m")>-1 : # always show markers #if markCnt==0: if False : print("mlen:",mlen) print("line.mlen:"+line[:mlen]) print("mkr:"+marker) #if end if(line[:mlen]== marker): # is it a marker line markCnt+=1 llen=len(line) filename=line[mlen:llen-1] # get filename without LF print("#",lNo, "m "+filename) #if end #if cmdList.find("o")>-1 functionList on line: # also show oreilly markers if(line[:olen]== omarker): # is it a o-marker line markCnt+=1 llen=len(line) filename=line[olen:llen-1] # get filename without LF print() print("#",lNo, "o "+filename+" oooooooo Oreilly marker oooooooo") print() #if end ##if end isY=False if cmdList.find("c")>-1 : if line.find("class ")>-1: isY=True # is it an class line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("i")>-1 : if line.find("import ")>-1: isY=True # is it an import line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("g")>-1 : if line.find("global ")>-1: isY=True # is it a global line if line.find("global(")>-1: isY=True # is it a global line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("s")>-1 : if line.find("source:" )>-1: isY=True # is it a source line if line.find("Source:" )>-1: isY=True # is it a Source line if line.find("Web Source M")>-1: isY=True # is it a Source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False uS="_" if cmdList.find("_")>-1 : if line.find(uS+uS)>-1: isY=True # is it a source line if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end isY=False if cmdList.find("u")>-1 : #print("in n.py before calling functionListNew") for fName in functionList(line,0): isY=True # default is to print the function name # # but don't print std python function names pyL= ",if,append,close,cleanup,exit,fltest,find,findall,finditer" pyL=pyL+",globals,imports,input,int,len,lstrip" #v05 pyL=pyL+",names,number,not,open" pyL=pyL+",output,pac,print,read,range,read,readline,readlines" pyL=pyL+",remove,replace,rstrip,search,sleep,start,split,str" pyL=pyL+",strip,system,time,type,sub,write,yield," if fName in pyL: isY=False if False : if fName=="if" :isY=False # bad #if fName=="functionList" :isY=False #in IX if fName=="globals" :isY=False #IX main test if fName=="imports" :isY=False #IX main test if fName=="mainroutine" :isY=False #IX main test if fName=="names" :isY=False #IX main test #if fName=="output" :isY=False #if fName=="posNFnUsed" :isY=False #in IX #if fName=="setup" :isY=False #if fName=="setmode" :isY=False #if fName=="SMBus" :isY=False #in IX #if end if cmdList.find("d")>-1 : if line.find("def ") >-1 : #so "d" will also print it out isY=False #so don't print it twice #if end #if end if isY : print("#",lNo," "+fName+"()") #print("#",lNo,line) #if end #for end #if end isY=False if cmdList.find("d")>-1 : if line.find("def " )>-1: isY=True # is it a def line #defList=defList+[1] if line.find("#def ")>-1: isY=False if line.find("#end def ")>-1: isY=False if line.find("#def end ")>-1: isY=False if isY : llen=len(line) pline=" "+line[:llen-1] # get line without LF print("#",lNo,pline) #if end #if end #for end if markCnt==0 : print("#::: WARNING: pkg has no markers") print("#",lNo,"eof") print("#::: end of list by n.py "+vsn) #if end #if end #def end mainroutine if __name__ == '__main__' : mainroutine( ) #end of n_v05.py ::::::::::textpak=>pack.py.txt def pack(): #by D@CC #on 7/2/2021 2021GJul02 import sys # load the system module # must invoke on CLI followed by " >resultFileName" #move marker statement here #maybe: move marker statement into the pack function marker = ':'*10 + 'textpak=>' # hopefully unique separator for name in sys.argv[1:]: # for all command-line arguments input = open(name, 'r') # open the next input file print marker + name # write a separator line print input.read( ), # and write the file's contents #if __name__ == '__main__': pack( ) # pack files listed on cmdline #Web Source:https://www.oreilly.com/library/view/programming-python-second/0596000855/ch04s05.html #end def textpack_py.py #/pack_py.py #def end ****************************************************** /pack.py.txt ::::::::::textpak=>parseComplex.py.txt #import cmath def parseComplex(x,y): #Complex=('3+5j') xComplex=complex(x,y) print("xComplex:",xComplex) xReal=xComplex.real print("xReal:",xReal) #xImag=xComplex.imag #print("xImag:",xImag) y=2*xComplex print("y:",y) return #end def ::::::::::textpak=>picoButton_pico.py.txt # This example uses Maker Pi Pico import machine import utime #by PicoLe-22 (D@CC) #on 2021EMay24 progName="picoButton_pico.py" print(progName) button22 = machine.Pin(22, machine.Pin.IN) while True: state=button22.value() print("GP22 button (active low) state:",state) utime.sleep(1) #end while # picoButton_pico.py # source: https://github.com/CytronTechnologies/MAKER-PI-PICO/blob/main/Example%20Code/MicroPython/maker-pi-pico-rgb-led.py # date: 2021EMay24 #/picoButton_pico.py.txt ::::::::::textpak=>PixObj.py.txt #IXled_onboard.py def value(s1): return #/IXled_onboard.py #IXmachine.py def Pin(s1,s2): return def machine_Pin_OUT(): return def Pin_OUT(): return def UART(s1,s2,parity=None,stop=None,bits=None,rx=None,tx=None): return #/IXmachine.py #uart.py def any(): return True def read(s1): return "b'r'" def write(aStr): print() print(" at 7 uart.write :"+aStr+":") return #/IXuart.py #IXutime.py def sleep(s1): return def time(): return 0 #/IXutime.py ::::::::::textpak=>printPicoUniqueId.py.txt #printPicoUniqueID.py #by D@CC #Date 2022EMay30 import machine s = machine.unique_id() for b in s: #print("b:",b,end=" ") print(hex(b)[2:],end=" ") print() #print("s:",s) # MMBasic print mm.info(ID) #List of Pico IDs owned by D@CC as of 2022AJan07 # Pico Unique ID Item from Label Use # 36 60 58 38 83 3d 4f 31 Maker Pi Pico Cytron Pico_4f_31 MicroPython Examples # E6605481DB4 Pi Pico Cytron Pico_1DB4 MMBasic on picomite #Source: # https://forums.raspberrypi.com/viewtopic.php?p=1851234&hilit=read+pico+flash+unique+id#p1851234 #/printPicoUniqueId.py ::::::::::textpak=>printTemp.py.txt import machine import utime # this worked fine on 2021FJun09 with MPiADC board #ADC0 with SW2 ON and CDS0 had no effect. #blowing (w a straw) on the pico R2040 made temp go up 4 degrees. sensor_temp = machine.ADC(4) conversion_factor = 3.3 / (65535) tim0=utime.time() print("tim0:",tim0) while True: reading = sensor_temp.read_u16() * conversion_factor temperature = 27 - (reading - 0.706)/0.001721 tim=utime.time()-tim0 print(tim,temperature) utime.sleep(2) #while end #printTemp.py ::::::::::textpak=>printTempQ.py.txt import machine from machine import * import utime sensor_temp = machine.ADC(0) conversion_factor = 3.3 / (65535) tim0=utime.time() print("tim0:",tim0) temp=ADC(ADC.CORE_TEMP) conversion=3.3/65535 while True: reading = sensor_temp.read_u16() * conversion_factor temperature = 27 - (reading - 0.706)/0.001721 tim=utime.time()-tim0 print(tim,temperature) tempR=temp.read_u16()*conversion tempNow=tempR print("tempNow:",tempNow) utime.sleep(2) #while end #printTimTemp.py ::::::::::textpak=>printTimTemp_pico.py.txt import machine from machine import * import utime #by D@CC #on 2022EMay30 #sensor_temp = machine.ADC(0) #original code sensor_temp = machine.ADC(0) conversion_factor = 3.3 / (65535) tim0=utime.time() print("tim0:",tim0) temp=ADC(ADC.CORE_TEMP) conversion=3.3/65535 while True: reading = sensor_temp.read_u16() * conversion_factor temperature = 27 - (reading - 0.706)/0.001721 tim=utime.time()-tim0 print(tim,temperature) tempR=temp.read_u16()*conversion tempNow=tempR print("tempNow:",tempNow) utime.sleep(2) #while end #/printTimTemp_pico.py ::::::::::textpak=>serTxC_[pico_BU2021FJun18_2257.py.txt import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun18 #Note: as of today, partially tested # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# print("txtToBeSent:",txtToBeSent,":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now print() print("oP:"+oP+":") #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom print("sending M") isLastPack=True while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) isLastPack=False # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data w/o eom lastChar=cntUsed+pktSize show("lastChar",lastChar) #thisMsg="12345678901234567" print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntUsed:lastChar]",thisMsg[cntUsed:lastChar]) opToSend=thisMsg[cntUsed:lastChar] print("opToSend:"+opToSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntUsedFromMsg=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if print("after Last Packet of Msg") toSend=lenM-cntUsed-1 show("toSend:",toSend) print("end of while") #end while # the above sent all packets except the last one print("after end of while") #end if "M" print("after while") if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP print() print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) print("tx sent:"+oP+":") #keep user informed during testing return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def def sendLastPack(uartObject, opIn, eom = "]", pktSize=16): #sendLastPack() #actually sends the character packet in oP # but pads the packet with "eom"s first # replace any eom with "?" lenopIn=len(opIn) oP=opIn pos=oP.find(eom) if pos==-1: # Good: eom not found pass else: print("ERROR E in serTx", eom, "found in message") oP.replace(eom,"?") #end if len=len(oP) #pad packet with eoms show("lenOp",lenOp) for k in range(16,lenOp): oPtoSend=oPtoSend+eom # add eoms for padding #end for lenOp=len(oP) # is the pktSize correct if (lenOp==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenOp) #end if #send the 16 character packet uartObject.write(oPtoSend) print("tx padded (if needed) and sent:"+oP+":") return lenOpIn # return # of chars used. #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=3 #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def ########################################################################################## progName="testTxC_pico.py" print("progName:"+progName) if True: bps=600 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): serTx_pico(uart,bps, txtToBeSent="Hello,JoeMaxRoyBob") if False: serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H]") serTx_pico(uart,bps, txtToBeSent="[H]") serTx_pico(uart,bps, txtToBeSent="2.97") serTx_pico(uart,bps, txtToBeSent="99.987654") serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") serTx_pico(uart,bps, txtToBeSent="1234567890123") serTx_pico(uart,bps, txtToBeSent="12345678901234") serTx_pico(uart,bps, txtToBeSent="Hello,World") serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") #end if if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /testTxC_pico.py ::::::::::textpak=>serTxC_pico.py.txt import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun18 #Note: as of today, partially tested # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# print("txtToBeSent:"+txtToBeSent+":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz print("end of serTx()") return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now print() print("oP:"+oP+":") cntUsed=0 #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom print("sending M") #cntSent of the packet is already in oP #cntUsed is 0 going into the while # note that lenM also includes 1 eom # in the while loop, cntUsed will increase until cntUsed=lenM while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) print("going into the M while") show("upon entry M-while cntUsed:",cntUsed) # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data # lastChar is the lastChar of Msg to send in this packet cntCanAdd=pktSize-len(oP) print("cntCanAdd:",cntCanAdd,":") show("cntUsed:",cntUsed) #should be 0 entering first loop cntRemainOfM=lenM-cntUsed-1 #this cnts the remaining chars of M cntToAdd=pktSize-len(oP) #this cnts the remaining space in oP # a packet is always sent in this next "if clause" show("cntRemainOfM:",cntRemainOfM) show("cntToAdd:",cntToAdd) if cntRemainOfM>cntToAdd : # this packet cannot hold rest of Msg plus an eom isLastPack=False opToAdd=thisMsg[cntUsed:cntUsed+cntToAdd] # to add to oP opToSend=oP+opToAdd # to be sent print("AopToSend:"+opToSend+":") cntPadding=0 sendThisPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt without any padding cntUsed=cntUsed+cntToAdd+1 # remember to count the first EOM as a character in cntUsed show("cntUsed:",cntUsed) show("lenM:",lenM) oP="" cntSent=0 #continue the while loop else : isLastPack=True # the pkt can hold the whole cntRemainOfM opToAdd=thisMsg[cntUsed:cntUsed+cntRemainOfM] #print("BopToSend:"+opToSend+":") cntPadding=pktSize-cntSent-cntRemainOfM strPadding=eom*cntPadding opToSend=oP+opToAdd+strPadding print("CopToSend:"+opToSend+":") sendLastPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt including the padding cntUsed=cntUsed+len(opToAdd) show("lenM:",lenM) show("cntUsed:",cntUsed) oP="" cntSent=0 print("after Last Packet of Msg") toSend=lenM-cntUsed show("toSend:",toSend) print("end of while") break #out of the while #if end cntUnsent=lenM-cntUsed-1 show("cntUnsent:",cntUnsent) print("repeat the M while") #end while if False : # we need to send at least 1 more full packet isLastpack=False lastChar=cntUsed+(pktSize-len(oP)) #this is lastChar of Msg yet to send opToAdd=thisMsg[cntUsed:lastChar] # to add to oP opTosend=oP+opToAdd print("opToSend:"+opToSend+":") sendThisPack(uartObject, opToSend, eom, pktSize) # no padding was necessary cntUsed=cntUsed+len(opToAdd) show("cntUsed:",cntUsed) # the while will loop once more #end if if False : lastChar=pktSize-cntSent show("lastChar",lastChar) #thisMsg="12345678901234567" print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntSent:lastChar]",thisMsg[cntUsed:lastChar]) opWasSent=thisMsg[cntUsed:lastChar] print("opWasSend:"+opWasSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if #end if False if False : # a packet has just been sent leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if False : if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) oP=opToSend toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if #end if False # a packet was just sent print("M while might end now") print("after end of while") #end if False #end if "M" if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP print() print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) print("tx sent:"+oP+":") #keep user informed during testing return pktSize #end def def sendLastPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP print() print("in sendLastPack") oP=opIn print("oP:"+oP+":") lenopIn=len(opIn) show("lenopIn:",lenopIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if #search for eom in the non-padding portion of oPIn suboPIn=opIn[0:pktSize-cntPadding] print("suboPIn:"+suboPIn+":") pos=suboPIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) print("tx sent:"+oP+":") #keep user informed during testing return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=3 #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def ########################################################################################## progName="testTxC_pico.py" print("progName:"+progName) if True: bps=600 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): serTx_pico(uart,bps, txtToBeSent="Hello,JoeMaxRoyBob") if False: serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H]") serTx_pico(uart,bps, txtToBeSent="[H]") serTx_pico(uart,bps, txtToBeSent="2.97") serTx_pico(uart,bps, txtToBeSent="99.987654") serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") serTx_pico(uart,bps, txtToBeSent="1234567890123") serTx_pico(uart,bps, txtToBeSent="12345678901234") serTx_pico(uart,bps, txtToBeSent="Hello,World") serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") #end if if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /testTxC_pico.py ::::::::::textpak=>serTxD3_pico.py.txt import os #import utime #from machineIX import UART, Pin import IXutime as utime import IXmachine as machine import IXled_onboard as IXled_onboard import IXuart as uart def Pin(s1): #IX return #IX #uart.write("12 zyx") #by D@CC #Date: 2024BFeb13 #Note: as of today, partially tested # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# print("54 in serTx_pico txtToBeSent :"+txtToBeSent+":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" print("74 msgOut :",msgOut,":") #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #IX #print("125 end of serTx()") #print("126 Hit ^C to stop!") #print() return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() #show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack #print("149 into txParse") oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet #show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM #print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #print() #print("oP:"+oP+":") cntUsed=0 #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom #print("sending M") #cntSent of the packet is already in oP #cntUsed is 0 going into the while # note that lenM also includes 1 eom # in the while loop, cntUsed will increase until cntUsed=lenM while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) #print("going into the M while") #show("upon entry M-while cntUsed:",cntUsed) # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data # lastChar is the lastChar of Msg to send in this packet cntCanAdd=pktSize-len(oP) #print("cntCanAdd:",cntCanAdd,":") #show("cntUsed:",cntUsed) #should be 0 entering first loop cntRemainOfM=lenM-cntUsed-1 #this cnts the remaining chars of M cntToAdd=pktSize-len(oP) #this cnts the remaining space in oP # a packet is always sent in this next "if clause" #show("cntRemainOfM:",cntRemainOfM) #show("cntToAdd:",cntToAdd) if cntRemainOfM>cntToAdd : # this packet cannot hold rest of Msg plus an eom isLastPack=False opToAdd=thisMsg[cntUsed:cntUsed+cntToAdd] # to add to oP opToSend=oP+opToAdd # to be sent #print("AopToSend:"+opToSend+":") cntPadding=0 sendThisPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt without any padding cntUsed=cntUsed+cntToAdd+1 # remember to count the first EOM as a character in cntUsed #show("cntUsed:",cntUsed) #show("lenM:",lenM) oP="" cntSent=0 #continue the while loop else : isLastPack=True # the pkt can hold the whole cntRemainOfM opToAdd=thisMsg[cntUsed:cntUsed+cntRemainOfM] #print("BopToSend:"+opToSend+":") cntPadding=pktSize-cntSent-cntRemainOfM strPadding=eom*cntPadding opToSend=oP+opToAdd+strPadding #print("CopToSend:"+opToSend+":") sendLastPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt including the padding cntUsed=cntUsed+len(opToAdd) #show("lenM:",lenM) #show("cntUsed:",cntUsed) oP="" cntSent=0 #print("after Last Packet of Msg") toSend=lenM-cntUsed #show("toSend:",toSend) #print("end of while") break #out of the while #if end cntUnsent=lenM-cntUsed-1 #show("cntUnsent:",cntUnsent) #print("repeat the M while") #end while if False : # we need to send at least 1 more full packet isLastpack=False lastChar=cntUsed+(pktSize-len(oP)) #this is lastChar of Msg yet to send opToAdd=thisMsg[cntUsed:lastChar] # to add to oP opTosend=oP+opToAdd print("opToSend:"+opToSend+":") sendThisPack(uartObject, opToSend, eom, pktSize) # no padding was necessary cntUsed=cntUsed+len(opToAdd) show("cntUsed:",cntUsed) # the while will loop once more #end if if False : lastChar=pktSize-cntSent show("lastChar",lastChar) #thisMsg="12345678901234567" #print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntSent:lastChar]",thisMsg[cntUsed:lastChar]) opWasSent=thisMsg[cntUsed:lastChar] print("opWasSend:"+opWasSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if #end if False if False : # a packet has just been sent leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if False : if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) oP=opToSend toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if #end if False # a packet was just sent print("M while might end now") print("after end of while") #end if False #end if "M" if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def txParse def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char #print("#") print(char, end='') #"end" suppresses the line feed #IX return char #end def txChar def sendThisPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) print("377 tx sent :"+oP+":") #keep user informed during testing return pktSize #end def def sendLastPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendLastPack") oP=opIn #print("oP:"+oP+":") lenopIn=len(opIn) #show("lenopIn:",lenopIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if #search for eom in the non-padding portion of oPIn suboPIn=opIn[0:pktSize-cntPadding] #print("suboPIn:"+suboPIn+":") pos=suboPIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) print("405 tx sent:"+oP+":") #keep user informed during testing return pktSize #end def def mpyRead(uart): import IXuart as IXuart #keep read1 character packet until timeOut print("415 into mpyRead") txtRead="" bRead="" IXany=IXuart.any() while IXany: aByte=str(IXuart.read(1)) show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead IXany=False #IX loop once #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #IX print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=timeOut #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer show("time:",time) show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut print("458 I should be flashing the green LED while receiving") # I don't know if it is still receiving # it should write the received msg to a file. print("461 any") strA=mpyRead(uart) show("strA:",strA) oP=oP+strA show("465 oP:",oP) #end if time=utime.time() time=time+1 #IX show("time",time) if len(oP)>5 : break #IX break out of while loop #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def ########################################################################################## ########################################################################################## progName="testTxD3_pico.py" print("496 progName:"+progName) import IXuart as uart uart.write("501 zzz") if True: bps=60 tPause=4 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin_OUT) IXled_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) IXled_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #IX #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete #uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): print("547 transmitting Hello msg on Pin(GP4) in 2 16 byte packets at") print("548 60 bps, continuously preceded by an 'A' at 2 sec intervals") print("549 Issue 01: it erroneously skips the 'o' in 'Roy'. Doh!") print("550 Issue 02: it includes the '[16' in the msg len count of 16. Doh!") # [16Hello,JoeMaxR # 1234567890123456 # yBob]]]]]]]]]]]] print("557 Hit ^C to stop!") print() while True : try: #print("558 before write") uart.write("A") #print("566 before write") utime.sleep(tPause) #print("568 before write") serTx_pico(uart,bps, txtToBeSent="Hello,JoeMaxRoyBob") #print( "570 before write") utime.sleep(tPause) #print("572 before except") except: print("574 interrupted by ^c") break finally: print("577 after finally") aReply=input("579 Hit Enter to Continue") #end try #end while if False: serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H]") serTx_pico(uart,bps, txtToBeSent="[H]") serTx_pico(uart,bps, txtToBeSent="2.97") serTx_pico(uart,bps, txtToBeSent="99.987654") serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") serTx_pico(uart,bps, txtToBeSent="1234567890123") serTx_pico(uart,bps, txtToBeSent="12345678901234") serTx_pico(uart,bps, txtToBeSent="Hello,World") serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") #end if if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if # This should be run this as a separate thread #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) #uart="machine.uart" #IX print("636 machine.uart:",uart) uart.write("642 yyy") if True: #IX uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if charIn="" if False: print("receiving mpy routine") if uart.any() : #print("663 reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("675 end of serRX()") print("676 end of:",progName) #IX #end /testTxD3_pico.py ::::::::::textpak=>serTxRx_Fast_pico.py.txt import os import utime from machine import UART, Pin #print("unfixed ERROR thinks msg is fully received at 1500 (sees a ']' at 35th byte") progName="serTxRx_Fast_pico.py" bps=1500 # baud (bits/sec) rate First Att/ saw Second Attp saw # 3000 32 0 # 1700 32 all # 1525 32 all # 1525 - hung # 1500 32 lost in mid 2 # 1440 garbage hung # 1440 all all # 1350 all all # 1000 all all # 500 all all # 300 - hung # 300 all all t10c=100/bps t1000c=10000/bps def setTBuff(bps,minTBuff=5,maxTBuff=15): tBuff=1000/bps if tBuffmaxTBuff: tBuff=maxTBuff return tBuff #end def tBuffer=setTBuff(bps) print("tBuffer:",tBuffer) errThreshold=99 rxtxEndChar="]" isUsingFirstAttempt=True isUsingSecondAttempt=True # tested OK on 2021FJun15 by D@CC # the b'H' has been converted to "H" # backed up as serTxRx_pico_BU2021FJun15-1702.py #based pm progName="mpy_uart_pico.py" print("progName:"+progName) print("Error occurs when using pins 8 and 9 as Rx and Tx") txPin=4 rxPin=5 print("Jumper GP"+str(rxPin)+" to GP"+str(txPin)) #print sys info print(os.uname()) #indicate program started visually led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) #create uart object if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) # speed of 400 only reads 4 bytes . . Doh? # bps=9000 pass #end if #tBuff=setTBuff(bps) uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print uart info #uart = machine.UART(1) print(uart) def bChar(strB): # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="zz" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTxRx_pico(uartObject,bps, rOrT="R",txtToBeSent="[UUUUUUUU]",tBuff=3,rxtxEndChar="]"): t10c=100/bps t1000c=10000/bps # requires a uart object (below) to be created before this function is called #uart = machine.UART(1,600, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print("entering serTxRx") #print("rOrT:"+rOrT) #Note: there appears to be an internal error in either the Tx or the Rx function. This # error causes messages (simple text strings) longer than 32 bytes to be chopped, resulting # in a loss of data no matter how long the program waits for the remainder of the message # to arrive. What is really strange is that this issue is speed-dependant at both extremes # of speed. The result is that the last character of the message ("]") might never arrive # or in some cases, characters in the middle of the message have been lost. This issue # would dissappear if an ACK/NAK protocol were used, but this level of sophistication should # NOT be necessary for communication between two boards that are only inches apart. # # To further explore this issue, a wait count (called an "Error Threshold: errThreshold" is # used internally to count how many times the code receives an empty message before it # "gives up" and terminates with an error note. As this Threshold is raised, a second # threshold (a time-out) is used after which an error note is received. This is complicated # by the fact that unix times on the pico do NOT seem to be measured in intervals less than # a second. # Precision in milliseconds would be needed to work on this issue. Exceeding a time # limit of 31.4159 seconds will also result in program termination with a different error message. # Another complication is that this issue is intermittent, and cannot always be reproduced. # This makes me wonder if something similar to "RAM garbage collection" might be in play. We # have been told that "RAM garbage collection" does NOT occur in the Pico. Doh! #errThreshold of 99 works at low baud rates (even down to 200 bps) # tested by D@CC with MPA board down to 20 with errThreshold=99 # sending longer messages (>32 characters) cause data loss by the receiver # apparently very slow and very fast baud rates cause problems with 60 character msgs # D@CC saw it fail at 450 bps sometimes (but "usually" works at 400) # testing was done on an RPi model 4 with a RP4020 pico # D@CC doesn't yet know what the high baud rate limit is isValidRorT=False txtIn=" mt " if rOrT=="T": isValidRorT=True txtOut=txtToBeSent #print("A transmitting:"+txtOut+":") if txtOut=="": txtOut="[HelloThere]" #end if print("B1 transmitting:"+txtOut+":") uartObject.write(txtOut) utime.sleep(0.1) print("transmission complete") return #end if if rOrT=="X": isValidRorT=True txtIn="" while uartObject.any(): txtIn=uartObject.read(1) #end while if txtIn=="": pass else: print(txtIn) #end if #end if m=0 if rOrT=="R" : #print("Receiving t10c:",t10c) isValidRorT=True #print("doing R") utime.sleep(t10c) #wait for 10 char to be received txtMsg="" tBeg=utime.time() #print("tBeg:",tBeg) # # loop while the pico thinks that "any" more of the message is expected # How can it know how long the message should be? unless it senses # a non-empty "buffer queue" of unprocessed characters exists? while uart.any(): m=m+1 # this next statement reads "one character at a time" # If more than 1 character is requested to be read, the routine # will "wait" internally until the requested count of characters # has been received, essentially "hanging" the code until then. byteOne=uart.read(1) char1=str(byteOne) # the following routine named bChar() converts the message # containing the one character (eg b'h') to the character "h" # by stripping the superfluous text surrounding the character. #txtMsg=txtMsg+str(m)+bChar(char1) txtMsg=txtMsg+bChar(char1) #print(m,char1) utime.sleep(0.01) #end while tNow=utime.time() dT=tNow-tBeg #print("dT:",dT,"txtMsg:"+txtMsg) #print("txtMsg:"+txtMsg) if txtMsg=="": # an empty txtIn messge will NOT be returned # this can result in a "hung" program if # data has been truly lost. txtIn=txtMsg if dT> 31.4159: print(" ERROR B wait time exceeds 31.4159 seconds") exit #break out of this hung situation else: pass #end if else: txtIn=txtMsg return txtIn #end if #print("after R loop") #end if if isValidRorT : #print("returning") return txtIn else: txtIn="?" #print("returning") return txtIn #end if #end def def timeOut(t0,tOut): tNow=utime.time() dT=tNow-t0 #print("q:",q,rxtxEndChar,"dT:",dT) if dT>tOut: return True #print("ERROR E wait time exceeds",t1000c,"secs") else: return False #end if #################################################################################### #transmit the default text (then print and return any received text) #serTxRx_pico(uart,bps,"T","[UUUUUUUUUUUUUUUUUUUUUUUUAUU30123456789UUUUUUUUUUU]") if isUsingFirstAttempt : pass #end if # the program executes so fast that we must wait for the message # to be fully sent before we start reading the message. # if we sleep(0), we will only see the final "o" Doh! if False: while uart.any(): print(uart.read(1)) #end while #end if if isUsingFirstAttempt==False: print("skipping first attempt at coding this.") else: print("First attempt at coding this.") serTxRx_pico(uart,bps, "T","[UUUUUUUUUUUUUUUUUUUUUUUUAUU301234567890abcdefghij]") #serTxRx_pico(uart,bps, "T","[UUUUUUUUUUUUUUUUUUUUUUUUAUU3012345678901234567890]") print("receiving 2 t10c:",t10c) utime.sleep(t10c) # throttle transmission by 10 character pause kk=0 partMsg="" tBeg=utime.time() dT=-1 #print(kk,dT,"partMsg:"+partMsg+":") print("receiving 2 t10c:",t10c) while (len(partMsg)==0 or ((partMsg[-1:]==rxtxEndChar)==False)): # leng==0 or last char not "]" # keep reading characters msgStr="testing part Msg[-1:] :" #print(msgStr+partMsg[-1:]) tNow=utime.time() dT=tNow-tBeg if dT>t1000c: print("dT:",dT) print("Error rX delay > ",t1000c,"secs") break #out of while loop #end if kk=kk+1 #print(kk,dT,"partMsg:"+partMsg+":") msgRecd=serTxRx_pico(uart,bps,"R",tBuff=tBuffer) partMsg=partMsg+msgRecd #print("XpartMsg:"+partMsg) # if kk>errThreshold: print("Error F -missing ']' at end of reading") break # out of the while loop else: pass #end if # get the result ready in case the while loop stops with a ")" #end while print("bps:",bps) print("Msg received 1st Try:"+partMsg+":") #end if # Reading if False: for j in range(51): byteRecd=serTxRx_pico(uart,bps,"R",tBuff=tBuffer) strRecd=str(byteRecd) #print("strRecd:"+strRecd+":") if strRecd==" mt ": pass else: #strRecd=str(byteRecd) print(j,"txtRecd:"+strRecd+":") #end if #end for #end if #print("end of j loop") print("bps:",bps) pauseN=tBuffer #pause time set to 5 seconds print("tBuffer:",tBuffer) utime.sleep(t10c) #let the buffers settle down (10 char delay) if isUsingSecondAttempt : print() print("pausing to wait for buffers to settle:",pauseN,"secs") print("isUsingSecondAttempt") print("First . . clear out any residual message:") while uart.any(): inStr=str(uart.read(1)) inStr=bChar(inStr) print(inStr, end='') #end while print() print("end of search for residual character(s)") print("transmitting") #serTxRx_pico(uart, bps,"T","[UUUUUUUUUUUUUUUUUUUUUUUUAUU3012345678901234567890]") serTxRx_pico(uart,bps, "T","[UUUUUUUUUUUUUUUUUUUUUUUUAUU301234567890abcdefghij]") print("t10c:",t10c) #utime.sleep(t10c) #10 char delay to allow the transmission to be sent print("receiving 2nd attempt") q=0 if True: partMsg="" leng=0 tBeg=utime.time() print("rxtxEndChar:"+rxtxEndChar) #while (leng==0 or (partMsg[-1:]==rxtxEndChar)==False): if (partMsg[-1:]==rxtxEndChar) : isKeepChecking=False else: isKeepChecking=True # or if (leng==0): isKeepChecking=True while isKeepChecking: #print("starting the while loop") # empty msg or last char not == "]" #print("q:",q, "before uart.any") isCheckUartAny=True if isCheckUartAny and uart.any(): #print("after if uart any") inByte=uart.read(1) inStr=bChar(str(inByte)) #print("inStr:",inStr) partMsg=partMsg+inStr isToTest=(partMsg[-1:]==rxtxEndChar) #print("isToTest:"+str(isToTest)) if isToTest : #That was the "end" character=="]" print(" partMsg:"+partMsg+":") #break #out of the while loop isKeepChecking=False #end if #print("end of uart.any") #end if if False: if False: # skipping this########################## q=q+1 #print("q:",q,rxtxEndChar) tNow=utime.time() dT=tNow-tBeg if dT>t1000c: print("ERROR C wait time exceeds",t1000c, "secs") break else: pass #end if #end if ######################################## inStr=str(uart.read(1)) print("inStr:"+inStr) #leng=len(inStr) #leng=1 #if leng>0 : #print("inStr:"+inStr) #for r in range(leng): chrStr=str(inStr) chrStr=bChar(chrStr) partMsg=partMsg+chrStr print("isToTest:"+str(partMsg[-1:]==rxtxEndChar)) #end for #end if # end else: if False: #print("WARNING: still not any chars received") q=q+1 print("q2:",q,rxtxEndChar) if timeOut(tBeg,t1000c): print(" partMsg:"+partMsg+":") print("timeOut exiting") break #out of while #end if utime.sleep(t10c) #end if #end while print("endWhile") #print(" partMsg:"+partMsg+":") #end if #end if print() print("- bye -") #end def #Source:http://helloraspberrypi.blogspot.com/2021/01/raspberry-pi-picomicropython-simple.html #program end #/serTxRx_Fast_pico.py ::::::::::textpak=>signalGenerator_pico.py.txt # Example of using PIO for function generation using hacked PWM example from machine import ADC from time import sleep_us, sleep_ms import _thread #DC from pio_dac import PIOPWM #DC copied PIOPWM from fadeLed_pico.py from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep @asm_pio(sideset_init=PIO.OUT_LOW) def pwm_prog(): pull(noblock) .side(0) mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock mov(y, isr) # ISR must be preloaded with PWM count max label("pwmloop") jmp(x_not_y, "skip") nop() .side(1) label("skip") jmp(y_dec, "pwmloop") class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) #DC end class PIOPWM copied from fadeLed_pico.py #DC where is pio_dac ? [Answer: non-existant pot] progName="signalGenerator_pico.py" print(progName) #DC suppressed use of pot [potentiometer on ADC(26) for frequency] #DC Pin GP22 is output count_freq is generation interval not freq. #DC pwm = PIOPWM(0, 22, max_count=250, count_freq=10_000_000) pwm = PIOPWM(0, 18, max_count=250, count_freq=10_000_000) #DC vector has 250 samples sines = [ 124, 127, 130, 133, 136, 139, 142, 145, 148, 152, 155, 158, 161, 164, 167, 170, 172, 175, 178, 181, 184, 186, 189, 192, 194, 197, 200, 202, 204, 207, 209, 211, 214, 216, 218, 220, 222, 224, 226, 227, 229, 231, 232, 234, 235, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 247, 248, 248, 248, 248, 249, 249, 248, 248, 248, 248, 247, 247, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 235, 234, 232, 231, 229, 227, 226, 224, 222, 220, 218, 216, 214, 211, 209, 207, 204, 202, 200, 197, 194, 192, 189, 186, 184, 181, 178, 175, 172, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 127, 124, 120, 117, 114, 111, 108, 105, 102, 99, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 40, 38, 36, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 36, 38, 40, 43, 45, 48, 50, 53, 55, 58, 61, 63, 66, 69, 72, 75, 77, 80, 83, 86, 89, 92, 95, 99, 102, 105, 108, 111, 114, 117, 120, ] #DCx pot = ADC(26) #DCpot = ADC(1) #works with MPA ver1 DCpot = ADC(1) #works with MPA ver1 (my pot is on 1) delay = [400] def read_pot(): while True: #DCx v = pot.read_u16() #DC v = pot.read_u16() #works with MPA ver 1 #DCx // is floor division (i.e. discard fractionary value) #DCx delay[0] = 20 + (400 * v)// 65000 #DC delay[0] = 20 + (400 * v)// 65000 #works with MPA ver 1 #DC delay[0] = 20 + 10 #200 is midpoint on pot #DC 20 + 10 is about 600 Hz sleep_ms(100) _thread.start_new_thread(read_pot, ()) while True: for i in range(0, 250, 25): pwm.set(sines[i]) sleep_us(delay[0]) #DC Source: http://blog.rareschool.com/2021/02/raspberry-pi-pico-simple-projects.html #DC end program #signalGenerator_pico.py #signalGenerator_pico.py ::::::::::textpak=>signalGenerator_w_Pot_pico.py.txt ************************************* signalGenerator_w_Pot_pico.py ************************************* by D@CC on 2022EMay05 # Example of using PIO for function generation using hacked PWM example # with freq control using a potentiometer #functions used pwm_prog() PIO statements_5 @asm_pio() pull() mov() label() jmp() nop() ._sm ._sm.put() ._sm.exec() ._sm.active() ._sm.mac_count max() min() sm.put() set() PIOPWM() ADC() pot.read() read_pot() sleep_ms() sleep_us() from machine import ADC from time import sleep_us, sleep_ms import _thread #DC from pio_dac import PIOPWM #DC copied PIOPWM from fadeLed_pico.py from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep @asm_pio(sideset_init=PIO.OUT_LOW) def pwm_prog(): pull(noblock) .side(0) mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock mov(y, isr) # ISR must be preloaded with PWM count max label("pwmloop") jmp(x_not_y, "skip") nop() .side(1) label("skip") jmp(y_dec, "pwmloop") class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) #DC end class PIOPWM copied from fadeLed_pico.py #DC where is pio_dac ? [Answer: non-existant pot] progName="signalGenerator_w_Pot_pico.py" print(progName) #DC suppressed use of pot [potentiometer on ADC(26) for frequency] #DC Pin GP22 is output count_freq is generation interval not freq. #DC pwm = PIOPWM(0, 22, max_count=250, count_freq=10_000_000) pwm = PIOPWM(0, 18, max_count=250, count_freq=10_000_000) #DC vector has 250 samples sines = [ 124, 127, 130, 133, 136, 139, 142, 145, 148, 152, 155, 158, 161, 164, 167, 170, 172, 175, 178, 181, 184, 186, 189, 192, 194, 197, 200, 202, 204, 207, 209, 211, 214, 216, 218, 220, 222, 224, 226, 227, 229, 231, 232, 234, 235, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 247, 248, 248, 248, 248, 249, 249, 248, 248, 248, 248, 247, 247, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 235, 234, 232, 231, 229, 227, 226, 224, 222, 220, 218, 216, 214, 211, 209, 207, 204, 202, 200, 197, 194, 192, 189, 186, 184, 181, 178, 175, 172, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 127, 124, 120, 117, 114, 111, 108, 105, 102, 99, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 40, 38, 36, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 36, 38, 40, 43, 45, 48, 50, 53, 55, 58, 61, 63, 66, 69, 72, 75, 77, 80, 83, 86, 89, 92, 95, 99, 102, 105, 108, 111, 114, 117, 120, ] pot = ADC(26) delay = [400] def read_pot(): while True: # potentiometer is 4K8 (4800 ohms) v = pot.read_u16() #DC // is floor division (i.e. discard fractionary value) delay[0] = 20 + (400 * v)// 65000 #DC delay[0] = 20 + 10 #200 is midpoint on pot #DC 20 + 10 is about 600 Hz sleep_ms(100) _thread.start_new_thread(read_pot, ()) while True: for i in range(0, 250, 25): pwm.set(sines[i]) sleep_us(delay[0]) #DC Source: http://blog.rareschool.com/2021/02/raspberry-pi-pico-simple-projects.html #DC end program #signalGenerator_w_Pot_pico.py ::::::::::textpak=>signalGenerator_w_PotOn1_pico.py.txt # Example of using PIO for function generation using hacked PWM example from machine import ADC from time import sleep_us, sleep_ms import _thread #DC from pio_dac import PIOPWM # worked with MakPiADC board with pot on 2021FJun09 #DC copied PIOPWM from fadeLed_pico.py from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep @asm_pio(sideset_init=PIO.OUT_LOW) def pwm_prog(): pull(noblock) .side(0) mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock mov(y, isr) # ISR must be preloaded with PWM count max label("pwmloop") jmp(x_not_y, "skip") nop() .side(1) label("skip") jmp(y_dec, "pwmloop") class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) #DC end class PIOPWM copied from fadeLed_pico.py #DC where is pio_dac ? [Answer: non-existant pot] progName="signalGenerator_w_Pot_pico.py" print(progName) #DC suppressed use of pot [potentiometer on ADC(26) for frequency] #DC Pin GP22 is output count_freq is generation interval not freq. #DC pwm = PIOPWM(0, 22, max_count=250, count_freq=10_000_000) pwm = PIOPWM(0, 18, max_count=250, count_freq=10_000_000) #DC vector has 250 samples sines = [ 124, 127, 130, 133, 136, 139, 142, 145, 148, 152, 155, 158, 161, 164, 167, 170, 172, 175, 178, 181, 184, 186, 189, 192, 194, 197, 200, 202, 204, 207, 209, 211, 214, 216, 218, 220, 222, 224, 226, 227, 229, 231, 232, 234, 235, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 247, 248, 248, 248, 248, 249, 249, 248, 248, 248, 248, 247, 247, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 235, 234, 232, 231, 229, 227, 226, 224, 222, 220, 218, 216, 214, 211, 209, 207, 204, 202, 200, 197, 194, 192, 189, 186, 184, 181, 178, 175, 172, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 127, 124, 120, 117, 114, 111, 108, 105, 102, 99, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 40, 38, 36, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 36, 38, 40, 43, 45, 48, 50, 53, 55, 58, 61, 63, 66, 69, 72, 75, 77, 80, 83, 86, 89, 92, 95, 99, 102, 105, 108, 111, 114, 117, 120, ] #DCx pot = ADC(26) #DC pot = ADC(1) # my pot in MPA is on ADC1 #DC pot = ADC(0) # my CDS0 in MPA is on ADC0 #DC # CDS0 doesn't control freq very well #DC # the calc needs adjustment pot = ADC(1) # my pot in MPA is on ADC1 delay = [400] def read_pot(): while True: # potentiometer is 4K8 (4800 ohms) v = pot.read_u16() #DC // is floor division (i.e. discard fractionary value) delay[0] = 20 + (400 * v)// 65000 #DC delay[0] = 20 + 10 #200 is midpoint on pot #DC 20 + 10 is about 600 Hz sleep_ms(100) _thread.start_new_thread(read_pot, ()) while True: for i in range(0, 250, 25): pwm.set(sines[i]) sleep_us(delay[0]) #DC Source: http://blog.rareschool.com/2021/02/raspberry-pi-pico-simple-projects.html #DC end program #signalGenerator_w_Pot_pico.py ::::::::::textpak=>signalGenerator_wo_Pot_pico.py.txt # Example of using PIO for function generation using hacked PWM example from machine import ADC from time import sleep_us, sleep_ms import _thread #DC from pio_dac import PIOPWM #DC copied PIOPWM from fadeLed_pico.py from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep @asm_pio(sideset_init=PIO.OUT_LOW) def pwm_prog(): pull(noblock) .side(0) mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock mov(y, isr) # ISR must be preloaded with PWM count max label("pwmloop") jmp(x_not_y, "skip") nop() .side(1) label("skip") jmp(y_dec, "pwmloop") class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) #DC end class PIOPWM copied from fadeLed_pico.py #DC where is pio_dac ? [Answer: non-existant pot] progName="signalGenerator_wo_Pot_pico.py" print(progName) #DC suppressed use of pot [potentiometer on ADC(26) for frequency] #DC Pin GP22 is output count_freq is generation interval not freq. #DC pwm = PIOPWM(0, 22, max_count=250, count_freq=10_000_000) pwm = PIOPWM(0, 18, max_count=250, count_freq=10_000_000) #DC vector has 250 samples sines = [ 124, 127, 130, 133, 136, 139, 142, 145, 148, 152, 155, 158, 161, 164, 167, 170, 172, 175, 178, 181, 184, 186, 189, 192, 194, 197, 200, 202, 204, 207, 209, 211, 214, 216, 218, 220, 222, 224, 226, 227, 229, 231, 232, 234, 235, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 247, 248, 248, 248, 248, 249, 249, 248, 248, 248, 248, 247, 247, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 235, 234, 232, 231, 229, 227, 226, 224, 222, 220, 218, 216, 214, 211, 209, 207, 204, 202, 200, 197, 194, 192, 189, 186, 184, 181, 178, 175, 172, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 127, 124, 120, 117, 114, 111, 108, 105, 102, 99, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 40, 38, 36, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 36, 38, 40, 43, 45, 48, 50, 53, 55, 58, 61, 63, 66, 69, 72, 75, 77, 80, 83, 86, 89, 92, 95, 99, 102, 105, 108, 111, 114, 117, 120, ] #DCx pot = ADC(26) # deleted pot reference here for wo Pot delay = [400] def read_pot(): while True: #DCx v = pot.read_u16() #DCx // is floor division (i.e. discard fractionary value) #DCx delay[0] = 20 + (400 * v)// 65000 delay[0] = 20 + 10 #200 is midpoint on pot #DC 20 + 10 is about 600 Hz sleep_ms(100) _thread.start_new_thread(read_pot, ()) while True: for i in range(0, 250, 25): pwm.set(sines[i]) sleep_us(delay[0]) #DC Source: http://blog.rareschool.com/2021/02/raspberry-pi-pico-simple-projects.html #DC end program #signalGenerator_pico.py ::::::::::textpak=>Test_readCD2works.py.txt import sys, time #sys.path.append("/home/pi/Desktop/IX_assets/ix") ########################### def initCD2(PPin): import RPi.GPIO as GPIO #By D@CC on 2023KNov01 #PPin-2 is PPout (tested with PPin = 40) GPIO.setmode(GPIO.BOARD) #physical Board numbers #GPIO.setmode(GPIO.BMB) #BroadCoM numbering eg GPIO #s print("PPin-2:",PPin-2) isBadPin= ((PPin-2==1) or (PPin-2==17)) # they are 3v3 # Ground pins won't work either, nor 5v0 pins print("isBadPin:",isBadPin) if not isBadPin: GPIO.setup(PPin-2,GPIO.OUT) print("turn On phys pin:", PPin-2) GPIO.output(PPin-2, True) #if end # on a Raspberry Pi, PullUpDown is a 10k resistor # a photoresistor photocell (CD) when lit is 100. # when dark is >10k0. return #def end initCD2(PPin) #::::::::::textpak=>readCD2.py def readCD2(PPin): import RPi.GPIO as GPIO #By D@CC on 2023KNov01 #Purpose: to return True if both CDs are covered #HW: my device "CD2_Dongle(c)" #Tested with PPin=40 GPIO.setmode(GPIO.BOARD) #physical Board numbers GPIO.setup(PPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) reading=GPIO.input(PPin) # reading is True if the CD photoCells are Dark # Make them dark by covering them with a finger if reading: state=False else: state=True #if end return state #def end progName="Test_readCD2works.py" PPin=40 #works as GPIO21 on Maker pHAT #PPin=21 #for Maker pHAT #Purpose: test my device "CD2_Dongle(c)" #By: D@CC on 2023KNov01 #Issue: SW uses RPi.GPIO which is deprecated on RPi 5 #Warning: Ignore RuntimeWarning: . . . in use . . . #Status: HW & SW are both working #Functions Used: initCD2,readCD2 #Packages Used: Desktop/ix/ix_pkg.py #Python Packages Used: sys,time #Future: should use GPIO ZERO SW # Use Phy Pin 40 on the Pi400 # But when also using the Cytron Maker pHAT: # other devices are attached to various pins # so, use Phy Pin 21 as input (with Phy pin 19) # Closing Maker pHAT button 21 makes Phys Pin 40: # "Dark" equivalent to CD2 Dark between 38 & 40 print("progName:",progName,"Phys Pin:",PPin) import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) #physical Board numbers GPIO.setup(PPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #Purpose: to sense if 2CD photocells "see" Light or Dark # using an internal pulldown resistor #By D@CC on 2023JOct30 # tested with PPin=40 on a Raspberrry Pi400 #Cover the CDs with a thumb to "Make it Dark" print("uses RPi.GPIO (fails on RPi 5B)") print("always works with 2 CD in series (covering both), ") print("works with 1 CD sometimes. . . ") print("CDs from phys pin 38 (with output High).") # 19 print(" to phys pin 40 (as input with PUD_DOWN)") # 21 #PPout=38 #phys pin 38 #GPIO 20 output #PPin =40 #phys pin 40 #GPIO 21 input #This also works with PPin = 37 (But not PPin=3 nor 19) # It probably works with some other adjacent pin pairs initCD2(PPin) while True: print("PPin:",PPin) if readCD2(PPin): print("Dark") else: print("Light") #if end time.sleep(1) #while end #/Test_readCD2works.py.txt ::::::::::textpak=>test_TxG_pico.py.txt # test_TxG_pico.py # stored in Raspberry Pi Pico/ # and in /home/pi/Desktop/Python_new/ix_pico_test/ import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun21 #Note: as of today, no known errors ver F is first to work successfully # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack()actually transmits a full packet (wo any EOM) # 6. sendLastPack()actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): # # test_pktixRx_pi.py OUTLINE # #All Use: int,str,time,strip,hex,float #txToBeSent->|1.test_TxG_pico # ------------ # 1.RAPasc(->strRAPasc # ------- # 1.readADC_pico(->adcVoltage # 2.serTx_pico(->True # ----------- # 1.txParse( # # # |a.txParse(->a.sendThisPack(->| # | b.sendLastPack(->|->a.uart.write(->GP5 # | -------- -------------- # | 1.txchar( # | 2.sleep( # # # # |0.testpktixRx( # | ------------ #txIncoming->|1.machine.UART( # |2.serRx_pico(->oP # | ----------- # | 1.mpyRead(->strA # -------- # 1.bChar(->txtRead)))))))))))))) #Debugging notes: #"tx sent:" is what is actually sent # Errors and Warnings are embedded in the text transmitted. def readADC_pico(nn,cnvrt=5.035477e-05): #nn is the pico GPnn (ADCnn) to read #cnvrt = 5.035477e-05 converts the reading to volts. # that is the default cnvrt factor. adcFirst = machine.ADC(nn) adcValue=adcFirst.read_u16() #print("The value of ADC0 is", adcValue) #conversion_factor = 3.3 / (65535) #print("conversion_factor:",conversion_factor) adcVoltage=adcValue * cnvrt #print("The voltage at ADC0 is", adcVoltage) #print("-bye- from readADC_pico.py") return adcVoltage #end def def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# #print("txtToBeSent:"+txtToBeSent+":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz #print("end of serTx()") #print("Hit ^C to stop!") #print() return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() #show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet #show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM #print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #print() #print("oP:"+oP+":") cntUsed=0 #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom #print("sending M") #cntSent of the packet is already in oP #cntUsed is 0 going into the while # note that lenM also includes 1 eom # in the while loop, cntUsed will increase until cntUsed=lenM while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) #print("going into the M while") #show("upon entry M-while cntUsed:",cntUsed) # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data # lastChar is the lastChar of Msg to send in this packet cntCanAdd=pktSize-len(oP) #print("cntCanAdd:",cntCanAdd,":") #show("cntUsed:",cntUsed) #should be 0 entering first loop cntRemainOfM=lenM-cntUsed-1 #this cnts the remaining chars of M cntToAdd=pktSize-len(oP) #this cnts the remaining space in oP # a packet is always sent in this next "if clause" #show("cntRemainOfM:",cntRemainOfM) #show("cntToAdd:",cntToAdd) #if (cntRemainOfM)>cntToAdd : #{for debugging} if (cntRemainOfM+1)>cntToAdd : #{for debugging} ver F +1 # this packet cannot hold rest of Msg plus an eom isLastPack=False opToAdd=thisMsg[cntUsed:cntUsed+cntToAdd] # to add to oP opToSend=oP+opToAdd # to be sent #print("AopToSend:"+opToSend+":") cntPadding=0 sendThisPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt without any padding #cntUsed=cntUsed+cntToAdd+1 cntUsed=cntUsed+cntToAdd #{for debugging} ver F del "+1" # remember to count the first EOM as a character in cntUsed #show("cntUsed:",cntUsed) #show("lenM:",lenM) oP="" cntSent=0 #continue the while loop else : isLastPack=True # the pkt can hold the whole cntRemainOfM opToAdd=thisMsg[cntUsed:cntUsed+cntRemainOfM] #print("BopToSend:"+opToSend+":") cntPadding=pktSize-cntSent-cntRemainOfM strPadding=eom*cntPadding opToSend=oP+opToAdd+strPadding #print("CopToSend:"+opToSend+":") sendLastPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt including the padding cntUsed=cntUsed+len(opToAdd) #show("lenM:",lenM) #show("cntUsed:",cntUsed) oP="" cntSent=0 #print("after Last Packet of Msg") toSend=lenM-cntUsed #show("toSend:",toSend) #print("end of while") break #out of the while #if end cntUnsent=lenM-cntUsed-1 #show("cntUnsent:",cntUnsent) #print("repeat the M while") #end while if False : # we need to send at least 1 more full packet isLastpack=False lastChar=cntUsed+(pktSize-len(oP)) #this is lastChar of Msg yet to send opToAdd=thisMsg[cntUsed:lastChar] # to add to oP opTosend=oP+opToAdd print("opToSend:"+opToSend+":") sendThisPack(uartObject, opToSend, eom, pktSize) # no padding was necessary cntUsed=cntUsed+len(opToAdd) show("cntUsed:",cntUsed) # the while will loop once more #end if if False : lastChar=pktSize-cntSent show("lastChar",lastChar) #thisMsg="12345678901234567" #print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntSent:lastChar]",thisMsg[cntUsed:lastChar]) opWasSent=thisMsg[cntUsed:lastChar] print("opWasSend:"+opWasSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if #end if False if False : # a packet has just been sent leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if False : if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) oP=opToSend toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if #end if False # a packet was just sent print("M while might end now") print("after end of while") #end if False #end if "M" if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char #print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E1 in serTx", eom, "found eom in message") #oP=oP.replace(eom,"?") oP=oP.replace(eom,"?",1) #{for debugging} ver F replace once #end if uartObject.write(oP) #print("tx sent:" # in sendThisPack print(oP, end='') #this actually sends the text to the Shell # because in this early version, what is shown # in the Shell is actually sent. #print() #{for debugging} return pktSize #end def def sendLastPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendLastPack") oP=opIn #print("oP:"+oP+":") lenopIn=len(opIn) #show("lenopIn:",lenopIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if #search for eom in the non-padding portion of oPIn suboPIn=opIn[0:pktSize-cntPadding] #print("suboPIn:"+suboPIn+":") pos=suboPIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E2 in serTx", eom, "found in message") oPleft=opIn[0:pos] #{for debugging} ver F fix #print("oPleft:"+oPleft+":") lenOp=len(opIn) #{for debugging} ver F fix oPright=opIn[pos+1:lenOp] #{for debugging} ver F fix #print("oPright:"+oPright+":") #oP=oP.replace(eom,"?") #oP=oP.replace(eom,"?",1) #{for debugging} replace once didn't work oP=oPleft+"?"+oPright #{for debugging} ver F fix #end if uartObject.write(oP) # in sendLastPack(): #print("tx sent:"+ print(oP, end='') #keep user informed during testing #print() #{for debugging} return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=timeOut #in seconds #end if #timeOutUse=t100c time=utime.time() time=str(int(time)+secsToAdd)#{for debugging} #time=time+secsToAdd timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut print("I should be flashing the green LED while receiving") # I don't know if it is still receiving # it should write the received msg to a file. #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() time=str(int(time)+secsToAdd)#{for debugging} time=time+secsToAdd #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def def readADC_pico(nn,cnvrt=5.035477e-05): #nn is the pico GPnn (ADCnn) to read #cnvrt = 5.035477e-05 converts the reading to volts. # that is the default cnvrt factor. adcFirst = machine.ADC(nn) adcValue=adcFirst.read_u16() #print("The value of ADC0 is", adcValue) #conversion_factor = 3.3 / (65535) #print("conversion_factor:",conversion_factor) adcVoltage=adcValue * cnvrt #print("The voltage at ADC0 is", adcVoltage) #print("-bye- from readADC_pico.py") return adcVoltage #end def def RAPasc(reading,nnIn,rFormat): #returns the RAPasc packet #print("nnIn:",nnIn) if nnIn==0 : nn=0 #ADC number = 0 or 1 usually strNN=str(nn) #end if if nnIn==1 : nn=1 #ADC number = 0 or 1 usually strNN=str(nn) #end if if nnIn==26 : nn=26 #ADC number = 0 or 1 or 26 usually strNN=str(nn) #end if # prepare the time timeNow=utime.time() intTime=int(timeNow) #print("intTime:",intTime) intTime=intTime+secsToAdd #{for debugging} timeNow=str(intTime) #{for debugging} #timeNow=timeNow+secsToAdd #{for debugging} strTime=str(timeNow)+".000" strReading="???" #print("rFormat:"+rFormat) if rFormat=="X": # use strReading as Hex # (It comes as a Hex #) # I need to improve this by receiving the # # as a string and using f3() to convert it to float hexNumber=readADC_pico(nn,cnvrt=1.000) #print("hexNumber:",hexNumber) strReading=str(hexNumber) #print("|"+strReading+"|") strReading=strReading.strip() #h = str(hex(i))[2:] #h = h.upper() hexNumber=int(hexNumber) #print("hexNumber:",hexNumber) strReading=str(hex(hexNumber))[2:] #print("strReading:"+strReading) strReading="0x"+strReading.upper() #end if if rFormat=="F": # use strReading as Float # (It comes as a Hex #) strReading=str(float(readADC_pico(nn,cnvrt=5.035477e-05))) #print("|"+strReading+"|") strReading=strReading.strip() #end if #print("strNN:"+strNN) strRAPasc="ADC"+strNN+":("+strReading+"+"+strTime+"j)" return strRAPasc #end def RAPasc ########################################################################################## ########################################################################################## progName="test_TxG_pico.py" print("progName:"+progName) if True: bps=600 print("tx bps:",600) tPause=1 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # verifying and adjusting localtime and gmtime timeLocal=utime.localtime() strLocal=str(timeLocal) print("strLocal:"+strLocal) timeGMT=utime.gmtime() strGMT=str(timeGMT) print("strGMT :"+strGMT) strAnsw=input("Are these Correct?:") if "nN".find(strAnsw)==-1 : pass else: addToGMT=input("what N (hours) should we add to GMT?") #end if print("this routine will add",addToGMT,"hours to GMT") secsToAdd=3600*int(addToGMT) #convert hrs to secs # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1n, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete #uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): print("transmitting Hello msg on Pin(GP4) in 2 16 byte packets at") print("60 bps, continuously preceded by an 'A' at 2 sec intervals") print("the 'A' is not seen by the receiver") #print("it erroneously skips the 'o' in 'Roy'. Doh!") #fixed in ver F print("it erroneously skips a full packet of ']' when needed") print("Hit ^C to stop!") print() while True : uart.write("A") utime.sleep(tPause) #read and create format RAPasc using the following function call #strRAPasc=RAPasc(readADC_pico(n1,cnvrt=5.035477e-05),1,"F") # readADC_pico() reads ADC[nn], by default cvrts to volts # and returns the reading in volts # but can read ADC[nn], cvrts using another factor # and returns the converted reading # but can read ADC[nn], do no conversion (cnvrt=1.000) # and return the unconverted reading # RAPasc(accepts the reading, followed by the time into the format # ADC1:(56.789+875678.000j) if 2nd parm is "F" # RAPasc(accepts the reading, followed by the time into the format # ADC1:(0xffff+875678.000j) if 2nd parm is "X" # ************************************************************* strRAPasc=RAPasc(readADC_pico(0,cnvrt=5.035477e-05),0,"F") #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) strRAPasc=RAPasc(readADC_pico(1,cnvrt=1.0000),1,"X") #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) strRAPasc=RAPasc(readADC_pico(26,cnvrt=5.035477e-05),1,"X") #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) print() try: utime.sleep(tPause) #{for debugging} except: # this try/except code permits the tester to stop here using ^C print("interrupted by ^c") break finally: pass #end try #end while #end if True ########################################################################## # everything after here is old deprecated code # ########################################################################### # testpktixRx() if False: if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if False #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end False if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if False charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if False show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /test_TxG_pico.py # stored in Raspberry Pi Pico/ # stored in /home/pi/Desktop/Python_new/ix_pico_test/ ::::::::::textpak=>test_TxH_pico.py.txt # test_TxH_pico.py # stored in Raspberry Pi Pico/ # and in /home/pi/Desktop/Python_new/ix_pico_test/ import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun21 #Note: as of today, no known errors ver F is first to work successfully # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack()actually transmits a full packet (wo any EOM) # 6. sendLastPack()actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): # # test_pktixRx_pi.py OUTLINE # #All Use: int,str,time,strip,hex,float #txToBeSent->|1.test_TxG_pico # ------------ # 1.RAPasc(->strRAPasc # ------- # 1.readADC_pico(->adcVoltage # 2.serTx_pico(->True # ----------- # 1.txParse( # # # |a.txParse(->a.sendThisPack(->| # | b.sendLastPack(->|->a.uart.write(->GP5 # | -------- -------------- # | 1.txchar( # | 2.sleep( # # # # |0.testpktixRx( # | ------------ #txIncoming->|1.machine.UART( # |2.serRx_pico(->oP # | ----------- # | 1.mpyRead(->strA # -------- # 1.bChar(->txtRead)))))))))))))) #Debugging notes: #"tx sent:" is what is actually sent # Errors and Warnings are embedded in the text transmitted. #for pin 29 if False: if VSYS_ADC_INPUT == 3: Pin = machine.Pin Pin(29, Pin.IN) vsysChannel = machine.ADC(3) else: vsysChannel = machine.ADC(29) #end if while True: adcReading = vsysChannel.read_u16() adcVoltage = (adcReading * 3.3) / 65535 vsysVoltage = adcVoltage * 3 #end while #end if False def readADC_pico(nn,cnvrt=5.035477e-05): # this is the good version # the X prevents it from being used #nn is the pico GPnn (ADCnn) to read #cnvrt = 5.035477e-05 converts the reading to volts. # that is the default cnvrt factor. #print("in readADC_pico nn:",nn) adcFirst = machine.ADC(nn) adcValue=adcFirst.read_u16() #print("The value of ADC0 is", adcValue) convertedValue=888.88 print("96 convertedValue:",convertedValue) if nn==4 : adcVoltage=adcValue*5.035477e-05 #print("adcVoltage:",adcVoltage) convertedVoltage=adcVoltage #print("convertedVoltage:",convertedVoltage) #temperature = 27 - (reading - 0.706)/0.001721 convertedValue = 27 - (convertedVoltage - 0.706)/0.001721 print("104 convertedValue:",convertedValue) #end if if nn==3: if nn==3: VSYS_ADC_INPUT = 3 Pin = machine.Pin Pin(29, Pin.IN) vsysChannel = machine.ADC(3) else: vsysChannel = machine.ADC(29) #end if adcReading = vsysChannel.read_u16() adcVoltage = (adcReading * 3.3) / 65535 vsysVoltage = adcVoltage * 3 #print("vsysVoltage:",vsysVoltage) convertedValue=vsysVoltage print("120 convertedValue:",convertedValue) else: pass #conversion_factor = 3.3 / (65535) #print("conversion_factor:",conversion_factor) #convertedValue=adcValue * cnvrt print("126 convertedValue:",convertedValue) #print("The voltage at ADC0 is", convertedValue) #end if #print("-bye- from readADC_pico.py") return convertedValue #end def def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# #print("txtToBeSent:"+txtToBeSent+":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz #print("end of serTx()") #print("Hit ^C to stop!") #print() return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() #show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet #show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM #print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #print() #print("oP:"+oP+":") cntUsed=0 #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom #print("sending M") #cntSent of the packet is already in oP #cntUsed is 0 going into the while # note that lenM also includes 1 eom # in the while loop, cntUsed will increase until cntUsed=lenM while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) #print("going into the M while") #show("upon entry M-while cntUsed:",cntUsed) # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data # lastChar is the lastChar of Msg to send in this packet cntCanAdd=pktSize-len(oP) #print("cntCanAdd:",cntCanAdd,":") #show("cntUsed:",cntUsed) #should be 0 entering first loop cntRemainOfM=lenM-cntUsed-1 #this cnts the remaining chars of M cntToAdd=pktSize-len(oP) #this cnts the remaining space in oP # a packet is always sent in this next "if clause" #show("cntRemainOfM:",cntRemainOfM) #show("cntToAdd:",cntToAdd) #if (cntRemainOfM)>cntToAdd : #{for debugging} if (cntRemainOfM+1)>cntToAdd : #{for debugging} ver F +1 # this packet cannot hold rest of Msg plus an eom isLastPack=False opToAdd=thisMsg[cntUsed:cntUsed+cntToAdd] # to add to oP opToSend=oP+opToAdd # to be sent #print("AopToSend:"+opToSend+":") cntPadding=0 sendThisPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt without any padding #cntUsed=cntUsed+cntToAdd+1 cntUsed=cntUsed+cntToAdd #{for debugging} ver F del "+1" # remember to count the first EOM as a character in cntUsed #show("cntUsed:",cntUsed) #show("lenM:",lenM) oP="" cntSent=0 #continue the while loop else : isLastPack=True # the pkt can hold the whole cntRemainOfM opToAdd=thisMsg[cntUsed:cntUsed+cntRemainOfM] #print("BopToSend:"+opToSend+":") cntPadding=pktSize-cntSent-cntRemainOfM strPadding=eom*cntPadding opToSend=oP+opToAdd+strPadding #print("CopToSend:"+opToSend+":") sendLastPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt including the padding cntUsed=cntUsed+len(opToAdd) #show("lenM:",lenM) #show("cntUsed:",cntUsed) oP="" cntSent=0 #print("after Last Packet of Msg") toSend=lenM-cntUsed #show("toSend:",toSend) #print("end of while") break #out of the while #if end cntUnsent=lenM-cntUsed-1 #show("cntUnsent:",cntUnsent) #print("repeat the M while") #end while if False : # we need to send at least 1 more full packet isLastpack=False lastChar=cntUsed+(pktSize-len(oP)) #this is lastChar of Msg yet to send opToAdd=thisMsg[cntUsed:lastChar] # to add to oP opTosend=oP+opToAdd print("opToSend:"+opToSend+":") sendThisPack(uartObject, opToSend, eom, pktSize) # no padding was necessary cntUsed=cntUsed+len(opToAdd) show("cntUsed:",cntUsed) # the while will loop once more #end if if False : lastChar=pktSize-cntSent show("lastChar",lastChar) #thisMsg="12345678901234567" #print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntSent:lastChar]",thisMsg[cntUsed:lastChar]) opWasSent=thisMsg[cntUsed:lastChar] print("opWasSend:"+opWasSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if #end if False if False : # a packet has just been sent leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if False : if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) oP=opToSend toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if #end if False # a packet was just sent print("M while might end now") print("after end of while") #end if False #end if "M" if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char #print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E1 in serTx", eom, "found eom in message") #oP=oP.replace(eom,"?") oP=oP.replace(eom,"?",1) #{for debugging} ver F replace once #end if uartObject.write(oP) #print("tx sent:" # in sendThisPack print(oP, end='') #this actually sends the text to the Shell # because in this early version, what is shown # in the Shell is actually sent. #print() #{for debugging} return pktSize #end def def sendLastPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendLastPack") oP=opIn #print("oP:"+oP+":") lenopIn=len(opIn) #show("lenopIn:",lenopIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if #search for eom in the non-padding portion of oPIn suboPIn=opIn[0:pktSize-cntPadding] #print("suboPIn:"+suboPIn+":") pos=suboPIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E2 in serTx", eom, "found in message") oPleft=opIn[0:pos] #{for debugging} ver F fix #print("oPleft:"+oPleft+":") lenOp=len(opIn) #{for debugging} ver F fix oPright=opIn[pos+1:lenOp] #{for debugging} ver F fix #print("oPright:"+oPright+":") #oP=oP.replace(eom,"?") #oP=oP.replace(eom,"?",1) #{for debugging} replace once didn't work oP=oPleft+"?"+oPright #{for debugging} ver F fix #end if uartObject.write(oP) # in sendLastPack(): #print("tx sent:"+ print(oP, end='') #keep user informed during testing #print() #{for debugging} return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #not a duplicate #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=timeOut #in seconds #end if #timeOutUse=t100c time=utime.time() time=str(int(time)+secsToAdd)#{for debugging} #time=time+secsToAdd timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut print("I should be flashing the green LED while receiving") # I don't know if it is still receiving # it should write the received msg to a file. #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() time=str(int(time)+secsToAdd)#{for debugging} time=time+secsToAdd #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def show if False : #def readADC_pico(nn,cnvrt=5.035477e-05): # this is the bad version #nn is the pico GPnn (ADCnn) to read #cnvrt = 5.035477e-05 converts the reading to volts. # that is the default cnvrt factor. print("in other readADC_pico") adcFirst = machine.ADC(nn) adcValue=adcFirst.read_u16() #print("The value of ADC0 is", adcValue) #conversion_factor = 3.3 / (65535) #print("conversion_factor:",conversion_factor) adcVoltage=adcValue * cnvrt #print("The voltage at ADC0 is", adcVoltage) #print("-bye- from readADC_pico.py") return adcVoltage #end def #end if def RAPasc(reading,nnIn,rFormat): #returns the RAPasc packet #print("nnIn:",nnIn) if nnIn==0 : nn=0 #ADC number = 0 or 1 usually strNN=str(nn) #end if if nnIn==1 : nn=1 #ADC number = 0 or 1 usually strNN=str(nn) #end if if nnIn==4 : nn=4 #ADC number = 0 or 1 or 4 usually strNN=str(nn) #end if if nnIn==3 : nn=3 strNN=str(nn) #end if if nnIn==29 : nn=29 strNN=str(nn) #end if #end if # prepare the time timeNow=utime.time() intTime=int(timeNow) #print("intTime:",intTime) intTime=intTime+secsToAdd #{for debugging} timeNow=str(intTime) #{for debugging} #timeNow=timeNow+secsToAdd #{for debugging} strTime=str(timeNow)+".000" strReading="???" #print("rFormat:"+rFormat) if rFormat=="X": # use strReading as Hex # (It comes as a Hex #) # I need to improve this by receiving the # # as a string and using f3() to convert it to float #show("603 before readADC_pico, nn:",nn) hexNumber=readADC_pico(nn,cnvrt=1.000) print("hexNumber:",hexNumber) strReading=str(hexNumber) print("|"+strReading+"|") strReading=strReading.strip() #h = str(hex(i))[2:] #h = h.upper() hexNumber=int(hexNumber) #print("hexNumber:",hexNumber) strReading=str(hex(hexNumber))[2:] #print("strReading:"+strReading) strReading="0x"+strReading.upper() #end if if rFormat=="F": if nn==4 : #show("619 before readADC_pico, nn:",nn) strReading=str(readADC_pico(nn,cnvrt=1.000)) print("in 667 strReading:"+strReading) else: # use strReading as Float # (It comes as a Hex #) #show("623 before readADC_pico, nn:",nn) strReading=str(float(readADC_pico(nn,cnvrt=5.035477e-05))) #print("|"+strReading+"|") strReading=strReading.strip() #end if #end if #print("strNN:"+strNN) strRAPasc="ADC"+strNN+":("+strReading+"+"+strTime+"j)" return strRAPasc #end def RAPasc ########################################################################################## ########################################################################################## progName="test_TxH_pico.py" print("progName:"+progName) if True: bps=600 print("tx bps:",600) tPause=1 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # verifying and adjusting localtime and gmtime timeLocal=utime.localtime() strLocal=str(timeLocal) print("strLocal:"+strLocal) timeGMT=utime.gmtime() strGMT=str(timeGMT) print("strGMT :"+strGMT) strAnsw=input("Are these Correct?:") if "nN".find(strAnsw)==-1 : pass else: addToGMT=input("what N (hours) should we add to GMT?") #end if print("this routine will add",addToGMT,"hours to GMT") secsToAdd=3600*int(addToGMT) #convert hrs to secs # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1n, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete #uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): print("transmitting Hello msg on Pin(GP4) in 2 16 byte packets at") print("60 bps, continuously preceded by an 'A' at 2 sec intervals") print("the 'A' is not seen by the receiver") #print("it erroneously skips the 'o' in 'Roy'. Doh!") #fixed in ver F print("it erroneously skips a full packet of ']' when needed") print("Hit ^C to stop!") print() while True : uart.write("A") utime.sleep(tPause) #read and create format RAPasc using the following function call #strRAPasc=RAPasc(readADC_pico(n1,cnvrt=5.035477e-05),1,"F") # readADC_pico() reads ADC[nn], by default cvrts to volts # and returns the reading in volts # but can read ADC[nn], cvrts using another factor # and returns the converted reading # but can read ADC[nn], do no conversion (cnvrt=1.000) # and return the unconverted reading # RAPasc(accepts the reading, followed by the time into the format # ADC1:(56.789+875678.000j) if 2nd parm is "F" # RAPasc(accepts the reading, followed by the time into the format # ADC1:(0xffff+875678.000j) if 2nd parm is "X" # ************************************************************* nn=0 #show("726 before readADC_pico, nn:",nn) strRAPasc=RAPasc(readADC_pico(nn,cnvrt=5.035477e-05),nn,"F") #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) nn=1 #show("734 before readADC_pico, nn:",nn) strRAPasc=RAPasc(readADC_pico(nn,cnvrt=1.0000),nn,"X") #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) nn=3 #temperature = 27 - (reading - 0.706)/0.001721 #print() #show("744 before readADC_pico, nn:",nn) strRAPasc=RAPasc(readADC_pico(nn,cnvrt=1.000),nn,"F") #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) nn=4 #temperature = 27 - (reading - 0.706)/0.001721 print() show("802 before readADC_pico, nn:",nn) strFromReadADC_pico=str(readADC_pico(nn,cnvrt=1.000)) print("804 strFromReadADC_pico"+strFromReadADC_pico) strRAPasc=RAPasc(strFromReadADC_pico,nn,"F") print("in 806 strRAPasc:"+strRAPasc) #finally the the ADC1:(reading+timej) string is ready # to be converted into serial packets serTx_pico(uart,bps, txtToBeSent=strRAPasc) utime.sleep(tPause) print() try: utime.sleep(tPause) #{for debugging} except: # this try/except code permits the tester to stop here using ^C print("interrupted by ^c") break finally: pass #end try #end while #end if True ########################################################################## # everything after here is old deprecated code # ########################################################################### # testpktixRx() if False: if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if False #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end False if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if False charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if False show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /test_TxH_pico.py # stored in Raspberry Pi Pico/ # stored in /home/pi/Desktop/Python_new/ix_pico_test/ ::::::::::textpak=>test_VSYS_pico.py.txt # test_VSYS_pico.py import machine import time print("Example output VBUS VSYS") VSYS_ADC_INPUT = 3 # 3 or 29 # Using ADC(3) - Pin 29 needs to be set as input with no pulls. # Using ADC(29) - Pin 29 is automatically set as required. if VSYS_ADC_INPUT == 3: Pin = machine.Pin Pin(29, Pin.IN) vsysChannel = machine.ADC(3) else: vsysChannel = machine.ADC(29) while True: adcReading = vsysChannel.read_u16() adcVoltage = (adcReading * 3.3) / 65535 vsysVoltage = adcVoltage * 3 vbusVoltage = vsysVoltage + 0.275 # At 100mA print(adcReading >> 4, adcReading, adcVoltage, "|", vbusVoltage, "|", vsysVoltage) time.sleep(1) # end while #Source:https://www.raspberrypi.org/forums/viewtopic.php?t=301152 # See near end by hippy # test_VSYS_pico.py ::::::::::textpak=>testButton_pico.py.txt # IX_libr_pico.py # This example works with Maker Pi Pico # buttonAction() # returns True when button Action is down i.e. pressed within 10 seconds # else returns False. #imports for buttonAction import machine import utime def buttonAction(gPnn,withinTime): if gPnn <0 or gPnn>25: print("Error in buttonAction: pin # is out of range") return #end if if withinTime <0 or withinTime>180: print("Error in buttonAction: withinTime is out of range") return #end if button = machine.Pin(gPnn, machine.Pin.IN) t0=utime.time() #print("t0:",t0) tDelta=0 isDown=False while tDeltatestLeds.py.txt from machine import Pin import time #by D@CC #on 2022EMay30 # need to modify it for RPi Pi (not pico) print("testLeds.py") print("by PiCole22 on 2021EMay20") print(" pronounced 'pickle 22'") print("testing the Maker Pi Pico board by Cytron") print("The small green 3V3 led should always be ON") led=Pin(25,Pin.OUT) led.value(1) print("turning green pico led ON") i=0 print("turning each GPxx blue led ON (1/sec)") while i<28: i=i+1 led1=Pin(i,Pin.OUT) led1.value(1) time.sleep(1) # 1sec #end while print("Please check if all leds are ON") i=0 print("turning each GPxx blue led OFF (1/sec)") while i<28: i=i+1 led1=Pin(i,Pin.OUT) led1.value(0) time.sleep(1) # 1sec #end while print("Please check if all leds are OFF") led=Pin(25,Pin.OUT) led.value(1) print("turning green pico led ON") time.sleep(1) # 1sec led=Pin(25,Pin.OUT) led.value(0) print("turning green pico led OFF") print("end of testLeds.py") #end testLeds.py ::::::::::textpak=>testLeds_pico.py.txt from machine import Pin import time print("testLeds_pico.py") print("by PiCole22 on 2021EMay20") print(" pronounced 'pickle 22'") print("testing the Maker Pi Pico board by Cytron") print("The small green 3V3 led should always be ON") led=Pin(25,Pin.OUT) led.value(1) print("turning green pico led ON") i=0 print("turning each GPxx blue led ON (1/sec)") while i<28: i=i+1 led1=Pin(i,Pin.OUT) led1.value(1) time.sleep(1) # 1sec #end while print("Please check if all leds are ON") i=0 print("turning each GPxx blue led OFF (1/sec)") while i<28: i=i+1 led1=Pin(i,Pin.OUT) led1.value(0) time.sleep(1) # 1sec #end while print("Please check if all leds are OFF") led=Pin(25,Pin.OUT) led.value(1) print("turning green pico led ON") time.sleep(1) # 1sec led=Pin(25,Pin.OUT) led.value(0) print("turning green pico led OFF") print("end of testLeds.py") #end testLeds.py ::::::::::textpak=>testPlot.py.txt def plot(vector): # by D@CC # on 2021EMay22 # vector is a list of values to be plotted # values between 0 and 255 inclusive # the number of values should be less than 64 samples = [1,2,3,4,5,6] vlen = len(samples) #actual length -1 vmin = min(samples) vmax = max(samples) ncols = 60 nrows = 10 colThickness = 1 + ncols//vlen (e.g. 10) rowThickness = 1 + nrows//(vmax-vmin) # 2 dim array is shown below matrix = [[0,1,2],[2,4,6]] for i = 0,1: print matrix[i,0], matrix[i,1],matrix[i,2] #end def plot progName="testPlot.py" print(progName) plot(a) #source: https://www.educba.com/list-operations-in-python/ #end program testPlot.py ::::::::::textpak=>testRxD_pico.py.txt import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun19 #Note: as of today, partially tested ########################################################################################## # 1. serRx_pico() receives a full serial text message # 2. show() shows (displays) an object or variable # 3. mpyread() reads a character (borrowed routine) # testRx receives all test messages (TimeOut=t1000c) progName="testRxD_pico.py" print("progName:"+progName) if True: bps=600 txPin=5 rxPin=4 rxtxEndChar="]" # #print sys info print(os.uname()) #os, utime and machine were imported at top #end if #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times t9999c=10000/bps # 100000 bit times t60=60 # 60 seconds t10=10 # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" #end if #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing def mpyRead(uart): print("in mpyRead") #keep read1 character packet until not any characters txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=timeOut #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) k=0 while time < timeFail : k=k+1 #keep reading any 1 character packets until timeOut print(k,"waiting for any characters to arrive") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() utime.sleep(.5) #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def print("receiving my routine") timeNow=utime.time() tOut=60 print("waiting", tOut,"seconds to receive data, time:",0) #msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) msgIn=serRx_pico(uart,bps=600,timeOut=tOut) #times out after t10 seconds (100 char-times) print("msgIn:",msgIn) time=utime.time()-timeNow print("time:",time) print("end of serRX()") #end /testRxD_pico.py ::::::::::textpak=>testTxE_pico.py.txt # testTxE_pico.py # stored in Raspberry Pi Pico/ # and in /home/pi/Desktop/Python_new/ix_pico_test/ import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun18 #Note: as of today, partially tested # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): # #Debugging notes: #"tx sent:" is what is actually sent def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# #print("txtToBeSent:"+txtToBeSent+":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz #print("end of serTx()") #print("Hit ^C to stop!") #print() return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() #show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet #show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM #print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #print() #print("oP:"+oP+":") cntUsed=0 #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom #print("sending M") #cntSent of the packet is already in oP #cntUsed is 0 going into the while # note that lenM also includes 1 eom # in the while loop, cntUsed will increase until cntUsed=lenM while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) #print("going into the M while") #show("upon entry M-while cntUsed:",cntUsed) # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data # lastChar is the lastChar of Msg to send in this packet cntCanAdd=pktSize-len(oP) #print("cntCanAdd:",cntCanAdd,":") #show("cntUsed:",cntUsed) #should be 0 entering first loop cntRemainOfM=lenM-cntUsed-1 #this cnts the remaining chars of M cntToAdd=pktSize-len(oP) #this cnts the remaining space in oP # a packet is always sent in this next "if clause" #show("cntRemainOfM:",cntRemainOfM) #show("cntToAdd:",cntToAdd) if cntRemainOfM>cntToAdd : # this packet cannot hold rest of Msg plus an eom isLastPack=False opToAdd=thisMsg[cntUsed:cntUsed+cntToAdd] # to add to oP opToSend=oP+opToAdd # to be sent #print("AopToSend:"+opToSend+":") cntPadding=0 sendThisPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt without any padding #cntUsed=cntUsed+cntToAdd+1 cntUsed=cntUsed+cntToAdd #{for debugging} del "+1" # remember to count the first EOM as a character in cntUsed show("cntUsed:",cntUsed) show("lenM:",lenM) oP="" cntSent=0 #continue the while loop else : isLastPack=True # the pkt can hold the whole cntRemainOfM opToAdd=thisMsg[cntUsed:cntUsed+cntRemainOfM] #print("BopToSend:"+opToSend+":") cntPadding=pktSize-cntSent-cntRemainOfM strPadding=eom*cntPadding opToSend=oP+opToAdd+strPadding #print("CopToSend:"+opToSend+":") sendLastPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt including the padding cntUsed=cntUsed+len(opToAdd) #show("lenM:",lenM) #show("cntUsed:",cntUsed) oP="" cntSent=0 #print("after Last Packet of Msg") toSend=lenM-cntUsed #show("toSend:",toSend) #print("end of while") break #out of the while #if end cntUnsent=lenM-cntUsed-1 #show("cntUnsent:",cntUnsent) #print("repeat the M while") #end while if False : # we need to send at least 1 more full packet isLastpack=False lastChar=cntUsed+(pktSize-len(oP)) #this is lastChar of Msg yet to send opToAdd=thisMsg[cntUsed:lastChar] # to add to oP opTosend=oP+opToAdd print("opToSend:"+opToSend+":") sendThisPack(uartObject, opToSend, eom, pktSize) # no padding was necessary cntUsed=cntUsed+len(opToAdd) show("cntUsed:",cntUsed) # the while will loop once more #end if if False : lastChar=pktSize-cntSent show("lastChar",lastChar) #thisMsg="12345678901234567" #print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntSent:lastChar]",thisMsg[cntUsed:lastChar]) opWasSent=thisMsg[cntUsed:lastChar] print("opWasSend:"+opWasSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if #end if False if False : # a packet has just been sent leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if False : if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) oP=opToSend toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if #end if False # a packet was just sent print("M while might end now") print("after end of while") #end if False #end if "M" if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char #print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) #print("tx sent:" # in sendThisPack print(oP, end='') #this actually sends the text to the Shell # because in this early version, what is shown # in the Shell is actually sent. print() #{for debugging} return pktSize #end def def sendLastPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendLastPack") oP=opIn #print("oP:"+oP+":") lenopIn=len(opIn) #show("lenopIn:",lenopIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if #search for eom in the non-padding portion of oPIn suboPIn=opIn[0:pktSize-cntPadding] #print("suboPIn:"+suboPIn+":") pos=suboPIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) # in sendLastPack(): #print("tx sent:"+ print(oP, end='') #keep user informed during testing print() #{for debugging} return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=timeOut #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut print("I should be flashing the green LED while receiving") # I don't know if it is still receiving # it should write the received msg to a file. #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def ########################################################################################## ########################################################################################## progName="testTxE_pico.py" print("progName:"+progName) if True: bps=60 tPause=4 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete #uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): print("transmitting Hello msg on Pin(GP4) in 2 16 byte packets at") print("60 bps, continuously preceded by an 'A' at 2 sec intervals") print("it erroneously skips the 'o' in 'Roy'. Doh!") print("Hit ^C to stop!") print() while True : try: uart.write("A") utime.sleep(tPause) serTx_pico(uart,bps, txtToBeSent="Hello,JoeMaxRoyBob") utime.sleep(tPause) except: print("interrupted by ^c") break #end try #end while if False: serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H]") serTx_pico(uart,bps, txtToBeSent="[H]") serTx_pico(uart,bps, txtToBeSent="2.97") serTx_pico(uart,bps, txtToBeSent="99.987654") serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") serTx_pico(uart,bps, txtToBeSent="1234567890123") serTx_pico(uart,bps, txtToBeSent="12345678901234") serTx_pico(uart,bps, txtToBeSent="Hello,World") serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") #end if if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /testTxE_pico.py # stored in Raspberry Pi Pico/ ::::::::::textpak=>testTxF_pico.py.txt # testTxF_pico.py # stored in Raspberry Pi Pico/ # and in /home/pi/Desktop/Python_new/ix_pico_test/ import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun20 #Note: as of today, no known errors ver F is first to work successfully # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): # #Debugging notes: #"tx sent:" is what is actually sent # Errors and Warnings are embedded in the text transmitted. def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# #print("txtToBeSent:"+txtToBeSent+":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz #print("end of serTx()") #print("Hit ^C to stop!") #print() return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() #show("thisMsg:",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet #show("msgFormat:",msgFormat) for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM #print("send SOM") oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #print() #print("oP:"+oP+":") cntUsed=0 #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom #print("sending M") #cntSent of the packet is already in oP #cntUsed is 0 going into the while # note that lenM also includes 1 eom # in the while loop, cntUsed will increase until cntUsed=lenM while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) #print("going into the M while") #show("upon entry M-while cntUsed:",cntUsed) # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data # lastChar is the lastChar of Msg to send in this packet cntCanAdd=pktSize-len(oP) #print("cntCanAdd:",cntCanAdd,":") #show("cntUsed:",cntUsed) #should be 0 entering first loop cntRemainOfM=lenM-cntUsed-1 #this cnts the remaining chars of M cntToAdd=pktSize-len(oP) #this cnts the remaining space in oP # a packet is always sent in this next "if clause" #show("cntRemainOfM:",cntRemainOfM) #show("cntToAdd:",cntToAdd) #if (cntRemainOfM)>cntToAdd : #{for debugging} if (cntRemainOfM+1)>cntToAdd : #{for debugging} ver F +1 # this packet cannot hold rest of Msg plus an eom isLastPack=False opToAdd=thisMsg[cntUsed:cntUsed+cntToAdd] # to add to oP opToSend=oP+opToAdd # to be sent #print("AopToSend:"+opToSend+":") cntPadding=0 sendThisPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt without any padding #cntUsed=cntUsed+cntToAdd+1 cntUsed=cntUsed+cntToAdd #{for debugging} ver F del "+1" # remember to count the first EOM as a character in cntUsed #show("cntUsed:",cntUsed) #show("lenM:",lenM) oP="" cntSent=0 #continue the while loop else : isLastPack=True # the pkt can hold the whole cntRemainOfM opToAdd=thisMsg[cntUsed:cntUsed+cntRemainOfM] #print("BopToSend:"+opToSend+":") cntPadding=pktSize-cntSent-cntRemainOfM strPadding=eom*cntPadding opToSend=oP+opToAdd+strPadding #print("CopToSend:"+opToSend+":") sendLastPack(uartObject, opToSend, cntPadding, eom, pktSize) # that sent a full pkt including the padding cntUsed=cntUsed+len(opToAdd) #show("lenM:",lenM) #show("cntUsed:",cntUsed) oP="" cntSent=0 #print("after Last Packet of Msg") toSend=lenM-cntUsed #show("toSend:",toSend) #print("end of while") break #out of the while #if end cntUnsent=lenM-cntUsed-1 #show("cntUnsent:",cntUnsent) #print("repeat the M while") #end while if False : # we need to send at least 1 more full packet isLastpack=False lastChar=cntUsed+(pktSize-len(oP)) #this is lastChar of Msg yet to send opToAdd=thisMsg[cntUsed:lastChar] # to add to oP opTosend=oP+opToAdd print("opToSend:"+opToSend+":") sendThisPack(uartObject, opToSend, eom, pktSize) # no padding was necessary cntUsed=cntUsed+len(opToAdd) show("cntUsed:",cntUsed) # the while will loop once more #end if if False : lastChar=pktSize-cntSent show("lastChar",lastChar) #thisMsg="12345678901234567" #print("thisMsg:"+thisMsg+":") show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntSent:lastChar]",thisMsg[cntUsed:lastChar]) opWasSent=thisMsg[cntUsed:lastChar] print("opWasSend:"+opWasSend+":") if len(opToSend)>=16 : print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,opToSend, eom, pktSize) #returns 16 should print the Pkt oP="" show("cntUsedFromMsg:",cntUsedFromMsg) cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 show("lenM",lenM) show("cntUsed",cntUsed) isLastPacket=False else: print("need to send padded Packet") isLastPacket=True #end if #end if False if False : # a packet has just been sent leftToSend=lenM-cntUsed-1 show("leftToSend:",leftToSend) if False : if isLastPacket==True : # will send the Last Packet (containing at least 1 EOM) print("isLastPack is True") #useStr=thisStr cntUsedFromMsg=len(opToSend) oP=opToSend toAdd=16-cntUsedFromMsg show("toAdd:",toAdd) for x in range(toAdd): # must insert correct range !!!!! oP=oP+txChar(eom) # must insert correct char from fullMsg !!!!! cntSent=cntSent+1 #end for print() print("before sendThisPack oP:"+oP+":") cntSent=sendThisPack(uartObject,oP, eom, pktSize) #returns 16 should print the Pkt oP="" cntUsed=cntUsed+cntUsedFromMsg show("cntUsed:",cntUsed) #end if #end if False # a packet was just sent print("M while might end now") print("after end of while") #end if False #end if "M" if False : if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent print("msgPart=P") if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if "P" #end if False #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char #print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendThisPack") oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E1 in serTx", eom, "found eom in message") #oP=oP.replace(eom,"?") oP=oP.replace(eom,"?",1) #{for debugging} ver F replace once #end if uartObject.write(oP) #print("tx sent:" # in sendThisPack print(oP, end='') #this actually sends the text to the Shell # because in this early version, what is shown # in the Shell is actually sent. #print() #{for debugging} return pktSize #end def def sendLastPack(uartObject, opIn, cntPadding, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP #print() #print("in sendLastPack") oP=opIn #print("oP:"+oP+":") lenopIn=len(opIn) #show("lenopIn:",lenopIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if #search for eom in the non-padding portion of oPIn suboPIn=opIn[0:pktSize-cntPadding] #print("suboPIn:"+suboPIn+":") pos=suboPIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E2 in serTx", eom, "found in message") oPleft=opIn[0:pos] #{for debugging} ver F fix #print("oPleft:"+oPleft+":") lenOp=len(opIn) #{for debugging} ver F fix oPright=opIn[pos+1:lenOp] #{for debugging} ver F fix #print("oPright:"+oPright+":") #oP=oP.replace(eom,"?") #oP=oP.replace(eom,"?",1) #{for debugging} replace once didn't work oP=oPleft+"?"+oPright #{for debugging} ver F fix #end if uartObject.write(oP) # in sendLastPack(): #print("tx sent:"+ print(oP, end='') #keep user informed during testing #print() #{for debugging} return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=timeOut #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut print("I should be flashing the green LED while receiving") # I don't know if it is still receiving # it should write the received msg to a file. #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def ########################################################################################## ########################################################################################## progName="testTxF_pico.py" print("progName:"+progName) if True: bps=60 tPause=4 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete #uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): print("transmitting Hello msg on Pin(GP4) in 2 16 byte packets at") print("60 bps, continuously preceded by an 'A' at 2 sec intervals") print("the 'A' is not seen by the receiver") #print("it erroneously skips the 'o' in 'Roy'. Doh!") #fixed in ver F print("it erroneously skips a full packet of ']' when needed") print("Hit ^C to stop!") print() while True : uart.write("A") utime.sleep(tPause) serTx_pico(uart,bps, txtToBeSent="Hello,JoeMaxRoyBob") utime.sleep(tPause) serTx_pico(uart,bps, txtToBeSent="H") #{for debugging} utime.sleep(tPause) #{for debugging} #serTx_pico(uart,bps, txtToBeSent="H]") #{for debugging} #utime.sleep(tPause) serTx_pico(uart,bps, txtToBeSent="2.97") utime.sleep(tPause) #{for debugging} serTx_pico(uart,bps, txtToBeSent="99.987654") utime.sleep(tPause) #{for debugging} serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") # recv'd ADC0:(0x4000,1622428309.0 b'' utime.sleep(tPause) serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") # recv'd 1234567890123456789012345 b'01234567890' try: utime.sleep(tPause) #{for debugging} except: print("interrupted by ^c") break finally: pass #end try #end while if False: serTx_pico(uart,bps, txtToBeSent="2.97") serTx_pico(uart,bps, txtToBeSent="99.987654") serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") serTx_pico(uart,bps, txtToBeSent="1234567890123") serTx_pico(uart,bps, txtToBeSent="12345678901234") serTx_pico(uart,bps, txtToBeSent="Hello,World") serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") #end if if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /testTxF_pico.py # stored in Raspberry Pi Pico/ ::::::::::textpak=>testTxRxB_pico.py.txt import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun18 #Note: as of today, fully untested # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx() transmits many test messages # testRx() receives all test messages def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize): #serTx_pico# #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ S + M + E + P + X""" where A is the letter "A" meaning "16 bit packets (pktSize)" S is SOM M is Message text to be sent (will be followed by EOM) E is EOM P is the padding characters (enough EOMs to fill the packet) X is t10c (ten character time delay: "roman numeral X") C is t100c (100 character time delay: "roman numeral C") Most messages will have msgOut = "AC" "SMEPX" Between messages, the transmitter will send "0" every minute indicating that its alive but has no message to send. Before sending each message the transmitter will send a single "A" which is 0x41 indicating that the following message will be in packets of 16 characters. In the future when the packet size. changes to 32 characters, the transmitter will precede each message with a single "B" indicating the each packet will contain 32 characters. This will allow future packet sizes at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without using any control characters in the "ascii" preamble. Future versions will have msgOut = "DSNKMEPX" with packets having the format: AX SNKMV MV MV etc MEPX The optional packet of 16 x D permits synchronization where D is a full packet of Delete characters (optional for synchronization N is the 2-character packet Number K is the 2-character message character "Kount" including the only the first final EOM V is t5c (5 character time delay: "roman numeral V") When a receiver starts up (and between messages) it should start by expecting packets of single characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an "A",the character will be discarded, but the receiver will presume that it is reading a character stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. After the last "]", the next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that this means subsequent packets will be packets of 16 characters. The receiver is now fully synchonized with the transmitter. If something other than an "A" is received, the receiver should begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message continues 10 times, a human operator should be informed the that this ERROR is occuring. #send the message def txParse(uartObject, fullMsg, bps=300, msgFormat="SMEPX", T5C=-1, packetSize=16, eom="]"): #txParse() # # uartObject is the uart being used # fullMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if # in 2021 msgOut="SMEPX" lenM=len(fullMsg)+1 #length of fullMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom isLastPack=True while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) isLastPack=False # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data w/o eom cntUsedFromMsg=sendThisPack(fullMsg,cntUsed,cntUsed+pktSize, cntSent ,cntUsed,pktSize) #returns 16 should print the Pkt cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 #end while # the above sent all packets except the last one if isLastPack==True # will send the Last Packet (containing at least 1 EOM) for x in range(): # must insert correct range !!!!! oP=oP+txChar(?) # must insert correct char from fullMsg !!!!! cntUsed=cntUsed+? cntSent=cntSent+1 #end for oP=oP+txChar(eom) # send the first eom #cntUsed should be = lenMsg +1 (for the eom) #end if #end if if msgPart=="P" # P means Padding (with more EOMs) if any needs to be sent if (True or False) # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if cntUsedFromMsg = sendLastPack(fullMsg, cntSent ,cntUsed, eom) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char print(char end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, oPIn, pktSize): #sendThisPack() # #actually sends the 16 characters in oP oP=opIn lenOpIn=len(oPIn) if (lenOpIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenOpIn) #end if pos=oPIn.find(eom) if pos=-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP.replace(eom,"?") #end if uartObject.write(oPIn) print("tx sent:"+oPIn+":") #keep user informed during testing return pktSize #end def def sendLastPack(uartObject, oPIn, eom = "]") #sendLastPack() #actually sends the character packet in oP # but pads the packet with "eom"s first # replace any eom with "?" lenOpIn=len(oPIn) oP=opIn pos=oP.find(eom) if pos=-1: # Good: eom not found pass else: print("ERROR E in serTx", eom, "found in message") oP.replace(eom,"?") #end if len=len(oP) #pad packet with eoms for k in range(16-lenOp): oPtoSend=oPtoSend+eom #end for lenOp=len(oP) # is the pktSize correct if (lenOp==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenOp) #end if #send the 16 character packet uartObject.write(oP) print("tx padded (if needed) and sent:"+oP+":") return lenOpIn # return # of chars used. #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject,bps=300, timeOut, eom="]"): if timeOut="": t100c= 1000/bps else: t100c=timeOut #end if timeOutUse=t100c timeNow=unix.time() timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut print("waiting",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer while time < timeFail : #keep reading any 1 character packets until timeOut if uartObject.any() : oP=oP+uartObject.read(1) #end if #end while print("ERROR T in serRx((): timeOut after",timeOutUse,"seconds") #end if #end while lenOp=len(oP) if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received. ) #end if #end if print("serRx() received:"+oP+":") #during testing return lenOp #end def serRx_pico(uart,300,timeOut(in secs)) ########################################################################################## progName="testTxB_pico.py" print("progName:"+progName) bps=300 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete uartObject.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): serTx_pico(uartObject,bps, txtToBeSent="") serTx_pico(uartObject,bps, txtToBeSent="H") serTx_pico(uartObject,bps, txtToBeSent="H]") serTx_pico(uartObject,bps, txtToBeSent="[H]") serTx_pico(uartObject,bps, txtToBeSent="2.97") serTx_pico(uartObject,bps, txtToBeSent="99.987654") serTx_pico(uartObject,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)"") serTx_pico(uartObject,bps, txtToBeSent="1234567890123") serTx_pico(uartObject,bps, txtToBeSent="12345678901234") serTx_pico(uartObject,bps, txtToBeSent="Hello,World") serTx_pico(uartObject,bps, txtToBeSent="1234567890123456789012345678901234567890") if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=300 t100c=1000/bps #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=5, rx=4)) print(serRx(uart,300,t1000c)) #times out after t1000c seconds (1000 char-times) print("end of serRX()") #/testTxRxB_pico.py ::::::::::textpak=>testTxRxC_pico.py.txt import os import utime from machine import UART, Pin #by D@CC #Date: 2021FJun18 #Note: as of today, partially tested # all functions and subroutines are at top of program # 1. bChar() converts 4 char byte into 1 char # 2. serTx_pico() transmits a full serial text message # 3. txParse() parses the outgoing text message and calls txChar # 4. txChar() adds the char to oP which is the output text packet queue # 5. sendThisPack actually transmits a full packet (wo any EOM) # 6. sendLastPack actually transmits text (with at least one EOM) # 7. serRx_pico() receives a full serial text message # testTx transmits many test messages # testRx receives all test messages #calling parms #bChar(strB): #serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txChar(char): #sendThisPack(uartObject, oPIn, eom, pktSize): #sendLastPack(oPIn, cntSent, cntUsed, eom = "]", pktSize=16): #serRx_pico(uartObject, bps=300, timeOut=-1, eom="]"): def bChar(strB): #bChar() # given a string like b'z' this returns the "z" # tested by D@CC on 2021FJun15 #strB=input("eg b'h' :") b=strB[2:] #print("b:"+b) c=b[0] #c="z" #print("bChar("+'"'+strB+ '"):'+c) return c #end def def serTx_pico(uartObject,bps=300, txtToBeSent="Hello,World",rxtxEndChar="]",pktSize=16): #serTx_pico# print("txtToBeSent:",txtToBeSent,":") #every parameter has a default setting except the uartObject (which needs to be defined). t5c=50/bps # 50 bit times = 5 character times t10c=100/bps # 100 bit times = 10 character times t1000c=10000/bps # 10000 bit times = 1000 character times # requires a uart object (below) to be created before this function is called #uart = machine.UART(1, 300, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) print("entering serTx_pico.py") if rxtxEndChar=="]": som = "[" eom = "]" msgOut = """ #S + #M + #E + #P + #C""" #where #A is the letter "A" meaning "16 bit packets (pktSize)" #S is SOM #M is Message text to be sent (will be followed by EOM) #E is EOM #P is the padding characters (enough EOMs to fill the packet) #X is t10c (ten character time delay: "roman numeral X") #C is t100c (100 character time delay: "roman numeral C") #Most messages will have msgOut = "AC" "SMEPX" #Between messages, the transmitter will send "0" every minute indicating that its alive but #has no message to send. #Before sending each message the transmitter will send a single "A" which is 0x41 indicating #that the following message will be in packets of 16 characters. In the future when the #packet size. #changes to 32 characters, the transmitter will precede each message with a single "B" #indicating the each packet will contain 32 characters. This will allow future packet sizes #at least as big as 16x16x4 = 1024 characters and total message lengths of around 32768 without #using any control characters in the "ascii" preamble. # Future versions will have msgOut = "DSNKMEPX" # with packets having the format: # AX SNKMV MV MV etc MEPX #The optional packet of 16 x D permits synchronization # #where #D is a full packet of Delete characters (optional for synchronization #N is the 2-character packet Number #K is the 2-character message character "Kount" including the only the first final EOM #V is t5c (5 character time delay: "roman numeral V") #When a receiver starts up (and between messages) it should start by expecting packets of single #characters. It will read a single 8-bit character expecting it to be a "0" meaning an idle transmitter. #If it is not a "0", it will read another single 8-bit character expecting it to be an "A". If it is not an #"A",the character will be discarded, but the receiver will presume that it is reading a character #stream that is mid-message. It will read single 8-bit characters searching for a "]" which will indicate #that this is the last packet of the message. It will keep reading and discarding all the "]" that it sees. #After the last "]", the #next 8-bit character should be a "0" or an "A". The receiver should keep reading and discarding the "0" #characters. When an "A" is finally received (while reading single 8-bit characters), the receiver knows that #this means subsequent packets will be packets of 16 characters. The receiver is now fully #synchonized with the transmitter. If something other than an "A" is received, the receiver should #begin looking for a "]" ()meaning "end of message" again. If the state of "being in mid-message #continues 10 times, a human operator should be informed the that this ERROR is occuring. # #send the message txParse(uart,txtToBeSent) #xyz return True #end def serTx_pico() def txParse(uartObject, thisMsg, bps=300, msgFormat="SMEPX", T5C=-1, pktSize=16, eom="]"): #txParse() show("thisMsg",thisMsg) # # uartObject is the uart being used # thisMsg is the full text message to be sent (It should not contain (EOM="]") they will become "?") # (An EOM is added as the last character of a message, do not put the EOM in the msg) # bps is the baud rate (bits/sec) # msgFormat is the form of the Msg e.g. SMEPX (first E is counted as last char of M) # (P is enough additional EOMs to pad to packetSize=16) # (t5c is interval between packets (-1 defaults to t5c) # t5c indicates time interval of 5 characters. The transmitter will follow each packet with # this time delay # packetSize defaults to 16 # eom is the definition of the 'EOM" character (usually "]") #oP is the full outgoing Packet that is sent by sendThisPack # or by sendLastPack oP="" # outgoing msg is initially empty if T5C==-1: # if the calling routine doesn't specify t5c=50/bps t10c=100/bps t1000c=10000/bps else: t5c=T5C #if the calling routine does specify T5C t10c=T5C*2 t1000c=T5C*200 #end if if eom=="]": som="[" #end if # in 2021 msgOut="SMEPX" lenM=len(thisMsg)+1 #length of thisMsg -1 (+1 for the EOM character cntUsed=0 # number of characters in msgOut used so far cntSent=0 # number of character actually sent (incl all chars sent) isEOMsent=False #EOM not sent yet for msgPart in msgFormat: # do each message segment if msgPart=="S": # send SOM oP=oP+txChar(som) oP=oP+txChar("1") # in future these 2 characters will contain parity or CRC oP=oP+txChar("6") # today they contain the packet size (ie character count) cntSent=cntSent+3 #3 actually sent now #end if if msgPart=="X": # time delay doesn't send any characters utime.sleep(t10c) #end if if msgPart=="M": # sends the msg followed by 1 eom isLastPack=True while (lenM-cntUsed) >= 1 : #lenM incl the EOM, cntUsed does also (after the EOM is sent) isLastPack=False # the packet being sent should not include any EOM characters. (EOM is only in the last pk) # send a packet of data w/o eom lastChar=cntUsed+pktSize show("lastChar",lastChar) thisMsg="12345678901234567" show("thisMsg",thisMsg) show("cntUsed",cntUsed) show("lastChar",lastChar) show("thisMsg[cntUsed:lastChar]",thisMsg[cntUsed:lastChar]) opSent=thisMsg[cntUsed:lastChar] show("opSent",opSent) cntUsedFromMsg=sendThisPack(uartObject,opSent, eom, pktSize) #returns 16 should print the Pkt cntUsed=cntUsed+cntUsedFromMsg # should be 16 ...... to verify cntSent=cntSent+16 #end while # the above sent all packets except the last one if isLastPack==True : # will send the Last Packet (containing at least 1 EOM) #useStr=thisStr for x in thisStr: # must insert correct range !!!!! oP=oP+txChar(x) # must insert correct char from fullMsg !!!!! cntUsed=cntUsed+1 # ?????? cntSent=cntSent+1 #end for oP=oP+txChar(eom) # send the first eom #cntUsed should be = lenMsg +1 (for the eom) #end if #end if if msgPart=="P": # P means Padding (with more EOMs) if any needs to be sent if False : if True: # to be decided oP=oP+txChar(eom) # how many eoms of padding !!!!! cntUsed=cntUsed+1 cntSent=cntSent+1 #end if show("cntUsed",cntUsed) strSent=thisMsg[cntUsed:cntUsed+16] show("strSent:",strSent) cntUsedFromMsg = sendLastPack(uartObject, strSent, eom, pktSize) # should print the Pkt cntUsed=cntUsed+cntUsedFromMsg cntSent=cntSent+pktSize #pktSize is usually 16 #end if #end if #end for # all msg parts have now been sent # should check that cntUsed = len(Msg) +1 # should check that cntSent is a muliple of pktSize(eg 16) return #from parsing and transmitting #end def def txChar(char): #txChar() #simply records that "char" has been sent # just prints it during testing # doesn't actually send the char print(char, end='') #"end" suppresses the line feed return char #end def def sendThisPack(uartObject, opIn, eom, pktSize): #sendThisPack() # #actually sends the 16 characters in oP oP=opIn lenopIn=len(opIn) if (lenopIn==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenopIn) #end if pos=opIn.find(eom) if pos==-1: # -1 if not found pass else: print("WARNING E in serTx", eom, "found in message") oP=oP.replace(eom,"?") #end if uartObject.write(oP) print("tx sent:"+oP+":") #keep user informed during testing return pktSize #end def def mpyRead(uart): #keep read1 character packet until timeOut txtRead="" bRead="" while uart.any(): aByte=str(uart.read(1)) #show("aByte:",aByte) bRead=bChar(aByte) #show("bRead:",bRead) txtRead=txtRead+bRead #end while return txtRead #end def def sendLastPack(uartObject, opIn, eom = "]", pktSize=16): #sendLastPack() #actually sends the character packet in oP # but pads the packet with "eom"s first # replace any eom with "?" lenopIn=len(opIn) oP=opIn pos=oP.find(eom) if pos==-1: # Good: eom not found pass else: print("ERROR E in serTx", eom, "found in message") oP.replace(eom,"?") #end if len=len(oP) #pad packet with eoms show("lenOp",lenOp) for k in range(16,lenOp): oPtoSend=oPtoSend+eom # add eoms for padding #end for lenOp=len(oP) # is the pktSize correct if (lenOp==pktSize)==False: print("ERROR",pktSize, "is not the size of the packet to send:",lenOp) #end if #send the 16 character packet uartObject.write(oPtoSend) print("tx padded (if needed) and sent:"+oP+":") return lenOpIn # return # of chars used. #end def # serRx_pico() receives a full serial text message #serRx_pico() def serRx_pico(uartObject, bps=600, timeOut=-1, eom="]"): #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) print("my uart:",uart) #print("timeOut is set to:",timeOut) if timeOut==-1: t100c = 1000/bps timeOutUse=int(t100c+1.0) #at least 1 sec #show("timeOutUse:",timeOutUse) else: timeOutUse=3 #in seconds #end if #timeOutUse=t100c time=utime.time() timeNow=time #show("timeNow:",timeNow) timeFail=timeNow+timeOutUse # defaults to a 3 second TimeOut #print("waiting my:",timeOutUse," seconds for data receipt. . . . .") oP="" # reset input buffer #show("time:",time) #show("timeFail:",timeFail) while time < timeFail : #keep reading any 1 character packets until timeOut #print("any") strA=mpyRead(uart) #show("strA:",strA) oP=oP+strA #show("oP:",oP) #end if time=utime.time() #end while #show("oP:",oP) lenOp=len(oP) if oP=="": print("ERROR T in serRx (): timeOut after",timeOutUse,"seconds") lenOp=len(oP) #end if if lenOp > 0: if oP.find("?")==-1: pass # ? not found else: print("WARNING '?' seen in message received.") #end if #end if #print("serRx() received:"+oP+":") #during testing return oP #end def serRx_pico(uart,300,timeOut(in secs)) def show(strA,parmA): # show print(strA,parmA) return #end def ########################################################################################## progName="testTxB_pico.py" print("progName:"+progName) if True: bps=600 txPin=5 rxPin=4 # #print sys info print(os.uname()) #os, utime and machine were imported at top #indicate program started visually (by blinking the green LED) led_onboard = machine.Pin(25, machine.Pin.OUT) led_onboard.value(0) # onboard LED OFF for 0.5 sec utime.sleep(0.5) led_onboard.value(1) # leaving it ON #create uart object sample code if False : #self.uart = UART(1, 115200, parity=None, stop=1, bits=8, rx=Pin(rxPin), tx=Pin(txPin)) pass #end if #create actual uart object uart = machine.UART(1,bps, parity=None, stop=1, bits=8, rx=Pin(5), tx=Pin(4)) #print uart info #uart = machine.UART(1) print(uart) # during testing # create uartObject #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=txPin, rx=rxPin) # send a single "A" which is 0x41 ("A"-0x40 * 16 is the packet length which is 16 # initialization is complete uart.write("A") #every group of messages is preceeded by a single "A" # prior to the "A", the transmitter should send a synchronizing sequence to permit # the (human) receiver to "guess" or "determine" the baud rate (the bps) # hopefully the operator of the transmitter and receiver is the same human. # the serRx_pico should be running in a separate thread. #def serTx_pico(uartObject,bps, txtToBeSent="[UUUUUUUU]",rxtxEndChar="]"): serTx_pico(uart,bps, txtToBeSent="Hello,Joe") if False: serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H") serTx_pico(uart,bps, txtToBeSent="H]") serTx_pico(uart,bps, txtToBeSent="[H]") serTx_pico(uart,bps, txtToBeSent="2.97") serTx_pico(uart,bps, txtToBeSent="99.987654") serTx_pico(uart,bps, txtToBeSent="ADC0:(0x4000,1622428309.000j)") serTx_pico(uart,bps, txtToBeSent="1234567890123") serTx_pico(uart,bps, txtToBeSent="12345678901234") serTx_pico(uart,bps, txtToBeSent="Hello,World") serTx_pico(uart,bps, txtToBeSent="1234567890123456789012345678901234567890") #end if if False: # the above is the current format of the rxtx protocol # The som,eom,t10c and are 1-character special codes # each must be converted into outgoing text or actions or both # all normal text does not need to be converted before transmission # # The txParse routine analyses the msgOut Format and separates it into # special codes (text and actions). Each special code is sent to the txChar() # routine to be processed. Each character of outgoing text is sent to the # txChar() routine to be processed. # # The serTx_pico() routine is used to # transmit a special code of text ("S" and "M") # cause a time delay (V is "t5c X is "t10c " and M is "t1000c") # transmit msg as 16-byte packets (msg should not contain "]" which is replaced by "?" ) # # early testing Format is "SMEPX" # # Note that the "P" also inserts at least 1 "]" character and # enough extra "]" characters (or none) to make a message with an exact multiple # of 16 characters. This is because there are always 16 characters sent per # packet. Each packet is followed by a time delay of t5c. # The last packet is always followed by a time delay of t10c. # These time delays permit the receiver to resync with the transmitter. # These time delays are never included in the character count of the # message # The serRx_pico() routine times out after an interval of 1000 character times: t1000c pass #end if # This should be run this as a separate thread # print whatever has been received bps=600 t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times #end if #uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(txPin), rx=Pin(rxPin)) bps=600 uart = machine.UART(1,bps, parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5)) print("uart:",uart) if False: uart.write("hello") t100c=1000/bps utime.sleep(t100c) #wait for an interval of 100 char times uart.write("Hello,World") utime.sleep(t100c) #wait for an interval of 100 char times utime.sleep(1) #1 sec #if end if False: print("receiving mpy routine") while uart.any(): print(uart.read(1)) #end while #end if charIn="" if False: print("receiving mpy routine") if uart.any() : #print("reading now") charIn=uart.read(1) #show("charIn:",charIn) #oP=oP+uartObject.read(1) #end if print("end of mpy routine") #end if show("charIn:",charIn) #end if print("receiving my routine") msgIn=serRx_pico(uart,bps=600) #times out after t100c seconds (100 char-times) print("msgIn:",msgIn) print("end of serRX()") #end /testTxRxC_pico.py ::::::::::textpak=>textpack_py.py.txt #!/usr/local/bin/python #by D@CC #on 7/2/2021 2021GJul02 import sys # load the system module marker = ':'*10 + 'textpak=>' # hopefully unique separator def pack( ): for name in sys.argv[1:]: # for all command-line arguments input = open(name, 'r') # open the next input file print marker + name # write a separator line print input.read( ), # and write the file's contents if __name__ == '__main__': pack( ) # pack files listed on cmdline #Web Source:https://www.oreilly.com/library/view/programming-python-second/0596000855/ch04s05.html #end def textpack_py.py #/textpack_py.py ::::::::::textpak=>tickLed.py.txt from machine import Pin,Timer #create class led and class tim led = Pin(25, Pin.OUT) tim = Timer() def tick(timer): global led led.toggle() tim.init(freq=2.5, mode=Timer.PERIODIC, callback=tick) #/tickLed.py tickLed_py.txt ::::::::::textpak=>tickLed_pi.py.txt from machine import Pin,Timer #worked fine on 2021FJun09 #create class led and class tim led = Pin(25, Pin.OUT) tim = Timer() def tick(timer): global led led.toggle() tim.init(freq=2.5, mode=Timer.PERIODIC, callback=tick) #/tickLed.py tickLed_pi.py ::::::::::textpak=>ws2812_pico.py.txt def ws2812(): #used in maker-pi-pico-rgb-led_pico()d #in-line code T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] #def end /ws2812.py.txt