diemastermonkey

monkeyboxcontroller

Jan 15th, 2016
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.24 KB | None | 0 0
  1. //      Internet Toybox - Performer/Audience Interaction Platform
  2. //      "Toybox" Controller Code version 0.24 @diemastermonkey
  3. //
  4. //      http://pastebin.com/Y4MemCCQ
  5. //
  6. //  Ver 0.24
  7. //  Support for RGB "Head Module" (bonus module)
  8. //  RGB insert! Sending analog values to RGB pins
  9. //  interrupts fading, then fades to the value.
  10. //
  11. //  Ver 0.20
  12. //  Java Serial port bridge working! TCP no longer part of unit.
  13. //  Chat venue support for Moobot, NightBot (thx to JAYBOCC2!)
  14. //  Configurable via file
  15. //
  16. //  Ver 0.10
  17. //  Internal command syntax functional
  18. //
  19. //      b#p##TD(..)
  20. //    b, p - static syntax tokens.
  21. //    b#      monkeybox number
  22. //    p##     pin number
  23. //    T       Either "d" (digital) or "a" (analog)
  24. //    D(...)  1 to 3 digits
  25. //
  26. // Examples:
  27. //      b0p00d000   "All boxes, all pins, treat digital, set 0 (off)"
  28. //      b1p13d1     "Box 1, pin 13, treat digital, set 1 (on/high)"
  29. //      b1p13d001   Same as above
  30. //      b9p16a077   "Box 9 (?!), pin 16, treat analog, set 0.77 (of what?)"
  31. //
  32.  
  33. #include <Servo.h>              // Servo control only
  34.  
  35. // Globals
  36. int iBlinker = 13;               // I/O pin for diag LED
  37. int iOBLed = 13;                // Backup diag
  38. boolean bServerActive = false;  // True when clients connected
  39.  
  40. // Servo control
  41. Servo oServo;                   // Servo object rom servo.h
  42. boolean bServoInverted = true;  // Set true if hung upside down!
  43. boolean bServoInit = false;
  44. int iServoPin = 8;              // Which pin servo attached
  45. int iServoDelay = 11;           // Min delay to update servo
  46. int iServoMove = 12;            // Target?
  47. int iServoMin = 10;             // Min/max (%) servo position
  48. int iServoMax = 177;
  49. int iServoRange = iServoMax - iServoMin;      // Oft-needed so pre-calc
  50. int iServoMid = iServoRange / 2 + iServoMin;  // To save runtime cycles
  51. int iServoDegrees = iServoMid;        // Current pos in deg
  52. int iServoCmd = 0;                    // Globally pending cmd from outside
  53. int I_SERVO_SLOW = 66; int I_SERVO_NORMAL = 44; int I_SERVO_FAST = 11;
  54. boolean bFastMove = false;            // Optional fast cam
  55.  
  56. // V0.24: Support for separate "RGB Output" object
  57. // See RGB functions below
  58. // To get from bridge/config: What pins are RGB unit
  59. int iRedPin = 9;
  60. int iGreenPin = 10;
  61. int iBluePin = 11;
  62. // Target values - user may change at any time
  63. // RGB Step routine continuously moving toward them
  64. int iRedTarget = -1;
  65. int iBlueTarget = -1;
  66. int iGreenTarget = -1;
  67. // Current values - more efficient than reading them
  68. int iRedNow = 0;
  69. int iBlueNow = 0;
  70. int iGreenNow = 0;
  71. // v 0.25 user prefs for each rgb - if set, don't change
  72. int iRedPref = -1;
  73. int iBluePref = -1;
  74. int iGreenPref = -1;
  75.  
  76. // A counter for RGB updates: This controls rate of color fades
  77. // Decrement each cycle, then when zero, update RGB and recharge
  78. // Read this as ie "fade time" in user config
  79. int iRGBCounter = 0;
  80. int iRGBCounterCharge = 555;    // Recharge to this - 50 is nice fade
  81.  
  82. // For user: How often to randomly change (use 0 for never)
  83. // This is 'sides' on the dice for changes
  84. long iRGBRandomDice = 65536^3;    // smaller = changes more often
  85.  
  86.  
  87. // Runs once on boot
  88. void setup() {
  89.   Serial.begin(9600);                // Init usb
  90.   pinMode (iBlinker, OUTPUT);  
  91.  
  92.   randomSeed (analogRead(A1));
  93.  
  94.   // Funky RGB startup display
  95.   for (int i=0; i < 16; i++) {
  96.     analogWrite (iRedPin + i % 3, (i % 2) * random(256));
  97.     delay (24);
  98.   }
  99.  
  100.   // To do: Fade to users startup color    
  101. /*  iRedTarget = 255;
  102.   iBlueTarget = 224;
  103.   iGreenTarget = 0;  
  104. */
  105.   fnRGBStep();      // Does all rgb maintenance
  106. }
  107.  
  108. /*
  109.  * Main
  110.  */
  111. void loop() {
  112.  
  113.   // V0.24: Automatic RGB "screen saver"
  114.   // Update RGB pins if time to do so, else mb randomize targets
  115.   if (fnRGBStep() == 0) {
  116.     // No RGB underway, maybe randomize?
  117.     if (random(iRGBRandomDice) == 1) {   // 1-in-x chance of changing
  118.       if (-1 == iRedPref) { iRedTarget = random (256); }
  119.       if (-1 == iGreenPref) { iGreenTarget = random (256); }
  120.       if (-1 == iBluePref) { iBlueTarget = random (256); }      
  121.     }
  122.   }
  123.  
  124.   // Command processing  
  125.   // Shunt out now if no serial input
  126.   if (! Serial.available() ) { return; }  
  127.   String sInput = Serial.readString();    
  128.   int iTargetPin = fn_PinFromCommand (sInput);
  129.   int iTargetData = fn_DataFromCommand (sInput);
  130.  
  131.   // Handle digital commands first (they're easy)
  132.   if (fn_IsDigitalCommand (sInput)) {
  133.      // "Siren commands"
  134.     if (iTargetData == 1) {              // Digital pin going on
  135.       digitalWrite (iTargetPin, HIGH);   // set it on
  136.     } else {                             // Else digital pin going off
  137.       digitalWrite (iTargetPin, LOW);    // off
  138.     }
  139.     return;
  140.   }                                      // End if (is digital)
  141.  
  142.   // Handle commands to RGB pins first, lest they be handled as PWM
  143.   // Just set target, fade is automatic. Not elegant but computationally cheap.
  144.   // Could be optimized
  145.   if (iTargetPin == iRedPin) {
  146.     iRedTarget = iTargetData;
  147.     iRedPref = iTargetData;
  148.   }
  149.  
  150.   if (iTargetPin == iGreenPin) {
  151.     iGreenTarget = iTargetData;
  152.     iGreenPref = iTargetData;
  153.   }
  154.  
  155.   if (iTargetPin == iBluePin) {
  156.     iBlueTarget = iTargetData;
  157.     iBluePref = iTargetData;
  158.   }
  159.  
  160.   // Assume any remaining commands are analog PWMs i.e. servos
  161.   int iPWMTarget = fn_PwmFromCommand (sInput);
  162.   if (iPWMTarget > 0) {
  163.     fn_Servo_Move_To (iTargetPin, iPWMTarget, I_SERVO_NORMAL);
  164.   }    
  165. }                              // End (main) loop
  166.  
  167. void fn_Servo_Move_To (int iArgServoPin, int iArgPos, int iArgDelayMS) {
  168.  
  169.   // Yes init servo regardless, pins may change in our scenario
  170.    oServo.attach (iArgServoPin, 1100, 1200);        // 1100,1200 for eMax ES08A
  171.  
  172.    if (bFastMove) {                 // Optional fast move
  173.       fn_Servo_Position(iArgServoPin, iArgPos);
  174.       oServo.detach();
  175.       return;                       // shunt
  176.    }
  177.  
  178.    int iDir = +1;               // Assume forward
  179.    if (iArgPos < iServoDegrees) {
  180.     iDir = -1;
  181.    }
  182.  
  183.    // Move smoothly to target position
  184.    for (int iGoPos = iServoDegrees; iGoPos != iArgPos; iGoPos += iDir) {
  185.     delay (iArgDelayMS);           // Else it 'runs'
  186.     fn_Servo_Position(iArgServoPin, iGoPos);    
  187.    }
  188.    oServo.detach();     // maybe need it :) blame jonm_cs
  189. }
  190.  
  191. void fn_Servo_Position (int iArgServoPin, int iArgPosition) {
  192.   // Skip if invalid args
  193.   if (iArgPosition < iServoMin || iArgPosition > iServoMax || iArgPosition > 175) {
  194.     Serial.println ("Error: Beyond servo limits");
  195.     return;
  196.   }
  197.  
  198.   // Actually move servo
  199.   if (bServoInverted) {
  200.     oServo.write (iServoMax - iArgPosition);    
  201.   } else {
  202.     oServo.write (iArgPosition);
  203.   }
  204.  
  205.   iServoDegrees = iArgPosition;
  206.  
  207.   // Superfluous? https://www.arduino.cc/en/Reference/ServoDetach
  208.   //  oServo.detach();    
  209.  
  210. }     // End method
  211.  
  212. // Return the pin specified in a cmd it BETTER be right!
  213. int fn_PinFromCommand (String sArgCommand) {
  214.   return (sArgCommand.substring(3,5)).toInt();  // ( ex b1p08a75 )
  215. }    
  216.  
  217. // Return the data value from command (always an int)
  218. int fn_DataFromCommand (String sArgCommand) {
  219.   return (sArgCommand.substring(6)).toInt();  
  220. }    
  221.  
  222. // Return true if command is digital, else false
  223. boolean fn_IsDigitalCommand (String sArgCommand) {
  224.   return (
  225.     sArgCommand.substring(5,6).equals("d")  // Q: char compar faster?
  226.   );
  227. }         // end fn_IsDigitalCommand
  228.  
  229. // Return PWM data only from cmd (better be there!)
  230. int fn_PwmFromCommand (String sArgCommand) {
  231.   return (
  232.     sArgCommand.substring (6, sArgCommand.length())
  233.   ).toInt(); // WARE HARDWIRED INDEX!
  234. }            // end fn_PinFromCommand}
  235.  
  236. // Move and set RGB values toward current global "target" values
  237. // Also handles RGB "update" counter. Returns 1 if it was event time.
  238. int fnRGBStep () {
  239.  
  240.     // Decrement counter, ditch if not time yet to update rgbs
  241.     iRGBCounter--;          
  242.     if (iRGBCounter > 0) {
  243.       return (1);
  244.     }
  245.    
  246.     // Ditch now if components = targets
  247.     if (iRedNow == iRedTarget
  248.       && iGreenNow == iGreenTarget
  249.       && iBlueNow == iBlueTarget) {
  250.         return (0);
  251.     }  
  252.    
  253.     // If still here time it's time for RGB update - recharge counter
  254.     iRGBCounter = iRGBCounterCharge;
  255.    
  256.     // Superfluous but safe as user may change things?
  257.     pinMode (iRedPin, OUTPUT);
  258.     pinMode (iGreenPin, OUTPUT);
  259.     pinMode (iBluePin, OUTPUT);      
  260.    
  261.     iRedNow += fnToward (iRedNow, iRedTarget);  // Red, Green, Blue...
  262.     analogWrite (iRedPin, iRedNow);
  263.     iGreenNow += fnToward (iGreenNow, iGreenTarget);
  264.     analogWrite (iGreenPin, iGreenNow);
  265.     iBlueNow += fnToward (iBlueNow, iBlueTarget);
  266.     analogWrite (iBluePin, iBlueNow);
  267.  
  268.    return (1);    // PS caller, not done with rgb work yet
  269. }
  270.  
  271. // Return value that should be added to get from argFrom to argTo
  272. int fnToward (int iArgFrom, int iArgTo) {
  273.   if (iArgFrom < iArgTo) { return (+1); }
  274.   if (iArgFrom > iArgTo) { return (-1); }
  275.   return (0);      // If same
  276. }
  277.  
  278. // RETIRED Return a random destination for the arg RGB value, or the arg value
  279. // Die is sides set by user in iRGBRandomDice, thus == 1 allows "0 for never"
  280. /*
  281. int fnRGBTargetRand (int iArgNow) {
  282.      return (random(255));
  283.   return (iArgNow);                    // Else what you sent me
  284. }
  285. */
Advertisement
Add Comment
Please, Sign In to add comment