123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /*********
- Blinkinlove / Materix
- Techno-romantic jewelery based on
- Adafruit Feather HUZZAH boards and
- 4*8 NeoPixel Matrix FeatherWings
- *********/
-
- #define DEBUG true
-
- #define BUTTON_PIN 2
- #define PSEUDO_GND 14 // physically close to button. Set to LOW at setup
- #define DEBOUNCE_MILLIS 250
- unsigned long last_press = 0;
- bool is_active = false;
-
-
- #include "config.h"
-
- #include <Adafruit_NeoPixel.h>
-
- // 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 <PGMWrap.h>
-
- int8_p heart0[8 * 4] PROGMEM = {
- 0, 16, 64, 0, 116, 16, 0, 0,
- 0, 64, 32, 64, 32, 144, 0, 0,
- 0, 0, 128, 48, 128, 0, 0, 0,
- 0, 0, 0, 128, 0, 0, 0, 0
- };
-
- int8_p heart1[8 * 4] PROGMEM = {
- 0, 32, 160, 0, 160, 32, 0, 0,
- 0, 192, 64, 128, 64, 192, 0, 0,
- 0, 0, 192, 96, 192, 0, 0, 0,
- 0, 0, 0, 192, 0, 0, 0, 0
- };
-
- void drawImage(int8_p *img, int rscale, int gscale, int bscale) {
- for (int i = 0; i < 8 * 4; i++) {
- int level = img[i];
- strip.setPixelColor(i, strip.Color((level * rscale) / 100, (level * gscale) / 100, (level * bscale) / 100));
- }
- 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 SCAN_FRAME_DURATION 200
- #define SCAN_COMMON_COLOR_YANG strip.Color(16, 0, 64)
- #define SCAN_ANIM_COLOR_YANG strip.Color(16, 0, 128)
- #define SCAN_COMMON_COLOR_YIN strip.Color(64, 0, 16)
- #define SCAN_ANIM_COLOR_YIN strip.Color(128, 0, 16)
-
- #define NUM_SCAN_ANIM_FRAMES 4
-
- int scan_yang_common[] = { 31, -1};
- int scan_yang_frame_a[] = { 23, -1};
- int scan_yang_frame_b[] = { 15, -1};
- int scan_yang_frame_c[] = { 7, -1};
- int scan_yang_frame_d[] = { -1};
-
- int *scan_anim_frames_yang[NUM_SCAN_ANIM_FRAMES] = {
- scan_yang_frame_a,
- scan_yang_frame_b,
- scan_yang_frame_c,
- scan_yang_frame_d
- };
-
- int scan_yin_common[] = { 31, -1};
- int scan_yin_frame_a[] = { 30, -1};
- int scan_yin_frame_b[] = { 22, -1};
- int scan_yin_frame_c[] = { 23, -1};
-
- int *scan_anim_frames_yin[NUM_SCAN_ANIM_FRAMES] = {
- scan_yin_frame_a,
- scan_yin_frame_b,
- scan_yin_frame_c,
- scan_yin_frame_b
- };
-
-
-
- // 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;
- bool is_yang;
-
- // 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) {
- int rscale = is_yang ? 50 : 100, gscale = 0, bscale = is_yang ? 100 : 75;
- 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], rscale, gscale, bscale);
- current_frame = (current_frame + 1) % NUM_FRAMES;
- last_flip = nowmillis;
- }
- } else {
- drawImage(heart0, rscale, gscale, bscale);
- current_frame = 0;
- }
- if (scanning) {
- // Show scanning indication
- int *frame = is_yang ? scan_yang_common : scan_yin_common;
- for (int i = 0; frame[i] >= 0; i++) {
- strip.setPixelColor(frame[i], is_yang ? SCAN_COMMON_COLOR_YANG : SCAN_COMMON_COLOR_YIN);
- }
- if (!rssi) {
- int frame_index = (nowmillis / SCAN_FRAME_DURATION) % NUM_SCAN_ANIM_FRAMES;
- frame = is_yang ? scan_anim_frames_yang[frame_index] : scan_anim_frames_yin[frame_index];
- for (int i = 0; frame[i] >= 0; i++) {
- strip.setPixelColor(frame[i], is_yang ? SCAN_ANIM_COLOR_YANG : SCAN_ANIM_COLOR_YIN);
- }
- }
- }
- strip.show();
- }
-
- void setup()
- {
- Serial.begin(115200);
- delay(1000);
-
- pinMode(BUTTON_PIN, INPUT_PULLUP);
- pinMode(PSEUDO_GND, OUTPUT);
- digitalWrite(PSEUDO_GND, LOW);
-
- 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(YIN)) {
- is_yang = false;
- mate_mac = String(YANG);
- } else {
- is_yang = true;
- mate_mac = String(YIN);
- }
- WiFi.softAP(String("blinkinlove:") + my_mac.substring(12), "whereartthou");
- }
-
- void loop()
- {
- unsigned long nowmillis = millis();
- if ((nowmillis < last_press || nowmillis > last_press + DEBOUNCE_MILLIS) && digitalRead(BUTTON_PIN) == LOW) {
- last_press = nowmillis;
- is_active = !is_active;
- if (DEBUG) {
- Serial.print("is_active set to ");
- Serial.println(is_active);
- }
- if (!is_active) {
- for (int i = 0; i < NEOPIXEL_COUNT; i++) {
- strip.setPixelColor(i, strip.Color(0, 0, 0));
- }
- strip.show();
- }
-
- }
- if (is_active) {
- 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);
- }
|