Mercurial > code > home > repos > homeauto
changeset 34:90ff65ccd46b
garage: videoselect and shiftbrite move from parallel to arduino
Ignore-this: 45c791caa87d4c054826020eeae8298b
author | drewp@bigasterisk.com |
---|---|
date | Mon, 25 Jun 2012 00:50:33 -0700 |
parents | c3c203100e06 |
children | 912a3dae5c2c |
files | service/garageArduino/garage/garage.pde service/garageArduino/garageArduino.py service/garageArduino/index.html |
diffstat | 3 files changed, 155 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/service/garageArduino/garage/garage.pde Mon May 07 00:17:40 2012 -0700 +++ b/service/garageArduino/garage/garage.pde Mon Jun 25 00:50:33 2012 -0700 @@ -1,4 +1,51 @@ - void setup() { +/* +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); @@ -16,6 +63,21 @@ // 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 + + for (int i=0; i < 1; i++) { + setCurrent(127, 127, 127); + } + Serial.begin(115200); } @@ -74,7 +136,30 @@ 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 < arg / 4; i++) { + setCurrent(127, 127, 127); + } + */ + for (int i=0; i<arg; i++) { + while (Serial.available() == 0) NULL; + SHIFT(Serial.read()); + } + latch(); + Serial.print("{\"ok\":1}\n"); + + } } }
--- a/service/garageArduino/garageArduino.py Mon May 07 00:17:40 2012 -0700 +++ b/service/garageArduino/garageArduino.py Mon Jun 25 00:50:33 2012 -0700 @@ -5,7 +5,7 @@ from __future__ import division -import cyclone.web, json, traceback, os, sys, time, logging +import cyclone.web, json, traceback, os, sys, time, logging, bitstring from twisted.internet import reactor, task, defer from twisted.web.client import getPage sys.path.append("/my/proj/house/frontdoor") @@ -18,6 +18,15 @@ sys.path.append("/my/site/magma") from stategraph import StateGraph from rdflib import Namespace, RDF, Literal +from webcolors import hex_to_rgb, rgb_to_hex + +def rgbFromHex(h): + """returns tuple of 0..1023""" + norm = hex_to_rgb(h) + return tuple([x * 4 for x in norm]) + +def hexFromRgb(rgb): + return rgb_to_hex(tuple([x // 4 for x in rgb])) ROOM = Namespace("http://projects.bigasterisk.com/room/") @@ -52,6 +61,25 @@ 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 + """ + current = "".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 = current + out + self.ser.write("\x60\x06" + chr(len(out)) + out) + msg = self.ser.readJson() + assert msg == {"ok":1}, msg class Index(PrettyErrorHandler, cyclone.web.RequestHandler): def get(self): @@ -132,6 +160,23 @@ 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) + post = put + class Application(cyclone.web.Application): def __init__(self, ard, poller): handlers = [ @@ -142,11 +187,13 @@ (r'/housePower/raw', HousePowerRaw), (r'/housePower/threshold', HousePowerThreshold), (r'/garageDoorOpen', GarageDoorOpen), + (r'/videoSelect', VideoSelect), + (r"/brite/(\d+)", Brite), ] - settings = {"arduino" : ard, "poller" : poller} + colors = [(0,0,0)] * 1 # stored 10-bit + 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
--- a/service/garageArduino/index.html Mon May 07 00:17:40 2012 -0700 +++ b/service/garageArduino/index.html Mon Jun 25 00:50:33 2012 -0700 @@ -29,8 +29,12 @@ <p><button type="submit" id="refresh">refresh</button></p> + <p>Bathroom shiftbrite</p> + <div class="colorpicker" id="p0"></div> + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"/> - + <script type="text/javascript" src="http://bigasterisk.com/bathroomLight/static/farbtastic/farbtastic.js"></script> + <link rel="stylesheet" href="http://bigasterisk.com/bathroomLight/static/farbtastic/farbtastic.css" type="text/css" /> <script type="text/javascript"> // <![CDATA[ @@ -71,6 +75,19 @@ } refresh(); $("#refresh").click(refresh); + + $.each([ + ["#p0", "brite/0"], + ], function (i, row) { + var picker = $.farbtastic(row[0], function (newColor) { + $.ajax({ + type: "put", url: row[1], + contentType: "text/plain", data: newColor + }); + }); + $.get(row[1], picker.setColor); + }); + }); // ]]> </script>