Buscar

Projeto de Interface de Dados ACC Uno Pi

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()

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Outros materiais