diff --git a/SonarDisplay.py b/SonarDisplay.py index b7ab21f..8650c2a 100644 --- a/SonarDisplay.py +++ b/SonarDisplay.py @@ -2,36 +2,44 @@ import ultrasonic import pyb -from ST7735 import NAVY, CYAN, Point, TFTColor +from ST7735 import NAVY, CYAN, TFTColor import terminalfont -ZeroPoint = Point(0, 0) +ZeroPoint = (0, 0) SONAR_DELAY = 100 +MAX_RANGE = 25.0 FONT_HEIGHT = terminalfont.terminalfont["Height"] +NUM_DISTANCES = 4 #The number of distances to use for throwing away anomalies +THRESHOLD = 1.0 #100-15 = blue #15-10 = green #10-5 = yellow #5-0 = red -COLORS = [(0, 255, 0, 0) +COLORS = [(0, 255, 0, 0), (5, 255, 255, 0), (10, 0, 255, 0), - (15, 0, 0, 255), + (15, 0, 255, 255), + (20, 0, 0, 255) ] +def round( aValue ) : + '''Round float value to 2 decimal places''' + return (aValue - (aValue % 0.01)) + def getrgb( aDistance ) : '''Get an interpolated TFTColor based on distance. Uses the COLORS list.''' clr = NAVY def interp(l, v0, v1): - return (v0 * (1.0 - l) + (v1 * l)) + return int(v0 * (1.0 - l) + (v1 * l)) for i in range(1, len(COLORS)) : - c = colors[i] + c = COLORS[i] if c[0] >= aDistance: - rng0, r0, g0, b0 = colors[i - 1] + rng0, r0, g0, b0 = COLORS[i - 1] rng1, r1, g1, b1 = c #interpolate between rng0 and rng1 l = (aDistance - rng0) / float(rng1 - rng0) @@ -39,6 +47,7 @@ def getrgb( aDistance ) : g = interp(l, g0, g1) b = interp(l, b0, b1) clr = TFTColor(r,g,b) + break return clr @@ -46,24 +55,26 @@ class RangePoint(object): """Display a point on the screen""" def __init__(self, aSize): - self.size = aSize - self.pos = Point(-1, 0) + self.size = (50, aSize) + self.pos = (-1, 0) self.prevdistance = -1 def update( self, aDisplay, aDistance, aTime ) : if (self.prevdistance != aDistance): self._draw(aDisplay, 0) clr = getrgb(aDistance) - self.pos.x = int((aDisplay.size.x / 2) - (self.size / 2)) - y = min(1.0, aDistance / MAXRANGE) - self.pos.y = int(y * aDisplay.size.y) + y = min(1.0, aDistance / MAX_RANGE) + self.pos = (int((aDisplay.size[0] / 2) - (self.size[0] / 2)), int(y * aDisplay.size[1] - self.size[1])) self._draw(aDisplay, clr) self.prevdistance = aDistance def _draw( self, aDisplay, aColor ) : - if self.pos.x >= 0: + if self.pos[0] >= 0: aDisplay.fillrect(self.pos, self.size, aColor) +def wrap( aVal, aMax ) : + return aVal if aVal < aMax else 0 + class SonarDisplay(object): """Display HC-SR04 distance on ST7735 LCD with text and a box""" def __init__( self, aDisplay, aTrigger, aEcho ): @@ -71,12 +82,32 @@ class SonarDisplay(object): self.triggerpin = aTrigger self.echopin = aEcho self.rangepoint = RangePoint(4) + self.curdistance = 0.0 + self.distances = [0.0] * NUM_DISTANCES + self.distindex = 0 self.hc = ultrasonic.Ultrasonic(self.triggerpin, self.echopin) def printdistance( self, aDistance ) : - s = "I: " + str(aDistance) - aDisplay.fillrect(ZeroPoint, Point(aDisplay.size.x, FONT_HEIGHT), 0) - aDisplay.drawstring(ZeroPoint, s, CYAN, terminalfont.terminalfont) + s = "I:" + str(round(aDistance)) + self.display.fillrect(ZeroPoint, (self.display.size[0], FONT_HEIGHT), 0) + self.display.text(ZeroPoint, s, CYAN, terminalfont.terminalfont) + + def _getdistance( self ) : + '''Throw away changes that are not averaged. This introduces + a slight delay in update but gets rid of most bad distances''' + + d = self.hc.distance_in_inches() + good = 0 + for c in self.distances : + if abs(c - d) < THRESHOLD: + good += 1 + if good > 2: + self.curdistance = d + break + + self.distances[self.distindex] = d + self.distindex = wrap(self.distindex + 1, NUM_DISTANCES) + return self.curdistance def run( self ): self.display.fill(0) @@ -84,7 +115,8 @@ class SonarDisplay(object): lasttime = pyb.millis() while sw() == False : pyb.delay(SONAR_DELAY) - distance = self.hc.distance_in_inches() + distance = self._getdistance() + thistime = pyb.millis() t = thistime - lasttime self.printdistance(distance) diff --git a/bombs.py b/bombs.py index d9b3186..0c59be8 100644 --- a/bombs.py +++ b/bombs.py @@ -1,7 +1,7 @@ import pyb import time -from ST7735 import Point, CYAN, RED, GREEN, YELLOW, TFTColor +from ST7735 import CYAN, RED, GREEN, YELLOW, TFTColor #todo: Pick a ransom spot, random radius, random color #todo: Animate the spot @@ -45,15 +45,15 @@ class bomber(object): self.sw = pyb.Switch() def addbomb( self ) : - x = int(randval(self.display.size.x)) - y = int(randval(self.display.size.y)) + x = int(randval(self.display.size[0])) + y = int(randval(self.display.size[1])) rad = randval(20) + 5 r = pyb.rng() & 0xFF g = pyb.rng() & 0xFF b = pyb.rng() & 0xFF spd = randval(30.0) + 1.0 clr = TFTColor(r,g,b) #colorA[pyb.rng() & 0x03] - self.bombs.insert(0, bomb(Point(x, y), rad, clr, spd)) + self.bombs.insert(0, bomb((x, y), rad, clr, spd)) def run( self ) : while self.sw() == False : diff --git a/level.py b/level.py index 62c3bdf..c582160 100644 --- a/level.py +++ b/level.py @@ -1,18 +1,18 @@ #Show level bubble run by the accelerometer import pyb -from ST7735 import RED, CYAN, Point +from ST7735 import RED, CYAN import terminalfont -ZeroPoint = Point(0, 0) +ZeroPoint = (0, 0) class Bubble(object): """Circle simulating the level bubble.""" def __init__(self, aCenter, aSpeed, aRadius, aColor): - self.center = aCenter.clone() - self.pos = aCenter.clone() - self.oldpos = pos.clone() + self.center = aCenter + self.pos = aCenter + self.oldpos = self.pos self.speed = aSpeed self.radius = aRadius self.color = aColor @@ -23,16 +23,14 @@ class Bubble(object): # xtilt = self.accel.x() # ytilt = self.accel.y() - xs = (aDisplay.size.x / 2) / 70.0 - ys = (aDisplay.size.y / 2) / 60.0 + xs = (aDisplay.size[0] / 2) / 70.0 + ys = (aDisplay.size[1] / 2) / 60.0 - self.oldpos.x = self.pos.x - self.oldpos.y = self.pos.y - self.pos.x = int(self.center.x + xtilt * xs) - self.pos.y = int(self.center.y - ytilt * ys) + self.oldpos = self.pos + self.pos = (int(self.center[0] + xtilt * xs), int(self.center[1] - ytilt * ys)) s = "x: " + str(xtilt) + " y: " + str(ytilt) - aDisplay.fillrect(ZeroPoint, Point(aDisplay.size.x, 10), 0) - aDisplay.drawstring(ZeroPoint, s, CYAN, terminalfont.terminalfont) + aDisplay.fillrect(ZeroPoint, (aDisplay.size[0], 10), 0) + aDisplay.text(ZeroPoint, s, CYAN, terminalfont.terminalfont) # aTime *= self.speed # self.pos.x += xtilt * aTime # self.pos.y -= ytilt * aTime @@ -47,20 +45,19 @@ class Bubble(object): def _clamp( self, aDisplay ) : l = self.radius t = l - r = aDisplay.size.x - l - b = aDisplay.size.y - l - self.pos.x = max(l, min(self.pos.x, r)) - self.pos.y = max(t, min(self.pos.y, b)) + r = aDisplay.size[0] - l + b = aDisplay.size[1] - l + self.pos = (max(l, min(self.pos[0], r)), max(t, min(self.pos[1], b))) class Level(object): """Simulate a level by controlling a bubble on the aDisplay controlled by the accelerometer.""" def __init__(self, aDisplay): self.display = aDisplay - center = aDisplay.size.clone() - center.x /= 2 - center.y /= 2 - self.bubble = Bubble(center, 10.0, 5, RED) + cx, cy = aDisplay.size + cx /= 2 + cy /= 2 + self.bubble = Bubble((cx, cy), 10.0, 5, RED) def run( self ) : self.display.fill(0)