Techno-romantic jewlery based on Adafruit Feather HUZZAH and NeoPixel Matrix Featherwing
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

blinkinlove-materix.ino 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*********
  2. Blinkinlove / Materix
  3. Techno-romantic jewelery based on
  4. Adafruit Feather HUZZAH boards and
  5. 4*8 NeoPixel Matrix FeatherWings
  6. *********/
  7. #define DEBUG true
  8. #define BUTTON_PIN 2
  9. #define PSEUDO_GND 14 // physically close to button. Set to LOW at setup
  10. #define DEBOUNCE_MILLIS 250
  11. unsigned long last_press = 0;
  12. bool is_active = false;
  13. #include "config.h"
  14. #include <Adafruit_NeoPixel.h>
  15. // Which pin on the Arduino is connected to the NeoPixels?
  16. // Default for the featherwing is 16, but for Huzzah it can't work
  17. // 15 is recommended (requires cutting 16 jumper and soldering 15)
  18. #define NEOPIXEL_PIN 15
  19. // How many NeoPixels are attached to the Arduino?
  20. #define NEOPIXEL_COUNT (4*8)
  21. Adafruit_NeoPixel strip(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
  22. #include <PGMWrap.h>
  23. int8_p heart0[8 * 4] PROGMEM = {
  24. 0, 16, 64, 0, 116, 16, 0, 0,
  25. 0, 64, 32, 64, 32, 144, 0, 0,
  26. 0, 0, 128, 48, 128, 0, 0, 0,
  27. 0, 0, 0, 128, 0, 0, 0, 0
  28. };
  29. int8_p heart1[8 * 4] PROGMEM = {
  30. 0, 32, 160, 0, 160, 32, 0, 0,
  31. 0, 192, 64, 128, 64, 192, 0, 0,
  32. 0, 0, 192, 96, 192, 0, 0, 0,
  33. 0, 0, 0, 192, 0, 0, 0, 0
  34. };
  35. void drawImage(int8_p *img, int rscale, int gscale, int bscale) {
  36. for (int i = 0; i < 8 * 4; i++) {
  37. int level = img[i];
  38. strip.setPixelColor(i, strip.Color((level * rscale) / 100, (level * gscale) / 100, (level * bscale) / 100));
  39. }
  40. strip.show();
  41. }
  42. #define NUM_FRAMES 9
  43. int8_p *frames[NUM_FRAMES] = {
  44. heart1, heart1, heart0,
  45. heart1, heart1, heart0,
  46. heart0, heart0, heart0
  47. };
  48. #define DURATION_FAST 30
  49. #define DURATION_SLOW 300
  50. int current_frame = 0;
  51. unsigned long last_flip = 0;
  52. #define SCAN_FRAME_DURATION 200
  53. #define SCAN_COMMON_COLOR_YANG strip.Color(16, 0, 64)
  54. #define SCAN_ANIM_COLOR_YANG strip.Color(16, 0, 128)
  55. #define SCAN_COMMON_COLOR_YIN strip.Color(64, 0, 16)
  56. #define SCAN_ANIM_COLOR_YIN strip.Color(128, 0, 16)
  57. #define NUM_SCAN_ANIM_FRAMES 4
  58. int scan_yang_common[] = { 31, -1};
  59. int scan_yang_frame_a[] = { 23, -1};
  60. int scan_yang_frame_b[] = { 15, -1};
  61. int scan_yang_frame_c[] = { 7, -1};
  62. int scan_yang_frame_d[] = { -1};
  63. int *scan_anim_frames_yang[NUM_SCAN_ANIM_FRAMES] = {
  64. scan_yang_frame_a,
  65. scan_yang_frame_b,
  66. scan_yang_frame_c,
  67. scan_yang_frame_d
  68. };
  69. int scan_yin_common[] = { 31, -1};
  70. int scan_yin_frame_a[] = { 30, -1};
  71. int scan_yin_frame_b[] = { 22, -1};
  72. int scan_yin_frame_c[] = { 23, -1};
  73. int *scan_anim_frames_yin[NUM_SCAN_ANIM_FRAMES] = {
  74. scan_yin_frame_a,
  75. scan_yin_frame_b,
  76. scan_yin_frame_c,
  77. scan_yin_frame_b
  78. };
  79. // Zzzen vanity logo (scrolls after reset)
  80. int8_p zzzen[24 * 4] PROGMEM = {
  81. 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 0, 0, 255, 0, 0, 255,
  82. 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 255, 128, 128, 255, 0, 255, 255, 0, 255,
  83. 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 255, 255,
  84. 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 255, 0, 255, 0, 0, 255
  85. };
  86. void scrollZzzen(int offs) {
  87. for (int y = 0; y < 4; y++) {
  88. for (int x = 0; x < 8; x++) {
  89. int xoffs = x + offs, level = 0;
  90. if (xoffs >= 0 && xoffs < 24) {
  91. level = zzzen[24 * y + xoffs];
  92. }
  93. strip.setPixelColor(8 * y + x, strip.Color(0, 0, level));
  94. }
  95. }
  96. strip.show();
  97. }
  98. #include "ESP8266WiFi.h"
  99. #define SCAN_INTERVAL 6000
  100. unsigned long next_scan = 0;
  101. String my_mac;
  102. String mate_mac;
  103. #define RSSI_NEAR -20
  104. #define RSSI_FAR -100
  105. int rssi = 0;
  106. bool scanning = false;
  107. bool is_yang;
  108. // set rssi to mate's rssi (0 if not found)
  109. void checkScanResult(int numResults) {
  110. rssi = 0;
  111. if (numResults == 0) {
  112. if (DEBUG) {
  113. Serial.println("no networks found");
  114. }
  115. } else {
  116. if (DEBUG) {
  117. Serial.print(numResults);
  118. Serial.println(" networks found");
  119. }
  120. for (int i = 0; i < numResults; ++i) {
  121. if (mate_mac.equals(WiFi.BSSIDstr(i))) {
  122. rssi = WiFi.RSSI(i);
  123. break;
  124. }
  125. }
  126. }
  127. if (DEBUG) {
  128. Serial.print(mate_mac);
  129. if (rssi) {
  130. Serial.print(" RSSI: ");
  131. Serial.println(rssi);
  132. } else {
  133. Serial.println(" not found");
  134. }
  135. }
  136. scanning = false;
  137. }
  138. // Show heart animation frame according to rssi)
  139. // If scanning: indicate that (animation if no rssi, single pixel otherwise)
  140. void animate(int rssi, bool scanning, unsigned long nowmillis) {
  141. int rscale = is_yang ? 50 : 100, gscale = 0, bscale = is_yang ? 100 : 75;
  142. if (rssi) {
  143. int duration = constrain(
  144. map(rssi, RSSI_NEAR, RSSI_FAR, DURATION_FAST, DURATION_SLOW),
  145. DURATION_FAST, DURATION_SLOW);
  146. if ((nowmillis - last_flip) > duration || nowmillis < last_flip) {
  147. drawImage(frames[current_frame], rscale, gscale, bscale);
  148. current_frame = (current_frame + 1) % NUM_FRAMES;
  149. last_flip = nowmillis;
  150. }
  151. } else {
  152. drawImage(heart0, rscale, gscale, bscale);
  153. current_frame = 0;
  154. }
  155. if (scanning) {
  156. // Show scanning indication
  157. int *frame = is_yang ? scan_yang_common : scan_yin_common;
  158. for (int i = 0; frame[i] >= 0; i++) {
  159. strip.setPixelColor(frame[i], is_yang ? SCAN_COMMON_COLOR_YANG : SCAN_COMMON_COLOR_YIN);
  160. }
  161. if (!rssi) {
  162. int frame_index = (nowmillis / SCAN_FRAME_DURATION) % NUM_SCAN_ANIM_FRAMES;
  163. frame = is_yang ? scan_anim_frames_yang[frame_index] : scan_anim_frames_yin[frame_index];
  164. for (int i = 0; frame[i] >= 0; i++) {
  165. strip.setPixelColor(frame[i], is_yang ? SCAN_ANIM_COLOR_YANG : SCAN_ANIM_COLOR_YIN);
  166. }
  167. }
  168. }
  169. strip.show();
  170. }
  171. void setup()
  172. {
  173. Serial.begin(115200);
  174. delay(1000);
  175. pinMode(BUTTON_PIN, INPUT_PULLUP);
  176. pinMode(PSEUDO_GND, OUTPUT);
  177. digitalWrite(PSEUDO_GND, LOW);
  178. strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  179. strip.setBrightness(32); // (max = 255)
  180. strip.show(); // Turn OFF all pixels ASAP
  181. for (int offs = -23 ; offs < 25; offs++) {
  182. scrollZzzen(offs);
  183. delay(100);
  184. }
  185. my_mac = WiFi.softAPmacAddress();
  186. if (DEBUG) {
  187. Serial.print("My MAC: ");
  188. Serial.println(my_mac);
  189. }
  190. if (my_mac.equals(YIN)) {
  191. is_yang = false;
  192. mate_mac = String(YANG);
  193. } else {
  194. is_yang = true;
  195. mate_mac = String(YIN);
  196. }
  197. WiFi.softAP(String("blinkinlove:") + my_mac.substring(12), "whereartthou");
  198. }
  199. void loop()
  200. {
  201. unsigned long nowmillis = millis();
  202. if ((nowmillis < last_press || nowmillis > last_press + DEBOUNCE_MILLIS) && digitalRead(BUTTON_PIN) == LOW) {
  203. last_press = nowmillis;
  204. is_active = !is_active;
  205. if (DEBUG) {
  206. Serial.print("is_active set to ");
  207. Serial.println(is_active);
  208. }
  209. if (!is_active) {
  210. for (int i = 0; i < NEOPIXEL_COUNT; i++) {
  211. strip.setPixelColor(i, strip.Color(0, 0, 0));
  212. }
  213. strip.show();
  214. }
  215. }
  216. if (is_active) {
  217. if (nowmillis > next_scan) {
  218. if (DEBUG) {
  219. Serial.print("Scanning for ");
  220. Serial.println(mate_mac);
  221. }
  222. scanning = true;
  223. WiFi.scanNetworksAsync(checkScanResult);
  224. next_scan = nowmillis + SCAN_INTERVAL;
  225. }
  226. animate(rssi, scanning, nowmillis);
  227. }
  228. delay(20);
  229. }