Skip to content

Commit

Permalink
GUI improvements - interrupt improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Hydrosys4 committed Apr 21, 2020
1 parent 90c34f4 commit f99dbbf
Show file tree
Hide file tree
Showing 22 changed files with 1,149 additions and 257 deletions.
194 changes: 156 additions & 38 deletions HWcontrol.py

Large diffs are not rendered by default.

213 changes: 213 additions & 0 deletions SlowWire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
"""
This file holds the SlowWire communication protocol class
"""
#!/usr/bin/env python
from __future__ import print_function

import time # this is in python 2.7 which does not have the routine "time.perf_counter" in python 2.7 need a way to operate
import sys
import logging

logger = logging.getLogger("hydrosys4."+__name__)

try:
# Python >= 3.3
from time import perf_counter
default_timer = time.perf_counter

except ImportError:
# Python < 3.3
if sys.platform == "win32":
# On Windows, the best timer is time.clock()
default_timer = time.clock
else:
# On most other platforms the best timer is time.time()
default_timer = time.time

import RPi.GPIO as GPIO


class SlowWire:
"""
HX711 represents chip for reading load cells.
"""

def __init__(self,dout_pin): # accept integer
self._dout_pin = dout_pin
self._t_init_low=0.020 # s
self._t_wait_sensor=2 # s
GPIO.setup(self._dout_pin, GPIO.OUT) # set pin to out, and to level high
GPIO.output(self._dout_pin, 1)
self.MAXCOUNT=1000
self.MAXSAMPLING=10000




def read_bytes(self): # return a tuple with boolean for OK and array of bytes (isOK, List)

MAXCOUNT=self.MAXCOUNT
MAXSAMPLING=self.MAXSAMPLING


