Beispiel #1
0
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...')
Beispiel #2
0
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)
Beispiel #3
0
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()
Beispiel #5
0
 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)
Beispiel #6
0
 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
Beispiel #7
0
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)
Beispiel #8
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)
Beispiel #9
0
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:
Beispiel #11
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
Beispiel #12
0
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)
Beispiel #13
0
            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)
Beispiel #14
0
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')
Beispiel #15
0
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)
Beispiel #16
0
# 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)
Beispiel #19
0
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)
Beispiel #20
0
 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)
Beispiel #21
0
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)
Beispiel #22
0
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()
Beispiel #25
0
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)
Beispiel #26
0
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)
Beispiel #27
0
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)
Beispiel #29
0
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
Beispiel #30
0
#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()
Beispiel #32
0
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
Beispiel #33
0
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