def sendRPi(toSend): #function to transmit data to RPi uart1 = UART(0, 115200, bits=8, parity=None, stop=1) uart1.init(baudrate=115200, bits=8, parity=None, stop=1) toSend = str("{0:0=3d}".format(len(toSend) + 3) ) + toSend #adds in the beginning the length of the buffer while True: uart1.write(bytes(toSend, 'utf-8')) receivedMessage = '' timeOut = time.time() + 0.02 while time.time( ) < timeOut: #waits for 0.02 seconds for message back from RPi if (uart1.any()): receivedMessage = uart1.readall().decode('utf-8') if 'received' in receivedMessage: #if receives 'received' breaks earlier break if 'received' in receivedMessage: #if is received,sends a new buffer print('\n***received!***') break else: #sends the same buffer again print('\nsend again...')
class SDS011: def __init__(self, uart=1, rxpin='P11'): self.uart = uart self.rxpin = rxpin self._hasValues = False self._uart = UART(uart, pins=(None, rxpin)) @property def has_values(self): return self._hasValues def values(self): b = self._uart.readall() #Empty the uart buffer while True: while self._uart.read(1) != b'\xaa': # Wait for packet start pass if self._uart.read(1) != b'\xc0': # Should be C0 continue b = self._uart.read(7) # Data + checksum if self._uart.read(1) != b'\xab': # Tail continue s = struct.unpack('BBBBBBB', b) # Check the checksum sum = s[0] + s[1] + s[2] + s[3] + s[4] + s[5] if sum % 256 != s[6]: continue return struct.unpack('<HHBB', b) # (PM2.5x10, PM10x10, ID1, ID2)
class SEN0177(object): def __init__(self, PTX='P10', PRX='P11', PSLEEP=None): self._PTX = PTX self._PRX = PRX self._PSLEEP = PSLEEP self._uart1 = UART(1, baudrate=9600, timeout_chars=7, pins=(PTX, PRX)) if self._PSLEEP is not None: self._set_pin = Pin(PSLEEP, mode=Pin.OUT, pull=Pin.PULL_DOWN) self._pm1_0 = 0 self._pm2_5 = 0 self._pm10 = 0 self._sleep() def _sleep(self): if self._PSLEEP is not None: self._set_pin.value(0) def _awake(self): if self._PSLEEP is not None: self._set_pin.value(1) def _get_pm1_0(self): return self._pm1_0 def _get_pm2_5(self): return self._pm2_5 def _get_pm10(self): return self._pm10 def _read_PM(self): #Wait 3 seconds to make sure that the buffer is filled time.sleep_ms(3000) raw_packet = self._uart1.readall() # finding the start/end of the packet and extracting it idx_begin = raw_packet.find(b'B') idx_end = idx_begin + 31 packet = raw_packet[idx_begin:idx_end] print(raw_packet) print(len(raw_packet)) print(raw_packet[0]) print(raw_packet[1]) print(packet[3:4]) # pm concentrations self._pm1_0 = int.from_bytes(packet[4:6], 'high') self._pm2_5 = int.from_bytes(packet[6:8], 'high') self._pm10 = int.from_bytes(packet[8:10], 'high') # return the concentrations return (self._pm1_0, self._pm2_5, self._pm10)
def takePhotoAndSaveToFile(filename=None, retry=True): global uart SDCard.mountSDCard() uart = UART(2, baudrate=BAUD, pins=(TX,RX), timeout_chars=5) uart.readall() setsize(VC0706_160x120) reset() uart.readall() if(not getversion()): print("Camera not found") return(0) if takephoto(): if(filename == None): filename = ''.join(map(str,RTC().now()))+'.jpg'; f = open('/sd/'+filename, 'wb'); try: gc.collect() readbuffer(getbufferlength(), f) return filename except Exception as e: print(e) if(retry): try: time.sleep(2) f.close() gc.collect() return takePhotoAndSaveToFile(filename, False) except Exception as ee: print(ee) finally: f.close() uart.deinit() gc.collect()
def writeCommand(self, command): output = command + '\r\n' uart = UART(1, baudrate=9600, pins=(Pin.exp_board.G9, Pin.exp_board.G8)) uart.write(output) #wait max 3(s) for output from the sensor waitcounter = 0 while (waitcounter < 5 and not uart.any()): time.sleep(0.5) waitcounter += 1 response = uart.readall() uart.deinit() print(response) return (response)
def identify(self): found = [] for one in self.UARTs: if (len(one) != 2) or (not type(one[0]) is str) or (not type(one[1]) is str): continue ser = UART(len(self.uart), baudrate=9600, pins=one, timeout_chars=20) if self.debug: print("Try UART pins Tx %s, Rx %s" % one) for i in range(0,3): # try 3 times to read known pattern line = [] sleep(2) try: line = ser.readall() except: print("Read error") continue if (line == None) or (not len(line)): # try to wake up if not 'dust' in found: if self.debug: print("Try to wake up device") if not i: ser.write(b'BM\xe1\x00\x01\x01q') # try activate PMS elif i < 2: ser.write(b'\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x06\xAB') # second try activate SDS continue # if self.debug: print("Read: %s" % line) if line.count(b'BM') > 0: # start char 0x42,0x4D self.dust = 'PMSx003'; self.D_Tx = one[0]; self.D_Rx = one[1] found.append('dust') elif line.count(b'\xAA') and line.count(b'\xC0'): # start char 0xAA,0xC0 tail 0xAB self.dust = 'SDS011'; self.D_Tx = one[0]; self.D_Rx = one[1] found.append('dust') elif line.count(b'\r\n') or (line.count(b',') > 1): self.useGPS = 'UART'; self.G_Tx = one[0]; self.G_Rx = one[1] found.append('gps') else: continue if self.debug: print("UART: %s on Tx %s, Rx %s" % (found[-1], one[0],one[1])) break if i > 2: print("Unknown device found on Tx %s, Rx %s" % one) ser.readall(); ser.deinit(); del ser return found
class SDS011(object): def __init__(self,PTX='P10',PRX='P11'): self._PTX = PTX self._PRX = PRX self._uart1 = UART(1, baudrate=9600, timeout_chars=7, pins=(PTX,PRX)) self._pm2_5 = 0 self._pm10 = 0 self.error=0 def _sleep(self): if self._PSLEEP is not None: self._set_pin.value(0) def _awake(self): if self._PSLEEP is not None: self._set_pin.value(1) def _get_pm1_0(self): return self._pm1_0 def _get_pm2_5(self): return self._pm2_5 def _get_pm10(self): return self._pm10 def _isError(self): return self.error == 1 def _read_PM(self): #Wait 3 seconds to make sure that the buffer is filled time.sleep_ms(3000) buffer = self._uart1.readall() if buffer is None: self.error = 1 return (0,0) if (buffer[0] == 0xAA and buffer[1] == 0xC0 and buffer[9] == 0xAB): receiveSum = 0 for i in range(2,8): receiveSum += buffer[i] if (receiveSum & 0xFF) == buffer[8]: self.error=0 self._pm2_5= ((buffer[3]<<8) + buffer[2]) self._pm10= ((buffer[5]<<8) + buffer[4]) return (self._pm2_5, self._pm10) else: self.error = 1 return (0,0)
def UARTtransmission(): uart1 = UART(0, 115200, bits=8, parity=None, stop=1) uart1.init(baudrate=115200, bits=8, parity=None, stop=1) SLEEP = 0.03 data1 = '' fileName = '' send = '' while True: if (uart1.any()): pycom.rgbled(0xFF0000) # set LED to RED data = uart1.readall().decode( 'utf-8') # recieves data and decodes from utf-8 if data != data1 and str(data[:3]) == str("{0:0=3d}".format( len(data))): if data[3:13] == 'filename: ': #new fileName fileName = data[13:] fileWrite = open(fileName, 'w').close() #clear ever$ elif data[3:] == 'Finish': #finished message fileName = '' pycom.rgbled(0xFFFFFF) # set LED to WHITE else: # writes inside of the file data = data[3:] fileWrite = open(fileName, 'a') #opens to write insi$ fileWrite.write(data) #writes inside the data fileWrite.close() #close file data1 = data print(data1) uart1.write( bytes('received', 'utf-8' )) #sends back a message to notify that was recieved time.sleep(SLEEP) elif data == data1: uart1.write( bytes('received', 'utf-8' )) #sends back a message to notify that was recieved time.sleep(SLEEP) else: pycom.rgbled(0xFFFFFF) # set LED to WHITE time.sleep(SLEEP)
def serialLoop(): lopy = b'f00a' # nom de la lopy node = b'effe' # nom de la node (deuxième lopy ) cle_node = b'$\n\xc4\x00\xef\xfe' #initialisation com = UART(1, 9600) com.init(9600, bits=8, parity=None, stop=1, pins=("P3", "P4")) gw = Gateway(lopy) gw.addNewNode(node, cle_node) gw.startLoRa() global x while True: #Lopy f00a reception port UART, envoie en LORA if (com.any()): lecture = com.readall() print(lecture) if (type(lecture) is bytes): print(lecture.decode()) gw.sendMsg(lecture, node) #Lopy f00a reception LoRa, emission en UART gw.recvMsg() data = gw.popOldestMsg() try: if (data[1] != b''): #print("Connexion etablie : ") x += 1 #print(data[0]+'\t'+data[1]+'\n') com.write(str(data[0])) com.write('\t') com.write(str(data[1]) + '\n') time.sleep(0.020) except IndexError: #print((x)) pass
#f = open('/flash/test.py', '+a') #create file (append mode) #f.write("Buffer=\n") #f.write(bytes(buffer[1]) #f.close() #try: # temperature=int(sensor.temperature()) # print('temperature = ',temperature) #except NameError as msg: # print(msg) # si7021presence=False #if( temperature !=-255): # print('temperature reported = ',temperature) #print('si7021 presence = ',si7021presence) #The first 5 seconds of dust data always seems irregular, so let's delay and clear the buffer data = uart.readall() time.sleep(10) data = uart.readall() time.sleep(1) # then give it another second for the next good byte to come in. while (1): readytosend = False print('polling Dust Sensor') data = uart.readall() # get everythitng from the serial buffer if data is not None: #make sure it'st not an empty buffer bytestream = data.split(b'BM')[1][ 0:31] # HPMA sends 32 byte packets that start with \x42\x4D ('BM') if len( bytestream ) == 30: #check tthat we actually got 30 bytes (excluding the data we split out) if bytestream[ 0:
def getConf(self, atype, pins, pwr=None): #self.conf = { # PCB TTL defaults example # 'usb': {'name':'usb', 'pins':('P1','P0','P20'), 'use':False, 'baud':None}, # 'dust': {'name':'PMSx003','pins':('P11','P10','P9'), 'use':None, 'baud':9600}, # 'gps': {'name':'NEO-6', 'pins':('P4'.'P3','P19'), 'use':None, 'baud':9600}, # } pins = tuple(pins) try: if self.conf[atype]['pins'] == pins: if self.conf[atype]['name']: return self.conf[atype] except: pass data = [ (b'\x42\x4D\xE1\x00\x01\x01\x71',9600), # PMS (b'\x7E\x00\xD0\x01\x01\x2D\x7E',115200), # SPS info (b'\x7E\x00\x00\x02\x01\x03\xF9\x7E',115200), # SPS start (b'\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x06\xAB',9600), # SDS ] for baudrate in [9600, 115200]: if self.debug: print("Try uart (baud=%d) pins: " % baudrate, pins) if not (0 <= self.index < 3): raise ValueError("UART index %d fail" % nr) prev = self.Power(pins, on=True) if not prev: sleep_ms(500) ser = UART(self.index, baudrate=baudrate, pins=pins[:2], timeout_chars=20) fnd = None if self.debug: print("getIdent type %s" % atype) for i in range(0,2*len(data)): if data[i%len(data)][1] != baudrate: continue if not ser.any(): sleep_ms(5*500 if atype == 'dust' else 500) try: line = ser.readall() if self.debug: print("Read: ", line) except Exception as e: if self.debug: print("TTL dev search %s" % e) continue if (atype == 'dust') and ((line == None) or (not len(line))): # try to wake up activate = data[i % len(data)][0] if self.debug: print("%d: Try a wakeup, send: " % i, activate) ser.write(activate) sleep_ms(500) continue else: if not line: continue if line.count(b'u-blox'): fnd = 'NEO-6' elif line.count(b'$GPTXT') or line.count(b'$GNG') or line.count(b'$GPG'): fnd = 'GPS' elif line.count(b'\x42\x4D') or line.count(b'BM\x00\x1C'): fnd = 'PMSx003' elif line.count(b'\xAA') and line.count(b'\xC0'): fnd = 'SDS011' elif line.count(b'~\x00\xD0\x00'): fnd = 'SPS30' elif line.count(b'~\x00\x00') or line.count(b'\x00\xFF~'): fnd = 'SPS30' if fnd: break ser.readall(); ser.deinit(); del ser; self.Power(pins,on=prev) use = True; Dexplicit = None; calibrate = None if atype == 'dust': try: from Config import useDust as use except: pass Dexplicit = False try: from Config import Dexplicit except: pass if not 'calibrate' in self.conf.keys(): calibrate = None try: from Config import calibrate except: pass self.config['calibrate'] = calibrate elif atype.lower() == 'gps': try: from Config import useGPS as use except: pass if fnd: thisConf = { 'name': fnd, 'baud': baudrate, 'pins': pins, 'use': use } if Dexplicit != None: thisConf['explicit'] = Dexplicit if calibrate != None: thisConf['calibrate'] = calibrate self.conf[atype] = thisConf; self.conf['updated'] = True self.allocated.append(pins) return self.conf[atype] if (not pins[2]) and pwr: for dlf in 'P19','P20': # try dflts: P1? in V2.1 fnd = self.getConf(atype,(pins[0],pins[1],dlf),baudrate=baudrate) if fnd: return fnd return None
class PMS5003T(object): def __init__(self,PTX='P10',PRX='P11',PSLEEP=None): self._PTX = PTX self._PRX = PRX self._PSLEEP = PSLEEP self._uart1 = UART(1, baudrate=9600, timeout_chars=7, pins=(PTX,PRX)) if self._PSLEEP is not None: self._set_pin = Pin(PSLEEP, mode=Pin.OUT, pull=Pin.PULL_DOWN) self._pm1_0 = 0 self._pm2_5 = 0 self._pm10 = 0 self.error = False self._sleep() def _sleep(self): if self._PSLEEP is not None: self._set_pin.value(0) def _awake(self): if self._PSLEEP is not None: self._set_pin.value(1) def _get_pm1_0(self): return self._pm1_0 def _get_pm2_5(self): return self._pm2_5 def _get_pm10(self): return self._pm10 def _isError(self): return self.error def _read_PM(self): raw_packet = None while raw_packet is None: raw_packet = self._uart1.readall() # finding the start/end of the packet and extracting it idx_begin = raw_packet.find(b'B') idx_end = idx_begin + 32 packet = raw_packet[idx_begin+1:idx_end] if(packet[0] == 0x4d): receiveflag=0 receiveSum=0 for i in range(0,28): receiveSum = receiveSum + packet[i] receiveSum = receiveSum + 0x42 if (receiveSum == ((packet[29]<<8)+packet[30])): self.error = False else: self.error = True # pm concentrations self._pm1_0 = ((packet[3]<<8) + packet[4]) self._pm2_5 = ((packet[5]<<8) + packet[6]) self._pm10 = ((packet[7]<<8) + packet[8]) # return the concentrations return (self._pm1_0, self._pm2_5, self._pm10)
tx_power=14, bandwidth=LoRa.BW_250KHZ, sf=7, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=False, rx_iq=False) # create a raw LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) com = UART(1, 9600) com.init(9600, bits=8, parity=None, stop=1, pins=("P3", "P4")) while True: if (com.any() > 0): # send some data) print("Liaison UART detecté") lecture = com.readall() print(lecture) if (type(lecture) is bytes): s.setblocking(True) print(lecture.decode()) s.send(lecture) # get any data received... # s.setblocking(False) # data = s.recv(64) # print(data) # wait a random amount of time # time.sleep(machine.rng() & 0x0F)
buf = bytearray(3) print(uart1.readinto(buf, 1) == 1) print(buf) print(uart1.readinto(buf) == 2) print(buf) # try initializing without the id uart0 = UART(baudrate=1000000, pins=uart_pins[0][0]) uart0.write(b'1234567890') time.sleep_ms(2) # because of the fifo interrupt levels print(uart1.any() == 10) print(uart1.readline() == b'1234567890') print(uart1.any() == 0) uart0.write(b'1234567890') print(uart1.readall() == b'1234567890') # tx only mode uart0 = UART(0, 1000000, pins=('GP12', None)) print(uart0.write(b'123456') == 6) print(uart1.read() == b'123456') print(uart1.write(b'123') == 3) print(uart0.read() == None) # rx only mode uart0 = UART(0, 1000000, pins=(None, 'GP13')) print(uart0.write(b'123456') == 6) print(uart1.read() == None) print(uart1.write(b'123') == 3) print(uart0.read() == b'123')
class MotorBoardMD49: # ============================================================================ # ===( Constants )============================================================ # ============================================================================ # READ COMMANDS, GET_SPEED_1 = b'\x21' GET_SPEED_2 = b'\x22' GET_ENCODER_1 = b'\x23' GET_ENCODER_2 = b'\x24' GET_ENCODERS = b'\x25' GET_VOLTS = b'\x26' GET_CURRENT_1 = b'\x27' GET_CURRENT_2 = b'\x28' GET_VERSION = b'\x29' GET_ACCELERATION = b'\x2A' GET_MODE = b'\x2B' GET_VI = b'\x2C' GET_ERROR = b'\x2D' # WRITE COMMANDS, SET_SPEED_1 = b'\x31' SET_SPEED_2_TURN = b'\x32' SET_ACCELERATION = b'\x33' SET_MODE = b'\x34' RESET_ENCODERS = b'\x35' DISABLE_REGULATOR = b'\x36' ENABLE_REGULATOR = b'\x37' DISABLE_TIMEOUT = b'\x38' ENABLE_TIMEOUT = b'\x39' # ============================================================================ # ===( Constructor )========================================================== # ============================================================================ def __init__(self, uartBus, txPinNum, rxPinNum): txPinId = "P" + str(txPinNum) rxPinId = "P" + str(rxPinNum) self._uart = UART(uartBus, baudrate=38400, bits=8, parity=None, stop=1, pins=(txPinId, rxPinId, None, None)) self._mode = 0 # ============================================================================ # ===( Utils )================================================================ # ============================================================================ def _txCmd(self, cmdByte, valueByte=None): if cmdByte is not None and len(cmdByte) == 1 and \ ( valueByte is None or len(valueByte) == 1 ) : if valueByte is not None: buf = b'\x00' + cmdByte + valueByte else: buf = b'\x00' + cmdByte for i in range(100): res = self._uart.write(buf) if res is not None and res == len(buf): return True sleep_ms(10) return False # ---------------------------------------------------------------------------- def _rxRet(self, retSize): ret = b'' ok = False for i in range(100): buf = self._uart.readall() if buf is not None: ret += buf if len(ret) == retSize: ok = True break sleep_ms(10) return ret if ok else None # ---------------------------------------------------------------------------- def bitIsUpInByte(self, bitPos, byte): if bitPos >= 1 and bitPos <= 8: return (byte[0] & pack('B', 0 | 1 << 8 - bitPos)[0]) > 0 return byte # ============================================================================ # ===( Functions )============================================================ # ============================================================================ def GetSpeed1(self): if self._txCmd(MotorBoardMD49.GET_SPEED_1): ret = self._rxRet(1) if ret is not None: fmt = 'B' if self._mode == 0 or self._mode == 2 else 'b' return unpack(fmt, ret)[0] return None # ---------------------------------------------------------------------------- def GetSpeed2(self): if self._txCmd(MotorBoardMD49.GET_SPEED_2): ret = self._rxRet(1) if ret is not None: fmt = 'B' if self._mode == 0 or self._mode == 2 else 'b' return unpack(fmt, ret)[0] return None # ---------------------------------------------------------------------------- def GetEncoder1(self): if self._txCmd(MotorBoardMD49.GET_ENCODER_1): ret = self._rxRet(4) if ret is not None: return unpack('>i', ret)[0] return None # ---------------------------------------------------------------------------- def GetEncoder2(self): if self._txCmd(MotorBoardMD49.GET_ENCODER_2): ret = self._rxRet(4) if ret is not None: return unpack('>i', ret)[0] return None # ---------------------------------------------------------------------------- def GetEncoders(self): if self._txCmd(MotorBoardMD49.GET_ENCODERS): ret = self._rxRet(8) if ret is not None: return unpack('>ii', ret) return None # ---------------------------------------------------------------------------- def GetVolts(self): if self._txCmd(MotorBoardMD49.GET_VOLTS): ret = self._rxRet(1) if ret is not None: return unpack('B', ret)[0] return None # ---------------------------------------------------------------------------- def GetCurrent1(self): if self._txCmd(MotorBoardMD49.GET_CURRENT_1): ret = self._rxRet(1) if ret is not None: return unpack('B', ret)[0] / 10 return None # ---------------------------------------------------------------------------- def GetCurrent2(self): if self._txCmd(MotorBoardMD49.GET_CURRENT_2): ret = self._rxRet(1) if ret is not None: return unpack('B', ret)[0] return None # ---------------------------------------------------------------------------- def GetVersion(self): if self._txCmd(MotorBoardMD49.GET_VERSION): ret = self._rxRet(1) if ret is not None: return unpack('B', ret)[0] return None # ---------------------------------------------------------------------------- def GetAcceleration(self): if self._txCmd(MotorBoardMD49.GET_ACCELERATION): ret = self._rxRet(1) if ret is not None: return unpack('B', ret)[0] return None # ---------------------------------------------------------------------------- def GetMode(self): if self._txCmd(MotorBoardMD49.GET_MODE): ret = self._rxRet(1) if ret is not None: return unpack('B', ret)[0] return None # ---------------------------------------------------------------------------- def GetVI(self): if self._txCmd(MotorBoardMD49.GET_VI): ret = self._rxRet(3) if ret is not None: return unpack('BBB', ret) return None # ---------------------------------------------------------------------------- def GetError(self): if self._txCmd(MotorBoardMD49.GET_ERROR): ret = self._rxRet(1) if ret is not None: return { "MOTOR_1_TRIP": self.bitIsUpInByte(6, ret), "MOTOR_2_TRIP": self.bitIsUpInByte(5, ret), "MOTOR_1_SHORT": self.bitIsUpInByte(4, ret), "MOTOR_2_SHORT": self.bitIsUpInByte(3, ret), "OVER_30V": self.bitIsUpInByte(2, ret), "UNDER_16V": self.bitIsUpInByte(1, ret) } return None # ---------------------------------------------------------------------------- def SetSpeed1(self, value): if self._mode == 0 or self._mode == 2: fmt = 'B' if value < 0 or value > 255: return False else: fmt = 'b' if value < -128 or value > 127: return False return self._txCmd(MotorBoardMD49.SET_SPEED_1, pack(fmt, value)) # ---------------------------------------------------------------------------- def SetSpeed2Turn(self, value): if self._mode == 0 or self._mode == 2: fmt = 'B' if value < 0 or value > 255: return False else: fmt = 'b' if value < -128 or value > 127: return False return self._txCmd(MotorBoardMD49.SET_SPEED_2_TURN, pack(fmt, value)) # ---------------------------------------------------------------------------- def SetAcceleration(self, value): if value >= 1 and value <= 10: return self._txCmd(MotorBoardMD49.SET_ACCELERATION, pack('B', value)) return False # ---------------------------------------------------------------------------- def SetMode(self, mode): if mode >= 0 and mode <= 3: if self._txCmd(MotorBoardMD49.SET_MODE, pack('B', mode)): self._mode = mode return True return False # ---------------------------------------------------------------------------- def ResetEncoders(self): return self._txCmd(MotorBoardMD49.RESET_ENCODERS) # ---------------------------------------------------------------------------- def DisableRegulator(self): return self._txCmd(MotorBoardMD49.DISABLE_REGULATOR) # ---------------------------------------------------------------------------- def EnableRegulator(self): return self._txCmd(MotorBoardMD49.ENABLE_REGULATOR) # ---------------------------------------------------------------------------- def DisableTimeout(self): return self._txCmd(MotorBoardMD49.DISABLE_TIMEOUT) # ---------------------------------------------------------------------------- def EnableTimeout(self): return self._txCmd(MotorBoardMD49.ENABLE_TIMEOUT)
# VARIABLE initialization stat = None # Update times updateWeather = utime.ticks_ms() updateGPS = utime.ticks_ms() while True: try: pycom.rgbled(0x000500) # hearbeat # Updating GPS position if (utime.ticks_ms() - updateGPS >= UPDATE_GPS): updateGPS = utime.ticks_ms() stat = my_gps.updateall(uart.readall()) # Reporting GPS Status if (stat != None): my_display.drawCircle(149, 117, 5, my_display.COLOR_GREEN) else: # update status my_display.drawCircle(149, 117, 5, my_display.COLOR_RED) # Updating weather condition if (utime.ticks_ms() - updateWeather >= UPDATE_WEATHER): updateWeather = utime.ticks_ms() initDisplay() updatingWeather(stat, my_gps, my_display) # hearbeat
class Euglena_ameba_port(Euglena_port): def __init__(self): super(Euglena_ameba_port, self).__init__(0) self.uart = UART(1, pins=(self.S2.id(), self.S1.id()), baudrate=115200) ##receive machine self.buffer = [] self.bufferIndex = 0 self.isParseStart = False self.exiting = False self.isParseStartIndex = 0 self.parseResult = None def float2bytes(self, fval): return struct.pack("f", fval) def short2bytes(self, sval): return struct.pack("h", sval) def clean_buffer(self): self.buffer = [] self.bufferIndex = 0 self.isParseStart = False self.exiting = False self.isParseStartIndex = 0 self.parseResult = None def onParse(self, byte): position = 0 value = None self.buffer += [byte] bufferLength = len(self.buffer) if bufferLength >= 2: ##frame head: 0x55 0xff if (self.buffer[bufferLength - 1] == 0x55 and self.buffer[bufferLength - 2] == 0xff): self.isParseStart = True self.isParseStartIndex = bufferLength - 2 ##frame tail: 0x0d 0x0a if (self.buffer[bufferLength - 1] == 0xa and self.buffer[bufferLength - 2] == 0xd and self.isParseStart == True): self.isParseStart = False position = self.isParseStartIndex + 2 extID = self.buffer[position] position += 1 data_type = self.buffer[position] position += 1 # 1 byte 2 float 3 short 4 len+string 5 double if data_type == 1: value = self.buffer[position] if data_type == 2: value = self.readFloat(position) if (value < -255 or value > 1023): value = 0 if data_type == 3: value = self.readShort(position) if data_type == 4: data_value = self.readString(position) if data_type == 5: value = self.readDouble(position) if (data_type <= 5): ##self.responseValue(extID,value) self.buffer = [] self.parseResult = value def readFloat(self, position): v = [ self.buffer[position], self.buffer[position + 1], self.buffer[position + 2], self.buffer[position + 3] ] return struct.unpack('<f', struct.pack('4B', *v))[0] def readShort(self, position): v = [self.buffer[position], self.buffer[position + 1]] return struct.unpack('<h', struct.pack('2B', *v))[0] def readString(self, position): l = self.buffer[position] position += 1 s = "" for i in Range(l): s += self.buffer[position + i].charAt(0) return s def getUartResponseValue(self, time_out=1200): for i in range(0, time_out, 20): try: for o_byte in self.uart.readall(): self.onParse(o_byte) if self.parseResult != None: break except Exception: pass time.sleep_ms(20) v = self.parseResult self.clean_buffer() return v def readDouble(self, position): v = [ self.buffer[position], self.buffer[position + 1], self.buffer[position + 2], self.buffer[position + 3] ] return struct.unpack('<f', struct.pack('4B', *v))[0] def responseValue(self, extID, value): self.__selectors["callback_" + str(extID)](value) def __writePackage(self, pack): self.uart.write(pack) def doRGBLed(self, index, port, slot, red, green, blue): self.__writePackage( bytearray([ 0xff, 0x55, 0x9, 0x0, 0x2, 0x8, port, slot, index, red, green, blue ])) def doRGBLedOnBoard(self, index, red, green, blue): self.doRGBLed(index, 0x7, 0x2, red, green, blue) def doBuzzer(self, buzzer, time=0): self.__writePackage( bytearray([0xff, 0x55, 0x7, 0x0, 0x2, 0x22]) + self.short2bytes(buzzer) + self.short2bytes(time)) def doMotor(self, port, speed): self.__writePackage( bytearray([0xff, 0x55, 0x6, 0x0, 0x2, 0xa, port]) + self.short2bytes(speed)) def doMove(self, leftSpeed, rightSpeed): self.__writePackage( bytearray([0xff, 0x55, 0x7, 0x0, 0x2, 0x5]) + self.short2bytes(-leftSpeed) + self.short2bytes(rightSpeed)) def requestLineFollower(self, extID, port): self.uart.read() ##clean the uart rx buff self.__writePackage( bytearray([0xff, 0x55, 0x4, extID, 0x1, 0x11, port])) return self.getUartResponseValue() def requestBlueUltrasonicSensor(self, exitID, port): self.uart.read() self.__writePackage( bytearray([0xff, 0x55, 0x4, exitID, 0x1, 0x62, port])) return s self.uart.read() self.__writePackage( bytearray([0xff, 0x55, 0x4, exitID, 0x1, 0x1, port])) return self.getUartResponseValue() def requestJoyStick(self, exitID, port, slot): self.uart.read() self.__writePackage( bytearray([0xff, 0x55, 0x4, exitID, 0x1, 0x5, port, slot])) return self.getUartResponseValue()
class Euglena_vguang_port(Euglena_port): def __init__(self): super(Euglena_ameba_port, self).__init__(0) self.uart = UART(1, pins=(self.S1.id(), self.S2.id()), baudrate=115200) from euglena_board import BQ_24195 self.bq = BQ_24195() self.mqtt = None self.mqtt_username = None #self.bq.enable_otg(0) self.err_count = 0 self.err = None return def pp(self): pass def init_mqtt(self): import euglena_board board = euglena_board.Euglena_board() mqtt_account = board.get_mqtt_account() self.mqtt = mqtt.MQTT('esp32-' + ubinascii.hexlify(os.urandom(4)).decode()) self.mqtt.username_pw_set(mqtt_account['username'], mqtt_account['password']) self.mqtt_username = mqtt_account['username'] self.mqtt.on_message(self.pp) self.mqtt.connect_async(board.get_mqtt_host(), port=8882) self.mqtt.init() def mqtt_publish_single(self, arg): if self.mqtt == None: self.init_mqtt() try: out_s = self.uart.readall() if out_s != None and len(out_s) > 0: self.mqtt.publish( "redis/set/shop-data/%s" % self.mqtt_username, json.dumps({ "expire": 60, "data": out_s, "type": "barcode" })) except Exception as ex: self.mqtt = None ##reInint mqtt late self.err_count += 1 self.err = str(ex) if self.err_count > 10: import machine machine.reset() return def mqtt_publish_status(self, arg): if self.mqtt == None: self.init_mqtt() try: self.mqtt.publish( "redis/set/machine-status/%s" % self.mqtt_username, json.dumps({ "timestamp": int(time.time()), "lan_ip": get_lan_ip(), "expire": 20 })) except Exception as ex: self.err = str(ex) self.err_count += 1 def read_single(self): self.bq.enable_otg(0) out_s = self.uart.readall() return out_s def __short2bytes(self, sval): return struct.pack("h", sval) def get_command_pack(self, cmd, value, cmd_len=2): pack = bytearray([0x55, 0xaa, cmd ]) + self.__short2bytes(cmd_len) + bytearray([value]) check = pack[0] for c in pack[1:]: check = c ^ check pack = pack + struct.pack('b', check) return pack def init_auto_publish(self, s, ms): from machine import Timer Timer.Alarm(handler=self.mqtt_publish_single, s=s, ms=ms, us=0, periodic=1) Timer.Alarm(handler=self.mqtt_publish_status, s=15, ms=0, us=0, periodic=1)
class PMS5003: def __init__(self, en, tx, rx, rst): self.en = en self.tx = tx self.rx = rx self.rst = rst self.en.mode(Pin.OUT) self.rst.mode(Pin.OUT) self.uart = UART(1, baudrate=9600, pins=(self.tx, self.rx)) self.uart.deinit() def wake_up(self): self.en(True) self.rst(True) self.uart.init(pins=(self.tx, self.rx)) # sleep for 7 seconds to initialize the sensor properly utime.sleep_ms(7000) def idle(self): self.en(False) self.uart.deinit() def read_frames(self, count): frames = [] # flush the buffer to read fresh data self.uart.readall() while len(frames) < count: self.__wait_for_data(32) while self.uart.read(1) != b'\x42': machine.idle() if self.uart.read(1) == b'\x4D': self.__wait_for_data(30) try: data = PMSData.from_bytes(b'\x42\x4D' + self.uart.read(30)) print('cPM25: {}, cPM10: {}, PM25: {}, PM10: {}' \ .format(data.cpm25, data.cpm10, data.pm25, data.pm10)) frames.append(data) except ValueError as e: print('error reading frame: {}'.format(e.message)) pass return frames def __wait_for_data(self, byte_count): def idle_timer(alarm): pycom.rgbled(0x550000) alarm = None u = self.uart.any() if u < byte_count: alarm = machine.Timer.Alarm(idle_timer, 3) # print('waiting for data {}'.format(str(u))) while u < byte_count: u = self.uart.any() # 32*8*1000/9600 (32 bytes @9600kbps) # but let's assume byte is 10 bits to skip complex math machine.Timer.sleep_us(byte_count) try: alarm.cancel() except AttributeError: pass pycom.rgbled(0x000000)
for baudrate in ttl['baud'] + ttl['baud']: if serial: if serial.any(): serial.readall() serial.deinit() del serial serial = None sleep(1) if fnd: break if verbose: print("Open serial %d on %s, baudrate %d" % (i, str(ttl['pins'][:2]), baudrate)) serial = UART(i, baudrate=baudrate, pins=ttl['pins'][:2], timeout_chars=20) if serial.any(): serial.readall() if fnd: break for activate in activations: if activate[0]: if activate[2] != baudrate: continue if activate[1] in names: continue if activate[3] in found: continue if verbose: print("Try at baudrate %d, activate %s(%s)" % (activate[2], activate[3], activate[1])) serial.write(activate[0]) elif baudrate == 115200: continue if verbose: print("Wait", end='') for j in range(5): sleep(1)
pycom.heartbeat(False) # Initialise LoRa in LORAWAN mode. # Please pick the region that matches where you are using the device: # Asia = LoRa.AS923 # Australia = LoRa.AU915 # Europe = LoRa.EU868 # United States = LoRa.US915 pycom.rgbled(0xA00000) lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) uart = UART(1, baudrate=9600, bits=8, pins=('P20', 'P21'), timeout_chars=50) # create an OTAA authentication parameters app_eui = ubinascii.unhexlify('70B3D57ED00114D6') app_key = ubinascii.unhexlify('ED9425C459DD25020CA5A24AEE1539FC') uart2.write('C,0\r') uart2.readall() uart2.write('*OK,0\r') uart2.readall() ow = OneWire(Pin('P12')) temp_sens = DS18X20(ow) temp_raw = temp_sens.read_temp_async() time.sleep(1) temp_sens.start_conversion() # join a network using OTAA (Over the Air Activation) lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) print('try to join... (9600)') pycom.rgbled(0x0000A0) # wait until the module has joined the network while not lora.has_joined(): time.sleep(2.5)
class SDS011: ACTIVE = const(0) # default mode on power ON PASSIVE = const(1) # fan ON, values on request, not supported yet NORMAL = const(3) # state normal fan is ON STANDBY = const(4) # state standby fan is OFF # idle time minimal time to switch fan OFF IDLE = const(120000) # minimal idle time between sample time and interval def __init__(self, port=1, debug=False, sample=10, interval=1200, raw=False, calibrate=None, pins=('P3', 'P4')): self.ser = UART(1, baudrate=9600, pins=pins) self.firmware = None self.debug = debug self.interval = interval * 1000 # if interval == 0 no auto fan switching self.sample = sample * 1000 self.mode = self.STANDBY self.raw = raw self.deviceID = None # list of name, units, index in measurments, calibration factoring # pm1=[20,1] adds a calibration offset of 20 to measurement self.PM_fields = [ # the Plantower conversion algorithm is unclear! ['pm25', 'ug/m3', 0, [0, 1]], ['pm10', 'ug/m3', 1, [0, 1]], ] if type(calibrate) is dict: for key in calibrate.keys(): if calibrate[key] and type(calibrate[key]) != list: continue for pm in range(0, len(self.PM_fields)): if self.PM_fields[pm][0] == key: self.PM_fields[pm][3] = calibrate[key] break # decomment if not micropython try: self.ser.any except: self.ser.readall = self.ser.flushInput # reset_input_buffer self.ser.any = self.ser.inWaiting # calibrate by length calibration factor (Taylor) array def calibrate(self, cal, value): if self.raw: return value if (not cal) or (type(cal) != list): return round(value, 2) if type(value) is int: value = float(value) if not type(value) is float: return None rts = 0 pow = 0 for a in cal: rts += a * (value**pow) pow += 1 return rts def readSDSvalues(self): ''' read PM values ''' while True: n = self.ser.any() if n == 0: continue if n > 10: self.ser.read(n) continue rcv = self.ser.read(10) if len(rcv) != 10: continue if rcv[0] != 170 and rcv[1] != 192: # print("try to sychronize") continue i = 0 chksm = 0 while i < 10: if i >= 2 and i <= 7: chksm = (chksm + rcv[i]) & 255 i = i + 1 if chksm != rcv[8]: print("*** Checksum-Error") return -1, -1 pm25 = (rcv[3] * 256 + rcv[2]) pm10 = (rcv[5] * 256 + rcv[4]) if not self.deviceID: self.deviceID = '%X%X' % (rcv[6], rcv[7]) return pm25 / 10.0, pm10 / 10.0 # SDS anhalten bzw starten def startstopSDS(self, was): """ den SDS011 anhalten bzw. starten: was = NORMAL --> fan start, wait 15 secs was = ACTIVE --> fan was started, power on was = STANDBY --> fan stop """ if was == ACTIVE or was == NORMAL: start_SDS_cmd = bytearray( b'\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x06\xAB' ) self.ser.write(start_SDS_cmd) if self.debug: print("SDS fan/laser start.") elif was == STANDBY: stop_SDS_cmd = bytearray( b'\xAA\xB4\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x05\xAB' ) self.ser.write(stop_SDS_cmd) if self.debug: print("SDS fan/laser off") else: raise OSError("mode not supported") self.mode = was # passive mode, go into standby state / sleep: fan OFF def Standby(self): if self.mode != self.STANDBY: # if self.mode == self.ACTIVE: self.GoPassive() return self.startstopSDS(self.STANDBY) return True # passive mode, go into normal state: fan ON, allow data telegrams reading def Normal(self): if self.mode != self.NORMAL: #if self.mode == self.ACTIVE: self.GoPassive() if self.mode != self.NORMAL: return self.startstopSDS(self.NORMAL) return True # from passive mode go in active mode (same as with power on) def GoActive(self): if self.mode == self.STANDBY: self.Normal() if self.debug: print("wait 30 secs") sleep_ms(30000) self.startstopSDS(self.ACTIVE) return True # from active mode go into passive mode (passive normal state ?) #def GoPassive(self): # self.mode = self.PASSIVE # state NORMAL? # if self.mode == self.ACTIVE: # return self.startstopSDS(self.PASSIVE) # return True # in passive mode do one data telegram reading def PassiveRead(self): if self.mode == self.ACTIVE: return if self.mode == self.STANDBY: self.Normal() sleep_ms(30000) # wait 30 seconds to establish air flow return self.startstopSDS(self.ACTIVE) # original read routine comes from [email protected] http://http://irmus.tistory.com/ def getData(self): ''' read data telegrams from the serial interface (32 bytes) before actual read flush all pending data first during the period sample time: active (200-800 ms), passive read cmd 1 sec calculate average during sample seconds if passive mode fan off: switch fan ON and wait 30 secs. ''' ErrorCnt = 0 cnt = 0 PM_sample = {} # clear the input buffer first so we get latest reading # to do: allow sampling data to be done by sensor module StrtTime = ticks_ms() LastTime = ticks_ms() buff = [] if self.mode == self.STANDBY: self.GoActive() self.ser.readall() while True: # self.ser.readall() if self.mode != self.ACTIVE or self.mode != self.NORMAL: # in PASSIVE mode we wait one second per read if cnt: wait = ticks_ms() - LastTime if (wait < 1000) and wait: sleep_ms(wait) self.PassiveRead( ) # passive?:if fan off switch it on, initiate read data = self.readSDSvalues() #print("just a test") #print(data) #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if not cnt: StrtTime = ticks_ms() # one measurement 200-800ms or every second in sample time if cnt and (LastTime + 1000 > ticks_ms()): continue # skip measurement if time < 1 sec LastTime = ticks_ms() ErrorCnt = 0 sample = {} for fld in self.PM_fields: # concentrations in unit ug/m3 # concentration (generic atmosphere conditions) in ug/m3 # number of particles with diameter N in 0.1 liter air pcs/0.1dm3 sample[fld[0]] = float(data[fld[2]]) # make it float if self.debug: if not cnt: for fld in self.PM_fields: print("%8.8s " % fld[0], end='') print() for fld in self.PM_fields: print("%8.8s " % ('ug/m3' if fld[0][-4:] != '_cnt' else 'pcs/0.1dm3'), end='') print() for fld in self.PM_fields: print("%8.8s " % str(sample[fld[0]]), end='') print() cnt += 1 for fld in self.PM_fields: PM_sample[fld[0]] = PM_sample.setdefault(fld[0], 0.0) + sample[fld[0]] if ticks_ms() > StrtTime + self.sample: break SampleTime = ticks_ms() - StrtTime if SampleTime < 0: SampleTime = 0 if cnt: # average count during the sample time for fld in self.PM_fields: PM_sample[fld[0]] /= cnt PM_sample[fld[0]] = round( self.calibrate(fld[3], PM_sample[fld[0]]), 2) # turn fan off? if self.interval - SampleTime > 60 * 1000: self.Standby() # switch fan OFF return PM_sample
class DS2480b(object): """one wire master DS2480b Abfrage getestet mit Firmware LoPy4-1.18.0""" #lokale Konstanten #declare konstanten DS2480b __ACK = 0xCD __RESET = 0xC1 __PULLUP = 0x3B __DATAMODE = 0xE1 __COMMANDMODE = 0xE3 __PULLUPARM = 0xEF __PULLUPDISARM = 0xED __PULSETERMINATE = 0xF1 __PULLUPDISARM = 0xED __SEARCHROM = 0xF0 __ACCELERATORON = 0xB1 __ACCELERATOROFF = 0xA1 #declare konstanten DS1820 __CONVERTT = 0x44 __READ = 0xBE __SKIPROM = 0xCC __MATCHROM = 0x55 #delacre variabeln fuer die Klasse _iscmdmode = False #search state _lastdiscrepancy = 0 _lastdeviceflag = False _lastfamilydiscrepancy = 0 newromno = [0] * 8 #variabeln der Klasse --> oeffentlich def __init__(self, temperature=0, ds1920no=0, ds1920first=0, ds19b20no=0, ds19b20first=0, romstorage=[None] * 1024, interface="", debug=False, resetflag=True): """init der methoden variabeln""" self.temperature = temperature self.ds1920no = ds1920no self.ds1920first = ds1920first self.ds19b20no = ds19b20no self.ds19b20first = ds19b20first self.romstorage = romstorage self.interface = interface self.debug = debug self.resetflag = resetflag #******************RS232 Routinen*********************************************** def interfacereset(self): """reset interface""" print("Err OneWireBus --> Reset Interface") self.interface.deinit() self.initrs232(1) self.portwrite(self.__RESET) def initrs232(self, port=1, baud=9600): """Init RS232""" self.interface = UART(port, baud) self.interface.init(baud, bits=8, parity=None, stop=1) def closers232(self): """port schliessen""" self.interface.deinit() print("UART close") def getchrrs232(self): """Rx char""" result = self.interface.read(1) if result != None: if self.debug: print("debug ASCII in: ", end="") print(result + " hex:" + hex(ord(result))) return ord(result) else: return 0 def flushrs232(self): """clear input buffer""" self.interface.readall() #*********************DS2480B Routinen****************************************** def commandmode(self): """check commandmode""" if not self._iscmdmode: self._iscmdmode = True self.portwrite(self.__COMMANDMODE) return self.getchrrs232() def datamode(self): """check datamode""" if self._iscmdmode: self._iscmdmode = False self.portwrite(self.__DATAMODE) def portwrite(self, value=0): """write data""" if self.debug: print("debug value write:" + hex(value)) self.interface.write(bytearray([value])) if self._iscmdmode: #return chr if cmd mode sleep(0.010) return self.getchrrs232() def writebit(self, value=0, waitforreply=1): """Write a bit - actually returns the bit read back in case you care.""" getchr = 0 self.commandmode() #if self.debug: # print "writebit: " + bin(value) if value == 1: getchr = self.portwrite(0x91) #write a single "on" bit to onewire else: getchr = self.portwrite(0x81) #write a single "off" bit to onewire if waitforreply == 1: return getchr & 1 def readbit(self): """Read a bit - short hand for writing a 1 and seeing what we get back.""" return self.writebit(1) def writemode(self, value=0): """Tx UART value without return from DS2480b""" if self.debug: print("debug value write:" + hex(value)) self.interface.write([value]) def writecommand(self, value=0): """Tx UART value with return from DS2480b""" self.commandmode() self.interface.write([value]) result = self.getchrrs232() return result def reset(self): """reset one wire bus""" self.commandmode() char = self.portwrite(self.__RESET) if char == self.__ACK: self.resetflag = False return True else: print("Reset answer: " + hex(char)) self.resetflag = True self.datamode() self.readbit() self.interfacereset() return False def resetsearch(self, clearrom=0): """reset the search state""" if self.debug: print("Reset Interface for search.") self._lastdiscrepancy = 0 self._lastdeviceflag = False self._lastfamilydiscrepancy = 0 if clearrom == 1: self.newromno = [0] * 8 def search(self): """ // Perform a search. If this function returns a '1' then it has // enumerated the next device and you may retrieve the ROM from the // DS2480B::address variable. If there are no devices, no further // devices, or something horrible happens in the middle of the // enumeration then a 0 is returned. If a new device is found then // its address is copied to newAddr. Use DS2480B::reset_search() to // start over. // // --- Replaced by the one from the Dallas Semiconductor web site --- //-------------------------------------------------------------------------- // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing // search state. // Return TRUE : device found, ROM number in ROM_NO buffer // FALSE : device not found, end of search """ ##initialize for search id_bit_number = 1 last_zero = 0 rom_byte_number = 0 rom_byte_mask = 1 search_result = 0 id_bit = 0 cmp_id_bit = 0 search_direction = 0 if self.debug: print("search allgorithm") #if the last call was not the last one if not self._lastdeviceflag: if not self.reset(): self.resetsearch() return 0 self.datamode() self.portwrite(self.__SEARCHROM) self.getchrrs232() while True: #read a bit and its complement id_bit = self.readbit() cmp_id_bit = self.readbit() #if self.debug: #print "####bit read: " + bin(id_bit) +" comp: "+ bin(cmp_id_bit) #check for no devices on 1-wire if (id_bit == 1) and (cmp_id_bit == 1): break else: #all devices coupled have 0 or 1 if id_bit != cmp_id_bit: search_direction = id_bit #bit write value for search else: #if this discrepancy if before the Last Discrepancy # on a previous next then pick the same as last time if id_bit_number < self._lastdiscrepancy: search_direction = ((self.newromno[rom_byte_number] & rom_byte_mask) > 0) else: #if equal to last pick 1, if not then pick 0 search_direction = ( id_bit_number == self._lastdiscrepancy) #if 0 was picked then record its position in LastZero if search_direction == 0: last_zero = id_bit_number #check for Last discrepancy in family if last_zero < 9: self._lastfamilydiscrepancy = last_zero #set or clear the bit in the ROM byte rom_byte_number # with mask rom_byte_mask if search_direction == 1: self.newromno[rom_byte_number] |= rom_byte_mask else: self.newromno[rom_byte_number] &= ~rom_byte_mask #serial number search direction write bit self.writebit(search_direction) #increment the byte counter id_bit_number #and shift the mask rom_byte_mask id_bit_number += 1 rom_byte_mask <<= 1 #if the mask is 0 then go to new SerialNum #byte rom_byte_number and reset mask if rom_byte_mask >= 0xff: rom_byte_number += 1 rom_byte_mask = 1 #loop until through all ROM bytes 0-7 if rom_byte_number == 8: break #if the search was successful then if (id_bit_number < 65) == 0: #search successfulself.getchrrs232() #so set LastDiscrepancy,LastDeviceFlag,search_result self._lastdiscrepancy = last_zero #check for last device if self._lastdiscrepancy == 0: self._lastdeviceflag = 1 search_result = 1 #if no device found then reset counters #so next 'search' will be like a first if search_result == 0 or self.newromno[0] == 0: search_result = 0 else: for i in range(0, 8): #newAddr[i] = self.newromno[i] if self.debug: print(hex(self.newromno[i]) + " ", end='') if self.debug: print(" ") return search_result def getallid(self): """get all one wire id's""" i = 0 j = 0 while True: if self.search() == 0: break if self.crc8(self.newromno) == 0: self.romstorage[i] = deepcopy(self.newromno) print("No. {} ID:{}".format(i, self.romstorage[i])) i += 1 if i == len(self.romstorage): print("max. Anzahl OneWire Clients") break else: if self.debug: print("ERR CRC8 Test") raise CRCError() if self.debug: i = 0 print(" ") while self.romstorage[i] != None: print(str(i) + ": ") for j in range(0, len(self.romstorage[i])): print(hex(self.romstorage[i][j]), end="") i += 1 print(" ") return self.romstorage def crc8(self, data): """Compute CRC""" crc = 0 for i in range(len(data)): byte = data[i] for j in range(8): fb_bit = (crc ^ byte) & 0x01 if fb_bit == 0x01: crc = crc ^ 0x18 crc = (crc >> 1) & 0x7f if fb_bit == 0x01: crc = crc | 0x80 byte = byte >> 1 return crc #**********************DS18x20 Routinen***************************************** def converttemp(self): """DS1820 Temp.messung anstossen""" result = 0 self.commandmode() self.portwrite(self.__PULLUP) if self.reset(): self.datamode() self.portwrite(self.__SKIPROM) self.commandmode() self.portwrite(self.__PULLUPARM) self.portwrite(self.__PULSETERMINATE) self.datamode() self.portwrite(self.__CONVERTT) self.getchrrs232() self.commandmode() self.portwrite(self.__PULLUPDISARM) self.portwrite(self.__PULSETERMINATE) self.getchrrs232() self.reset() return result def acquiretemp(self, adress): """DS1820 aktuelle Temperatur abfragen""" scratchpad = [None] * 9 if self.debug: print("gettemp") self.commandmode() if self.reset(): self.datamode() self.portwrite(self.__MATCHROM) self.getchrrs232() for i in range(0, 8): self.portwrite(self.romstorage[adress][i]) #print (hex(self.romstorage[adress][i])+" ", end="") if self.debug: print(hex(self.romstorage[adress][i]), end='') self.portwrite(self.__READ) sleep(0.005) self.flushrs232() for i in range(9): self.portwrite(0xff) sleep(0.005) scratchpad[i] = self.getchrrs232() if self.debug: print(hex(scratchpad[i]) + " ", end="") self.commandmode() self.reset() if self.crc8(scratchpad) != 0: self.temperature = 9999.999 print("Err CRC") return self.temperature #calculate temperatur #ds1820 if self.romstorage[adress][0] == 0x10: integer = 0 for i in range(1, -1, -1): integer = integer * 256 + scratchpad[i] integer = integer / 2 self.temperature = ((scratchpad[7] - scratchpad[6]) / scratchpad[7]) + integer - 0.25 #ds18b20 if self.romstorage[adress][0] == 0x28: integer = 0 for i in range(1, -1, -1): integer = integer * 256 + scratchpad[i] self.temperature = (integer * 25.0) / 400.0 return self.temperature def checkdevices(self): """count onewire slaves""" devices = 0 kind = 0 self.ds1920no = 0 self.ds1920first = 0 self.ds19b20no = 0 self.ds19b20first = 0 if self.debug: print("get sensor type") for i in range(0, len(self.romstorage)): devices += 1 #check nesty value if self.romstorage[i] == None: break #mask of lsb kind = self.romstorage[i][0] if self.debug: print("kind:" + hex(kind)) if kind == 0x10: if self.ds1920no == 0: self.ds1920first = i if self.debug: print("first ds1920:" + hex(i)) self.ds1920no += 1 if kind == 0x28: if self.ds19b20no == 0: self.ds19b20first = i if self.debug: print("first ds19b20:" + hex(i)) self.ds19b20no += 1 return devices def update_state(self, state): for rom in self.romstorage: if rom is not None: name = " ".join(map(hex, rom)) id = "".join(map(str, rom)) state.add_sensor(id, name)
message : the string to send Returns: none """ try: _ = sock.sendto(message, send_to_address) except (OSError): print('Sending Timed Out') # define a time, because we only want to send every 1s but received as fast as possible last_time = time.time() try: while True: # always be receiving UDP_recv() # read UART, waiting for newline then, if data it SEND_TO_IP every 1s # if time.time() - last_time > 0.01: data = uart.readall() # read a line # Send some data if data is not None: string = 'Time: {:4.2f} Data: {}'.format( time.time() - last_time, data) UDP_send(string) # last_time = time.time() except (KeyboardInterrupt, SystemExit): sock.close()
app_eui = binascii.unhexlify('AD A4 DA E3 AC 12 67 6B'.replace(' ','')) app_key = binascii.unhexlify('11 B0 28 2A 18 9B 75 B0 B4 D2 D8 C7 FA 38 54 8B'.replace(' ','')) lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) while not lora.has_joined(): time.sleep(2.5) print('Searching for network...') print("Connected to the network.") # Open LoRaWAN socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) s.setblocking(True) def send_lora(data): print("Sending " + data) s.send(str(data)) uart1.write(b'Success') while True: if uart1.any(): data = uart1.readall() pycom.rgbled(0xFF0000) # set LED to RED on if data received if data == b'send': send_lora("data") pycom.rgbled(0x00FF00) # set LED to GREEN if data is b'send' time.sleep(1) pycom.rgbled(0x000000) time.sleep(0.25)
from machine import UART from machine import Pin import os import time uart_id_range = [1, 2] for uart_id in uart_id_range: uart = UART(uart_id, 38400) print(uart) uart.init(57600, 8, None, 1, pins=('P23', 'P9')) uart.init(baudrate=9600, stop=2, parity=UART.EVEN, pins=('P23', 'P9')) uart.init(baudrate=115200, parity=UART.ODD, stop=1, pins=('P23', 'P9')) #uart = UART(baudrate=1 uart.read() print(uart.readall()) print(uart.readline()) buff = bytearray(1) print(uart.readinto(buff, 1)) print(uart.read()) print(uart.any()) print(uart.write('a')) #uart.deinit() #uart = UART(baudrate=1000000) #uart = UART() #print(uart) #uart = UART(baudrate=38400, pins=('GP12', 'GP13')) #print(uart) #uart = UART(pins=('GP12', 'GP13')) #print(uart)
class PMSx003: # index of list PMS_FRAME_LENGTH = const(0) PMS_PM1P0_PAR1 = const(1) PMS_PM2P5_PAR2 = const(2) PMS_PM10P0_PAR3 = const(3) PMS_PM1P0 = const(4) PMS_PM2P5 = const(5) PMS_PM10P0 = const(6) PMS_PCNT_0P3 = const(7) PMS_PCNT_0P5 = const(8) PMS_PCNT_1P0 = const(9) PMS_PCNT_2P5 = const(10) PMS_PCNT_5P0 = const(11) PMS_PCNT_10P0 = const(12) PMS_VER = const(13) PMS_ERROR = const(14) PMS_SUMCHECK = const(15) ACTIVE = const(0) # mode active, default mode on power ON PASSIVE = const(1) # mode passive, similar as NORMAL mode NORMAL = const(3) # mode passive state normal fan is ON STANDBY = const(4) # mode passive, state standby fan is OFF # idle time minimal time to switch fan OFF IDLE = const(120000) # minimal idle time between sample time and interval def __init__(self, port=1, debug=False, sample=60, interval=1200, raw=False, calibrate=None, pins=('P3', 'P4'), clean=None, explicit=False): # read from UART1 V5/Gnd, PMS/Rx - GPIO P3/Tx, PMS/Tx - GPIO P4/Rx # measure average in sample time, interval freq. of samples in secs # explicit True: Plantower way of count (>PMi), False: Sensirion way (PM0.3-PMi) (dflt=False) try: if type(port) is str: # no PyCom case import serial self.ser = serial.Serial(port, 9600, bytesize=8, parity='N', stopbits=1, timeout=20, xonxoff=0, rtscts=0) self.ser.any = self.in_waiting self.ser.readall = self.ser.flushInput # reset_input_buffer elif type(port) is int: # micro python case from machine import UART self.ser = UART(port, baudrate=9600, pins=pins, timeout_chars=10) else: self.ser = port # fd except: raise OSError("PMS serial failed") self.firmware = None self.debug = debug self.interval = interval * 1000 # if interval == 0 no auto fan switching self.sample = sample * 1000 self.mode = self.STANDBY self.raw = raw self.explicit = explicit # counts are > PM size or < PM size # list of name, units, index in measurments, calibration factoring # pm1=[20,1] adds a calibration offset of 20 to measurement self.PM_fields = [ # the Plantower conversion algorithm is unclear! # internal parameters per size (not of use) ['pm1_par1', 'par', self.PMS_PM1P0_PAR1, None], ['pm25_par2', 'par', self.PMS_PM2P5_PAR2, None], ['pm10_par3', 'par', self.PMS_PM10P0_PAR3, None], # concentration (generic atmosphere conditions) in ug/m3 ['pm1', 'ug/m3', self.PMS_PM1P0, [0, 1]], ['pm25', 'ug/m3', self.PMS_PM2P5, [0, 1]], ['pm10', 'ug/m3', self.PMS_PM10P0, [0, 1]], # number of particles with diameter N in 0.1 liter air # 0.1 liter = 0.00353147 cubic feet, convert -> pcs / 0.01qf # std used here pcs/0.1dm3 (Plantower style) # grain: average particle size ['pm03_cnt', 'pcs/0.1dm3', self.PMS_PCNT_0P3, None], ['pm05_cnt', 'pcs/0.1dm3', self.PMS_PCNT_0P5, None], ['pm1_cnt', 'pcs/0.1dm3', self.PMS_PCNT_1P0, None], ['pm25_cnt', 'pcs/0.1dm3', self.PMS_PCNT_2P5, None], ['pm5_cnt', 'pcs/0.1dm3', self.PMS_PCNT_5P0, None], ['pm10_cnt', 'pcs/0.1dm3', self.PMS_PCNT_10P0, None], ['grain', 'um', 0, None], ] if type(calibrate) is dict: for key in calibrate.keys(): if calibrate[key] and type(calibrate[key]) != list: continue for pm in range(len(self.PM_fields)): if self.PM_fields[pm][0] == key: self.PM_fields[pm][3] = calibrate[key] break def in_waiting(self): # for non PyCom python try: return self.ser.in_waiting except: raise ValueError # calibrate by length calibration factor (Taylor) array def calibrate(self, cal, value): if self.raw: return value if (not cal) or (type(cal) != list): return round(value, 2) if type(value) is int: value = float(value) if not type(value) is float: return None rts = 0 pow = 0 for a in cal: rts += a * (value**pow) pow += 1 return rts # send mode/state change to PMS sensor # check answer def SendMode(self, cmd, ON): ''' send 42 4D cmd (E2,E4,E1) 00 ON (On=1,Off=0) chckH chckL no answer on cmd: E2 (read telegram) and E4 On (active mode) answer 42 4D 00 04 cmd 00 chckH chckL ''' if not cmd in (0xE1, 0xE2, 0xE4): return False if ON: ON = 0x1 if self.debug: if cmd == 0xE2: CMD = 'READ' elif cmd == 0xE1: CMD = 'ACTIVE' if ON else 'PASSIVE fan ON' else: CMD = 'NORMAL fan ON' if ON else 'STANDBY fan OFF' print("Send command %s" % CMD) ChckSum = 0x42 + 0x4D + cmd + 0x0 + ON data = struct.pack('!BBBBBH', 0x42, 0x4D, cmd, 0x0, ON, ChckSum) while self.ser.any(): self.ser.readall() try: self.ser.write(data) # print("Send command 0x%X 0x%X 0x%X 0x%X 0x%X 0x%x 0x%x" % struct.unpack('!BBBBBBB',data)) except: print('Unable to send mode/state change.') raise OSError("mode/state") if (cmd == 0xE2) or (cmd == 0xE4): return True # check the answer ChckSum += 4 try: c = [] err = 0 while True: if err > 20: print("PMS response failed") self.GoPassive() return False err += 1 if not self.ser.any(): sleep_ms(200) continue c = self.ser.read(1) if ORD(c[0]) != 0x42: continue c = self.ser.read(1) if c == None or ORD(c[0]) != 0x4D: continue check = 0x42 + 0x4D c = self.ser.read(6) for ch in c[:4]: check += ORD(ch) if (ORD(c[1]) == 0x4) and (ORD(c[2]) == cmd) and ( (ORD(c[4]) * 256 + ORD(c[5])) == check): return True print("Checksum 0X%x 0X%x != 0X%x" % (ChkSum, check, ORD(c[4]) * 256 + ORD(c[5]))) return False except: pass return False # passive mode, go into standby state / sleep: fan OFF def Standby(self): #print("Go standby from 0X%X" % self.mode) if self.mode != self.STANDBY: if self.mode == self.ACTIVE: self.GoPassive() self.mode = self.STANDBY return self.SendMode(0xE4, 0) return True # passive mode, go into normal state: fan ON, allow data telegrams reading def Normal(self): #print("Go normal from 0x%X" % self.mode) if self.mode != self.NORMAL: if self.mode == self.ACTIVE: self.GoPassive() if self.mode != self.NORMAL: self.mode = self.NORMAL return self.SendMode(0xE4, 1) return True # from passive mode go in active mode (same as with power on) def GoActive(self): #print("Go active from 0X%X" % self.mode) if self.mode == self.STANDBY: self.Normal() if self.debug: print("wait 30 secs") sleep_ms(30000) if self.interval - self.sample >= self.IDLE: return self.GoPassive() else: self.mode = self.ACTIVE #print("Active") return self.SendMode(0xE1, 1) # from active mode go into passive mode (passive normal state ?) def GoPassive(self): #print("Go Passive from 0X%X" % self.mode) if self.mode != self.PASSIVE: self.ser.readall() return self.SendMode(0xE1, 0) self.mode = self.PASSIVE return True # in passive mode do one data telegram reading def PassiveRead(self): if self.mode == self.STANDBY: self.Normal() for cnt in range(30): self.ser.readall() sleep_ms(1000) # wait 30 seconds to establish air flow if self.mode != self.PASSIVE: self.GoPassive() return self.SendMode(0xE2, 0) # check data array is decreasing and #pcs >10 def decreasing(self, data): tmp = data[0] if max(data) <= 10: return False for item in data[1:]: if tmp >= item: tmp = item else: print("found non decreasing data: ", data) return False return True # original read routine comes from [email protected] http://http://irmus.tistory.com/ # added active/passive and fan on/off handling # data telegram struct for PMS5003 and PMS7003 (32 bytes) # PMS1003/PMS4003 the data struct is similar (24 bytes) # Hint: use pmN_atm (atmospheric) data values in stead of pmN values def getData(self, debug=False): ''' read data telegrams from the serial interface (32 bytes) before actual read flush all pending data first during the period sample time: active (200-800 ms), passive read cmd 1 sec calculate average during sample seconds if passive mode fan off: switch fan ON and wait 30 secs. ''' ErrorCnt = 0 cnt = 0 PM_sample = {} # clear the input buffer first so we get latest reading StrtTime = ticks_ms() LastTime = ticks_ms() buff = [] inStartup = 4 if self.mode == self.STANDBY: self.GoActive() self.ser.readall() while True: # self.ser.readall() if self.mode != self.ACTIVE or self.mode != self.NORMAL: # in PASSIVE mode we wait one second per read if cnt: wait = ticks_ms() - LastTime if (wait < 1000) and wait: sleep_ms(wait) # passive?:if fan off switch it on, initiate read if not self.PassiveRead(): return {} while True: # search header (0x42 0x4D) of data telegram if ErrorCnt >= 20: return {} waitcnt = 0 while waitcnt < 10 and self.ser.any() < 2: sleep_ms(1000) waitcnt += 1 if self.ser.any() < 2: ErrorCnt += 1 if self.debug: print("reactivate PMS") if self.mode == self.ACTIVE or self.mode == self.NORMAL: self.mode = self.PASSIVE if self.GoActive(): continue else: self.PassiveRead() continue try: buff = self.ser.read(1) # 1st byte header if ORD(buff[0]) == 0x42: buff = self.ser.read(1) # 2nd byte header if buff and ORD(buff[0]) == 0x4d: break except: ErrorCnt += 1 continue # try next data telegram if not cnt: StrtTime = ticks_ms() # packet remaining. fixed length packet structure for w in range(40): if self.ser.any() >= 30: break if w > 39: raise OSError("read telegram timeout") if (self.debug or debug) and (w % 2): print("wait %d on sensor data" % w) sleep_ms(200) buff = self.ser.read(30) # one measurement 200-800ms or every second in sample time if cnt and (LastTime + 1000 > ticks_ms()): print("Skip %d dust measurement" % cnt) self.ser.readall() continue # skip measurement if time < 1 sec LastTime = ticks_ms() check = 0x42 + 0x4d # sum check every byte from HEADER to ERROR byte for b in buff[0:28]: check += ORD(b) data = list(struct.unpack('!HHHHHHHHHHHHHBBH', buff)) if not sum(data[self.PMS_PCNT_0P3:self.PMS_VER]): # first reads show 0 particle counts, skip telegram if self.debug: print("null data, skipped") continue # compare check code if check != data[self.PMS_SUMCHECK]: if self.debug or debug: print( "Incorrect check code check 0X%x != data check 0x%x" % (check, data[self.PMS_SUMCHECK])) ErrorCnt += 1 if ErrorCnt >= 20: raise OSError("too many sum check") # self.ser.readall() continue if inStartup > 0: # skip first measurements inStartup -= 1 sleep_ms(500) continue if max(data[self.PMS_PM1P0:self.PMS_PM10P0 + 1]) > 500: # del 1st spikes if self.debug: print("Skip spike = %0.1f" % data[self.PMS_PM1P0]) continue # first 2 reads if data[self.PMS_ERROR]: print("PMS device error: %s" % str(data[self.PMS_ERROR])) ErrorCnt += 1 if ErrorCnt > 20: raise ValueError("Module errors %s" % str(data[self.PMS_ERROR])) continue ErrorCnt = 0 if not self.firmware: self.firmware = str(data[self.PMS_VER]) #print("firmware: %s" % self.firmware) sample = {} for i in range(self.PMS_PM1P0_PAR1, self.PMS_PCNT_10P0 + 1): data[i] = float(data[i]) # make them all float if not self.decreasing( data[self.PMS_PCNT_0P3:self.PMS_PCNT_10P0 + 1]): continue # estimate avg PM size grain = ( 0.4 * (data[self.PMS_PCNT_0P3] - data[self.PMS_PCNT_0P5]) + 0.75 * (data[self.PMS_PCNT_0P5] - data[self.PMS_PCNT_1P0]) + 1.75 * (data[self.PMS_PCNT_2P5] - data[self.PMS_PCNT_1P0]) + 3.75 * (data[self.PMS_PCNT_2P5] - data[self.PMS_PCNT_5P0]) + 7.5 * (data[self.PMS_PCNT_5P0] - data[self.PMS_PCNT_10P0])) / ( data[self.PMS_PCNT_0P3] - data[self.PMS_PCNT_10P0]) if self.debug: print("Raw data: ", data) if debug: print("Sample data") if not cnt: for fld in self.PM_fields: print("%8.8s " % fld[0], end='') print() for fld in self.PM_fields: print("%8.8s " % fld[1], end='') print() for fld in self.PM_fields: print("%8.2f " % data[fld[2]], end='') print() for fld in self.PM_fields: if fld[2] != 0: PM_sample[fld[0]] = PM_sample.setdefault( fld[0], 0.0) + data[fld[2]] else: PM_sample[fld[0]] = PM_sample.setdefault(fld[0], 0.0) + grain cnt += 1 # average read time is 0.85 secs. Plantower specifies 200-800 ms # Plantower: in active smooth mode actual data update is 2 secs. sleep_ms(5 * 1000) if ticks_ms() > StrtTime + self.sample: break SampleTime = ticks_ms() - StrtTime if SampleTime < 0: SampleTime = 0 if cnt: # average count during the sample time for fld in self.PM_fields: PM_sample[fld[0]] /= cnt if self.raw or (fld[3] == None): PM_sample[fld[0]] = round(PM_sample[fld[0]] + 0.05, 2) else: PM_sample[fld[0]] = round( self.calibrate(fld[3], PM_sample[fld[0]]) + 0.05, 2) if not self.explicit: for item in '05', '1', '25', '5', '10': PM_sample['pm%s_cnt' % item] = PM_sample['pm03_cnt'] - PM_sample[ 'pm%s_cnt' % item] del PM_sample['pm03_cnt'] # turn fan off? if self.interval - SampleTime > 60 * 1000: self.Standby() # switch fan OFF # print("Sample PM: ",PM_sample) return PM_sample
# set the clock c = untplib.NTPClient() rtclock = RTC() clock_adjust() # set the regex for the uart answers re = ure.compile("\r\nOK\r\n") er = ure.compile("\r\nERROR\r\n") # config the uart and see if somethings answers uart = UART(1, baudrate=115200, pins=(TX_PIN, RX_PIN)) # uart #, baudrate, pins tx,rx uart.write('+++') uart.write('AT+COPS?\r\n') time.sleep(1) while uart.any() != 0: print(uart.readall()) # get the battery adc = ADC() bat = adc.channel(pin=BAT_PIN) # initialize Blynk blynk = BlynkLib.Blynk(BLYNK_AUTH, server=BLYNK_SERVER) # register virtual pin 4 (the button on the blynk that sends the temp sms right away) blynk.add_virtual_pin(4, write=v4_write_handler) # register my task blynk.set_user_task(sendData, 60000) # start Blynk (this call should never return)
class PMSx003: # index of list PMS_FRAME_LENGTH = const(0) PMS_PM1P0 = const(1) PMS_PM2P5 = const(2) PMS_PM10P0 = const(3) PMS_PM1P0_ATM = const(4) PMS_PM2P5_ATM = const(5) PMS_PM10P0_ATM = const(6) PMS_PCNT_0P3 = const(7) PMS_PCNT_0P5 = const(8) PMS_PCNT_1P0 = const(9) PMS_PCNT_2P5 = const(10) PMS_PCNT_5P0 = const(11) PMS_PCNT_10P0 = const(12) PMS_VER = const(13) PMS_ERROR = const(14) PMS_SUMCHECK = const(15) ACTIVE = const(0) # mode active, default mode on power ON PASSIVE = const(1) # mode passive, similar as NORMAL mode NORMAL = const(3) # mode passive state normal fan is ON STANDBY = const(4) # mode passive, state standby fan is OFF # idle time minimal time to switch fan OFF IDLE = const(120000) # minimal idle time between sample time and interval def __init__(self, port=1, debug=False, sample=60, interval=1200, raw=False, calibrate=None, pins=('P3', 'P4')): # read from UART1 V5/Gnd, PMS/Rx - GPIO P3/Tx, PMS/Tx - GPIO P4/Rx # measure average in sample time, interval freq. of samples in secs self.ser = UART(port, baudrate=9600, pins=pins) self.firmware = None self.debug = debug self.interval = interval * 1000 # if interval == 0 no auto fan switching self.sample = sample * 1000 self.mode = self.STANDBY self.raw = raw # list of name, units, index in measurments, calibration factoring # pm1=[20,1] adds a calibration offset of 20 to measurement self.PM_fields = [ # the Plantower conversion algorithm is unclear! ['pm1', 'ug/m3', self.PMS_PM1P0, [0, 1]], ['pm25', 'ug/m3', self.PMS_PM2P5, [0, 1]], ['pm10', 'ug/m3', self.PMS_PM10P0, [0, 1]], # concentration (generic atmosphere conditions) in ug/m3 ['pm1_atm', 'ug/m3', self.PMS_PM1P0_ATM, None], ['pm25_atm', 'ug/m3', self.PMS_PM2P5_ATM, None], ['pm10_atm', 'ug/m3', self.PMS_PM10P0_ATM, None], # number of particles with diameter N in 0.1 liter air # 0.1 liter = 0.00353147 cubic feet, convert -> pcs / 0.01qf ['pm03_cnt', 'pcs/0.1dm3', self.PMS_PCNT_0P3, None], ['pm05_cnt', 'pcs/0.1dm3', self.PMS_PCNT_0P5, None], ['pm1_cnt', 'pcs/0.1dm3', self.PMS_PCNT_1P0, None], ['pm25_cnt', 'pcs/0.1dm3', self.PMS_PCNT_2P5, None], ['pm5_cnt', 'pcs/0.1dm3', self.PMS_PCNT_5P0, None], ['pm10_cnt', 'pcs/0.1dm3', self.PMS_PCNT_10P0, None], ] if type(calibrate) is dict: for key in calibrate.keys(): if calibrate[key] and type(calibrate[key]) != list: continue for pm in range(len(self.PM_fields)): if self.PM_fields[pm][0] == key: self.PM_fields[pm][3] = calibrate[key] break # decomment if not micropython try: self.ser.any except: self.ser.readall = self.ser.flushInput # reset_input_buffer self.ser.any = self.ser.inWaiting # calibrate by length calibration factor (Taylor) array def calibrate(self, cal, value): if self.raw: return value if (not cal) or (type(cal) != list): return round(value, 2) if type(value) is int: value = float(value) if not type(value) is float: return None rts = 0 pow = 0 for a in cal: rts += a * (value**pow) pow += 1 return rts # send mode/state change to PMS sensor # check answer def SendMode(self, cmd, ON): ''' send 42 4D cmd (E2,E4,E1) 00 ON (On=1,Off=0) chckH chckL no answer on cmd: E2 (read telegram) and E4 On (active mode) answer 42 4D 00 04 cmd 00 chckH chckL ''' if not cmd in (0xE1, 0xE2, 0xE4): return False if ON: ON = 0x1 if self.debug: if cmd == 0xE2: CMD = 'READ' elif cmd == 0xE1: CMD = 'ACTIVE' if ON else 'PASSIVE fan ON' else: CMD = 'NORMAL fan ON' if ON else 'STANDBY fan OFF' print("Send command %s" % CMD) ChckSum = 0x42 + 0x4D + cmd + 0x0 + ON data = struct.pack('!BBBBBH', 0x42, 0x4D, cmd, 0x0, ON, ChckSum) while self.ser.any(): self.ser.readall() try: self.ser.write(data) if self.debug: print("Send command 0x%X 0x%X 0x%X 0x%X 0x%X 0x%x 0x%x" % struct.unpack('!BBBBBBB', data)) except: print('Unable to send mode/state change.') raise OSError("mode/state") if (cmd == 0xE2) or ((cmd == 0xE4) and ON): return True # check the answer ChckSum += 4 try: c = [] err = 0 while True: if err > 20: print("cmd response failed") return False err += 1 if not self.ser.any(): sleep_ms(200) continue c = self.ser.read(1) if ORD(c[0]) != 0x42: continue c = self.ser.read(1) if c == None or ORD(c[0]) != 0x4D: continue check = 0x42 + 0x4D c = self.ser.read(6) for ch in c[:4]: check += ORD(ch) if (ORD(c[1]) == 0x4) and (ORD(c[2]) == cmd) and ( (ORD(c[4]) * 256 + ORD(c[5])) == check): return True print("Checksum 0X%x 0X%x != 0X%x" % (ChkSum, check, ORD(c[4]) * 256 + ORD(c[5]))) return False except: pass return False # passive mode, go into standby state / sleep: fan OFF def Standby(self): if self.mode != self.STANDBY: if self.mode == self.ACTIVE: self.GoPassive() self.mode = self.STANDBY return self.SendMode(0xE4, 0) return True # passive mode, go into normal state: fan ON, allow data telegrams reading def Normal(self): if self.mode != self.NORMAL: if self.mode == self.ACTIVE: self.GoPassive() if self.mode != self.NORMAL: self.mode = self.NORMAL return self.SendMode(0xE4, 1) return True # from passive mode go in active mode (same as with power on) def GoActive(self): if self.mode == self.STANDBY: self.Normal() if self.debug: print("wait 30 secs") sleep_ms(30000) self.mode = self.ACTIVE self.SendMode(0xE1, 1) if self.interval - self.sample >= self.IDLE: self.GoPassive() return True # from active mode go into passive mode (passive normal state ?) def GoPassive(self): self.mode = self.PASSIVE # state NORMAL? if self.mode == self.ACTIVE: return self.SendMode(0xE1, 0) return True # in passive mode do one data telegram reading def PassiveRead(self): if self.mode == self.ACTIVE: return if self.mode == self.STANDBY: self.Normal() sleep_ms(30000) # wait 30 seconds to establish air flow return self.SendMode(0xE2, 0) # original read routine comes from [email protected] http://http://irmus.tistory.com/ # added active/passive and fan on/off handling # data telegram struct for PMS5003 and PMS7003 (32 bytes) # PMS1003/PMS4003 the data struct is similar (24 bytes) # Hint: use pmN_atm (atmospheric) data values in stead of pmN values def getData(self): ''' read data telegrams from the serial interface (32 bytes) before actual read flush all pending data first during the period sample time: active (200-800 ms), passive read cmd 1 sec calculate average during sample seconds if passive mode fan off: switch fan ON and wait 30 secs. ''' ErrorCnt = 0 cnt = 0 PM_sample = {} # clear the input buffer first so we get latest reading StrtTime = ticks_ms() LastTime = ticks_ms() buff = [] if self.mode == self.STANDBY: self.GoActive() self.ser.readall() while True: # self.ser.readall() if self.mode != self.ACTIVE or self.mode != self.NORMAL: # in PASSIVE mode we wait one second per read if cnt: wait = ticks_ms() - LastTime if (wait < 1000) and wait: sleep_ms(wait) self.PassiveRead( ) # passive?:if fan off switch it on, initiate read while True: # search header (0x42 0x4D) of data telegram if ErrorCnt >= 20: raise OSError("too many read errors") waitcnt = 0 while waitcnt < 10 and self.ser.any() < 2: sleep_ms(1000) waitcnt += 1 if self.ser.any() < 2: ErrorCnt += 1 if self.debug: print("reactivate") if self.mode == self.ACTIVE or self.mode == self.NORMAL: self.mode = self.PASSIVE if self.GoActive(): continue else: self.PassiveRead() continue try: buff = self.ser.read(1) # 1st byte header if ORD(buff[0]) == 0x42: buff = self.ser.read(1) # 2nd byte header if buff and ORD(buff[0]) == 0x4d: break except: ErrorCnt += 1 continue # try next data telegram if not cnt: StrtTime = ticks_ms() # packet remaining. fixed length packet structure for w in range(40): if self.ser.any() >= 30: break if w > 39: raise OSError("read telegram timeout") if self.debug and (w % 2): print("wait on telegram") sleep_ms(2000) buff = self.ser.read(30) # one measurement 200-800ms or every second in sample time if cnt and (LastTime + 1000 > ticks_ms()): continue # skip measurement if time < 1 sec LastTime = ticks_ms() check = 0x42 + 0x4d # sum check every byte from HEADER to ERROR byte for b in buff[0:28]: check += ORD(b) data = struct.unpack('!HHHHHHHHHHHHHBBH', buff) if not sum(data[self.PMS_PCNT_0P3:self.PMS_VER]): # first reads show 0 particle counts, skip telegram if self.debug: print("null telegram skipped") continue # compare check code if check != data[self.PMS_SUMCHECK]: if self.debug: print( "Incorrect check code check 0X%x != data check 0x%x" % (check, data[self.PMS_SUMCHECK])) ErrorCnt += 1 if ErrorCnt >= 20: raise OSError("too many sum check") # self.ser.readall() continue if data[self.PMS_ERROR]: print("Module returned error: %s" % str(data[self.PMS_ERROR])) ErrorCnt += 1 if ErrorCnt > 20: raise ValueError("Module errors %s" % str(data[self.PMS_ERROR])) continue ErrorCnt = 0 if not self.firmware: self.firmware = str(data[self.PMS_VER]) print("firmware: %s" % self.firmware) sample = {} for fld in self.PM_fields: # concentrations in unit ug/m3 # concentration (generic atmosphere conditions) in ug/m3 # number of particles with diameter N in 0.1 liter air pcs/0.1dm3 sample[fld[0]] = float(data[fld[2]]) # make it float if self.debug: if not cnt: for fld in self.PM_fields: print("%8.8s " % fld[0], end='') print() for fld in self.PM_fields: print("%8.8s " % ('ug/m3' if fld[0][-4:] != '_cnt' else 'pcs/0.1dm3'), end='') print() for fld in self.PM_fields: print("%8.8s " % str(sample[fld[0]]), end='') print() cnt += 1 for fld in self.PM_fields: PM_sample[fld[0]] = PM_sample.setdefault(fld[0], 0.0) + sample[fld[0]] # average read time is 0.85 secs. Plantower specifies 200-800 ms # Plantower: in active smooth mode actual data update is 2 secs. if ticks_ms() > StrtTime + self.sample: break SampleTime = ticks_ms() - StrtTime if SampleTime < 0: SampleTime = 0 if cnt: # average count during the sample time for fld in self.PM_fields: PM_sample[fld[0]] /= cnt PM_sample[fld[0]] = round( self.calibrate(fld[3], PM_sample[fld[0]]), 2) # turn fan off? if self.interval - SampleTime > 60 * 1000: self.Standby() # switch fan OFF return PM_sample
#p_in = Pin('P23', mode=Pin.IN, pull=Pin.PULL_UP) p_out_ctrla = Pin('P21', mode=Pin.OUT) p_out_ctrlb = Pin('P20', mode=Pin.OUT) p_out_ctrla.value(0) p_out_ctrlb.value(0) time.sleep(0.5) p_out_led = Pin('P2', mode=Pin.OUT) p_out_led.value(1) dev_addr = bytes([0x00, 0x00, 0x0F]) + bytes([psd_json["firmware"]["devaddr"]]) lora_addr = dev_addr[2:4] cfg_r_str = 'NO' while cfg_r_str[0:2] != 'OK': uart_as62.readall() uart_as62.write(bytes([0xC2]) + lora_addr + bytes([0x1D, 0x17, 0xC0])) #write cfg bytes time.sleep(0.5) cfg_r_str = uart_as62.readall().decode('utf-8') print(cfg_r_str) time.sleep(0.5) time.sleep(0.5) p_out_md1.value(0) p_out_md0.value(0) time.sleep(0.5) pdata_bytes = peripheral_query.peripheral_query(0, p_out_ctrla, p_out_ctrlb) state = 0 # state = 0 unregistered # state = 1 registered
message : the string to send Returns: none """ try: _ = sock.sendto(message, send_to_address) except (OSError): print('Sending Timed Out') # define a time, because we only want to send every 1s but received as fast as possible last_time = time.time() try: while True: # always be receiving UDP_recv() # read UART, waiting for newline then, if data it SEND_TO_IP every 1s # if time.time() - last_time > 0.01: data = uart.readall() # read a line # Send some data if data is not None: string = 'Time: {:4.2f} Data: {}'.format(time.time()-last_time, data) UDP_send(string) # last_time = time.time() except (KeyboardInterrupt, SystemExit): sock.close()
class Serial: def __init__(self, uart_id, baudrate=9600, data_bits=8, stop_bits=1, parity=None, pins=None, ctrl_pin=None): self._uart = UART(uart_id, baudrate=baudrate, bits=data_bits, parity=parity, \ stop=stop_bits, timeout_chars=2, pins=pins) if ctrl_pin is not None: self._ctrlPin = Pin(ctrl_pin, mode=Pin.OUT) else: self._ctrlPin = None if baudrate <= 19200: self._t35chars = (3500000 * (data_bits + stop_bits + 2)) // baudrate else: self._t35chars = 1750 def _calculate_crc16(self, data): crc = 0xFFFF for char in data: crc = (crc >> 8) ^ Const.CRC16_TABLE[((crc) ^ char) & 0xFF] return struct.pack('<H', crc) def _bytes_to_bool(self, byte_list): bool_list = [] for index, byte in enumerate(byte_list): bool_list.extend([bool(byte & (1 << n)) for n in range(8)]) return bool_list def _to_short(self, byte_array, signed=True): response_quantity = int(len(byte_array) / 2) fmt = '>' + (('h' if signed else 'H') * response_quantity) return struct.unpack(fmt, byte_array) def _exit_read(self, response): if response[1] >= Const.ERROR_BIAS: if len(response) < Const.ERROR_RESP_LEN: return False elif (Const.READ_COILS <= response[1] <= Const.READ_INPUT_REGISTER): expected_len = Const.RESPONSE_HDR_LENGTH + 1 + response[ 2] + Const.CRC_LENGTH if len(response) < expected_len: return False elif len(response) < Const.FIXED_RESP_LEN: return False return True def _uart_read(self): response = bytearray() for x in range(1, 40): if self._uart.any(): response.extend(self._uart.readall()) # variable length function codes may require multiple reads if self._exit_read(response): break time.sleep(0.05) return response def _uart_read_frame(self, timeout=None): bytes = bytearray() start_ms = time.ticks_ms() while timeout == None or time.ticks_diff(start_ms, time.ticks_ms()) <= timeout: last_byte_ts = time.ticks_us() while time.ticks_diff(last_byte_ts, time.ticks_us()) <= self._t35chars: r = self._uart.readall() if r != None: bytes.extend(r) last_byte_ts = time.ticks_us() if len(bytes) > 0: return bytes return bytes def _send(self, modbus_pdu, slave_addr): serial_pdu = bytearray() serial_pdu.append(slave_addr) serial_pdu.extend(modbus_pdu) crc = self._calculate_crc16(serial_pdu) serial_pdu.extend(crc) if self._ctrlPin: self._ctrlPin(1) self._uart.write(serial_pdu) if self._ctrlPin: while not self._uart.wait_tx_done(2): machine.idle() time.sleep_us(self._t35chars) self._ctrlPin(0) def _send_receive(self, modbus_pdu, slave_addr, count): # flush the Rx FIFO self._uart.read() self._send(modbus_pdu, slave_addr) return self._validate_resp_hdr(self._uart_read(), slave_addr, modbus_pdu[0], count) def _validate_resp_hdr(self, response, slave_addr, function_code, count): if len(response) == 0: raise OSError('no data received from slave') resp_crc = response[-Const.CRC_LENGTH:] expected_crc = self._calculate_crc16(response[0:len(response) - Const.CRC_LENGTH]) if (resp_crc[0] != expected_crc[0]) or (resp_crc[1] != expected_crc[1]): raise OSError('invalid response CRC') if (response[0] != slave_addr): raise ValueError('wrong slave address') if (response[1] == (function_code + Const.ERROR_BIAS)): raise ValueError('slave returned exception code: {:d}'.format( response[2])) hdr_length = (Const.RESPONSE_HDR_LENGTH + 1) if count else Const.RESPONSE_HDR_LENGTH return response[hdr_length:len(response) - Const.CRC_LENGTH] def read_coils(self, slave_addr, starting_addr, coil_qty): modbus_pdu = functions.read_coils(starting_addr, coil_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_discrete_inputs(self, slave_addr, starting_addr, input_qty): modbus_pdu = functions.read_discrete_inputs(starting_addr, input_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_holding_registers(self, slave_addr, starting_addr, register_qty, signed=True): modbus_pdu = functions.read_holding_registers(starting_addr, register_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def read_input_registers(self, slave_addr, starting_address, register_quantity, signed=True): modbus_pdu = functions.read_input_registers(starting_address, register_quantity) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def write_single_coil(self, slave_addr, output_address, output_value): modbus_pdu = functions.write_single_coil(output_address, output_value) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_COIL, output_address, value=output_value, signed=False) return operation_status def write_single_register(self, slave_addr, register_address, register_value, signed=True): modbus_pdu = functions.write_single_register(register_address, register_value, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_REGISTER, register_address, value=register_value, signed=signed) return operation_status def write_multiple_coils(self, slave_addr, starting_address, output_values): modbus_pdu = functions.write_multiple_coils(starting_address, output_values) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_COILS, starting_address, quantity=len(output_values)) return operation_status def write_multiple_registers(self, slave_addr, starting_address, register_values, signed=True): modbus_pdu = functions.write_multiple_registers( starting_address, register_values, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_REGISTERS, starting_address, quantity=len(register_values)) return operation_status def send_response(self, slave_addr, function_code, request_register_addr, request_register_qty, request_data, values=None, signed=True): modbus_pdu = functions.response(function_code, request_register_addr, request_register_qty, request_data, values, signed) self._send(modbus_pdu, slave_addr) def send_exception_response(self, slave_addr, function_code, exception_code): modbus_pdu = functions.exception_response(function_code, exception_code) self._send(modbus_pdu, slave_addr) def get_request(self, unit_addr_list, timeout=None): req = self._uart_read_frame(timeout) if len(req) < 8: return None if req[0] not in unit_addr_list: return None req_crc = req[-Const.CRC_LENGTH:] req_no_crc = req[:-Const.CRC_LENGTH] expected_crc = self._calculate_crc16(req_no_crc) if (req_crc[0] != expected_crc[0]) or (req_crc[1] != expected_crc[1]): return None try: request = Request(self, req_no_crc) except ModbusException as e: self.send_exception_response(req[0], e.function_code, e.exception_code) return None return request
class PZEM_V3: """ Communication with the device PZEM-004T-100A(V3.0) """ def __init__(self, address): # init UART with given parameters self.uart = UART(1, baudrate=9600, pins=('P3', 'P11')) # uart.init(). It is not needed and will reset the pins to the default values. # self.uart.init(9600, bits=8, parity=None, stop=1, timeout_chars=2) # Command format to reset energy registry self.reset = [address, 0x42, 0xC2, 0x41] # Command format to request measurement self.command = [address, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x64] # Read measurement function def readData(self): ''' Read the device´s variables 0xF8 0x04 0x00 0x00 0x00 0x0A 0x64 0x64 0x6464 is the CRC of the 6 most significant bytes NOTE: THE CODE INSIDE THIS FUNCTION WORKS WELL WHEN ALL VARIABLES ARE REQUESTED. IN CASE OF REQUIRING A DIFFERENT BEHAVIOR IT WILL NEED TO BE MODIFIED TOTALLY OR PARTIALLY. BESIDES, THE "data2measures" FUNCTION IS WRITTEN ACCORDING TO THIS FUNCTION (readData), THEREFORE "data2measures" WILL NEED MODIFICATION ''' # Definition of the reset and error variables response = [] ### error = [] ### # For-loop to transmit byte by byte and read response from PZEM device for d in self.command: self.uart.write(bytes([d])) # Check if response´s length is different from the desired response data # length. Then Check if response´s length is equal to the error command # format, If TRUE return the negation of the abnormal code. Otherwise, # return code number -6 (Other error). # If response´s length is equal to the correct reply format, return response time.sleep(1) availableChars = self.uart.any() if availableChars != 25: if availableChars == 5: response = self.uart.readall() error = [-1 * response[2]] return error else: error = [-6] return error else: response = self.uart.readall() return response def resetEnergy(self): ''' Reset energy registers to 0 and read its response 0xF8 0x42 0xC2 0x41 0x41C2 is the CRC of the 2 most significant bytes ''' # Definition of the reset and error variables response = [] error = 0 # For-loop to transmit byte by byte and read response from PZEM device for d in self.reset: self.uart.write(bytes([d])) # Check if response´s length is different from the desired response data # length. Then Check if response´s length is equal to the error command # format, If TRUE return the negation of the abnormal code. Otherwise, # return code number -6 (Other error). # If response´s length is equal to the correct reply format, return response time.sleep(1) availableChars = self.uart.any() if availableChars != 4: if availableChars == 5: response = self.uart.readall() error = -1 * response[2] return error else: error = -6 return error else: response = self.uart.readall() return response def data2measures(self, data): ''' This functions returns a vector with the 10 measures from the PZEM_100A_V3 device. NOTE: IN CASE OF MODIFIYING THE "readData" FUNCTION OR REQUIRING A DIFFERENT BEHAVIOR, THIS FUNCTION WILL NEED TO BE MODIFIED COMPLETELLY OR PARTIALLY ''' if len(data) == 1: values = [ data[0], data[0], data[0], data[0], data[0], data[0], data[0] ] else: ''' NOTE: DECIMAL VALUES ARE RETURNED, FURTHER CONVERSION IS REQUIRED ''' voltage = data[3] << 8 | data[4] current = data[7] << 24 | data[8] << 16 | data[5] << 8 | data[6] power = data[11] << 24 | data[12] << 16 | data[9] << 8 | data[10] energy = data[15] << 24 | data[16] << 16 | data[13] << 8 | data[14] frequency = data[17] << 8 | data[18] power_factor = data[19] << 8 | data[20] alarm = data[21] << 8 | data[22] values = [ voltage, current, power, energy, frequency, power_factor, alarm ] return values