#Set pin to output.
GPIO.setup(self._dout_pin, GPIO.OUT)
GPIO.output(self._dout_pin, 1)
time.sleep(0.001)
# Set pin low for t_init_low milliseconds. This will tell the sensor to start measuring and get beck the data
GPIO.output(self._dout_pin, 0)
time.sleep(self._t_init_low)
GPIO.output(self._dout_pin, 1)
time.sleep(0.001)
#Set pin to imput, ready to receive data. Configuration pull-up
GPIO.setup(self._dout_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

cyclewait=0.001
numcycles=int(self._t_wait_sensor/cyclewait)
print ("numero di cicli --------------------------->", numcycles)

# Wait for sensor to pull pin low.
count = 0
while (GPIO.input(self._dout_pin))and(numcycles>count):
count=count+1
time.sleep(cyclewait)

print ("Conta --------------------------->", count)
if (count >= numcycles):
# Timeout waiting for response.
print ("error reading the SlowWire sensor: Wait too long for sensor answer")
logger.error("error reading the SlowWire sensor: Wait too long for sensor answer")
return False,0

# Record pulse widths for the self.PULSES bits expected from the sensor
LowpulseCounts=[]
HighpulseCounts=[]
n=MAXSAMPLING
exitcondition=False
while (n>0)and(not exitcondition):
#for i in range(0,self.PULSES*2,2): # i starts from zero and increase by +2
# Count how long pin is low and store in pulseCounts[i]
thispulsecount=0
while (not GPIO.input(self._dout_pin))and(not exitcondition):
thispulsecount=thispulsecount+1
time.sleep(0.0001)
if (thispulsecount >= MAXCOUNT):
# Timeout waiting for pulse lenght.
exitcondition=True
if (not exitcondition)and(thispulsecount):
LowpulseCounts.append(thispulsecount)

# Count how long pin is high and store in pulseCounts[i+1]
thispulsecount=0
while GPIO.input(self._dout_pin)and(not exitcondition):
thispulsecount=thispulsecount+1
time.sleep(0.0001)
if (thispulsecount >= MAXCOUNT):
# Timeout waiting for pulse lenght.
exitcondition=True
if (not exitcondition)and(thispulsecount):
HighpulseCounts.append(thispulsecount)

print ("High pulse count ------------------------------------>", HighpulseCounts)
#check data consistency:
if len(HighpulseCounts)>7:
print ("lenghts High=%d Low=%d ", len(HighpulseCounts),len(LowpulseCounts))
if not ((len(HighpulseCounts)+1)==len(LowpulseCounts)):
#data mismatch
print ("error reading the SlowWire sensor: Data mismatch ")
logger.error("error reading the SlowWire sensor: Data mismatch ")
return False,0
else:
print ("error reading the SlowWire sensor: Insufficient data")
logger.error("error reading the SlowWire sensor: Insufficient data")
return False,0


# Compute the average low pulse width in terms of number of samples
# Ignore the first readings because it is not relevant.
threshold = 0
for i in range(1,len(LowpulseCounts)): # i starts from 2 and increase by +2
threshold = threshold + LowpulseCounts[i]

threshold /= len(LowpulseCounts)-1
threshold /=2
print("Slow Wire Threshold: -------------------------------------------- ", threshold)
#Interpret each high pulse as a 0 or 1 by comparing it to the average size of the low pulses.

data=[]
databyte=0
# skip the first 1 pulse
for i in range(1,len(HighpulseCounts)):
databyte = (databyte >> 1)
if (HighpulseCounts[i] <= threshold):
# One bit for long pulse.
databyte |= 0x80
# Else zero bit for short pulse.
if (i%8==0): # got one byte
data.append(databyte)
databyte=0


print("Slow Wire Data: -------------------------------------------- ", data)
for item in data:
print("The hexadecimal data" , hex(item))



# Verify checksum of received data.
if len(data)>=2:
if self.checkCRC(data):
print ("CRC OK --------------------")
data.pop() # remove last byte from list as this is the CRC
return True, data
else:
print ("error reading the SlowWire sensor: Data Checksum error")
logger.error("error reading the SlowWire sensor: Data Checksum error")
return False,0
else:
print ("error reading the SlowWire sensor: Not enough bites of data")
logger.error("error reading the SlowWire sensor: Not enough bites of data")

return False,0



def TwoBytesOneInt(self, byteslist): # return array of int grouping two bytes togeter
# return it to integer
intlist=[]
for i in range(0,len(byteslist)-1,2):
result = (byteslist[i+1] << 8) + byteslist[i]
intlist.append(result)
# debugging
print("Int Data: -------------------------------------------- ", intlist)
return intlist


def read_uint(self):
uintlist=[]
isOK, byteslist = self.read_bytes()
if isOK:
uintlist = self.TwoBytesOneInt(byteslist)
if uintlist:
return True, uintlist
return False, 0

def AddToCRC(self, b, crc):
generator=0x1D
crc ^= b
for i in xrange(8):
if ((crc & 0x80) != 0):
crc = (crc << 1) ^ generator
else:
crc <<= 1
crc= crc & 0xFF
return crc

def checkCRC(self, byteslist): # input is a list of bytes, the last byte should be the CRC code sent by the transmitter
check = 0x00
for i in byteslist:
check = self.AddToCRC(i, check)
if (check==0):
return True
return False

6 changes: 3 additions & 3 deletions actuatordbmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ def getAllActuatorDataPeriodv2(enddate,pastdays):
num = int(pastdays)
tdelta=timedelta(days=num)
startdate=enddate-tdelta
print " actuatordbmod"
print " stratdate " ,startdate
print " enddate ", enddate
#print " actuatordbmod"
#print " stratdate " ,startdate
#print " enddate ", enddate
outputallsensordata=[]
sensorlist=gettablelist()
for selsensor in sensorlist:
Expand Down
2 changes: 1 addition & 1 deletion autofertilizerdbmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def getrowdata(recordvalue,paramlist,index): #for parameters with array of integ
try:
datalist.append(int(ln[param][index]))
except Exception, e:
print 'Failed to load value ',param ,' set value to zero. Error: '+ str(e)
#print 'Failed to load value ',param ,' set value to zero. Error: '+ str(e)
datalist.append(0)

return datalist
Expand Down
2 changes: 1 addition & 1 deletion automationdbmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def getrowdata(recordvalue,paramlist,index): #for parameters with array of integ
try:
datalist.append(int(ln[param][index]))
except Exception, e:
print 'Failed to load value, set value to zero. Error: '+ str(e)
#print 'Failed to load value, set value to zero. Error: '+ str(e)
datalist.append(0)

return datalist
Expand Down
2 changes: 1 addition & 1 deletion autowateringdbmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def getrowdata(recordvalue,paramlist,index): #for parameters with array of integ
try:
datalist.append(int(ln[param][index]))
except Exception, e:
print 'Failed to load value, set value to zero. Error: '+ str(e)
#print 'Failed to load value, set value to zero. Error: '+ str(e)
datalist.append(0)

return datalist
Expand Down
62 changes: 62 additions & 0 deletions changelog/change
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,68 @@ Verified clock setting behavior, when the Internet connection is present the set

- Force rfkill to unlock wlan

2020-03-25 -> release 113d

- create the slowwire interface for the digital hygrometer

2020-03-26 -> release 113e

- more work on the SlowWire protocol, add CRC check

2020-04-06 -> release 113g

- add sensor value reading in the logs
- add 3 repeat reading for the SlowWire when got CRC error.

2020-04-06 -> release 113g

- add sensor value reading in the logs
- add 3 repeat reading for the SlowWire when got CRC error.

2020-04-11 -> release 114

- Add option for frequency counter in interrupt
- Rework the interrupt data recording system, add an InterruptFrequencyCounter which report the frequency. New row in the hardware setting, same PIN of the interrupt.

2020-04-11 -> release 115

- Home page add the enable disable buttons (check / uncheck) , should be better tested.

2020-04-14 -> release 115a

- added AutomationHATv10 hardware rpeset
- interrupt counter working even without setting the association between interrupt and actuator.
- interrupt event set to 1 when start Event and Zero when stop blocking mode, multiple events overlap managed as sum.

2020-04-14 -> release 115b

- interrupt event fix visualization.

2020-04-14 -> release 115c

- Added other inputs panel in homepage

2020-04-14 -> release 115d

- Improve the interrupt event data graph
- Fix the startup when the interrups should occurr at level
- Associate the StopPulse at the disable button (Enable/Disable only for pulse type output)

2020-04-17 -> release 115e

- Fix enable/disable

2020-04-17 -> release 115g-h

- Add the delay proportional to the bouncetime to identify interrupt firstEdge/SecondEdge

2020-04-20 -> release 116

- Improve the reset for interrupt, tune bouncetime.

2020-04-20 -> release 116a

- Improve interrupt Counter Algorithm.


------- Future releases: -----------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_1", "pin": "5", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_2", "pin": "6", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_3", "pin": "12", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_4", "pin": "13", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_5", "pin": "19", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_6", "pin": "16", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_7", "pin": "26", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay1_8", "pin": "20", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_1", "pin": "14", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_2", "pin": "4", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_3", "pin": "15", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_4", "pin": "18", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_5", "pin": "17", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_6", "pin": "27", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_7", "pin": "23", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "output", "controllercmd": "pulse", "logic": "neg", "measure": "Time", "name": "Relay2_8", "pin": "22", "schedulingtype": "oneshot", "unit": "sec", "usefor": "watercontrol"}
{"IOtype": "input", "controllercmd": "tempsensor", "measure": "Temperature", "name": "tempsensor1", "pin": "24", "schedulingtype": "periodic", "time": "00:15:05", "unit": "C", "usefor": "temperaturecontrol"}
{"IOtype": "input", "controllercmd": "humidsensor", "measure": "Humidity", "name": "humidsensor1", "pin": "24", "schedulingtype": "periodic", "time": "00:15:03", "unit": "%", "usefor": "humiditycontrol"}
{"IOtype": "input", "controllercmd": "pressuresensor", "measure": "Pressure", "name": "pressuresensor1", "pin": "I2C", "schedulingtype": "periodic", "time": "00:15:01", "unit": "hPa", "usefor": "Pressurecontrol"}
{"IOtype": "input", "controllercmd": "lightsensor", "measure": "Light", "name": "lightsensor1", "pin": "I2C", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Lum", "usefor": "lightcontrol"}
{"ADCchannel": "0", "IOtype": "input", "controllercmd": "analogdigital", "direction": "dir", "logic": "pos", "measure": "Moisture", "name": "Analog0", "pin": "SPI", "powerpin": "N/A", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "1", "IOtype": "input", "controllercmd": "analogdigital", "direction": "dir", "logic": "pos", "measure": "Moisture", "name": "Analog1", "pin": "SPI", "powerpin": "N/A", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "2", "IOtype": "input", "controllercmd": "analogdigital", "direction": "dir", "logic": "pos", "measure": "Moisture", "name": "Analog2", "pin": "SPI", "powerpin": "N/A", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "3", "IOtype": "input", "controllercmd": "analogdigital", "direction": "dir", "logic": "pos", "measure": "Moisture", "name": "Analog3", "pin": "SPI", "powerpin": "N/A", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "4", "IOtype": "input", "controllercmd": "analogdigital", "direction": "dir", "logic": "pos", "max": "", "measure": "Moisture", "min": "", "name": "Analog4", "offset": "", "pin": "SPI", "powerpin": "N/A", "scale": "", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "5", "IOtype": "input", "controllercmd": "analogdigital", "direction": "dir", "logic": "pos", "max": "4.01", "measure": "Moisture", "min": "0", "name": "Analog5_15v", "offset": "", "pin": "SPI", "powerpin": "N/A", "scale": "12", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "6", "IOtype": "input", "controllercmd": "analogdigital", "direction": "inv", "logic": "pos", "max": "5", "measure": "Moisture", "min": "0", "name": "Hygrometer1", "pin": "SPI", "powerpin": "25", "scale": "100", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"ADCchannel": "7", "IOtype": "input", "controllercmd": "analogdigital", "direction": "inv", "logic": "pos", "max": "5", "measure": "Moisture", "min": "0", "name": "Hygrometer2", "pin": "SPI", "powerpin": "7", "scale": "100", "schedulingtype": "periodic", "time": "00:15:01", "unit": "Volt", "usefor": "Moisturecontrol"}
{"IOtype": "output", "address": "", "controllercmd": "mail+info+link", "measure": "Mail", "name": "mail1", "schedulingtype": "oneshot", "time": "10:00", "title": "Hydrosys today report", "unit": "pcs", "usefor": "mailcontrol"}
{"IOtype": "output", "address": "", "controllercmd": "mail+info", "measure": "Mail", "name": "mail2", "schedulingtype": "oneshot", "time": "10:00", "title": "Hydrosys today report", "unit": "pcs", "usefor": "mailcontrol"}
{"IOtype": "output", "controllercmd": "photo", "measure": "Photo", "name": "photo", "schedulingtype": "oneshot", "time": "09:30", "unit": "pcs", "usefor": "photocontrol"}
{"ADCchannel": "0", "IOtype": "output", "address": "", "controllercmd": "servo", "frequency": "50", "logic": "pos", "max": "12", "measure": "Percentage", "min": "2", "name": "servo1", "pin": "21", "powerpin": "N/A", "schedulingtype": "oneshot", "time": "", "title": "", "unit": "C", "usefor": "N/A"}
{"IOtype": "input", "controllercmd": "returnzero", "measure": "Time", "name": "TimeTrigger", "pin": "N/A", "schedulingtype": "periodic", "time": "00:05:00", "unit": "%", "usefor": "N/A"}
Loading

0 comments on commit f99dbbf

Please sign in to comment.