Advertisement
skizziks_53

Photobooth_NanoDuo_USB_Listener

Feb 2nd, 2018
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.89 KB | None | 0 0
  1. /*
  2.    Photobooth NanoDuo LED controller ---- 31 January 2018
  3.    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4.    This sketch uses the current Adafruit Neopixel library.
  5.  
  6.    The NanoDuo is two Arduino Nanos set up to act as a USB adressable-LED controller.
  7.    Using the same Nano to do both jobs seems to result in interrupt conflicts,
  8.        so the task is divided between two Nano boards here.
  9.  
  10.    In the NanoDuo setup, one Nano board receives the USB messages
  11.        and sets eight output pins in a way that represents the current LED settings.
  12.    The second Nano monitors eight input pins, and changes the LED values accordingly.
  13.    The pins used to communicate between the boards are pins D2 through D9, using external 220k pulldown resistors.
  14.  
  15.    This sketch is for the Nano that receives the USB signals.
  16.    The sketch for the other Nano is named "Photobooth NanoDuo LED".
  17.  
  18.    This code was tested with a string of 8 and 64 WS2812 LEDs.
  19.  
  20.    ----------------------------
  21.    PATTERNS NEEDED:
  22.    The 1st letter I assume starts and stops the LEDS. When I run the command in the software for "stop LED", it just sends one message: #0=101 [e]
  23.   The 2nd letter represents the speed. s=slow, m=medium, q=fast
  24.   The number [8] represents a color choice: 1=white, 2=red, 3=green, 4=blue, 5=purple, 6=yellow, 7=cyan, 8=orange
  25.   The final letter represents the pattern. z=spinning wheel, x=right fill, c=left fill, v=right ball, b=left ball
  26.  
  27.  
  28. */
  29.  
  30. char inputLetter;
  31. char messageLetters[4];
  32. int messageCounter = 0;
  33. int serialMessage_timeOut = 500; // This is the milliseconds that a USB control message must complete in before it is reset.
  34. // I just guessed at this value, 9600 baud is about 960 characters per second.
  35. // Note that the length of this waiting period is how long it will take to turn off the lights.
  36. unsigned long serialMessage_beginTime = 0;
  37. unsigned long serialMessage_currentTime = 0;
  38. bool messageIncoming = false;
  39. bool charOutOfRange = false; // This is a value to indicate if a character was not within range (if it was not one of the accepted values)
  40.  
  41.  
  42.  
  43. // function prototypes
  44. void beginMessageTimer();
  45. void resetMessage();
  46. void turnAllLedsOff();
  47. void performMessage();
  48. bool perform_character_filter(char);
  49.  
  50.  
  51.  
  52. bool returnMessage = true; // test variable to enable the echo function below.
  53. void echoMessage() { // This is a function to return the sent message, only for testing. Set returnMessage to false to disable it.
  54.   Serial.print(messageLetters[0]);
  55.   Serial.print(messageLetters[1]);
  56.   Serial.print(messageLetters[2]);
  57.   Serial.println(messageLetters[3]);
  58. }
  59.  
  60. void setup() {
  61.   Serial.begin(9600);
  62.  
  63.   // pins 2 through 9 are the machine state pins, using external 220k pulldown resistors.
  64.   pinMode(2, OUTPUT);
  65.   pinMode(3, OUTPUT);
  66.   pinMode(4, OUTPUT);
  67.   pinMode(5, OUTPUT);
  68.   pinMode(6, OUTPUT);
  69.   pinMode(7, OUTPUT);
  70.   pinMode(8, OUTPUT);
  71.   pinMode(9, OUTPUT);
  72.  
  73.   for (int x = 0; x < 4; x++) {
  74.     messageLetters[x] = 0; // init the message array to nothing
  75.   }
  76.  
  77.   turnAllLedsOff(); // This really turns I/O pins off, there is no LEDs connected to this board.
  78. }
  79.  
  80.  
  81. void loop() {
  82.  
  83.   // This section gets characters off the serial connection, if any are there to get.
  84.   if (Serial.available()) {
  85.     while (Serial.available() > 0) {
  86.       if (messageCounter < 4) {
  87.         inputLetter = Serial.read();
  88.         if (perform_character_filter(inputLetter)) {
  89.           // If the input character is a recognized one, it is stored here.
  90.           messageLetters[messageCounter] = inputLetter;
  91.           messageCounter++;
  92.           if (messageCounter == 1) {
  93.             beginMessageTimer();
  94.           }
  95.         }
  96.       }
  97.       else { // if (messageCounter >= 4)
  98.         // If an incoming USB message reaches four [recognized] characters in length, then the function to perform it is called.
  99.         // If the message is just the single 'e' command, that waits for the message timeout to occur and is performed then.
  100.         //Serial.println("message sent?");
  101.         performMessage();
  102.       }
  103.     }
  104.   }
  105.  
  106.  
  107.   // This section resets a partial message, if it takes too long to complete.
  108.   // -Which is not very likely to happen really, but just in case...
  109.   if (messageIncoming == true) {
  110.     serialMessage_currentTime = millis();
  111.     if (serialMessage_currentTime > serialMessage_beginTime) {
  112.       if (serialMessage_currentTime > (serialMessage_beginTime + serialMessage_timeOut)) {
  113.         // The single 'e' letter to shut off the LEDs is caught and performed here.
  114.         // You cannot catch it in performMessage() because performMessage() is only called when the message is 4 valid characters long.
  115.         // If you called performMessage() on either 1 or 4 characters, then it would get called on the first 'e' every time and never reach 4 characters.
  116.         // This messaging system is kinda lousy because whoever wrote it used the same letter 'e' for both commands-
  117.         //   (the 1-letter STOP command, and the 4-letter display commands).
  118.         // If they would have used a different letter (k) to signal to turn off the LEDs, this would have been a lot easier.
  119.         if (messageCounter == 1) {
  120.           if (messageLetters[0] == 'e') {
  121.             // If the message is only one character long and it is the letter 'e',
  122.             // The the control pins are all turned off and the message is reset.
  123.             messageIncoming = false;
  124.             turnAllLedsOff();
  125.             resetMessage();
  126.           }
  127.         }
  128.         else {
  129.           // If the message was more than one letter but less than four letter long,
  130.           // then it did not complete in the allowed time, and is reset here.
  131.           resetMessage();
  132.         }
  133.       }
  134.     }
  135.     else {
  136.       // This bit is to handle the millis() rollover condition, should it ever occur.
  137.       serialMessage_beginTime = millis();
  138.     }
  139.   }
  140.  
  141. } // end of main loop
  142.  
  143.  
  144. void beginMessageTimer() {
  145.   // This is used to set a time limit for sending a message to the USB arduino. {in serialMessage_timeOut}
  146.   // At the end of the time limit, whatever message has been received is attempted.
  147.   // This is the only way to catch the single 'e' used to shut off the lights.
  148.   messageIncoming = true;
  149.   serialMessage_beginTime = millis();
  150. }
  151.  
  152.  
  153. void resetMessage() {
  154.   if (returnMessage == true) { // This is for testing only.
  155.     echoMessage();
  156.   }
  157.   for (int x = 0; x < 4; x++) {
  158.     messageLetters[x] = 0; // Wipe out the old message.
  159.   }
  160.   messageCounter = 0; // Reset the message character counter.
  161.   messageIncoming = false; // Disable the message timing section.
  162.  
  163. }
  164.  
  165. void turnAllLedsOff() {
  166.   // This function turns off the LEDs by setting all the communication pins to LOW.
  167.   // Really only the first two pins need to be set low to turn off, but anyway.
  168.  
  169.     digitalWrite(2, LOW);
  170.     digitalWrite(3, LOW);
  171.     digitalWrite(4, LOW);
  172.     digitalWrite(5, LOW);
  173.     digitalWrite(6, LOW);
  174.     digitalWrite(7, LOW);
  175.     digitalWrite(8, LOW);
  176.     digitalWrite(9, LOW);
  177. }
  178.  
  179. void performMessage() {
  180.   // If this function is called, then the message is four valid letters long.
  181.   bool messageCheck = true;
  182.   if (messageLetters[0] == 'e') { // The first char must be 'e'.
  183.     // The 2nd char represents the speed. s=slow, m=medium, q=fast
  184.     switch (messageLetters[1]) {
  185.       case 's':
  186.       case 'm':
  187.       case 'q':
  188.         // do nothing if the char is an acceptable value
  189.         break;
  190.       default:
  191.         messageCheck = false;
  192.     }
  193.     //Serial.println(messageLetters[1]);
  194.     //Serial.println(messageCheck);
  195.     // third number is a color indicator: 1=white, 2=red, 3=green, 4=blue, 5=purple, 6=yellow, 7=cyan, 8=orange
  196.     switch (messageLetters[2]) {
  197.       case '1':
  198.       case '2':
  199.       case '3':
  200.       case '4':
  201.       case '5':
  202.       case '6':
  203.       case '7':
  204.       case '8':
  205.         // do nothing if the char is an acceptable value
  206.         break;
  207.       default:
  208.         messageCheck = false;
  209.     }
  210.     //Serial.println(messageLetters[2]);
  211.     //Serial.println(messageCheck);
  212.     // The fourth char represents the pattern. z=spinning wheel, x=right fill, c=left fill, v=right ball, b=left ball
  213.     switch (messageLetters[3]) {
  214.       case 'z':
  215.       case 'x':
  216.       case 'c':
  217.       case 'v':
  218.       case 'b':
  219.         // do nothing if the char is an acceptable value
  220.         break;
  221.       default:
  222.         messageCheck = false;
  223.     }
  224.     //Serial.println(messageLetters[1]);
  225.     //Serial.println(messageCheck);
  226.   }
  227.   else {
  228.     messageCheck = false;
  229.   }
  230.  
  231.   // The section above verified that the message has valid characters in all four positions.
  232.   // If it passes that test, then the section below writes the values to the output pins.
  233.  
  234.   // If the message has valid characters in each position, then it can be used:
  235.   if (messageCheck == true) {
  236.     // The first letter isn't used, since it's always 'e'.
  237.  
  238.     // The 2nd char represents the speed. s=slow, m=medium, q=fast
  239.     // The first two communication pins (D2 and D3) represent the speed.
  240.     switch (messageLetters[1]) {
  241.       case 's':
  242.         digitalWrite(2, LOW);
  243.         digitalWrite(3, HIGH);
  244.         break;
  245.       case 'm':
  246.         digitalWrite(2, HIGH);
  247.         digitalWrite(3, LOW);
  248.         break;
  249.       case 'q':
  250.         digitalWrite(2, HIGH);
  251.         digitalWrite(3, HIGH);
  252.         break;
  253.     }
  254.  
  255.  
  256.     // third number is a color indicator: 1=white, 2=red, 3=green, 4=blue, 5=purple, 6=yellow, 7=cyan, 8=orange
  257.     // The next three communication pins (D4, D5, D6) represent the color.
  258.     switch (messageLetters[2]) {
  259.       case '1':
  260.         digitalWrite(4, LOW);
  261.         digitalWrite(5, LOW);
  262.         digitalWrite(6, LOW);
  263.         break;
  264.       case '2':
  265.         digitalWrite(4, LOW);
  266.         digitalWrite(5, LOW);
  267.         digitalWrite(6, HIGH);
  268.         break;
  269.       case '3':
  270.         digitalWrite(4, LOW);
  271.         digitalWrite(5, HIGH);
  272.         digitalWrite(6, LOW);
  273.         break;
  274.       case '4':
  275.         digitalWrite(4, LOW);
  276.         digitalWrite(5, HIGH);
  277.         digitalWrite(6, HIGH);
  278.         break;
  279.       case '5':
  280.         digitalWrite(4, HIGH);
  281.         digitalWrite(5, LOW);
  282.         digitalWrite(6, LOW);
  283.         break;
  284.       case '6':
  285.         digitalWrite(4, HIGH);
  286.         digitalWrite(5, LOW);
  287.         digitalWrite(6, HIGH);
  288.         break;
  289.       case '7':
  290.         digitalWrite(4, HIGH);
  291.         digitalWrite(5, HIGH);
  292.         digitalWrite(6, LOW);
  293.         break;
  294.       case '8':
  295.         digitalWrite(4, HIGH);
  296.         digitalWrite(5, HIGH);
  297.         digitalWrite(6, HIGH);
  298.         break;
  299.     }
  300.  
  301.  
  302.     // The fourth char represents the pattern. z=spinning wheel, x=right fill, c=left fill, v=right ball, b=left ball
  303.     // The next three communication pins (D7, D8, D9) represent the color.
  304.     switch (messageLetters[3]) {
  305.       case 'z':
  306.         digitalWrite(7, LOW);
  307.         digitalWrite(8, LOW);
  308.         digitalWrite(9, LOW);
  309.         break;
  310.       case 'x':
  311.         digitalWrite(7, LOW);
  312.         digitalWrite(8, LOW);
  313.         digitalWrite(9, HIGH);
  314.         break;
  315.       case 'c':
  316.         digitalWrite(7, LOW);
  317.         digitalWrite(8, HIGH);
  318.         digitalWrite(9, LOW);
  319.         break;
  320.       case 'v':
  321.         digitalWrite(7, LOW);
  322.         digitalWrite(8, HIGH);
  323.         digitalWrite(9, HIGH);
  324.         break;
  325.       case 'b':
  326.         digitalWrite(7, HIGH);
  327.         digitalWrite(8, LOW);
  328.         digitalWrite(9, LOW);
  329.         break;
  330.       default:
  331.         // nothing here.
  332.         break;
  333.     }
  334.  
  335.     // Once the message has been performed, the message array is reset:
  336.     resetMessage();
  337.  
  338.   } // if (messageCheck == true)
  339.   else {
  340.     // If the message cannot be performed because it is incorrect, then it is reset.
  341.     resetMessage();
  342.   }
  343.  
  344. } // performMessage()
  345.  
  346.  
  347. bool perform_character_filter(char tLetter) {
  348.   // This function is for checking the input letters as they are received.
  349.   // Only the desired letters will return TRUE, any others will return FALSE.
  350.   bool letterInRange = false;
  351.  
  352.   if (tLetter == 'e') {
  353.     letterInRange = true;
  354.   }
  355.  
  356.   if (tLetter == 's') {
  357.     letterInRange = true;
  358.   }
  359.   if (tLetter == 'm') {
  360.     letterInRange = true;
  361.   }
  362.   if (tLetter == 'q') {
  363.     letterInRange = true;
  364.   }
  365.  
  366.   if (tLetter == '1') {
  367.     letterInRange = true;
  368.   }
  369.   if (tLetter == '2') {
  370.     letterInRange = true;
  371.   }
  372.   if (tLetter == '3') {
  373.     letterInRange = true;
  374.   }
  375.   if (tLetter == '4') {
  376.     letterInRange = true;
  377.   }
  378.   if (tLetter == '5') {
  379.     letterInRange = true;
  380.   }
  381.   if (tLetter == '6') {
  382.     letterInRange = true;
  383.   }
  384.   if (tLetter == '7') {
  385.     letterInRange = true;
  386.   }
  387.   if (tLetter == '8') {
  388.     letterInRange = true;
  389.   }
  390.  
  391.   if (tLetter == 'z') {
  392.     letterInRange = true;
  393.   }
  394.   if (tLetter == 'x') {
  395.     letterInRange = true;
  396.   }
  397.   if (tLetter == 'c') {
  398.     letterInRange = true;
  399.   }
  400.   if (tLetter == 'v') {
  401.     letterInRange = true;
  402.   }
  403.   if (tLetter == 'b') {
  404.     letterInRange = true;
  405.   }
  406.  
  407.   return letterInRange;
  408. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement