# HG changeset patch
# User drewp@bigasterisk.com
# Date 1555835664 25200
# Node ID 139eee3a17c020f12620c929e269613251b462a1
# Parent 92d01aba812a62b99b3b3f33612d038ad8a6c582
rm old arduino code for a few boards. includes driver for IR sensor taped to power meter; virtualwire communications from garage to bathroom.
Ignore-this: de7e267e47243e122d0d8cc111d4497a
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/bathroom_recv/bathroom_recv.ino
--- a/service/garageArduino/bathroom_recv/bathroom_recv.ino Sun Apr 21 01:33:13 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- board: 'Digispark (Tiny Core)'
- programmer: 'Digispark'
-
- pin 0 DI from radio
- pin 1 DO to radio (and green status led)
- pin 2 SCK to radio
- pin 3 output to LED string
- pin 4 input from garage arduino
- pin 5 output to garage arduino
-
- (attiny85 pin 5 is MOSI, pin 6 is MISO, 7 might be clock)
-
-*/
-#include
-
-#include
-
-// Parameter 1 = number of pixels in strip
-// Parameter 2 = pin number (most are valid)
-// Parameter 3 = pixel type flags, add together as needed:
-// NEO_RGB Pixels are wired for RGB bitstream
-// NEO_GRB Pixels are wired for GRB bitstream
-// NEO_KHZ400 400 KHz bitstream (e.g. FLORA pixels)
-// NEO_KHZ800 800 KHz bitstream (e.g. High Density LED strip)
-Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, 3, NEO_GRB + NEO_KHZ800);
-
-#define SET(i, r, g, b) strip.setPixelColor(i, strip.Color(r, g, b)); strip.show();
-
-int numLeds = 4;
-
-void wakeUpPattern() {
- for (int t = 0; t < 255; t += 2) {
- for (int i = 0; i < numLeds; i++) {
- //SET(i, 255 - t, max(0, 255 - t * 2), max(0, 255 - t * 3));
- SET(i,
- (i % 2) ? (255 - t) : 0,
- (i % 2) ? 0 : (255 - t),
- (i % 2) ? (255 - t) : 0);
- }
- delay(10);
- }
- SET(0, 0, 0, 0);
- SET(1, 0, 0, 0);
- SET(2, 0, 0, 0);
- SET(3, 0, 0, 0);
-}
-
-void blinkFailedMessageError() {
- digitalWrite(1, 1);
- delay(100);
- digitalWrite(1, 0);
-}
-
-void blinkShortBufferError() {
- digitalWrite(1, 1);
- delay(100);
- digitalWrite(1, 0);
- delay(50);
- digitalWrite(1, 1);
- delay(100);
- digitalWrite(1, 0);
-}
-
-void setup() {
- pinMode(1, OUTPUT); // for errors
-
- vw_set_rx_pin(4);
- vw_setup(2000); // Bits per sec
-
- vw_rx_start(); // Start the receiver PLL running
-
- strip.begin();
- strip.show();
-
- wakeUpPattern();
-}
-
-void loop() {
- uint8_t buf[VW_MAX_MESSAGE_LEN];
- uint8_t buflen = VW_MAX_MESSAGE_LEN;
-
- vw_wait_rx();
- int success = vw_get_message(buf, &buflen);
- if (!success) {
- blinkFailedMessageError();
- return;
- }
- if (buflen < numLeds * 3) {
- blinkShortBufferError();
- return;
- }
-
- for (int i=0; i < numLeds; i++) {
- strip.setPixelColor(i, strip.Color(
- buf[i * 3 + 0],
- buf[i * 3 + 1],
- buf[i * 3 + 2]));
- }
- strip.show();
-}
-
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/bathroom_satt/bathroom_satt.ino
--- a/service/garageArduino/bathroom_satt/bathroom_satt.ino Sun Apr 21 01:33:13 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-/*
- - DI from radio
- - DO to radio
- - SCK to radio
- - output to the LED string
- - PIR in
- - room light analog in
- - temp/humid https://github.com/adafruit/DHT-sensor-library
-*/
-
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/garage/garage.ino
--- a/service/garageArduino/garage/garage.ino Sun Apr 21 01:33:13 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-#include
-
-/*
-board is Arduino UNO with '328
- */
-
-int datapin = 7; // DI
-int latchpin = 9; // LI
-int clockpin = 8; // CI
-
-unsigned long SB_CommandPacket;
-int SB_CommandMode;
-int SB_BlueCommand;
-int SB_RedCommand;
-int SB_GreenCommand;
-
-#define SHIFT(val) shiftOut(datapin, clockpin, MSBFIRST, val)
-
-void SB_SendPacket() {
- /* high bits are 00 for color, 01 for current */
- SB_CommandPacket = SB_CommandMode & B11;
- SB_CommandPacket = (SB_CommandPacket << 10) | (SB_BlueCommand & 1023);
- SB_CommandPacket = (SB_CommandPacket << 10) | (SB_RedCommand & 1023);
- SB_CommandPacket = (SB_CommandPacket << 10) | (SB_GreenCommand & 1023);
-
- SHIFT(SB_CommandPacket >> 24);
- SHIFT(SB_CommandPacket >> 16);
- SHIFT(SB_CommandPacket >> 8);
- SHIFT(SB_CommandPacket);
-}
-
-void latch() {
- delayMicroseconds(100);
- digitalWrite(latchpin,HIGH); // latch data into registers
- delayMicroseconds(100);
- digitalWrite(latchpin,LOW);
-}
-
-void setCurrent(byte r, byte g, byte b) {
- /* 127 = max */
- SB_CommandMode = B01; // Write to current control registers
- SB_RedCommand = r;
- SB_GreenCommand = g;
- SB_BlueCommand = b;
- SB_SendPacket();
- latch();
-}
-
-
-void setup() {
-
- pinMode(2, INPUT);
- digitalWrite(2, LOW);
-// PIR sensor on here is a
-// http://octopart.com/555-28027-parallax-708653 in a
-// http://octopart.com/1551ggy-hammond-15686 box
-
- // the phototransistor on analog2 is jameco 2006414
-
- pinMode(3, OUTPUT);
- digitalWrite(3, LOW);
- // this drives a relay for the garage door. There is a
- // LP filter on it so the garage doesn't open if there's
- // an arduino power-on glitch. It may be that atmel has
- // circuitry to prevent such glitches, so a pull-down
- // resistor may be enough. I haven't checked carefully.
-
- pinMode(4, OUTPUT);
- pinMode(5, OUTPUT);
- // video input selector. picks which video input will be multiplexed
- // into the bt848 capture card
-
- pinMode(6, OUTPUT); // front yard light
-
- pinMode(7, OUTPUT); // bathroom shiftbrite data
- pinMode(8, OUTPUT); // bathroom shiftbrite clk
- pinMode(9, OUTPUT); // bathroom shiftbrite latch
-
- vw_set_ptt_pin(11); // waste, but VW will be writing to this
- vw_set_tx_pin(10); // bathroom new virtualwire out
-
- // Bits per sec. Match this in bathroom_recv.
- // The reason to have this anywhere high is to
- // make a color change block the sending arduino
- // for less time.
- // 2000bps -> 120ms PUT requests
- // 8000bps -> 30ms PUT requests, but lots of message errors
- vw_setup(2000);
-
- for (int i=0; i < 1; i++) {
- setCurrent(127, 127, 127);
- }
-
- Serial.begin(115200);
-}
-
-int newBlinks = 0;
-int lastLevel = 0;
-int threshold = 750;
-int hold = 3; // pulse must last this many loops. Guessing-- I don't know the loop rate or the pulse width
-int seenFor = 0;
-
-void loop()
-{
- unsigned char head, cmd, arg;
- int level = analogRead(3) < threshold;
-
- if (level) {
- seenFor++;
- if (seenFor == hold) {
- newBlinks++;
- }
- } else {
- seenFor = 0;
- }
-
- if (Serial.available() >= 3) {
- head = Serial.read();
- if (head != 0x60) {
- Serial.flush();
- return;
- }
- cmd = Serial.read();
- arg = Serial.read();
- Serial.flush();
- if (cmd == 0x00) {
- Serial.print("{\"ok\":true}\n");
- } else if (cmd == 0x01) { // poll
- Serial.print("{\"newBlinks\":");
- Serial.print(newBlinks);
- Serial.print(", \"motion\":");
- Serial.print(digitalRead(2) ? "true" : "false");
- Serial.print("}\n");
- newBlinks = 0;
- } else if (cmd == 0x02) {
- // current level
- Serial.print("{\"z\":");
- Serial.print(analogRead(3));
- Serial.print("}\n");
- } else if (cmd == 0x03) {
- if (arg != 0) {
- threshold = arg << 2;
- }
- Serial.print("{\"threshold\":");
- Serial.print(threshold);
- Serial.print("}\n");
- } else if (cmd == 0x04) {
- digitalWrite(3, arg);
- Serial.print("{\"garage\":");
- Serial.print(arg ? "true" : "false");
- Serial.print("}\n");
- } else if (cmd == 0x05) { // set video
- digitalWrite(4, arg & 1);
- digitalWrite(5, arg & 2);
- Serial.print("{\"videoSelect\":");
- Serial.print(arg);
- Serial.print("}\n");
- } else if (cmd == 0x06) { // talk to shiftbrite
- /*
- one byte for the string length, then a buffer to be shifted
- out to all the shiftbrites
- */
- for (int i=0; i> 2))
- return self.ser.readJson()['threshold']
-
- def setGarage(self, level):
- """set garage door opener pin"""
- self.ser.write("\x60\x04"+chr(int(bool(level))))
- return self.ser.readJson()['garage']
-
- def setVideoSelect(self, chan):
- """set video select bits from 0..3"""
- self.ser.write("\x60\x05"+chr(chan))
-
- return self.ser.readJson()['videoSelect']
-
- def shiftbrite(self, colors):
- """
- shift out this sequence of (r,g,b) triples of 10-bit ints
- """
- resetCurrent = "".join(bitstring.pack("0b01, uint:10, uint:10, uint:10",
- 127, 127, 127).bytes
- for loop in range(len(colors)))
- out = "".join(bitstring.pack("0b00, uint:10, uint:10, uint:10",
- b, r, g).bytes
- for r,g,b in colors)
- out = resetCurrent + out
- self.ser.write("\x60\x06" + chr(len(out)) + out)
- msg = self.ser.readJson()
- assert msg == {"ok":1}, msg
-
- def virtualwire(self, colors):
- """
- send this sequence of (r,g,b) 8-bit triples
- """
- numLeds = 4
- # vw receiver wants data for all leds every time
- colors = (list(colors) + [(0,0,0)] * numLeds)[:numLeds]
- msg = "".join("%s%s%s" % (chr(r), chr(g), chr(b)) for r,g,b in colors)
- self.ser.write("\x60\x07" + chr(len(msg)) + msg)
- msg = self.ser.readJson()
- assert msg == {"sent": 12}, msg
-
-
-class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
- def get(self):
- """
- this is an acceptable status check since it makes a round-trip
- to the arduino before returning success
- """
- self.settings.arduino.ping()
-
- self.set_header("Content-Type", "application/xhtml+xml")
- self.write(open("index.html").read())
-
-class GraphPage(PrettyErrorHandler, cyclone.web.RequestHandler):
- def get(self):
- self.set_header("Content-Type", "application/x-trig")
- g = StateGraph(ROOM['garageArduino'])
- self.settings.poller.assertIsCurrent()
- g.add((DEV['frontDoorMotion'], ROOM['state'],
- ROOM['motion'] if self.settings.poller.lastValues['motion'] else
- ROOM['noMotion']))
- g.add((ROOM['house'], ROOM['usingPower'],
- Literal(self.settings.poller.lastWatts, datatype=ROOM["#watts"])))
- self.write(g.asTrig())
-
-class FrontDoorMotion(PrettyErrorHandler, cyclone.web.RequestHandler):
- def get(self):
- self.set_header("Content-Type", "application/javascript")
- self.settings.poller.assertIsCurrent()
- self.write(json.dumps({"frontDoorMotion" :
- self.settings.poller.lastValues['motion']}))
-
-class HousePower(PrettyErrorHandler, cyclone.web.RequestHandler):
- def get(self):
- self.set_header("Content-Type", "application/javascript")
- self.settings.poller.assertIsCurrent()
- w = self.settings.poller
- self.write(json.dumps({
- "currentWatts" : round(w.lastWatts, 2) if isinstance(w.lastWatts, float) else w.lastWatts,
- "lastPulseAgo" : "%.1f sec ago" % (time.time() - w.lastBlinkTime) if w.lastBlinkTime is not None else "unknown",
- "kwhPerBlink" : w.kwhPerBlink}))
-
-class HousePowerRaw(PrettyErrorHandler, cyclone.web.RequestHandler):
- """
- raw data from the analog sensor, for plotting or picking a noise threshold
- """
- def get(self):
- self.set_header("Content-Type", "application/javascript")
- pts = []
- for i in range(60):
- level = self.settings.arduino.lastLevel()
- pts.append((round(time.time(), 3), level))
-
- self.write(json.dumps({"irLevels" : pts}))
-
-class HousePowerThreshold(PrettyErrorHandler, cyclone.web.RequestHandler):
- """
- the level that's between between an IR pulse and the noise
- """
- def get(self):
- self.set_header("Content-Type", "application/javascript")
- self.settings.poller.assertIsCurrent()
- self.write(json.dumps({"threshold" : thr}))
-
- def put(self):
- pass
-
-class GarageDoorOpen(PrettyErrorHandler, cyclone.web.RequestHandler):
- def post(self):
- self.set_header("Content-Type", "text/plain")
- self.settings.arduino.setGarage(True)
- self.write("pin high, waiting..\n")
- self.flush()
- d = defer.Deferred()
- def finish():
- self.settings.arduino.setGarage(False)
- self.write("pin low. Done")
- d.callback(None)
- reactor.callLater(1.5, finish) # this time depends on the LP circuit
- return d
-
-class VideoSelect(PrettyErrorHandler, cyclone.web.RequestHandler):
- def post(self):
- self.set_header("Content-Type", "application/javascript")
- v = self.settings.arduino.setVideoSelect(int(self.request.body))
- self.write(json.dumps({"videoSelect" : v}))
-
-class Brite(PrettyErrorHandler, cyclone.web.RequestHandler):
- def get(self, chan):
- self.set_header("Content-Type", "text/plain")
- self.write(hexFromRgb(self.settings.colors[int(chan)]))
-
- def put(self, chan):
- s = self.settings
- s.colors[int(chan)] = rgbFromHex(self.request.body)
- #s.arduino.shiftbrite(s.colors)
- s.arduino.virtualwire([(r//4, g//4, b//4) for r,g,b in s.colors])
- post = put
-
-class Application(cyclone.web.Application):
- def __init__(self, ard, poller):
- handlers = [
- (r"/", Index),
- (r"/graph", GraphPage),
- (r"/frontDoorMotion", FrontDoorMotion),
- (r'/housePower', HousePower),
- (r'/housePower/raw', HousePowerRaw),
- (r'/housePower/threshold', HousePowerThreshold),
- (r'/garageDoorOpen', GarageDoorOpen),
- (r'/videoSelect', VideoSelect),
- (r"/brite/(\d+)", Brite),
- ]
- colors = [(0,0,0)] * 4 # stored 10-bit for legacy (or future!) reasons
- settings = {"arduino" : ard, "poller" : poller, "colors" : colors}
- cyclone.web.Application.__init__(self, handlers, **settings)
-
-class Poller(object):
- """
- times the blinks to estimate power usage. Captures the other
- returned sensor values too in self.lastValues
- """
- def __init__(self, ard, period):
- self.ard = ard
- self.period = period
- self.carbon = CarbonClient(serverHost='bang')
- self.lastBlinkTime = None
- self.lastValues = None
- self.lastPollTime = 0
- self.lastWatts = "(just restarted; wait no data yet)"
- self.kwhPerBlink = 1.0 # unsure
- self.lastMotion = False
-
- def assertIsCurrent(self):
- """raise an error if the poll data is not fresh"""
- dt = time.time() - self.lastPollTime
- if dt > period * 2:
- raise ValueError("last poll time was too old: %.1f sec ago" % dt)
-
- def poll(self):
- now = time.time()
- try:
- try:
- newData = ard.poll()
- except ValueError, e:
- print e
- os.abort()
- else:
- self.lastPollTime = now
- self.lastValues = newData # for other data besides the blinks
- self.processBlinks(now, newData['newBlinks'])
- self.processMotion(newData['motion'])
-
- except (IOError, OSError):
- os.abort()
- except Exception, e:
- print "poll error", e
- traceback.print_exc()
-
- def processBlinks(self, now, b):
- if b > 0:
- if b > 1:
- # todo: if it's like 1,1,2,2,2,2,1,1 then we
- # need to subdivide those inner sample periods
- # since there might really be two blinks. But
- # if it's like 0,0,0,2,0,0, that should be
- # treated like b=1 since it's probably noise
- pass
-
- if self.lastBlinkTime is not None:
- dt = now - self.lastBlinkTime
- dth = dt / 3600.
- watts = self.kwhPerBlink / dth
-
- if watts > 20000:
- # this pulse (or the previous one) is
- # likely noise. Too late for the previous
- # one, but we're going to skip this one
- return
- else:
- self.lastWatts = watts
-
- # todo: remove this; a separate logger shall do it
- self.carbon.send('system.house.powerMeter_w', watts, now)
-
- self.lastBlinkTime = now
-
- def processMotion(self, state):
- if state == self.lastMotion:
- return
- self.lastMotion = state
- msg = json.dumps(dict(board='garage',
- name="frontDoorMotion", state=state))
- getPage('http://bang.bigasterisk.com:9069/inputChange',
- method="POST",
- postdata=msg,
- headers={'Content-Type' : 'application/json'}
- ).addErrback(self.reportError, msg)
-
- def reportError(self, msg, *args):
- print "post error", msg, args
-
-if __name__ == '__main__':
-
- config = { # to be read from a file
- 'arduinoPort': '/dev/serial/by-id/usb-Arduino__www.arduino.cc__Arduino_Uno_6493534323335161A2F1-if00',
- 'servePort' : 9050,
- 'pollFrequency' : 5,
- 'boardName' : 'garage', # gets sent with updates
- }
-
- #from twisted.python import log as twlog
- #twlog.startLogging(sys.stdout)
-
- log.setLevel(logging.DEBUG)
-
- ard = ArduinoGarage(port=config['arduinoPort'])
-
- period = 1/config['pollFrequency']
- p = Poller(ard, period)
- task.LoopingCall(p.poll).start(period)
- reactor.listenTCP(config['servePort'], Application(ard, p))
- reactor.run()
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/index.html
--- a/service/garageArduino/index.html Sun Apr 21 01:33:13 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-
-
-
-
- garageArduino
-
-
-
-
-
- garageArduino service
-
- Talking to an arduino uno on host slash
-
- Pulse pin 3 to trigger garage door opener
-
- PIR sensor (in a box) measuring front door motion:
-
- phototransistor watching IR pulses on the power meter: last pulse was ; current power usage is watts (assuming kwh/blink)
-
- Recent raw IR sensor data:
-
-
-
- Bathroom LEDs
- Send first color to all LEDs
-
-
-
-
-
-
-
-
-
-
-
-
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/powermeter/analog-samples.png
Binary file service/garageArduino/powermeter/analog-samples.png has changed
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/powermeter/end-of-day.png
Binary file service/garageArduino/powermeter/end-of-day.png has changed
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/powermeter/sensor.sch
--- a/service/garageArduino/powermeter/sensor.sch Sun Apr 21 01:33:13 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-v 20100214 2
-C 40000 40000 0 0 0 title-B.sym
-C 44400 47000 1 0 0 photo-transistor-1.sym
-{
-T 44200 47500 5 6 0 1 0 0 1
-device=PS2501-1
-T 44660 47100 5 10 1 1 0 0 1
-refdes=Q?
-T 44360 47000 5 10 0 1 0 0 1
-device=photo-transistor
-}
-C 48000 48000 1 180 0 connector5-1.sym
-{
-T 46200 46500 5 10 0 0 180 0 1
-device=CONNECTOR_5
-T 47900 46300 5 10 1 1 180 0 1
-refdes=ARDUINO
-}
-N 44600 47000 44900 46900 4
-N 44900 46900 45900 46900 4
-N 44600 47400 46000 47400 4
-N 46000 47400 46300 47200 4
-C 46200 45600 1 0 0 ground.sym
-N 46400 45900 45900 46900 4
-C 50100 47300 1 180 0 terminal-1.sym
-{
-T 49790 46550 5 10 0 0 180 0 1
-device=terminal
-T 49790 46700 5 10 0 0 180 0 1
-footprint=CONNECTOR 1 1
-T 49850 47250 5 10 1 1 180 6 1
-refdes=~INPUT
-}
-N 49200 47200 47500 47200 4
-C 48800 47200 1 90 0 resistor-1.sym
-{
-T 48400 47500 5 10 0 0 90 0 1
-device=RESISTOR
-T 48500 47400 5 10 1 1 90 0 1
-refdes=20K
-}
-C 48500 48100 1 0 0 vcc-1.sym
-C 44400 49500 1 270 0 led-1.sym
-{
-T 45000 48700 5 10 0 0 270 0 1
-device=LED
-T 44800 48700 5 10 1 1 270 0 1
-refdes=LED?
-T 45200 48700 5 10 0 0 270 0 1
-symversion=0.1
-}
-N 44100 49500 48300 49500 4
-N 48300 48100 48300 49500 4
-N 48300 48100 48700 48100 4
-C 44500 48300 1 270 0 resistor-1.sym
-{
-T 44900 48000 5 10 0 0 270 0 1
-device=RESISTOR
-T 44800 48100 5 10 1 1 270 0 1
-refdes=150
-}
-N 44600 48600 44600 48300 4
-C 48700 45900 1 180 0 connector4-1.sym
-{
-T 46900 45000 5 10 0 0 180 0 1
-device=CONNECTOR_4
-T 48700 44500 5 10 1 1 180 0 1
-refdes=RJ11
-}
-N 47000 44800 44100 44800 4
-N 44100 44800 44100 49500 4
-N 47000 45100 45200 45100 4
-N 45200 45100 45200 47400 4
-N 46400 45900 47000 45900 4
-N 47000 45900 47000 45700 4
diff -r 92d01aba812a -r 139eee3a17c0 service/garageArduino/pydeps
--- a/service/garageArduino/pydeps Sun Apr 21 01:33:13 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-Twisted==12.1.0
-argparse==1.2.1
-bitstring==3.0.2
-cyclone==0.4
-isodate==0.4.8
-pyserial==2.6
-python-dateutil==2.1
-rdflib==3.2.1
-webcolors==1.4