/********* * Blinkinlove / Materix * Techno-romantic jewelery based on * Adafruit Feather HUZZAH boards and * 4*8 NeoPixel Matrix FeatherWings *********/ #include "config.h" #include // Which pin on the Arduino is connected to the NeoPixels? // Default for the featherwing is 16, but for Huzzah it can't work // 15 is recommended (requires cutting 16 jumper and soldering 15) #define NEOPIXEL_PIN 15 // How many NeoPixels are attached to the Arduino? #define NEOPIXEL_COUNT (4*8) Adafruit_NeoPixel strip(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); #include int8_p heart0[8 * 4 * 3] PROGMEM = { 0, 0, 0, 16, 0, 0, 64, 0, 0, 0, 0, 0, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 32, 0, 0, 60, 0, 0, 29, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 1, 1, 48, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int8_p heart1[8 * 4 * 3] PROGMEM = { 0, 0, 0, 32, 0, 0, 160, 0, 0, 0, 0, 0, 185, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 64, 0, 0, 120, 0, 0, 58, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 1, 1, 96, 0, 0, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void drawImage(int8_p *img) { for (int i = 0; i < 8 * 4; i++) { strip.setPixelColor(i, strip.Color(img[i * 3], img[i * 3 + 1], img[i * 3 + 2])); } strip.show(); } #define NUM_FRAMES 9 int8_p *frames[NUM_FRAMES] = { heart1, heart1, heart0, heart1, heart1, heart0, heart0, heart0, heart0 }; #define DURATION_FAST 30 #define DURATION_SLOW 300 int current_frame = 0; unsigned long last_flip = 0; #define NUM_SCAN_PIXELS 4 int scan_pixels[NUM_SCAN_PIXELS] = { 31, 23, 15, 7 }; #define SCAN_FRAME_DURATION 200 // Zzzen vanity logo (scrolls after reset) int8_p zzzen[24 * 4] PROGMEM = { 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 255, 128, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 255, 0, 255, 0, 0, 255 }; void scrollZzzen(int offs) { for (int y = 0; y < 4; y++) { for (int x = 0; x < 8; x++) { int xoffs = x+offs, level = 0; if (xoffs>=0 && xoffs<24) { level = zzzen[24*y+xoffs]; } strip.setPixelColor(8 * y + x, strip.Color(0, 0, level)); } } strip.show(); } #include "ESP8266WiFi.h" #define SCAN_INTERVAL 6000 unsigned long next_scan = 0; String my_mac; String mate_mac; #define RSSI_NEAR -20 #define RSSI_FAR -100 int rssi = 0; bool scanning = false; // set rssi to mate's rssi (0 if not found) void checkScanResult(int numResults) { rssi = 0; if (numResults == 0) { if (DEBUG) { Serial.println("no networks found"); } } else { if (DEBUG) { Serial.print(numResults); Serial.println(" networks found"); } for (int i = 0; i < numResults; ++i) { if (mate_mac.equals(WiFi.BSSIDstr(i))) { rssi = WiFi.RSSI(i); break; } } } if (DEBUG) { Serial.print(mate_mac); if (rssi) { Serial.print(" RSSI: "); Serial.println(rssi); } else { Serial.println(" not found"); } } scanning = false; } // Show heart animation frame according to rssi) // If scanning: indicate that (animation if no rssi, single pixel otherwise) void animate(int rssi, bool scanning, unsigned long nowmillis) { if (rssi) { int duration = constrain( map(rssi, RSSI_NEAR, RSSI_FAR, DURATION_FAST, DURATION_SLOW), DURATION_FAST, DURATION_SLOW); if ((nowmillis - last_flip) > duration || nowmillis < last_flip) { drawImage(frames[current_frame]); current_frame = (current_frame + 1) % NUM_FRAMES; last_flip = nowmillis; } } else { drawImage(heart0); current_frame = 0; } if (scanning) { if (rssi) { strip.setPixelColor(scan_pixels[0], strip.Color(0, 0, 16)); } else { int bright = (nowmillis / SCAN_FRAME_DURATION) % NUM_SCAN_PIXELS; for (int i = 0; i < NUM_SCAN_PIXELS; i++) { int blueness = i == bright ? 64 : i < bright ? 16 : 0; strip.setPixelColor(scan_pixels[i], strip.Color(0, 0, blueness)); } } strip.show(); } } void setup() { Serial.begin(115200); delay(1000); strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) strip.setBrightness(32); // (max = 255) strip.show(); // Turn OFF all pixels ASAP for (int offs = -23 ; offs < 25; offs++) { scrollZzzen(offs); delay(100); } my_mac = WiFi.softAPmacAddress(); if (DEBUG) { Serial.print("My MAC: "); Serial.println(my_mac); } if (my_mac.equals(HERS)) { mate_mac = String(HIS); } else { mate_mac = String(HERS); } WiFi.softAP(String("blinkinlove:") + my_mac.substring(12), "whereartthou"); } void loop() { unsigned long nowmillis = millis(); if (nowmillis > next_scan) { if (DEBUG) { Serial.print("Scanning for "); Serial.println(mate_mac); } scanning = true; WiFi.scanNetworksAsync(checkScanResult); next_scan = nowmillis + SCAN_INTERVAL; } animate(rssi, scanning, nowmillis); delay(20); }