Guest User

network rgb

a guest
Jan 24th, 2017
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.83 KB | None | 0 0
  1.  
  2. [code]
  3. // This #include statement was automatically added by the Particle IDE.
  4. #include "neopixel/neopixel.h"
  5.  
  6.  
  7. #include "application.h"
  8.  
  9. // CONFIGURATION SETTINGS START
  10. // DEBUG SETTINGS:
  11. #define D_SERIAL true
  12. #define D_WIFI true
  13.  
  14. #define NUM_SPARKS 2 // number of Filimins in your group
  15. String sparkId[] = {
  16. "", // 0
  17. "40003400053138333038", // number each Filimin starting at 1. Replace the number in the quotes with Spark ID for Filimin 1
  18. "2d003d00132313031", // Filimin 2
  19.  
  20. };
  21.  
  22.  
  23. // TWEAKABLE VALUES FOR CAP SENSING. THE BELOW VALUES WORK WELL AS A STARTING PLACE:
  24. #define BASELINE_VARIANCE 600.0// the higher the number the less the baseline is affected by current readings. (was 4)
  25. #define SENSITIVITY 8 // Integer. Higher is more sensitive (was 8)
  26. #define BASELINE_SENSITIVITY 16 // Integer. This is a trigger point such that values exceeding this point will not affect the baseline. Higher values make the trigger point sooner. (was 16)
  27. #define SAMPLE_SIZE 512 // 512 // Number of samples to take for one reading. Higher is more accurate but large values cause some latency.(was 32)
  28. #define SAMPLES_BETWEEN_PIXEL_UPDATES 32
  29. #define LOOPS_TO_FINAL_COLOR 150
  30. const int minMaxColorDiffs[2][2] = {
  31. {5,20}, // min/Max if color change last color change from same Filimin
  32. {50,128} // min/Max if color change last color change from different Filimin
  33. };
  34.  
  35. // CONFIGURATION SETTINGS END
  36.  
  37. int sPin = D4;
  38. int rPin = D3;
  39.  
  40. // STATES:
  41. #define PRE_ATTACK 0
  42. #define ATTACK 1
  43. #define DECAY 2
  44. #define SUSTAIN 3
  45. #define RELEASE1 4
  46. #define RELEASE2 5
  47. #define OFF 6
  48.  
  49. #define END_VALUE 0
  50. #define TIME 1
  51.  
  52. // END VALUE, TIME
  53. // 160 is roximately 1 second
  54. const long envelopes[6][2] = {
  55. {0, 0} , // OFF
  56. {255, 30} , // ATTACK
  57. {200, 240}, // DECAY
  58. {200, 1000}, // SUSTAIN
  59. {150, 60}, // RELEASE1
  60. {0, 1000000} // RELEASE2 (65535 is about 6'45")
  61. };
  62.  
  63. // NEOPIXEL
  64. #define PIXEL_PIN D2
  65. #define PIXEL_COUNT 16
  66. #define PIXEL_TYPE WS2812B
  67.  
  68. #define tEVENT_NONE 0
  69. #define tEVENT_TOUCH 1
  70. #define tEVENT_RELEASE 2
  71.  
  72. Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
  73. int currentEvent = tEVENT_NONE;
  74.  
  75. int finalColor = 0; // 0 to 255
  76. int initColor = 0;
  77. int currentColor = 0; // 0 to 255
  78. int brightness = 0; // 0 to 255
  79. int initBrightness = 0; // 0 to 255
  80. uint32_t colorAndBrightness = 0;
  81. int brightnessDistanceToNextState = 0;
  82. int colorChangeToNextState = 0;
  83. unsigned char state = OFF;
  84. unsigned char prevState = OFF;
  85. unsigned char deviceId = 0;
  86. unsigned char lastColorChangeDeviceId = 0;
  87. long loopCount = 0;
  88. long colorLoopCount = 0;
  89. int touchEvent;
  90.  
  91. double tDelayExternal = 0;
  92. double tBaselineExternal = 0;
  93. uint8_t updateServer = tEVENT_NONE;
  94. unsigned char myId = 0;
  95.  
  96. // timestamps
  97. unsigned long tS;
  98. volatile unsigned long tR;
  99.  
  100. // reading and baseline
  101. long tReading;
  102. float tBaseline;
  103.  
  104. void setup()
  105. {
  106. Particle.function("poll", pollLamp);
  107. if (D_SERIAL) Serial.begin(9600);
  108. if (D_WIFI) {
  109. Particle.variable("tDelay", &tDelayExternal, DOUBLE);
  110. Particle.variable("tBaseline", &tBaselineExternal, DOUBLE);
  111. }
  112.  
  113. strip.begin();
  114. strip.show(); // Initialize all pixels to 'off'
  115. pinMode(sPin,OUTPUT);
  116. attachInterrupt(rPin,touchSense,RISING);
  117. for (int i = 1; i < (NUM_SPARKS + 1); i++) {
  118. if (!sparkId[i].compareTo(Particle.deviceID())) {
  119. myId = i;
  120. break;
  121. }
  122. finalColor = random(256);
  123. }
  124.  
  125. for (byte i = 0; i < 1; i++) {
  126. for (byte j=0; j<strip.numPixels(); j++) {
  127. strip.setPixelColor(j, 255, 255, 255);
  128. }
  129. strip.show();
  130. delay(250);
  131. for (byte j=0; j<strip.numPixels(); j++) {
  132. strip.setPixelColor(j, 0,0,0);
  133. }
  134. strip.show();
  135. delay(250);
  136. }
  137. // calibrate touch sensor- Keep hands off!!!
  138. tBaseline = touchSampling(); // initialize to first reading
  139. if (D_WIFI) tBaselineExternal = tBaseline;
  140.  
  141. for (int i =0; i < 256; i++) {
  142. uint32_t color = wheelColor(i,255);
  143. for (byte j = 0; j < strip.numPixels(); j++) {
  144. strip.setPixelColor(j, color);
  145. strip.show();
  146. }
  147. delay(1);
  148. }
  149. for (int j = 255; j >= 0; j--) {
  150. uint32_t color = wheelColor(255, j);
  151. for (byte k = 0; k < strip.numPixels(); k++) {
  152. strip.setPixelColor(k, color);
  153. strip.show();
  154. }
  155. delay(1);
  156. }
  157. }
  158.  
  159. void loop() {
  160. touchEvent = touchEventCheck();
  161. if (touchEvent == tEVENT_TOUCH) {
  162. if (D_SERIAL) Serial.println("touch");
  163. currentEvent = touchEvent;
  164. state = PRE_ATTACK;
  165. } else if (touchEvent == tEVENT_RELEASE) {
  166. if (D_SERIAL) Serial.println("release");
  167. currentEvent = touchEvent;
  168. }
  169. }
  170.  
  171. //============================================================
  172. // Touch UI
  173. //============================================================
  174. //------------------------------------------------------------
  175. // ISR for touch sensing
  176. //------------------------------------------------------------
  177. void touchSense() {
  178. tR = micros();
  179. }
  180.  
  181. //------------------------------------------------------------
  182. // touch sampling
  183. //
  184. // sample touch sensor SAMPLE_SIZE times and get average RC delay [usec]
  185. //------------------------------------------------------------
  186. long touchSampling() {
  187. long tDelay = 0;
  188. int mSample = 0;
  189.  
  190. for (int i=0; i<SAMPLE_SIZE; i++) {
  191. if (!(i % SAMPLES_BETWEEN_PIXEL_UPDATES)) {
  192. stateAndPixelMagic();
  193. }
  194. pinMode(rPin, OUTPUT); // discharge capacitance at rPin
  195. digitalWrite(sPin,LOW);
  196. digitalWrite(rPin,LOW);
  197. pinMode(rPin,INPUT); // revert to high impedance input
  198. // timestamp & transition sPin to HIGH and wait for interrupt in a read loop
  199. tS = micros();
  200. tR = tS;
  201. digitalWrite(sPin,HIGH);
  202. do {
  203. // wait for transition
  204. } while (digitalRead(rPin)==LOW);
  205.  
  206. // accumulate the RC delay samples
  207. // ignore readings when micros() overflows
  208. if (tR>tS) {
  209. tDelay = tDelay + (tR - tS);
  210. mSample++;
  211. }
  212. }
  213.  
  214. // calculate average RC delay [usec]
  215. if ((tDelay > 0) && (mSample>0)) {
  216. tDelay = tDelay/mSample;
  217. } else {
  218. tDelay = 0; // this is an error condition!
  219. }
  220. //if (D_SERIAL) Serial.println(tDelay);
  221. if (D_WIFI) tDelayExternal = tDelay;
  222. //autocalibration using exponential moving average on data below specified point
  223. if (tDelay<(tBaseline + tBaseline/BASELINE_SENSITIVITY)) {
  224. tBaseline = tBaseline + (tDelay - tBaseline)/BASELINE_VARIANCE;
  225. if (D_WIFI) tBaselineExternal = tBaseline;
  226. }
  227. return tDelay;
  228. }
  229.  
  230. //------------------------------------------------------------
  231. // touch event check
  232. //
  233. // check touch sensor for events:
  234. // tEVENT_NONE no change
  235. // tEVENT_TOUCH sensor is touched (Low to High)
  236. // tEVENT_RELEASE sensor is released (High to Low)
  237. //
  238. //------------------------------------------------------------
  239. int touchEventCheck() {
  240. int touchSense; // current reading
  241. static int touchSenseLast = LOW; // last reading
  242.  
  243. static unsigned long touchDebounceTimeLast = 0; // debounce timer
  244. int touchDebounceTime = 50; // debounce time
  245.  
  246. static int touchNow = LOW; // current debounced state
  247. static int touchLast = LOW; // last debounced state
  248.  
  249. int tEvent = tEVENT_NONE; // default event
  250.  
  251. // read touch sensor
  252. tReading = touchSampling();
  253.  
  254. // touch sensor is HIGH if trigger point some threshold above Baseline
  255. if (tReading>(tBaseline + tBaseline/SENSITIVITY)) {
  256. touchSense = HIGH;
  257. } else {
  258. touchSense = LOW;
  259. }
  260.  
  261. // debounce touch sensor
  262. // if state changed then reset debounce timer
  263. if (touchSense != touchSenseLast) {
  264. touchDebounceTimeLast = millis();
  265. }
  266. touchSenseLast = touchSense;
  267.  
  268. // accept as a stable sensor reading if the debounce time is exceeded without reset
  269. if (millis() > touchDebounceTimeLast + touchDebounceTime) {
  270. touchNow = touchSense;
  271. }
  272.  
  273. // set events based on transitions between readings
  274. if (!touchLast && touchNow) {
  275. tEvent = tEVENT_TOUCH;
  276. }
  277.  
  278. if (touchLast && !touchNow) {
  279. tEvent = tEVENT_RELEASE;
  280. }
  281.  
  282. // update last reading
  283. touchLast = touchNow;
  284. return tEvent;
  285. }
  286.  
  287. //============================================================
  288. // NEOPIXEL
  289. //============================================================
  290. //------------------------------------------------------------
  291. // Wheel
  292. //------------------------------------------------------------
  293.  
  294. uint32_t wheelColor(byte WheelPos, byte iBrightness) {
  295. float R, G, B;
  296. float brightness = iBrightness / 255.0;
  297.  
  298. if (WheelPos < 85) {
  299. R = WheelPos * 3;
  300. G = 255 - WheelPos * 3;
  301. B = 0;
  302. } else if (WheelPos < 170) {
  303. WheelPos -= 85;
  304. R = 255 - WheelPos * 3;
  305. G = 0;
  306. B = WheelPos * 3;
  307. } else {
  308. WheelPos -= 170;
  309. R = 0;
  310. G = WheelPos * 3;
  311. B = 255 - WheelPos * 3;
  312. }
  313. R = R * brightness + .5;
  314. G = G * brightness + .5;
  315. B = B * brightness + .5;
  316. return strip.Color((byte) R,(byte) G,(byte) B);
  317. }
  318.  
  319. void updateNeoPixels(uint32_t color) {
  320. for(char i=0; i<strip.numPixels(); i++) {
  321. strip.setPixelColor(i, color);
  322. }
  323. strip.show();
  324. }
  325.  
  326. int pollLamp(String command) {
  327. static int lastServerColorAndTouch = 0;
  328. static bool serverShouldBeUpdated = false;
  329. static unsigned char serverAndLocalDifferentLoopCount = 0;
  330. uint32_t serverResponse = command.toInt();
  331. uint32_t localResponse;
  332. static uint32_t lastLocalResponse;
  333. int serverColorAndTouch = serverResponse & 0x03ff; // color and touch
  334. deviceId = serverResponse >> 10;
  335. int serverTouch = serverColorAndTouch >> 8;
  336. if (D_SERIAL) {
  337. Serial.print("received id: ");
  338. Serial.print(deviceId);
  339. Serial.print(" cmd: ");
  340. Serial.print(serverTouch);
  341. Serial.print(" color: ");
  342. Serial.println(serverColorAndTouch & 0xff);
  343. }
  344. /*
  345. if (((serverColorAndTouch & 0xff) == (lastServerColorAndTouch & 0xff)) && (serverShouldBeUpdated) && false) {
  346. if (D_SERIAL) Serial.println("* SERVER LOST LAST UPDATE. RESENDING");
  347. return lastLocalResponse;
  348. }
  349. */
  350. if ((serverColorAndTouch != lastServerColorAndTouch) &&
  351. (deviceId != myId) &&
  352. (deviceId != 0)) { // server update
  353. serverAndLocalDifferentLoopCount = 0;
  354. if (D_SERIAL) Serial.println("SERVER -> LOCAL");
  355. // if the color changed but we have a release, we missed an event.
  356. // and if so, create the missing event
  357. // TODO: a queue for events would be a better solution but hey, it's Dec 24.
  358. if (((serverColorAndTouch & 0xff) != (lastServerColorAndTouch & 0xff)) &&
  359. (serverTouch == tEVENT_RELEASE)) { // &&
  360. // (finalColor != (serverColorAndTouch & 0xff))) {
  361. serverTouch = tEVENT_TOUCH;
  362. serverColorAndTouch = (serverTouch << 8) + (serverColorAndTouch & 0xff);
  363. if (D_SERIAL) Serial.println("*** missing server touch event created ***");
  364. }
  365. if (updateServer) { // local update
  366. if (D_SERIAL) {Serial.print("----& LOCAL -> SERVER: "); Serial.println(updateServer);}
  367. if (updateServer == tEVENT_TOUCH) {
  368. if (D_SERIAL) Serial.println("---- local touch");
  369. if (serverTouch == tEVENT_TOUCH) {
  370. if (D_SERIAL) Serial.println("---- server touch");
  371. lastColorChangeDeviceId = deviceId;
  372. generateColor();
  373. changeState(ATTACK);
  374. } else {
  375. if (D_SERIAL) Serial.println("---- server release");
  376. generateColor();
  377. }
  378. // serverTouch == touch or release:
  379. localResponse = (myId << 10) + (updateServer << 8) + (finalColor & 0xff);
  380. } else { // local touchEvent == tEVENT_RELEASE
  381. if (D_SERIAL) Serial.println("---- local release");
  382. if (serverTouch == tEVENT_TOUCH) {
  383. if (D_SERIAL) Serial.println("---- server touch");
  384. getColorFromServer(serverColorAndTouch & 0xff);
  385. changeState(ATTACK);
  386. } else { // server and local have tEVENT_RELEASE
  387. if (D_SERIAL) Serial.println("---- server release");
  388. changeState(RELEASE1);
  389. }
  390. localResponse = (deviceId << 10) + serverColorAndTouch;
  391. }
  392. } else { // no local update
  393. if (D_SERIAL) Serial.println("-no local update");
  394. if (serverTouch == tEVENT_TOUCH) {
  395. if (D_SERIAL) Serial.println("--server touch");
  396. getColorFromServer(serverColorAndTouch & 0xff);
  397. changeState(ATTACK);
  398. } else {
  399. if (D_SERIAL) Serial.println("--server release");
  400. changeState(RELEASE1);
  401. }
  402. localResponse = serverResponse;
  403. }
  404. } // no server update
  405. else {
  406. if ((updateServer) || (serverShouldBeUpdated)) {
  407. if (serverShouldBeUpdated) updateServer = tEVENT_TOUCH;
  408. serverShouldBeUpdated = false;
  409. serverAndLocalDifferentLoopCount = 0;
  410. if (D_SERIAL) Serial.println("LOCAL -> SERVER");
  411. localResponse = (myId << 10) + (updateServer << 8) + (finalColor & 0xff);
  412. } else { // no updates at all
  413. if (((finalColor & 0xff) != (serverColorAndTouch & 0xff)) && (deviceId != 0)) {
  414. if (++serverAndLocalDifferentLoopCount > 2) {
  415. //lastColorChangeDeviceId = myId;
  416. serverShouldBeUpdated = true;
  417. if (D_SERIAL) {Serial.println("*** forcing server update");
  418. }
  419. }
  420. }
  421. localResponse = serverResponse;
  422. }
  423. }
  424. if (D_SERIAL) {
  425. Serial.print("sending id: ");
  426. Serial.print(localResponse >> 10 );
  427. Serial.print(" cmd: ");
  428. Serial.print(localResponse >> 8 & 0x03);
  429. Serial.print(" color: ");
  430. Serial.println(localResponse & 0xff);
  431. }
  432. if ((updateServer) && (localResponse != serverResponse)) {
  433. lastLocalResponse = localResponse;
  434. //serverShouldBeUpdated = true;
  435. }
  436. updateServer = tEVENT_NONE;
  437. lastServerColorAndTouch = (serverColorAndTouch == 0 ? lastServerColorAndTouch : serverColorAndTouch);
  438. return localResponse;
  439. }
  440.  
  441. /* INTERRUPTS AND STATES */
  442.  
  443. void generateColor() {
  444. Serial.println("generating color...");
  445. int newColor = finalColor;
  446. if (prevState == OFF) {
  447. finalColor = newColor = currentColor = random(256);
  448. } else {
  449. bool diffId = (lastColorChangeDeviceId != myId);
  450. finalColor += (random(2)*2-1)*
  451. (minMaxColorDiffs[diffId][0] +
  452. random(minMaxColorDiffs[diffId][1]-minMaxColorDiffs[diffId][0]+1));
  453. finalColor = (finalColor + 256) % 256;
  454. // finalColor = 119; // FORCE A COLOR
  455. }
  456. colorChangeToNextState = finalColor - currentColor;
  457. colorChangeToNextState += ((colorChangeToNextState < 0) * 2 - 1) * (abs(colorChangeToNextState) > 127) * 256;
  458. initColor = currentColor;
  459. if (D_SERIAL) {Serial.print("final color: "); Serial.println(finalColor);}
  460. lastColorChangeDeviceId = myId;
  461. }
  462.  
  463. void getColorFromServer(int color) {
  464. finalColor = color;
  465. colorChangeToNextState = finalColor - currentColor;
  466. colorChangeToNextState += ((colorChangeToNextState < 0) * 2 - 1) * (abs(colorChangeToNextState) > 127) * 256;
  467. initColor = currentColor;
  468. if (D_SERIAL) {Serial.print("get Color From Server Final color: "); Serial.print(finalColor); Serial.print(", "); Serial.println(colorChangeToNextState);}
  469. lastColorChangeDeviceId = deviceId;
  470. colorLoopCount = 0;
  471. }
  472.  
  473. void changeState(unsigned char newState) {
  474. if (D_SERIAL) {Serial.print("state: "); Serial.println(newState);}
  475. prevState = state;
  476. state = newState;
  477. loopCount = 0;
  478. initBrightness = brightness;
  479. brightnessDistanceToNextState = envelopes[newState][END_VALUE] - brightness;
  480. }
  481.  
  482. void updatePixelSettings() {
  483. brightness = min(255, max(0, initBrightness + loopCount * brightnessDistanceToNextState / envelopes[state][TIME]));
  484. if (colorLoopCount > LOOPS_TO_FINAL_COLOR) {
  485. currentColor = finalColor;
  486. }
  487. if (currentColor != finalColor) {
  488. currentColor = (initColor + 256 + colorLoopCount * colorChangeToNextState / LOOPS_TO_FINAL_COLOR ) % 256;
  489. }
  490. }
  491.  
  492. void stateAndPixelMagic() {
  493. switch (state) {
  494. case PRE_ATTACK:
  495. generateColor();
  496. updateServer = tEVENT_TOUCH;
  497. changeState(ATTACK);
  498. colorLoopCount = 0;
  499. break;
  500. case ATTACK:
  501. updatePixelSettings();
  502. currentEvent = tEVENT_NONE;
  503. if (loopCount >= envelopes[ATTACK][TIME]) {
  504. changeState(DECAY);
  505. }
  506. break;
  507. case DECAY:
  508. updatePixelSettings();
  509. if ((loopCount >= envelopes[DECAY][TIME]) || (currentEvent == tEVENT_RELEASE)) {
  510. changeState(SUSTAIN);
  511. }
  512. break;
  513. case SUSTAIN:
  514. updatePixelSettings();
  515. if ((loopCount >= envelopes[SUSTAIN][TIME]) || (currentEvent == tEVENT_RELEASE)) {
  516. changeState(RELEASE1);
  517. updateServer = tEVENT_RELEASE;
  518. currentEvent = tEVENT_NONE;
  519. }
  520. break;
  521. case RELEASE1:
  522. updatePixelSettings();
  523. if (loopCount >= envelopes[RELEASE1][TIME]) {
  524. changeState(RELEASE2);
  525. }
  526. break;
  527. case RELEASE2:
  528. updatePixelSettings();
  529. if (loopCount >= envelopes[RELEASE2][TIME]) {
  530. changeState(OFF);
  531. }
  532. break;
  533. case OFF:
  534. brightness = 0;
  535. break;
  536. }
  537. colorAndBrightness = wheelColor(currentColor, brightness);
  538. updateNeoPixels(colorAndBrightness);
  539. loopCount++;
  540. colorLoopCount++;
  541. }
Add Comment
Please, Sign In to add comment