Techno-romantic jewlery based on Adafruit Feather HUZZAH and NeoPixel Matrix Featherwing
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

blinkinlove-materix.ino 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*********
  2. * Blinkinlove / Materix
  3. * Techno-romantic jewelery based on
  4. * Adafruit Feather HUZZAH boards and
  5. * 4*8 NeoPixel Matrix FeatherWings
  6. *********/
  7. #include "config.h"
  8. #include <Adafruit_NeoPixel.h>
  9. // Which pin on the Arduino is connected to the NeoPixels?
  10. // Default for the featherwing is 16, but for Huzzah it can't work
  11. // 15 is recommended (requires cutting 16 jumper and soldering 15)
  12. #define NEOPIXEL_PIN 15
  13. // How many NeoPixels are attached to the Arduino?
  14. #define NEOPIXEL_COUNT (4*8)
  15. Adafruit_NeoPixel strip(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
  16. #include <PGMWrap.h>
  17. int8_p heart0[8 * 4 * 3] PROGMEM = {
  18. 0, 0, 0, 16, 0, 0, 64, 0, 0, 0, 0, 0, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0,
  19. 0, 0, 0, 64, 0, 0, 32, 0, 0, 60, 0, 0, 29, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0,
  20. 0, 0, 0, 0, 0, 0, 125, 1, 1, 48, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  21. 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  22. };
  23. int8_p heart1[8 * 4 * 3] PROGMEM = {
  24. 0, 0, 0, 32, 0, 0, 160, 0, 0, 0, 0, 0, 185, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
  25. 0, 0, 0, 160, 0, 0, 64, 0, 0, 120, 0, 0, 58, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0,
  26. 0, 0, 0, 0, 0, 0, 190, 1, 1, 96, 0, 0, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  27. 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  28. };
  29. void drawImage(int8_p *img) {
  30. for (int i = 0; i < 8 * 4; i++) {
  31. strip.setPixelColor(i, strip.Color(img[i * 3], img[i * 3 + 1], img[i * 3 + 2]));
  32. }
  33. strip.show();
  34. }
  35. #define NUM_FRAMES 9
  36. int8_p *frames[NUM_FRAMES] = {
  37. heart1, heart1, heart0,
  38. heart1, heart1, heart0,
  39. heart0, heart0, heart0
  40. };
  41. #define DURATION_FAST 30
  42. #define DURATION_SLOW 300
  43. int current_frame = 0;
  44. unsigned long last_flip = 0;
  45. #define NUM_SCAN_PIXELS 4
  46. int scan_pixels[NUM_SCAN_PIXELS] = { 31, 23, 15, 7 };
  47. #define SCAN_FRAME_DURATION 200
  48. // Zzzen vanity logo (scrolls after reset)
  49. int8_p zzzen[24 * 4] PROGMEM = {
  50. 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 0, 0, 255, 0, 0, 255,
  51. 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 255, 128, 128, 255, 0, 255, 255, 0, 255,
  52. 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 255, 255,
  53. 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 255, 0, 255, 0, 0, 255
  54. };
  55. void scrollZzzen(int offs) {
  56. for (int y = 0; y < 4; y++) {
  57. for (int x = 0; x < 8; x++) {
  58. int xoffs = x+offs, level = 0;
  59. if (xoffs>=0 && xoffs<24) {
  60. level = zzzen[24*y+xoffs];
  61. }
  62. strip.setPixelColor(8 * y + x, strip.Color(0, 0, level));
  63. }
  64. }
  65. strip.show();
  66. }
  67. #include "ESP8266WiFi.h"
  68. #define SCAN_INTERVAL 6000
  69. unsigned long next_scan = 0;
  70. String my_mac;
  71. String mate_mac;
  72. #define RSSI_NEAR -20
  73. #define RSSI_FAR -100
  74. int rssi = 0;
  75. bool scanning = false;
  76. // set rssi to mate's rssi (0 if not found)
  77. void checkScanResult(int numResults) {
  78. rssi = 0;
  79. if (numResults == 0) {
  80. if (DEBUG) {
  81. Serial.println("no networks found");
  82. }
  83. } else {
  84. if (DEBUG) {
  85. Serial.print(numResults);
  86. Serial.println(" networks found");
  87. }
  88. for (int i = 0; i < numResults; ++i) {
  89. if (mate_mac.equals(WiFi.BSSIDstr(i))) {
  90. rssi = WiFi.RSSI(i);
  91. break;
  92. }
  93. }
  94. }
  95. if (DEBUG) {
  96. Serial.print(mate_mac);
  97. if (rssi) {
  98. Serial.print(" RSSI: ");
  99. Serial.println(rssi);
  100. } else {
  101. Serial.println(" not found");
  102. }
  103. }
  104. scanning = false;
  105. }
  106. // Show heart animation frame according to rssi)
  107. // If scanning: indicate that (animation if no rssi, single pixel otherwise)
  108. void animate(int rssi, bool scanning, unsigned long nowmillis) {
  109. if (rssi) {
  110. int duration = constrain(
  111. map(rssi, RSSI_NEAR, RSSI_FAR, DURATION_FAST, DURATION_SLOW),
  112. DURATION_FAST, DURATION_SLOW);
  113. if ((nowmillis - last_flip) > duration || nowmillis < last_flip) {
  114. drawImage(frames[current_frame]);
  115. current_frame = (current_frame + 1) % NUM_FRAMES;
  116. last_flip = nowmillis;
  117. }
  118. } else {
  119. drawImage(heart0);
  120. current_frame = 0;
  121. }
  122. if (scanning) {
  123. if (rssi) {
  124. strip.setPixelColor(scan_pixels[0], strip.Color(0, 0, 16));
  125. } else {
  126. int bright = (nowmillis / SCAN_FRAME_DURATION) % NUM_SCAN_PIXELS;
  127. for (int i = 0; i < NUM_SCAN_PIXELS; i++) {
  128. int blueness = i == bright ? 64 : i < bright ? 16 : 0;
  129. strip.setPixelColor(scan_pixels[i], strip.Color(0, 0, blueness));
  130. }
  131. }
  132. strip.show();
  133. }
  134. }
  135. void setup()
  136. {
  137. Serial.begin(115200);
  138. delay(1000);
  139. strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  140. strip.setBrightness(32); // (max = 255)
  141. strip.show(); // Turn OFF all pixels ASAP
  142. for (int offs = -23 ; offs < 25; offs++) {
  143. scrollZzzen(offs);
  144. delay(100);
  145. }
  146. my_mac = WiFi.softAPmacAddress();
  147. if (DEBUG) {
  148. Serial.print("My MAC: ");
  149. Serial.println(my_mac);
  150. }
  151. if (my_mac.equals(HERS)) {
  152. mate_mac = String(HIS);
  153. } else {
  154. mate_mac = String(HERS);
  155. }
  156. WiFi.softAP(String("blinkinlove:") + my_mac.substring(12), "whereartthou");
  157. }
  158. void loop()
  159. {
  160. unsigned long nowmillis = millis();
  161. if (nowmillis > next_scan) {
  162. if (DEBUG) {
  163. Serial.print("Scanning for ");
  164. Serial.println(mate_mac);
  165. }
  166. scanning = true;
  167. WiFi.scanNetworksAsync(checkScanResult);
  168. next_scan = nowmillis + SCAN_INTERVAL;
  169. }
  170. animate(rssi, scanning, nowmillis);
  171. delay(20);
  172. }