changeset 842:1f69e77411ba

add shiftbrites to bedroom arduino Ignore-this: c0ce65f20b52679af58b9e31bcc3cf2e darcs-hash:20120825212045-312f9-46f810a9229b60efb4db1200b17397c60c17c178
author drewp <drewp@bigasterisk.com>
date Sat, 25 Aug 2012 14:20:45 -0700
parents ddc2cdbfde50
children 9d7f9c487634
files service/bedroomArduino/bed/bed.pde service/bedroomArduino/bedroomArduino.py
diffstat 2 files changed, 111 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/service/bedroomArduino/bed/bed.pde	Tue Aug 07 23:24:10 2012 -0700
+++ b/service/bedroomArduino/bed/bed.pde	Sat Aug 25 14:20:45 2012 -0700
@@ -63,12 +63,66 @@
 #define SWITCH_SELECT_B 9
 #define SWITCH_SELECT_C 8
 #define SPEAKER_CHOICE 13
+#define SHIFTBRITE_L 5
+#define SHIFTBRITE_D 11
+#define SHIFTBRITE_C 12
+
+unsigned long SB_CommandPacket;
+int SB_CommandMode;
+int SB_BlueCommand;
+int SB_RedCommand;
+int SB_GreenCommand;
+
+#define LEDCHANS 5
+int vals[LEDCHANS * 3];
+
+#define SHIFT(val) shiftOut(SHIFTBRITE_D, SHIFTBRITE_C, MSBFIRST, val)
+
+void SB_SendPacket() {
+   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(SHIFTBRITE_L, HIGH); // latch data into registers
+   delayMicroseconds(100);
+   digitalWrite(SHIFTBRITE_L, LOW); 
+}
+void refresh() {
+  /* send all pixels */
+  SB_CommandMode = B00;
+  for (int pixel=0; pixel < LEDCHANS; pixel++) {
+    SB_RedCommand = vals[pixel * 3 + 0];
+    SB_GreenCommand = vals[pixel * 3 + 1];
+    SB_BlueCommand = vals[pixel * 3 + 2];
+    SB_SendPacket();
+  } 
+  latch();
+}
+void setCurrent(unsigned char r, unsigned char g, unsigned char 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 DC-SS015 from http://www.gadgettown.com/Pyroelectric-Infrared-PIR-Motion-Sensor-Detector-Module-E2013.html
+// PIR sensor DC-SS015 from http://www.gadgettown.com/Pyroelectric-Infrared-PIR-Motion-Sensor-Detector-Module-E2013.html but that didn't work well, so I got one from dealextreme that does. It's on analog 4 right now, not D2.
 
   pinMode(SWITCH_X, INPUT); digitalWrite(SWITCH_X, LOW);
   pinMode(SWITCH_Y, INPUT); digitalWrite(SWITCH_Y, LOW);
@@ -77,7 +131,13 @@
   pinMode(SWITCH_SELECT_B, OUTPUT);
   pinMode(SWITCH_SELECT_C, OUTPUT);
   pinMode(SPEAKER_CHOICE, OUTPUT);
+  pinMode(SHIFTBRITE_L, OUTPUT);
+  pinMode(SHIFTBRITE_D, OUTPUT);
+  pinMode(SHIFTBRITE_C, OUTPUT);
 
+  for (int i=0; i < LEDCHANS; i++) {
+    setCurrent(127, 127, 127);
+  }
   Serial.begin(115200);
 }
 
@@ -88,7 +148,7 @@
 
 void loop()                     
 {
-  unsigned char head, cmd, arg;
+  unsigned char head, cmd, arg, i;
 
   if (Serial.available() >= 3) {
     head = Serial.read();
@@ -131,14 +191,19 @@
       Serial.print(", \"door\":");
       Serial.print(digitalRead(SWITCH_Y));
 
-      Serial.print("}\n");
+      Serial.print(",\"led\":\"v2\"}\n");
     } else if (cmd == 0x02) { // speaker
       digitalWrite(SPEAKER_CHOICE, arg);
       Serial.print("{\"speakerChoice\":");
       Serial.print((int)arg);
       Serial.print("}\n");
+    } else if (cmd == 0x03) { // set leds. arg is the number of data bytes coming
+      while (arg--) {
+	while (Serial.available() < 1) NULL;
+	SHIFT(Serial.read());
+      }
+      latch();
+      Serial.print("{\"ok\":1}\n");
     }
   }
 }
