Advertisement
diemastermonkey

wurm

Feb 10th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.44 KB | None | 0 0
  1. /* wurm 00x
  2.  Genetic-Algorithm-Based Autonomous Robot
  3.  For Atmel ATTiny85
  4.  @diemastermonkey 2016
  5.  WORK IN PROGRESS
  6.  */
  7.  
  8. /*   GA DNA Program code
  9.  
  10.  0  Do nothing                            // Outpin stuff
  11.  2  Write from MemoryOut to OutPin        
  12.  4  Increment OutPin (w/wraparound)
  13.  6  Decrement OutPin
  14.  8  (Nothing...)
  15.  
  16.  10   Do nothing                            // Inpin stuff
  17.  12  Read from InPin to MemoryIn
  18.  14  Increment InPin (w/wraparound)
  19.  16  Decrement InPin
  20.  18  (Nothing...)
  21.  
  22.  20  Insert random value at MemoryIn       // Memory stuff
  23.  21  Insert random value at MemoryOut
  24.  22  Copy from MemoryIn to MemoryOut
  25.  23  Copy from MemoryOut to MemoryIn
  26.  24  Increment MemoryIn (w/wraparound)
  27.  25  Increment MemoryOut
  28.  26  Decrement MemoryIn
  29.  27  Decrement MemoryOut
  30.  28  Randomize MemoryIn
  31.  29  Randomize MemoryOut  
  32.  */
  33.  
  34. #include <EEPROM.h>
  35.  
  36. /* GA "Memory"
  37.  Each GA has a small buffer for integer data, and
  38.  'MemoryIn/MemoryOut' indexes into the buffer. Commands
  39.  can move the index, put data in or out of the buffer
  40.  and read or write them pins.
  41.  */
  42.  
  43. // New test smart servo/sensor code
  44. int iServoCharge = -1;            // Set high then charge, set low on 0 then -1 to disable
  45. int iServoPin = 2;                // For test only, GA must discover these things
  46. int led = 3;                      // diags
  47. int iContactPin = 1;              // Trigger switch or contact sensor pin
  48.  
  49. // Pins available to the GA
  50. int iPins[] = {
  51.   0, 1, 2, 3, 4, A1, A2, A3};
  52. int iPinsMax = 7;          // Fast for frequent use
  53.  
  54. // GA: These store the GA *currently* under test
  55. int iProgram[64];             // GAs entire program
  56. int iProgramMax = 64;         // Hardwired for fast lookup
  57. int iOutPin = 0;              // INDEX of iPins written to/read from
  58. int iInPin = 0;        
  59. int iMemory[16];              // 16 bytes GA internal storage
  60. int iMemoryIn = 0;            // INDEX where reading from memory
  61. int iMemoryOut = 0;           // Where writing to memory
  62. int iMemoryMax = 15;          // HARDWIRED limit of 'iMemory' for fast lookup
  63.  
  64. // The X genetic variants under test - copies of same structure
  65. // They get copied into/out of "NowProgram" etc for tests/updates
  66. int iGAProgram[3][64];
  67. int iGAOutPin[3];
  68. int iGAInPin[3];
  69. int iGAMemory[3];
  70. int iGAMemoryIn[3];
  71. int iGAMemoryOut[3];
  72.  
  73. // For servo controls
  74. int iPulseCycles = 32000;    // Total for 1 mhz clock
  75. int iPulseHigh = 0;         // How many to keep pulse high
  76. int iPulseLow = 0;          // For low (i.e. iPulseCycles - iPulseHigh)
  77.  
  78. // Setup run once on start
  79. void setup() {                
  80.   pinMode (led, OUTPUT);    
  81.   pinMode (iServoPin, OUTPUT);  
  82.  
  83.   // Eeprom tests
  84.   int iRead = EEPROM.read (0);    // Read from eeprom position 0
  85.   for (int i=0; i < iRead; i++) {  // Flash back number read
  86.     digitalWrite (led, HIGH);
  87.     delayMicroseconds (1000);
  88.     digitalWrite (led, LOW);
  89.   }
  90.   EEPROM.write (0, iRead++);    // increment for next test
  91.  
  92.   digitalWrite (iServoPin, HIGH);       // Nicety - position servo ~ halfway
  93.   delayMicroseconds (80);
  94.   digitalWrite (iServoPin, LOW);
  95.   delayMicroseconds (1024000);
  96.  
  97.   // Randseed
  98.   randomSeed (analogRead (0));
  99. }
  100.  
  101. // Main
  102. void loop() {
  103.  
  104.   // Simple GA tests
  105.   fnTest();          // Test the "current" GA
  106.  
  107.   // Crude health scoring (*needs* to be in-line, i.e. re-write testing routine)
  108.   // crude light sense test
  109.   pinMode (4, INPUT);            // Probably superfluous? Tho, GA might kludge em
  110.   int iLight = 1024 - analogRead (4);  // A2);
  111.   iLight = iLight / 256;
  112.   pinMode (iContactPin, INPUT);    // Again mb superfluous mb not
  113.   int iSwitch = digitalRead (iContactPin);
  114.   if (iSwitch == HIGH) { iSwitch = 1; }
  115.  
  116.   // Score is light level w/huge bonus if switch pressed NOW
  117.   int iScore = iLight + iSwitch;    
  118.  
  119.   // Flash out score
  120.   for (int i=0; i < iScore + 1; i++) {
  121.     digitalWrite (led, HIGH);
  122.     delayMicroseconds (300);
  123.     digitalWrite (led, LOW);
  124.     delayMicroseconds (100);    
  125.   }
  126.  
  127.   // To do: Comparison, selection, reproduction
  128.  
  129.   fnMutate ();       // Mutate it - no fitness yet so just a test
  130.  
  131.   // TO DO: Integrate working servo controls with GA
  132.   //  fnServoTask (10 + random(160));
  133.   fnServoProcess();
  134.  
  135. }                                          // end main loop
  136.  
  137. void fnTest () {
  138.   for (int i=0; i < iProgramMax; i++) {
  139.     // Simple runtime indicator
  140.     if (iProgram[i] != 0) {
  141.       // digitalWrite(led, HIGH);    
  142.       fnServoTask (60 + 200 * (iMemory[iMemoryOut]/255));
  143.     }
  144.     else {
  145.       // digitalWrite(led, LOW);    
  146.     }
  147.  
  148.     // Handle each 'instruction' in the GA's program
  149.     switch (iProgram[i]) {        
  150.     case 2:                 // Write from MemoryOut to OutPin
  151.     case 3:
  152.     case 8:
  153.     case 9:
  154.     case 10:  // Bonus instances!
  155.       fnSmartWrite (iOutPin, iMemory[iMemoryOut]);        
  156.       break;
  157.  
  158.     case 4:                 // Increment OutPin (w/wraparound)
  159.       iOutPin++;
  160.       if (iOutPin > iPinsMax) {
  161.         iOutPin = 0;
  162.       }
  163.       break;
  164.  
  165.     case 6:                 // Decrement OutPin
  166.       iOutPin--;
  167.       if (iOutPin < 0) {
  168.         iOutPin = iPinsMax;
  169.       }
  170.       break;
  171.  
  172.     case 12:                //  Read from InPin to MemoryIn
  173.     case 13:
  174.     case 15:
  175.     case 17:      // Bonus instances
  176.       iMemory[iMemoryIn] = fnSmartRead (iInPin);
  177.       break;
  178.  
  179.     case 14:               // Increment InPin (w/wraparound)
  180.       iInPin++;
  181.       if (iInPin > iPinsMax) {
  182.         iInPin = 0;
  183.       }
  184.       break;
  185.  
  186.     case 16:               // Decrement InPin
  187.       iInPin--;
  188.       if (iInPin < 0) {
  189.         iInPin = iPinsMax;
  190.       }
  191.       break;
  192.  
  193.     case 20:               // Insert random value at MemoryIn
  194.       iMemory[iMemoryIn] = random(256);
  195.       break;
  196.  
  197.     case 21:               // Insert random value at MemoryOut
  198.       iMemory[iMemoryOut] = random(256);
  199.       break;
  200.  
  201.     case 24:               // Increment MemoryIn (w/wraparound)
  202.       iMemoryIn++;
  203.       if (iMemoryIn > iMemoryMax) {
  204.         iMemoryIn = 0;
  205.       }
  206.       break;
  207.  
  208.     case 25:               // Increment MemoryOut
  209.       iMemoryOut++;
  210.       if (iMemoryOut > iMemoryMax) {
  211.         iMemoryOut = 0;
  212.       }
  213.       break;
  214.  
  215.     case 26:               // Decrement MemoryIn
  216.       iMemoryIn--;
  217.       if (iMemoryIn < 0) {
  218.         iMemoryIn = iMemoryMax;
  219.       }
  220.       break;
  221.  
  222.     case 27:               // Decrement MemoryOut
  223.       iMemoryOut--;
  224.       if (iMemoryOut < 0) {
  225.         iMemoryOut = iMemoryMax;
  226.       }
  227.       break;
  228.  
  229.     case 28:               // Randomize MemoryIn
  230.       iMemoryIn = random(iMemoryMax);
  231.       break;
  232.  
  233.       // case 29:               // Randomize MemoryOut
  234.       //  iMemoryOut = random(iMemoryMax);
  235.       //  break;            
  236.  
  237.       // MANUAL KLUDGE SERVO TEST
  238.     case 30:
  239.     case 31:
  240.       fnServoTask (10 + iMemory[iMemoryOut]);
  241.       break;
  242.     }                        // End switch/case
  243.  
  244.     // ---------------------------------------
  245.     // TO DO - ACCUMULATE SCORE FROM ACTIVITIES
  246.     //         FOR LATER USE IN EVALUATION
  247.     // ---------------------------------------    
  248.     /*
  249.           CODE HERE    
  250.      CODE HERE
  251.      CODE HERE
  252.      */
  253.   }
  254. }
  255.  
  256. // Evaluate Fitness
  257.  
  258. // Mutate the 'current' GA - Also for initial first-time mutation
  259. void fnMutate () {
  260.   int iMutation = 0;        // Which mutation
  261.   // Subject some of the GAs program to semirandom mutations
  262.   for (int i=0; i < iProgramMax; i++) {
  263.     if (0 == random (1000)) {            // 1-in-1000 chance each gene
  264.       iMutation = random (16);           // Which mutation (undefined = benign)
  265.  
  266.       switch (iMutation) {
  267.       case 0:                         // Gene erased
  268.         iProgram[i] = 0;
  269.         break;
  270.  
  271.       case 1:                      // Gene inverted
  272.         iProgram[i] = 256 - iProgram[i];
  273.         break;
  274.  
  275.       case 2:                      // Gene incremented
  276.         iProgram[i]++;
  277.         break;
  278.  
  279.       case 3:                      // Decremented
  280.         iProgram[i]--;
  281.         break;
  282.  
  283.       case 4:     // Gene dupes preceeding gene (cancer?) - nerfed if @ 0th          
  284.         if (i > 0) {
  285.           iProgram[i] = iProgram[i-1];
  286.         }
  287.         break;
  288.  
  289.         // Gene completely randomized
  290.         // BEWARE HARDWIRED DIE SIDES to approx. program cmds
  291.       case 5:
  292.       case 6:
  293.       case 7:
  294.       case 8:
  295.       case 9:
  296.       case 10:
  297.       case 11:
  298.       case 12:
  299.       case 13:
  300.       case 14:
  301.       case 15:
  302.         iProgram[i] = random(32);
  303.         break;
  304.       }                              // End switch/case
  305.     }                                // End if
  306.   }                                  // End for
  307. }                                    // End function
  308.  
  309.  
  310. /* Utility functions */
  311.  
  312. // SmartWrite - Write arg data to arg pin (of pins array) by expected means
  313. void fnSmartWrite (int iArgPinIndex, int iArgData) {
  314.   // Handle servos with "ServoTask", first
  315.   if (iPins[iArgPinIndex] == iServoPin) {
  316.     fnServoTask (iArgData);
  317.     return;
  318.   }
  319.  
  320.   if (iArgPinIndex < 5) {                  // First 4 in array are digital
  321.     if (iArgData < 128) {                  // Bottom half treated as low
  322.       digitalWrite (iPins[iArgPinIndex], HIGH);
  323.     }
  324.     else {
  325.       digitalWrite (iPins[iArgPinIndex], LOW);
  326.     }
  327.   }
  328.   else {                                 // Higher pins treat as analog
  329.     analogWrite (iPins[iArgPinIndex], iArgData);
  330.   }  
  331. }
  332.  
  333. // SmartRead - Just like SmartWrite but reads, returns result
  334. int fnSmartRead (int iArgPinIndex) {
  335.   if (iArgPinIndex < 5) {                
  336.     return (digitalRead(iPins[iArgPinIndex]));
  337.   }
  338.   else {                              
  339.     return (analogRead (iPins[iArgPinIndex]));
  340.   }  
  341. }
  342.  
  343.  
  344. // Init servo to go to destination i (60=0' 280=180
  345. void fnServoTask (int i) {
  346.   iServoCharge = i;      // Charge counter and send high to servo
  347.   digitalWrite (iServoPin, HIGH);  
  348.   // KLUDGE -v
  349.   delayMicroseconds (i);          // KLUDGE FIX TEST
  350.   digitalWrite (iServoPin, LOW);
  351.   delayMicroseconds(32000);          // KLUDGE FIX TEST
  352.   // KLUDGE end pwm signal -^
  353. }
  354.  
  355. // Process servo if necessary
  356. void fnServoProcess () {
  357.   if (iServoCharge == -1) {
  358.     return;
  359.   }      // Nothing to do
  360.   iServoCharge--;                          // Decrement charge
  361.   if (iServoCharge == 0) {
  362.     digitalWrite (iServoPin, LOW);             // Discharged, send low to servo
  363.     iServoCharge = -1;                     // Done, disable countdown
  364.   }
  365. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement