Baixe o app para aproveitar ainda mais
Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
#8-25-2018 #ACC #Uno Pi Data interface project import serial import RPi.GPIO as GPIO ##import sys import time import datetime import smtplib from email.mime.text import MIMEText import threading import multiprocessing as mp import smbus ## from luma.core.interface.serial import i2c from luma.core.render import canvas from PIL import ImageFont from luma.oled.device import ssd1306 OLEDdevice = ssd1306() import queue q = queue.Queue(maxsize = 0) #create threading queue set size to infinate oMP = None mpQsend = mp.Queue() mpQrcv = mp.Queue() mpTweakerEvent = mp.Event() #multiprocessing event ## oLockQput = threading.Lock() import cMpu6050 #interrupt from uno - time to read serial port iUnoDataReady = 4 #J8-7 #exit interrupt used to stop program iHalt = 17 #J8-11 iAlertOnOff = 5 ## iMPU6050int = 26 #J8-37 #object detected alert iAlertEmailTimerTrigger = 22 #Servo Tweaker triggers #iServoTweakerTriggers = 27 #out to uno iPiReady = 6 #Count Down Timer Trigger #set to trigger email sending #1X per hour ##iCDT_Trigger= 13 #low input voltage warning pin iLowInputVoltage = 23 iPinBuzzer0 = 16 iPinResetArduino = 25 iPinOnePPS = 24 iPinInt = 21 bIsGPIO_CleanUp = False #prevent object detection during distance aquisition bDistanceLengthBlanking = True iZero = 0 iOne = 1 iTwo = 2 iThree = 3 iFour = 4 iFive = 5 iSix = 6 iSeven = 7 bOKToTweak = False ##iTriggerCount = 0 #count for externial timming pulses bResetTimePassed = False #timer trigger counting enable disable oTriggerOLED = threading.Event() iTriggerOLED_Count = iZero oTriggerCM = threading.Event() oTrigger32K = threading.Event() oTriggerSerialSend = threading.Event() oAspectChange = threading.Event() oDoVolt = threading.Event() ## oPremptTweak = threading.Event() iSecondOfLastAlert = 0 sOLED_AlertMessage = "*:" ## sOLED_TweakX = "" ## sOLED_TweakY = "" ## iScans = [0] * 61 ## iCurrentCell = 0 ## fltAspectIncrement = 5.555 fltScanAspectChange = 1400.0 #dont put a zero in here bAspectIncrease = True ##fltAngleMid = 1450.00 ## bAspectChangeInProgress = False ############################################# sDistanceScanTime = "" ############################################# ## ############################################# ## save for reference ## s_cm = "cm" ## sVOlTS = "VOLTS" ## sDistance = "Distance" ## sAspectCng = "AspectCng " ## sPASSWORD = "PASSWORD" ## sPLATFORM = "PLATFORM" ## sAspectComplete = "AspectComplete" ## s_doVolts = "doVolts" #sFLD ="FLD" ## s_pwd_request = "pwd request " ## s_start_time = "start time " ## s_pwd_received = "pwd received" ############################################## bOK_Send = True ############################ ## fltDistanceAngle = 0.0 ################################################################################## # END VARIABLE DECLEARTIONS ################################################################################## ################################################################################## ################################################################################### # BEGIN CLASS ################################################################################## # Enviromental info container class cEnvermentals(): sTemperatureC = "" sTemperatureF = "" sHumidity = "" sPressure = "0.0" sAltitude = "0.0" sTrending = "" altitude = 0.0 iTrends = [0] iBase = 0 def __init__( self ): self.SealevelPressure = 101325.0 self.Var1 = 0.190295 self.Var2 = 44330.0 self.fltConversion = 133.3223684 self.fltOldPressure = 0.0 self.oTrigger = threading.Event() self.procE = threading.Thread(target = self.fConvertPascelsTo_mmHg ) self.Pascal = 0.0 self.fEnvermentalsInit() def fEnvermentalsInit( self ): self.oTrigger.clear() self.procE.daemon = True self.procE.start() return; def fDoThePressureThing( self, sPressure ): self.Pascal = float( sPressure ) self.oTrigger.set() return; def fConvertPascelsTo_mmHg( self ): while( 1 ): self.oTrigger.wait() ## print( "fConvertPascelsTo_mmHg" ) fltNew = 0.0 fltNew = round( self.Pascal / self.fltConversion, 2 ) # if ( fltNew == self.fltOldPressure ): # self.sTrending = "S" # elif ( fltNew > self.fltOldPressure ): # self.sTrending = "U" # elif ( fltNew < self.fltOldPressure ): # self.sTrending = "D" self.sPressure = str( fltNew ) ## print( "fConvertPascelsTo_mmHg self.sPressure " + self.sPressure ) self.fltOldPressure = fltNew self.bNewReading = False self.fPressureToAltitude( fltNew ) self.fStoreP( fltNew ) self.oTrigger.clear() ## sTemp = "%f\r\n" %( fltOldPressure ) ## ## print ( sTemp ) ## oF = open("PressureTrend.csv", "a+") ## oF.write(sTemp) ## oF.close() return; def fPressureToAltitude(self, fltPressure ): ## calculate altitude in meters if ( fltPressure > 0.0 ): self.altitude = self.Var2 * (1 - pow( (fltPressure/self.SealevelPressure), self.Var1 )) self.sAltitude = str( round(self.altitude, 2) ) ## return; def fStoreC_F_H( self, sTemperatureC, sHumidity): self.sTemperatureC = sTemperatureC self.sHumidity = sHumidity self.sTemperatureF = str( (int(sTemperatureC) * 9 / 5) + 32 ) ## return; def fStoreP( self, fltNew ): if( (self.iTrends[0] == 0) ): self.iTrends[0] = int(fltNew) self.iBase = int(fltNew) elif( len(self.iTrends) < 48 ): self.iTrends.append( int(fltNew) ) elif( len(self.iTrends) >= 48 ): self.iTrends.append( int(fltNew) ) self.iTrends.pop(0) self.iBase = self.iTrends[iZero] return; ################################################################################### # BEGIN CLASS ################################################################################### #Tweak mpu-6050 platform #runs threaded to check platform level ''' mpu gives tilt angle in degrees servo being tourqued in micro seconds (uS) servo at 0 degrees = 1000 uS. Servo to 180 = 2000uS. 1000 steps 1000/180 = 5.555. found 5.554 works better per degree 90+15 = 105 degrees 105 * 5.554 = 583 583+1000= 1583 or a max limit of 105 degrees. Info Position: ## 0 gX ## 1 gY ## 2 gZ ## 3 aX ## 4 aY ## 5 aZ ## 6 X rotation ## 7 y rotation ## 8 lastX ## 9 lastY ## 10 GxRaw ## 11 GyRaw ''' class cMP_Tweak(): def __init__(self, oQs, oQr, oEvent): self.oEvent = oEvent self.cMPU = cMpu6050.cMPU6050() self.oQs = oQs self.oQr = oQr self.bDo = True self.iCount = 0 self.oProcess = mp.Process self.iXgryoInitial = 1475 self.iXgryoHighLimit = 1780 self.iXgryoLowLimit = 1360 self.iYgryoInitial = 1475 self.iYgryoHighLimit = 1778 self.iYgryoLowLimit = 1378 self.sGx = "gX " self.sGy = "gY " self.mpProc = self.oProcess(target = self.fMP_MPUtweaker) def oMP_Start(self): try: self.mpProc.start() self.mpProc.join(None) #stops program from exiting except Exception as e: print("oMP_Start" + str(e)) def fMP_MPUtweaker( self ): bDoGyro = True oTweakerX = self.cPlatformTweaker(self.sGx, self.iXgryoInitial, self.iXgryoHighLimit, self.iXgryoLowLimit, 6, self.oQs) oTweakerY = self.cPlatformTweaker(self.sGy, self.iYgryoInitial, self.iYgryoHighLimit, self.iYgryoLowLimit, 7, self.oQs) oMPU = self.cMPU ## print( "COOLIES tweak init " ) while (self.bDo == True): #### self.oEvent.wait() #see fInt6050CallBack( iChannel ): ## print( "COOLIES tweak triggered " ) #### ## exit process? if ( not self.oQr.empty() ): ## print( "oQr.empty() " ) s = self.oQr.get_nowait() if ( s is not None ): if ( s == "HALT"): ## print( "mpHalt" ) self.bDo = False return; #### ## does not do unless last queued item has been processed if ( self.oQs.empty() ): try: ## print( "self.oQs.empty() " ) #### if (oMPU is None): oMPU = self.cMPU print("oMPU recovery") #### if ( bDoGyro ): ## print( "tweakX" ) oTweakerX.fProcess_MPU6050(oMPU.fReturnMPU_Info()) #### else: ## print( "tweakY" ) oTweakerY.fProcess_MPU6050(oMPU.fReturnMPU_Info()) #### ## print( bDoGyro ) except Exception as e: print( "fMP_MPUtweaker() " + str(e) + " doX " + str(bDoGyro) ) oMPU = None finally: bDoGyro = not bDoGyro self.oEvent.clear() return; def fMP_bDoToFalse(self): self.bDo = False self.mpProc.terminate() ## print( "done COOLIES ") return; class cPlatformTweaker(): def __init__(self, sAxis, iIdeal, iHighLimit, iLowLimit, iInfoPosition, oQ): self.sAxis = sAxis self.fltIdeal = float(iIdeal) self.fltMax = float(iHighLimit) self.fltMin = float(iLowLimit) self.iInfoPosition = iInfoPosition self.fltMaxTorqueAngle = 3.0 self.fltTorqueAngle_uSec = 22.22 self.fltSleepTime = 0.25 self.iRound = 2 self.fltMinTorqueAngle = 0.17 self.fltInitial = self.fltIdeal # default fltIdeal, incase fSetInitialPosition is not used self.oQ = oQ self.bInitialSet = False self.last = 0.0 self.lastOut = int(self.fltInitial) self.fSetInitialPosition() def fSetInitialPosition(self): #set platform to ideal posit at start self.oQ.put(self.sAxis + str(self.fltIdeal)) self.fltInitial = self.fltIdeal self.bInitialSet = True return; def fProcess_MPU6050(self, sMPUInfoIn): sMPU = "" ## using the cMPU6050.py module mpu6050 data is retrived. ## using X or Y gryo info an offset torque angle is derived ## for servo tilt angle correction ##infoposition defines position of data in stream from gyro ## print(sMPUInfoIn) #### sMPU = sMPUInfoIn.split() ## print( self.sAxis ) #### if (self.sAxis == "gX "): #### ## direction magnitude of change fltDir_Mag = float( sMPU[8] ) fltDir_Mag = -(fltDir_Mag * self.fltTorqueAngle_uSec) self.fltIdeal = self.fltInitial - fltDir_Mag ## print( self.fltIdeal ) if( abs(self.fltIdeal - self.fltInitial) > 5 ): self.oQ.put( self.sAxis + str(int(round(self.fltIdeal))) ) #### if (self.sAxis == "gY "): #### ## direction magnitude of change fltDir_Mag = float( sMPU[9] ) fltDir_Mag = fltDir_Mag * self.fltTorqueAngle_uSec self.fltIdeal = self.fltInitial + fltDir_Mag ## print( self.fltIdeal ) if( abs(self.fltIdeal - self.fltInitial) > 2 ): self.oQ.put( self.sAxis + str(int(round(self.fltIdeal))) ) #### ## sTemp = "%f,%f,%f,%f\r\n" %( self.lastX, self.fltIdeal, fltDir_Mag, fltB ) ## print ( sTemp ) ## oF = open("ChappieX.csv", "a+") ## oF.write(sTemp) ## oF.close() #### return; def fCheckMinMax(self, Ideal, Min, Max, Initial): if (Ideal > Max): Ideal = Initial if (Ideal < Min): Ideal = Initial return Ideal; ################################################################################### # BEGIN CLASS ################################################################################### #3/02/2018 class cCalculateVoltage: sVoltageMsg = "waiting" def __init__( self, fltR1, fltR2, fltVoltsNominal, fltVoltsRange ): self.fltR1 = fltR1 self.fltR2 = fltR2 self.fltAD_Factor = 0.0 self.fltDivisorFactor = 0.0 self.fltDivisorFactor = self.fltR1 / self.fltR2 self.fltAD_Factor = 4095 / 3.3 self.fltErrorFactor = 0.0 self.iRound = 2 self.fltZero = 0.0 self.fltVoltsNominal = fltVoltsNominal self.fltVoltsRange = fltVoltsRange self.fltVoltsLow = self.fltVoltsNominal - self.fltVoltsRange self.vRaw = 0.0 self.oTrigger = threading.Event() self.procV = threading.Thread(target = self.fVolts ) self.fVoltsInit() def fVoltsInit( self ): self.oTrigger.clear() self.procV.daemon = True self.procV.start() return; def fDoTheVoltageThing( self, sVRaw ): self.vRaw = float( sVRaw ) self.oTrigger.set() return; ##fltErrorFactor is from sampling Arduino VIN and not volts in directly. volts in measurement is after a arduino volts in protection circuit def fVolts( self ): try: while( 1 ): self.oTrigger.wait() fltVin = self.fltZero fltVin = ( self.vRaw / self.fltAD_Factor ) * self.fltDivisorFactor fltVin += self.fltErrorFactor fltVin = round( fltVin, self.iRound ) self.sVoltageMsg = "%sV %s" %(str(fltVin), str(self.fCalculateVoltsPrecentage( fltVin )) ) self.oTrigger.clear() except Exception as e: print( "cCalculateVoltage.fVolts() " + str(e) ) return; def fCalculateVoltsPrecentage( self, fltVin ): fltVoltsPercent = 0.00 if (fltVin >= self.fltVoltsNominal): fltVoltsPercent = 100.00 else: fltVoltsPercent = self.fltVoltsNominal - fltVin fltVoltsPercent = (fltVoltsPercent / self.fltVoltsRange) * 100 fltVoltsPercent = 100 - fltVoltsPercent GPIO.output(iLowInputVoltage, GPIO.LOW) if ( self.fltVoltsLow <= ( self.fltVoltsNominal - fltVin) ): fltVoltsPercent = 0.00 GPIO.output(iLowInputVoltage, GPIO.HIGH) if (fltVoltsPercent < 10.01): GPIO.output(iLowInputVoltage, GPIO.HIGH) return round( fltVoltsPercent, self.iRound ); ################################################################################## # END CLASS ################################################################################## #def fEmailAlertAlarm(): # fSendMail( str(datetime.datetime.now()) ) # return; #### def fSendMail(sBody): #print("entered send email") if (len(sBody) == iZero): #print("fSendMail(sBody) len 0") sBody = "No data to report<br>" try: if (len(sConstants[iZero])): #print("send mail") ## sFromAddr = sConstants[iSix] ## sToAddr = sConstants[iSeven] sSubject = "Pi report " + str(datetime.datetime.now()) sHeaders = "\r\n".join(["from: " + sConstants[iSix], "subject: " + sSubject, "to: " + sConstants[iSeven], "mime-version: 1.0", "content-type: text/html"]) # body_of_email can be plaintext or html sContent = sHeaders + "\r\n\r\n" + sBody #try: server = smtplib.SMTP("smtp.gmail.com", 587) server.ehlo() server.starttls() server.login( sConstants[iSix], sConstants[8] ) server.sendmail( sConstants[iSix], sConstants[iSeven], sContent ) server.close() #except SMTPAuthenticationError: #print("smtplib.SMTPAuthenticationError") #finally: else: print("password is 0 length") except Exception as e: print("fSendMail(sBody) " + str(e)) return; #################################################################################### #05-02-2018 ''' if password is not returned to pi and arduino told password has been received at pi pi will not continue nor will arduino begin collection and control. A password request disables arduino from data collection. password arrives in fProcessData().most likely password arrives while this routine is asleep. The pwdRcvd is sent to allow arduono to collect and control. ''' #################################################################################### ##def fPWD_Request(): ## ### password request ## if (len(sPWD) == iZero): ## serialPort.write(sPASSWORD.encode('utf-8')) ## #fSendSerial("PASSWORD") ## fDisplayOLED_Message("PWD Wait") ## time.sleep(iTwo) ###### ## if (len(sPWD) != iZero): ## serialPort.write("pwdRcvd".encode('utf-8')) ## time.sleep(iOne) #pause to give arduino time to process ## return True; ## else: ## return False; ## else: ## return False; ################################################################################### # ################################################################################### class cObjectDetection: iDog = 0 sMsg = "" sOLED_AlertMessage = "empty" DistanceLength = 0 oScans = { 0:0 } DistanceAngle = 0 bAspectChangeInProgress = False def __init__( self ): self.oTrigger = threading.Event() self.procOD = threading.Thread(target = self.fObjectDetection ) self.oLockCM = threading.Lock() self.ReturnPulse = 0 self.SignalStrength = 0 self.bMotion = False self.fOD_Init() def fOD_Init( self ): self.oTrigger.clear() self.procOD.daemon = True self.procOD.start() def fDoTheObjectDetectThing( self, sDistanceLength, sSignalStrength, sMotion ): try: self.ReturnPulse = int(sDistanceLength) self.SignalStrength = int( sSignalStrength ) self.bMotion = bool( sMotion ) ## print( "oOD.fDoTheObjectDetectThing 0" ) ## print( self.ReturnPulse ) self.oTrigger.set() except Exception as e: print("oOD.fDoTheObjectDetectThing " + str(e)) return; def fObjectDetection( self ): #sReturnPulse is the echo return from Arduino LIDAR while ( 1 ): ## print( "cObjectDetection.fObjectDetection 1" ) with self.oLockCM: if ( self.oScans[self.DistanceAngle] == 0 ): self.oScans[self.DistanceAngle] = self.ReturnPulse self.DistanceLength = self.ReturnPulse if ( self.DistanceAngle != 0.0 ): #### ## print( "cObjectDetection.fObjectDetection %d " %( self.ReturnPulse ) ) if ( not self.bAspectChangeInProgress ): ## print( "bAspectChange false" ) #### try: ## print( "fObjectDetection 0 " + str((abs(self.DistanceLength - self.ReturnPulse))) + " RTN " + str(self.ReturnPulse) + " DistL: " + str(self.DistanceLength) ) if ( (self.oScans[self.DistanceAngle]!= self.ReturnPulse) and self.bMotion ): if( (self.SignalStrength <= 600) and (self.SignalStrength >= 100) ): ## print( "fObjectDetection1 RTN " + str(self.ReturnPulse) + " DistL: " + str(self.iDistanceLength) ) if ( self.ReturnPulse < self.oScans[self.DistanceAngle]): ## print("alarm? fObjectDetection" ) # as the LIDAR sits in one spot the LIDAR ditstance increases # signal strength falls # if an object moves away not an alert condition # so LIDAR increasing distsnce is not an issue if ( (abs(self.oScans[self.DistanceAngle]- self.ReturnPulse)) > 29 ): ## print( "fObjectDetection 0 diff:" + str((abs(self.oScans[self.DistanceAngle] - self.ReturnPulse))) + " RTN " + str(self.ReturnPulse) + " DistL: " + str(self.iDistanceLength) + " signal " + str(self.SignalStrength) ) ## print( "cObjectDetection.fObjectDetection %d angle:value %d : %d" %( self.ReturnPulse, self.DistanceAngle, self.oScans[self.DistanceAngle]) ) ## sTemp = "%d,%d\r\n" %( self.ReturnPulse, self.SignalStrength ) ## print ( sTemp ) # oF = open("ObjectDetect.csv", "a+") # oF.write(sTemp) # oF.close() self.fTrigger() dt = datetime.datetime.now() ## self.sMsg += str(datetime.datetime.now()) + " " + "Angle " + str(iDistanceAngle) + " Dist " + str(self.iScans[self.iCurrentCell]) + " @cm " + sReturnPulse + " diff: " + str((abs(iDistanceLength - int(sReturnPulse)))) + "<br>" self.sOLED_AlertMessage = "%02d%02d %d @ %scm" %( dt.hour, dt.minute, self.DistanceAngle, self.ReturnPulse ) ## print( "fObjectDetection " + sOLED_AlertMessage ) except Exception as e: print("oOD.fObjectDetection " + str(e)) finally: self.iDog = 0 ## print( "fObjectDetection iDistanceLength = ReturnPulse" ) self.DistanceLength = self.ReturnPulse self.oScans[self.DistanceAngle] = self.ReturnPulse ## print( "finally" ) self.oTrigger.clear() ## oTriggerOLED.set() ## trigger display oAspectChange.set() ## release aspect change self.oTrigger.wait() return; def fTrigger( self ): ## print("BBBBBBBuzzzzzzzzz") GPIO.output(iPinBuzzer0, GPIO.HIGH) time.sleep(.5) GPIO.output(iPinBuzzer0, GPIO.LOW) return; ############################################################################## # ############################################################################## ################################################################################# # f32K( iChannel ): ################################################################################# def f32K( iChannel ): #### oTrigger32K.set() #### return; ################################################################################# # fInt6050CallBack( iChannel ) ################################################################################# def fInt6050CallBack( iChannel ): #### ## multiprocessing event see class cMP_Tweak() allows x y servo correction to be calculated mpTweakerEvent.set() #### return; ################################################################################## # fHaltCallBack() ################################################################################## def fHaltCallback(iChannel): mpQrcv.put_nowait("HALT") mpQsend.close() mpTweakerEvent.set() print("fHaltCallback") return; ################################################################################## # fSerialCallBack() ################################################################################## def fSerialCallBack(iChannel): sReceive = b"" ## print( "fSerialCallBack triggered") try: if serialPort.open: #disable uno from collecting and sending data while Pi is busy processing GPIO.output(iPiReady, GPIO.HIGH) sReceive = serialPort.readline() ## print( "fSerialCallBack triggered") oPS.fProcSerial( sReceive.decode('utf-8') ) else: print("Port", sConstants[iZero], " !open") except: pass finally: #RASPBERRY PI READY if serialPort.open: try: serialPort.flushInput() except: pass return; ################################################################################# # ################################################################################# #def fOnOffCallBack(iChannel): # # global bAlertOnOff # global bAlertWarning # # ##if Alert disabled enable # ##by starting enable sequence # ##see fHandleOnePPS_Triggers # if (bAlertOnOff == False): # bAlertWarning = not bAlertWarning # elif (bAlertOnOff == True): # bAlertOnOff = not bAlertOnOff # # #print("Alert message toggle") # # return; ''' June 15 2018 gpio 18 has an i/p from rtc putting out a 1 pulse per second interrupt if rtc looses power. rtc will loose 1pps. re enable 1pps interrupt from rts open command line, enter " sudo rmmod rtc_ds1307 " run: def fEnableOnePPS(): import smbus bus = smbus.SMBUS(1) ## enable interrupt bus.write_byte_data(0X68, 0X0E, 0x40) ## enable 32kHz out bus.write_byte_data(address, 0x0F, 0x8) return; enter command " sudo modprobe rtc_ds1307 " ''' ################################################################################ # def fHandlePPS_Triggers(): ################################################################################ ''' tic1 640 about 1/8 sec 1480 about 6X a sec 2560 tbd 5120 about 2X sec 10240 about 2 sec 20480 about 4 sec 40860 about 5 sec 83720 about 6.5 sec 167440 about 13 408600 about .6 min ''' def fHandlePPS_Triggers(): ## bDidVolts = False iTic = 1 ## iTic1 = 1 # every tic about 19 seconds while (not bIsGPIO_CleanUp): ## 4 if ( (iTic % 1480) == 0 ): ## ###send serial queue item 6X a sec oTriggerSerialSend.set() ## mpTweakerEvent.set() ## if ( bOKToTweak ): if ( (iTic % 2560) == 0 ): ## ## print( "tweak trigger" ) fSendTweak() mpTweakerEvent.set() ##### # if ( ((iTic % 40860) == iZero) ): # ##about every 6.5 seconds # oTriggerOLED.set() #### oOD.iDog += iOne if ( oOD.iDog == 10240 ): oOD.iDog = 0 oAspectChange.set() ## release aspect change iTic += iOne if ( iTic == 167440 ): iTic = 0 ## iTic1 += iOne #### oTrigger32K.clear() oTrigger32K.wait() return; ################################################################################# # ################################################################################# ################################################################################# ''' When running these routines and sub routines remember arduino has been placed in a Pi not ready state and arduino does not return to a ready state till after fProcessData has returned from the calling function. Sending serial data to the arduino CAN result in data fail to be sent. ''' ################################################################################# # fSendTweak(): ################################################################################# def fSendTweak(): ## print( "GET mpQ 0 " + str(datetime.datetime.now()) ) try: if ( mpQsend.empty() == False ): sTemp = str( mpQsend.get_nowait() ) sTemp += "\n" ## print( "fSendTweak " + sTemp ) q.put( sTemp ) else: while ( mpQsend.empty() == True ): sTemp = mpQsend.get_nowait() #### sTemp = str( mpQsend.get_nowait() ) sTemp += "\n" ## print( "fSendTweak " + sTemp ) q.put( sTemp ) ## print( "GET mpQ 1" ) except: pass return; ################################################################################# # ################################################################################# def fMeasureVoltageArduino(): while (not bIsGPIO_CleanUp): ## print( "fMeasureVoltageArduino" ) q.put( sConstants[iFour] + "\n" ) oDoVolt.clear() oDoVolt.wait() return; ################################################################################# # ################################################################################# def fSendSerial(sToSend0): if (not (GPIO.input(iPiReady))): ## serialPort.flushOutput() sToSend = sToSend0 + "\n" sToSend.replace( " ", "/" ) serialPort.write(sToSend.encode('utf-8')) return; ################################################################################### ### ################################################################################### ## see f32K( iChannel ) def fTh_SendSerial(): ## global bOK_Send sToSend = "" while (not bIsGPIO_CleanUp): ## print( "fTh_SendSerial " + str(datetime.datetime.now()) ) if ( 1 ): ## print( "fTh_SendSerial" ) if ( bOK_Send ): if (not q.empty()): ## print( "fTh_SendSerial" ) sToSend = q.get_nowait() if ( len( sToSend ) >= iOne ): ## bOK_Send = False ## sToSend += "\n" sToSend.replace( " ", "/" ) print( "fTh_SendSerial " + sToSend ) ## serialPort.flushOutput() serialPort.write(sToSend.encode('utf-8')) q.task_done() sToSend = "" oTriggerSerialSend.clear() oTriggerSerialSend.wait() return; ################################################################################# # ################################################################################# ## ################################################################################# # ################################################################################# ''' fltAspectIncrement = 5.554 fltScanAspectChange = 1395.00 #dont put a zero in here bAspectIncrease fltAngleLow = 1395.00 fltAngleMid = 1450 fltAngleHigh = 1505 ''' def fChangeScanAspect(): global fltScanAspectChange ## global bAspectChangeInProgress ## global bFirstAlert global bAspectIncrease ## global fltDistanceAngle #global fltAspectIncrement fltAngleLow = 1375.00 fltAspectIncrement = 5.0 fltAngleHigh = 1575.00 while (not bIsGPIO_CleanUp): try: ## bAspectChangeInProgress= True ## print( "fChangeScanAspect" ) sMessage = "" sMessage = sConstants[iThree] + str(round(fltScanAspectChange, iTwo) ) + "\n" ## print( "fChangeScanAspect " + sMessage ) ## with oLockQput: q.put(sMessage) ## save aspect angle for alert value if ( int(fltScanAspectChange) not in oOD.oScans ): oOD.oScans[int(fltScanAspectChange)] = 0 ## fltDistanceAngle = round(fltScanAspectChange, iTwo) oOD.DistanceAngle = int(fltScanAspectChange) ###### ## #setup next aspect change if ( bAspectIncrease ): ## fltScanAspectChange = fltScanAspectChange + fltAspectIncrement fltScanAspectChange += fltAspectIncrement if ( fltScanAspectChange > fltAngleHigh ): fltScanAspectChange = fltAngleLow oTriggerOLED.set() ## trigger display ##fltScanAspectChange = fltAngleHigh ## bAspectIncrease = not bAspectIncrease # else: # ## fltScanAspectChange = fltScanAspectChange - fltAspectIncrement # fltScanAspectChange -= fltAspectIncrement # if ( fltScanAspectChange < fltAngleLow ): # ##fltScanAspectChange = fltAngleLow # bAspectIncrease = not bAspectIncrease #### except Exception as e: print("fChangeScanAspect() " + str(e)) finally: ## oOD.iDistanceLength = iZero oAspectChange.clear() oAspectChange.wait() return; ################################################################################## # ################################################################################## ################################################################################# # fSendAlertEmail(): # triggered by fHandleOnePPS_Triggers(iChannel): ################################################################################# def fSendAlertEmail(): try: if (len(oOD.sMsg)): oT = threading.Thread(target = fSendMail, args = (oOD.sMsg,)) oT.start() oOD.sMsg = "" except Exception as e: print("fSendAlertEmail " + str(e)) return; ################################################################################# # ################################################################################### class cProcessSerial(): def __init__(self): self.oTrigger = threading.Event() self.procSerial = threading.Thread(target = self.fProcessData ) self.procSerial.start() ## self.oLockCM = threading.Lock() self.sTandH = "" def fProcSerial(self, sTandH ): ## print( "fProcessData " + sTandH) self.sTandH = sTandH ## print( "fProcessData " + self.sTandH) self.oTrigger.set() #### def fProcessData( self ): while (not bIsGPIO_CleanUp): self.oTrigger.wait() ## print( "fProcessData 1") sTemp = "" try: ## print( "fProcessData " + self.sTandH) sTemp = self.sTandH.strip() # for error massage if ( len(self.sTandH) <= iTwo ): return; ## print( "fProcessData " + sTandH) self.sTandH = self.sTandH.strip() self.sTandH = self.sTandH.split() #### if( self.sTandH[iZero] == sConstants[iOne] ): if( self.sTandH[iOne].isdigit() ): ## print( "fProcessData 1") oOD.fDoTheObjectDetectThing( self.sTandH[iOne], self.sTandH[iTwo], self.sTandH[iThree] ) #### elif ( self.sTandH[iZero] == sConstants[iTwo] ) : ##print( sTandH[iZero] + " " + sTandH[iOne] ) oVin.fDoTheVoltageThing( self.sTandH[iOne]) #### elif (self. sTandH[iZero] == sConstants[9] ): oE.fStoreC_F_H( self.sTandH[iOne], self.sTandH[iOne]) #### elif ( self.sTandH[iZero] == "Pa" ): ## print( "fProcessData Pa " + sTandH[iOne] ) oE.fDoThePressureThing( self.sTandH[iOne] ) #### # #### # elif ( sTandH[iZero] == sConstants[4] ): ## receipt of completion of aspect change, allow detecion to resume # bAspectChangeInProgress = False ## print( "aspect complete fProcessData" ) #### else: print("fProcessData(sTandH) else " + sTemp) #### except Exception as e: print( "fProcessData Exception with " + sTemp + " len=" + str(len(sTemp)) + " " + str(e) ) finally: #enable uno to collect and send data self.sTandH = "" ## GPIO.output(iPiReady, GPIO.LOW) self.oTrigger.clear() return; ################################################################################### # ################################################################################### class cRuntime(): def __init__(self): self.iStartTime = int( time.time() ) self.iRunTimeDays = iZero self.iRunTimeHours = iZero self.iRunTimeMinutes = iZero self.iRunTimeSeconds = iZero def fDoRunTime( self ): self.iRunTimeDays = divmod( (int(time.time()) - self.iStartTime), 86400 ) self.iRunTimeHours = divmod( self.iRunTimeDays[iOne], 3600 ) self.iRunTimeMinutes = divmod( self.iRunTimeHours[iOne], 60 ) self.iRunTimeSeconds = self.iRunTimeMinutes[iOne] return "%03d:%02d:%02d:%02d" %( self.iRunTimeDays[iZero], self.iRunTimeHours[iZero], self.iRunTimeMinutes[iZero], self.iRunTimeSeconds); ################################################################################### # ################################################################################### ################################################################################## # ################################################################################### ################################################################################### # ################################################################################### def fSetup(): try: ## GPIO.cleanup() GPIO.setmode(GPIO.BCM) ##triggred by Arduino to indicate serial data has been sent GPIO.setup(iUnoDataReady, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) #causes a signal to be sent-to the attached multiprocessing process to exit GPIO.setup(iHalt, GPIO.IN, pull_up_down = GPIO.PUD_UP) GPIO.setup( iPinInt, GPIO.IN) #pulse per second from rtc ## GPIO.setup( iAlertEmailTimerTrigger, GPIO.IN, pull_up_down = GPIO.PUD_UP ) # alarm from rtc GPIO.setup(iLowInputVoltage, GPIO.OUT) GPIO.setup(iPiReady, GPIO.OUT) GPIO.setup(iPinBuzzer0, GPIO.OUT) #### GPIO.output(iLowInputVoltage, GPIO.LOW) GPIO.output(iPinBuzzer0, GPIO.LOW) #### # event to read serial port GPIO.add_event_detect(iUnoDataReady, GPIO.RISING, callback=fSerialCallBack) #### GPIO.add_event_detect(iHalt, GPIO.FALLING, callback=fHaltCallback) #### GPIO.add_event_detect( iPinInt, GPIO.RISING, callback=f32K) #### ## GPIO.add_event_detect( iAlertEmailTimerTrigger, GPIO.FALLING, callback=fEmailAlertAlarm ) #enable uno to collect and send GPIO.output(iPiReady, GPIO.LOW) serialPort.flushOutput() serialPort.flushInput() except Exception as e: print("fSetup " + str(e)) return; ## return; ################################################################################### # ################################################################################### def fOperatingDisplayOLED(): ## global iOLED_MinuteCount iRowBase = 0 iRow = iRowBase oLock = threading.Lock() while ( not bIsGPIO_CleanUp): font = ImageFont.truetype("FreeMonoBold.ttf", 14, encoding="unic") ## font = ImageFont.truetype("code2000.ttf", 8, encoding="unic") with oLock: try: OLEDdevice.clear() with canvas( OLEDdevice ) as draw: draw.line((0, 32, 90, 32), fill="white") ## draw.line((0, 32, 5, 28), fill="white") # draw.line((0, 32, 45, 1), fill="white") # draw.line((0, 32, 45, 50), fill="white") for key, value in sorted(oOD.oScans.items(), reverse=True): if( oOD.oScans[key] != 0 ): ## print( key ) ## draw.line( (0, iRow, (oOD.oScans[key] / 5), iRow ), fill="white") draw.text( ((oOD.oScans[key] / 5), iRow ), ".", font=font, fill="white" ) iRow += 1 ## print( "Row %d angle %d dist %d %d" %(iRow, key, oOD.oScans[key],(oOD.oScans[key] / 5) ) ) finally: iRow = iRowBase oTriggerOLED.clear() ## oAspectChange.set() ## release aspect change oTriggerOLED.wait() return; def fOperatingDisplayOLED1(): ## global iOLED_MinuteCount iCount = iZero oLock = threading.Lock() while ( not bIsGPIO_CleanUp): font = ImageFont.truetype("FreeMonoBold.ttf", 14, encoding="unic") ## font = ImageFont.truetype("code2000.ttf", 8, encoding="unic") with oLock: try: with canvas( OLEDdevice ) as draw: dt = datetime.datetime.now() sM = "%02d:%02d:%02d" %(dt.hour, dt.minute, dt.second) draw.text( ( 20, iZero ), sM, font=font, fill="white" ) sM = "%02d/%02d/%02d" %( dt.month, dt.day, dt.year ) draw.text( ( 0, 15 ), sM, font=font, fill="white" ) draw.text( ( 85, 15 ), str(oOD.DistanceLength), font=font, fill="white" ) if( (iCount == iZero) or (iCount == iOne) ): draw.text( (iZero, 30), oVin.sVoltageMsg, font=font, fill="white" ) if( (iCount == iTwo) or (iCount == iThree) ): draw.text( (iZero, 30), "Run:" + oRT.fDoRunTime(), font=font, fill = iOne ) elif( (iCount == iFour) or (iCount == iFive) ): draw.text( (iZero, 30), oE.sTemperatureC + "C " + oE.sTemperatureF + "F " + oE.sHumidity + "%", font=font, fill=iOne ) elif( (iCount == iSix) or (iCount == iSeven) ): draw.text((iZero, 30), oE.sPressure + " mmHg " + oE.sTrending, font=font, fill=iOne ) elif( (iCount == 8) or (iCount == 9) ): draw.text((iZero, 30), "Alt:" + oE.sAltitude + "m", font=font, fill=iOne ) elif( (iCount == 10) or (iCount == 11) ): draw.text((iZero, 30), "Z:" + str(round(fltScanAspectChange, iTwo)), font=font, fill=iOne ) ## iTrends[] if( len(oE.iTrends) < 2 ): draw.line((iZero, 55, 5, 55), fill="white") else: x = 0 yBase = 55 y1 = yBase Pbase = oE.iTrends[iZero] for i in oE.iTrends: ## drawLine(x,y1,x+1,y2,color) ## draw line between previous reading and current y2 = yBase - (i - Pbase) draw.line((x, y1, x + 1, y2), fill="white") y1 = y2; ## Make current reading previous x = x + 2 ## print( "x:" + str(x) + " y:" + str(y) + " len:" + str(len(oE.iTrends)) + " trend;" + str(i) ) ## draw.line((iZero, 55, 5, 55), fill="white") ## draw.text((0, 0), oVin.sVoltageMsg, fill=1) ## draw.text((0, 0), oVin.sVoltageMsg, fill=1) iCount += 1 if( iCount >= 12 ): iCount = iZero finally: oTriggerOLED.clear() oTriggerOLED.wait() return; ################################################################################### # ################################################################################### #def fDisplayOLED_Message(sOLED_Message1, sOLED_Message2 =""): # # oled.cls() # oled.canvas.text((0,19), sOLED_Message1, fill=1) # if (len(sOLED_Message2)): # oled.canvas.text((0, 29), sOLED_Message2, fill=1) # # oled.display() # # return; ################################################################################### # read from rtc eeprom ################################################################################### class cEEPROM_READ: def __init__(self): self.EEPROMbus = smbus.SMBus(1) self.Device_Address = 0x57 def read_AT24C32_byteSeq(self, EEPROM_Memory_Address ): return self.EEPROMbus.read_byte(self.Device_Address); def set_current_AT24C32_address( self, EEPROM_Memory_Address ): a1 = int( EEPROM_Memory_Address/256 ) a0 = int( EEPROM_Memory_Address % 256 ) self.EEPROMbus.write_i2c_block_data( self.Device_Address, a1, [a0] ) return; ## def read_AT24C32_byte( self, EEPROM_Memory_Address ): ## self.set_current_AT24C32_address( EEPROM_Memory_Address ) ## return self.EEPROMbus.read_byte( self.Device_Address ); def fReadEEPROM( self, iStartingAddress, iEndingAddress ): sString = "" sTemp = b"" for iX in range( iStartingAddress, iEndingAddress ): if ( iX < (iEndingAddress - 1) ): sTemp = bytes( [self.read_AT24C32_byteSeq(iX)] ) sString = sString + sTemp.decode('utf-8') return sString; ################################################################################### # ################################################################################### def fDoTheThing(): global bIsGPIO_CleanUp global oMP #a must have try: #### oMP = cMP_Tweak(mpQsend, mpQrcv, mpTweakerEvent ) #### fSetup() #### #serial sending thread oTriggerSerialSend.clear()#see 32K handler procSerialSendQueue = threading.Thread(target = fTh_SendSerial) procSerialSendQueue.daemon = True procSerialSendQueue.start() #### ## oAspectChange.clear() procDoAspectChange = threading.Thread(target = fChangeScanAspect) procDoAspectChange.daemon = True procDoAspectChange.start() #### oDoVolt.clear() procDoVolts = threading.Thread(target = fMeasureVoltageArduino) procDoVolts.daemon = True procDoVolts.start() #### oTriggerOLED.clear() procOLED = threading.Thread(target = fOperatingDisplayOLED) procOLED.daemon = True procOLED.start() #### ## PPS Thread oTrigger32K.clear() proc32KTrigger = threading.Thread(target = fHandlePPS_Triggers) proc32KTrigger.daemon = True proc32KTrigger.start() #### oOD.sMsg = "Start time %s" %( str(time.time()) ) fSendAlertEmail() # ## join blocks this function from completing # ## press halt-switch for exit oMP.oMP_Start() # wait for stop # GPIO.wait_for_edge(iHalt, GPIO.FALLING) #### except Exception as e: print("fDoTheThing() " + str(e)) finally: bIsGPIO_CleanUp = True ## allow threads time to begin exit time.sleep(.05) #release threads to detect bIsGPIO_CleanUp = True or bResetTimePassed = False oAspectChange.set() oTriggerSerialSend.set() oTrigger32K.set() oTriggerOLED.set() time.sleep(.10) GPIO.remove_event_detect( iPinInt ) GPIO.remove_event_detect( iUnoDataReady ) GPIO.cleanup() ## serialPort.close() ## return; oRT = cRuntime() ################################################################################### # begin get string constants from eeprom ################################################################################### # get constants from EEPROM oE_Read = cEEPROM_READ() oE_Read.set_current_AT24C32_address( 0xC8 ) sConstants = oE_Read.fReadEEPROM( 0xC8, 0x13E ) oE_Read = None sConstants = sConstants.split( "^" ) ## print( sConstants[iZero] ) ################################################################################### # end getting constants from eeprom ################################################################################### ''' 0 = serial port 1 = cm 2 = VOLT 3 = AspectCng 4 = AspectComplete 6 = from 7 = to 9 = TH ''' ################# initialize serial port serialPort = serial.Serial( sConstants[iZero], 115200, timeout = 1) ################# end initialize serial port #### oPS = cProcessSerial() oVin = cCalculateVoltage( 100600, 10000, 8.1, 5.0 ) oE = cEnvermentals() oOD = cObjectDetection() OLEDdevice = ssd1306() #### fDoTheThing()
Compartilhar