-
-	
--- a/service/bedroomArduino/bedroomArduino.py	Tue Aug 07 23:24:10 2012 -0700
+++ b/service/bedroomArduino/bedroomArduino.py	Sat Aug 25 14:20:45 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
 from twisted.web.client import getPage
 sys.path.append("/my/proj/house/frontdoor")
@@ -14,6 +14,9 @@
 from cycloneerr import PrettyErrorHandler
 from logsetup import log
 
+sys.path.append("/my/proj/pixel/shiftweb")
+from shiftweb import hexFromRgb, rgbFromHex
+
 sys.path.append("/my/site/magma")
 from stategraph import StateGraph      
 from rdflib import Namespace
@@ -34,11 +37,28 @@
     def poll(self):
         self.ser.write("\x60\x01\x00")
         ret = self.ser.readJson()
+        ret['motion'] = int(ret['motion'] > 100)
         return ret
 
     def setSpeakerChoice(self, pillow):
         self.ser.write("\x60\x02" + chr(pillow))
-        return self.ser.readJson() 
+        return self.ser.readJson()
+
+    def setLeds(self, colors):
+        """
+        shift out this sequence of (r,g,b) triples of 10-bit ints
+        The nearest led gets color[0], etc.
+        """
+        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 reversed(colors))
+        out = resetCurrent + out
+        self.ser.write("\x60\x03" + chr(len(out)) + out)
+        msg = self.ser.readJson()
+        assert msg == {"ok":1}, msg
 
 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
     def get(self):
@@ -56,6 +76,18 @@
         ret = self.settings.arduino.setSpeakerChoice(int(self.get_argument('pillow')))
         self.write(ret)
 
+class Brite(PrettyErrorHandler, cyclone.web.RequestHandler):
+    def put(self, which):
+        which = int(which)
+        brites = self.settings.brites
+        if which + 1 > len(brites):
+            brites.extend([(0,0,0)] * (which + 1 - len(brites)))
+        brites[which] = rgbFromHex(self.request.body)
+                          
+        self.settings.arduino.setLeds(brites)
+        self.set_header("Content-Type", "text/plain")
+        self.write("ok")
+
 class GraphPage(PrettyErrorHandler, cyclone.web.RequestHandler):
     def get(self):
         self.set_header("Content-Type", "application/x-trig")
@@ -75,7 +107,7 @@
         self.period = period
         self.lastValues = None
         self.lastPollTime = 0
-        self.lastMotion = False
+        self.lastMotion = None
 
     def assertIsCurrent(self):
         """raise an error if the poll data is not fresh"""
@@ -91,8 +123,8 @@
             except ValueError, e:
                 print e
             else:
-                print newData
-                return
+                #print newData # for testing
+
                 self.lastPollTime = now
                 self.lastValues = newData # for other data besides the blinks
                 self.processMotion(newData['motion'])
@@ -121,7 +153,7 @@
 if __name__ == '__main__':
 
     config = { # to be read from a file
-        'arduinoPort': '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A4001lVK-if00-port0',
+        'arduinoPort': '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A4001nIu-if00-port0',
         'servePort' : 9088,
         'pollFrequency' : 6,
         'boardName' : 'bedroom', # gets sent with updates
@@ -142,5 +174,6 @@
         (r"/", Index),
         (r"/graph", GraphPage),
         (r'/speakerChoice', SpeakerChoice),
-        ], arduino=ard, poller=p))
+        (r'/brite/(\d+)', Brite),
+        ], arduino=ard, poller=p, brites=[]))
     reactor.run()