Advertisement
Guest User

Sirnoname Code

a guest
Jun 16th, 2019
409
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.98 KB | None | 0 0
  1. /*
  2.     X-Sim PID
  3.     This program will control two motor H-Bridge with analogue feedback and serial target input value
  4.     Target is a Arduino UNO R3 but should work on all Arduino with Atmel 328, Arduinos with an FTDI serial chip need a change to lower baudrates of 57600
  5.     Copyright (c) 2013 Martin Wiedenbauer, particial use is only allowed with a reference link to the x-sim.de project
  6.  
  7.     Command input protocol  (always 5 bytes, beginning with 'X' character and ends with a XOR checksum)
  8.     'X' 1 H L C             Set motor 1 position to High and Low value 0 to 1023
  9.     'X' 2 H L C             Set motor 2 position to High and Low value 0 to 1023
  10.     'X' 3 H L C             Set motor 1 P Proportional value to High and Low value
  11.     'X' 4 H L C             Set motor 2 P Proportional value to High and Low value
  12.     'X' 5 H L C             Set motor 1 I Integral value to High and Low value
  13.     'X' 6 H L C             Set motor 2 I Integral value to High and Low value
  14.     'X' 7 H L C             Set motor 1 D Derivative value to High and Low value
  15.     'X' 8 H L C             Set motor 2 D Derivative value to High and Low value
  16.  
  17.     'X' 200 0 0 C           Send back over serial port both analogue feedback raw values
  18.     'X' 201 0 0 C           Send back over serial port the current pid count
  19.     'X' 202 0 0 C           Send back over serial port the firmware version (used for x-sim autodetection)
  20.     'X' 203 M V C           Write EEPROM on address M (only 0 to 255 of 1024 Bytes of the EEPROM) with new value V
  21.     'X' 204 M 0 C           Read EEPROM on memory address M (only 0 to 255 of 1024 Bytes of the EEPROM), send back over serial the value
  22.     'X' 205 0 0 C           Clear EEPROM
  23.     'X' 206 0 0 C           Reread the whole EEPRom and store settings into fitting variables
  24.     'X' 207 0 0 C           Disable power on motor 1
  25.     'X' 208 0 0 C           Disable power on motor 2
  26.     'X' 209 0 0 C           Enable power on motor 1
  27.     'X' 210 0 0 C           Enable power on motor 2
  28.     'X' 211 0 0 C           Send all debug values
  29.    
  30.     EEPROM memory map
  31.     00      empty eeprom detection, 111 if set, all other are indicator to set default
  32.     01-02   minimum 1
  33.     03-04   maximum 1
  34.     05      dead zone 1
  35.     06-07   minimum 2
  36.     08-09   maximum 2
  37.     10      dead zone 2
  38.     11-12   P component of motor 1
  39.     13-14   I component of motor 1
  40.     15-16   D component of motor 1
  41.     17-18   P component of motor 2
  42.     19-20   I component of motor 2
  43.     21-22   D component of motor 2
  44.     23      pwm1 offset
  45.     24      pwm2 offset
  46.     25      pwm1 maximum
  47.     26      pwm2 maximum
  48.     27      pwm frequency divider (1,8,64)
  49.  
  50.     Pin out of arduino for H-Bridge
  51.  
  52.     Pin 10 - PWM1 - Speed for Motor 1.
  53.     Pin  9 - PWM2 - Speed for Motor 2.
  54.     Pin  2 - INA1 - motor 1 turn
  55.     Pin  3 - INB1 - motor 1 turn
  56.     Pin  4 - INB1 - motor 2 turn
  57.     Pin  5 - INB2 - motor 2 turn
  58.  
  59.     Analog Pins
  60.  
  61.     Pin A0 - input of feedback positioning from motor 1
  62.     Pin A1 - input of feedback positioning from motor 2
  63.  
  64.     As well 5v and GND pins tapped in to feed feedback pots too.
  65.  
  66. */
  67.  
  68. #include <EEPROM.h>
  69.  
  70. //Some speed test switches for testers ;)
  71. #define FASTADC  1 //Hack to speed up the arduino analogue read function, comment out with // to disable this hack
  72.  
  73. // defines for setting and clearing register bits
  74. #ifndef cbi
  75.     #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  76. #endif
  77. #ifndef sbi
  78.     #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  79. #endif
  80.  
  81. #define LOWBYTE(v)   ((unsigned char) (v))                              //Read
  82. #define HIGHBYTE(v)  ((unsigned char) (((unsigned int) (v)) >> 8))
  83. #define BYTELOW(v)   (*(((unsigned char *) (&v) + 1)))                  //Write
  84. #define BYTEHIGH(v)  (*((unsigned char *) (&v)))
  85.  
  86. #define   GUARD_MOTOR_1_GAIN   100.0    
  87. #define   GUARD_MOTOR_2_GAIN   100.0
  88.  
  89. //Firmware version info
  90. int firmaware_version_mayor=1;
  91. int firmware_version_minor =4;
  92.  
  93. //360° option for flight simulators
  94. bool turn360motor1 = false;
  95. bool turn360motor2 = false;
  96.  
  97. int virtualtarget1;
  98. int virtualtarget2;
  99. int currentanalogue1 = 0;
  100. int currentanalogue2 = 0;
  101. int target1=512;
  102. int target2=512;
  103. int low=0;
  104. int high=0;
  105. unsigned long hhigh=0;
  106. unsigned long hlow=0;
  107. unsigned long lhigh=0;
  108. unsigned long llow=0;
  109. int buffer=0;
  110. int buffercount=-1;
  111. int commandbuffer[5]={0};
  112. unsigned long pidcount  = 0;        // unsigned 32bit, 0 to 4,294,967,295
  113. byte errorcount = 0;        // serial receive error detected by checksum
  114.  
  115. // fixed DATA for direct port manipulation, exchange here each value if your h-Bridge is connected to another port pin
  116. // This pinning overview is to avoid the slow pin switching of the arduino libraries
  117. //
  118. //                  +-\/-+
  119. //            PC6  1|    |28  PC5 (AI 5)
  120. //      (D 0) PD0  2|    |27  PC4 (AI 4)
  121. //      (D 1) PD1  3|    |26  PC3 (AI 3)
  122. //      (D 2) PD2  4|    |25  PC2 (AI 2)
  123. // PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
  124. //      (D 4) PD4  6|    |23  PC0 (AI 0)
  125. //            VCC  7|    |22  GND
  126. //            GND  8|    |21  AREF
  127. //            PB6  9|    |20  AVCC
  128. //            PB7 10|    |19  PB5 (D 13)
  129. // PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
  130. // PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
  131. //      (D 7) PD7 13|    |16  PB2 (D 10) PWM
  132. //      (D 8) PB0 14|    |15  PB1 (D 9) PWM
  133. //                  +----+
  134. //
  135. int portdstatus             =PORTD;     // read the current port D bit mask
  136. int ControlPinM1Inp1        =2;         // motor 1 INP1 output, this is the arduino pin description
  137. int ControlPinM1Inp2        =3;         // motor 1 INP2 output, this is the arduino pin description
  138. int ControlPinM2Inp1        =4;         // motor 2 INP1 output, this is the arduino pin description
  139. int ControlPinM2Inp2        =5;         // motor 2 INP2 output, this is the arduino pin description
  140. int PWMPinM1                =10;        // motor 1 PWM output
  141. int PWMPinM2                =9;         // motor 2 PWM output
  142.  
  143. // Pot feedback inputs
  144. int FeedbackPin1            = A0;       // select the input pin for the potentiometer 1, PC0
  145. int FeedbackPin2            = A1;       // select the input pin for the potentiometer 2, PC1
  146. int FeedbackMax1            = 1021;     // Maximum position of pot 1 to scale, do not use 1023 because it cannot control outside the pot range
  147. int FeedbackMin1            = 2;        // Minimum position of pot 1 to scale, do not use 0 because it cannot control outside the pot range
  148. int FeedbackMax2            = 1021;     // Maximum position of pot 2 to scale, do not use 1023 because it cannot control outside the pot range
  149. int FeedbackMin2            = 2;        // Minimum position of pot 2 to scale, do not use 0 because it cannot control outside the pot range
  150. int FeedbackPotDeadZone1    = 0;        // +/- of this value will not move the motor       
  151. int FeedbackPotDeadZone2    = 0;        // +/- of this value will not move the motor
  152. float quarter1              = 254.75;
  153. float quarter2              = 254.75;
  154. float threequarter1         = 764.25;
  155. float threequarter2         = 764.25;
  156.  
  157. //PID variables
  158. int motordirection1     = 0;            // motor 1 move direction 0=brake, 1=forward, 2=reverse
  159. int motordirection2     = 0;            // motor 2 move direction 0=brake, 1=forward, 2=reverse
  160. int oldmotordirection1  = 0;
  161. int oldmotordirection2  = 0;
  162. double K_motor_1        = 1;
  163. double proportional1    = 4.200;        //initial value
  164. double integral1        = 0.400;
  165. double derivative1      = 0.400;
  166. double K_motor_2        = 1;
  167. double proportional2    = 4.200;
  168. double integral2        = 0.400;
  169. double derivative2      = 0.400;
  170. int OutputM1                    = 0;
  171. int OutputM2                    = 0;
  172. double integrated_motor_1_error = 0;
  173. double integrated_motor_2_error = 0;
  174. float last_motor_1_error        = 0;
  175. float last_motor_2_error        = 0;
  176. int disable                     = 1; //Motor stop flag
  177. int pwm1offset                  = 50;
  178. int pwm2offset                  = 50;
  179. int pwm1maximum                 = 255;
  180. int pwm2maximum                 = 255;
  181. float pwm1divider               = 0.8039;
  182. float pwm2divider               = 0.8039;
  183. float pwmfloat                  = 0;
  184. int pwmfrequencydivider         = 1; //31kHz
  185.  
  186. byte debugbyte =0;              //This values are for debug purpose and can be send via
  187. int debuginteger =0;            //the SendDebug serial 211 command to the X-Sim plugin
  188. double debugdouble =0; 
  189.  
  190. void setPwmFrequency(int pin, int divisor)
  191. {
  192.     byte mode;
  193.     if(pin == 5 || pin == 6 || pin == 9 || pin == 10)
  194.     {
  195.         switch(divisor)
  196.         {
  197.             case 1: mode = 0x01; break;
  198.             case 8: mode = 0x02; break;
  199.             case 64: mode = 0x03; break;
  200.             case 256: mode = 0x04; break;
  201.             case 1024: mode = 0x05; break;
  202.             default: return;
  203.         }
  204.         if(pin == 5 || pin == 6)
  205.         {
  206.             TCCR0B = TCCR0B & 0b11111000 | mode;
  207.         }
  208.         else
  209.         {
  210.             TCCR1B = TCCR1B & 0b11111000 | mode;
  211.         }
  212.     }
  213.     else
  214.     {
  215.         if(pin == 3 || pin == 11)
  216.         {
  217.             switch(divisor)
  218.             {
  219.                 case 1: mode = 0x01; break;
  220.                 case 8: mode = 0x02; break;
  221.                 case 32: mode = 0x03; break;
  222.                 case 64: mode = 0x04; break;
  223.                 case 128: mode = 0x05; break;
  224.                 case 256: mode = 0x06; break;
  225.                 case 1024: mode = 0x7; break;
  226.                 default: return;
  227.             }
  228.             TCCR2B = TCCR2B & 0b11111000 | mode;
  229.         }
  230.     }
  231. }
  232.  
  233. void setup()
  234. {
  235.     //Serial.begin(115200);   //Uncomment this for arduino UNO without ftdi serial chip
  236.     Serial.begin(9600);  //Uncomment this for arduino nano, arduino with ftdi chip or arduino duemilanove
  237.     portdstatus=PORTD;
  238.     pinMode(ControlPinM1Inp1, OUTPUT);
  239.     pinMode(ControlPinM1Inp2, OUTPUT);
  240.     pinMode(ControlPinM2Inp1, OUTPUT);
  241.     pinMode(ControlPinM2Inp2, OUTPUT);
  242.     pinMode(PWMPinM1,         OUTPUT);
  243.     pinMode(PWMPinM2,         OUTPUT);
  244.     analogWrite(PWMPinM1,     0);
  245.     analogWrite(PWMPinM2,     0);
  246.     UnsetMotor1Inp1();
  247.     UnsetMotor1Inp2();
  248.     UnsetMotor2Inp1();
  249.     UnsetMotor2Inp2();
  250.     disable=1;
  251.     //TCCR1B = TCCR1B & 0b11111100; //This is a hack for changing the PWM frequency to a higher value, if removed it is 490Hz
  252.     setPwmFrequency(9, 1);
  253.     setPwmFrequency(10, 1);
  254. #if FASTADC
  255.     // set analogue prescale to 16
  256.     sbi(ADCSRA,ADPS2) ;
  257.     cbi(ADCSRA,ADPS1) ;
  258.     cbi(ADCSRA,ADPS0) ;
  259. #endif
  260. }
  261.  
  262. void WriteEEPRomWord(int address, int intvalue)
  263. {
  264.     int low,high;
  265.     high=intvalue/256;
  266.     low=intvalue-(256*high);
  267.     EEPROM.write(address,high);
  268.     EEPROM.write(address+1,low);
  269. }
  270.  
  271. int ReadEEPRomWord(int address)
  272. {
  273.     int low,high, returnvalue;
  274.     high=EEPROM.read(address);
  275.     low=EEPROM.read(address+1);
  276.     returnvalue=(high*256)+low;
  277.     return returnvalue;
  278. }
  279.  
  280. void WriteEEProm()
  281. {
  282.     EEPROM.write(0,111);
  283.     WriteEEPRomWord(1,FeedbackMin1);
  284.     WriteEEPRomWord(3,FeedbackMax1);
  285.     EEPROM.write(5,FeedbackPotDeadZone1);
  286.     WriteEEPRomWord(6,FeedbackMin2);
  287.     WriteEEPRomWord(8,FeedbackMax2);
  288.     EEPROM.write(10,FeedbackPotDeadZone2);
  289.     WriteEEPRomWord(11,int(proportional1*10.000));
  290.     WriteEEPRomWord(13,int(integral1*10.000));
  291.     WriteEEPRomWord(15,int(derivative1*10.000));
  292.     WriteEEPRomWord(17,int(proportional2*10.000));
  293.     WriteEEPRomWord(19,int(integral2*10.000));
  294.     WriteEEPRomWord(21,int(derivative2*10.000));
  295.     if(pwm1offset > 180 || pwm2offset > 180 || pwm1maximum < 200 || pwm2maximum < 200)
  296.     {
  297.         pwm1offset=50;
  298.         pwm2offset=50;
  299.         pwm1maximum=255;
  300.         pwm2maximum=255;
  301.         pwm1divider=0.8039;
  302.         pwm2divider=0.8039;
  303.     }
  304.     EEPROM.write(23,pwm1offset);
  305.     EEPROM.write(24,pwm2offset);
  306.     EEPROM.write(25,pwm1maximum);
  307.     EEPROM.write(26,pwm2maximum);
  308.     if(pwmfrequencydivider != 1 && pwmfrequencydivider != 8)
  309.     {
  310.         pwmfrequencydivider=1;
  311.     }
  312.     EEPROM.write(27,pwmfrequencydivider);
  313. }
  314.  
  315. void ReadEEProm()
  316. {
  317.     int evalue = EEPROM.read(0);
  318.     if(evalue != 111) //EEProm was not set before, set default values
  319.     {
  320.         WriteEEProm();
  321.         return;
  322.     }
  323.     FeedbackMin1=ReadEEPRomWord(1);
  324.     FeedbackMax1=ReadEEPRomWord(3);
  325.     FeedbackPotDeadZone1=EEPROM.read(5);
  326.     FeedbackMin2=ReadEEPRomWord(6);
  327.     FeedbackMax2=ReadEEPRomWord(8);
  328.     FeedbackPotDeadZone2=EEPROM.read(10);
  329.     proportional1=double(ReadEEPRomWord(11))/10.000;
  330.     integral1=double(ReadEEPRomWord(13))/10.000;
  331.     derivative1=double(ReadEEPRomWord(15))/10.000;
  332.     proportional2=double(ReadEEPRomWord(17))/10.000;
  333.     integral2=double(ReadEEPRomWord(19))/10.000;
  334.     derivative2=double(ReadEEPRomWord(21))/10.000;
  335.     pwm1offset=EEPROM.read(23);
  336.     pwm2offset=EEPROM.read(24);
  337.     pwm1maximum=EEPROM.read(25);
  338.     pwm2maximum=EEPROM.read(26);
  339.     if(pwm1offset > 180 || pwm2offset > 180 || pwm1maximum < 200 || pwm2maximum < 200)
  340.     {
  341.         pwm1offset=50;
  342.         pwm2offset=50;
  343.         pwm1maximum=255;
  344.         pwm2maximum=255;
  345.         pwm1divider=0.8039;
  346.         pwm2divider=0.8039;
  347.         EEPROM.write(23,pwm1offset);
  348.         EEPROM.write(24,pwm2offset);
  349.         EEPROM.write(25,pwm1maximum);
  350.         EEPROM.write(26,pwm2maximum);
  351.     }
  352.     else
  353.     {
  354.         pwmfloat=float(pwm1maximum-pwm1offset);
  355.         pwm1divider=pwmfloat/255.000;
  356.         pwmfloat=float(pwm2maximum-pwm2offset);
  357.         pwm2divider=pwmfloat/255.000;
  358.     }
  359.     pwmfrequencydivider=EEPROM.read(27);
  360.     if(pwmfrequencydivider != 1 && pwmfrequencydivider != 8)
  361.     {
  362.         pwmfrequencydivider=1;
  363.         EEPROM.write(27,pwmfrequencydivider);
  364.     }
  365.     quarter1=float(FeedbackMax1-FeedbackMin1)/4.000;
  366.     quarter2=float(FeedbackMax2-FeedbackMin2)/4.000;
  367.     threequarter1=quarter1*3.000;
  368.     threequarter2=quarter1*3.000;
  369.     setPwmFrequency(9, pwmfrequencydivider);
  370.     setPwmFrequency(10, pwmfrequencydivider);
  371. }
  372.  
  373. void SendAnalogueFeedback(int analogue1, int analogue2)
  374. {
  375.     high=analogue1/256;
  376.     low=analogue1-(high*256);
  377.     Serial.write('X');
  378.     Serial.write(200);
  379.     Serial.write(high);
  380.     Serial.write(low);
  381.     high=analogue2/256;
  382.     low=analogue2-(high*256);
  383.     Serial.write(high);
  384.     Serial.write(low);
  385. }
  386.  
  387. void SendPidCount()
  388. {
  389.     unsigned long value=pidcount;
  390.     hhigh=value/16777216;
  391.     value=value-(hhigh*16777216);
  392.     hlow=value/65536;
  393.     value=value-(hlow*65536);
  394.     lhigh=value/256;
  395.     llow=value-(lhigh*256);
  396.     Serial.write('X');
  397.     Serial.write(201);
  398.     Serial.write(int(hhigh));
  399.     Serial.write(int(hlow));
  400.     Serial.write(int(lhigh));
  401.     Serial.write(int(llow));
  402.     Serial.write(errorcount);
  403. }
  404.  
  405. void SendDebugValues()
  406. {
  407.     //The double is transformed into a integer * 10 !!!
  408.     int doubletransfere=int(double(debugdouble*10.000));
  409.     Serial.write('X');
  410.     Serial.write(211);
  411.     Serial.write(debugbyte);
  412.     Serial.write(HIGHBYTE(debuginteger));
  413.     Serial.write(LOWBYTE(debuginteger));
  414.     Serial.write(HIGHBYTE(doubletransfere));
  415.     Serial.write(LOWBYTE(doubletransfere));
  416. }
  417.  
  418. void SendFirmwareVersion()
  419. {
  420.     Serial.write('X');
  421.     Serial.write('-');
  422.     Serial.write('P');
  423.     Serial.write('I');
  424.     Serial.write('D');
  425.     Serial.write(' ');
  426.     Serial.write(48+firmaware_version_mayor);
  427.     Serial.write('.');
  428.     Serial.write(48+firmware_version_minor);
  429. }
  430.  
  431. void EEPromToSerial(int eeprom_address)
  432. {
  433.     int retvalue=EEPROM.read(eeprom_address);
  434.     Serial.write('X');
  435.     Serial.write(204);
  436.     Serial.write(retvalue);
  437. }
  438.  
  439. void ClearEEProm()
  440. {
  441.     for(int z=0; z < 1024; z++)
  442.     {
  443.         EEPROM.write(z,255);
  444.     }
  445. }
  446.  
  447. void ParseCommand()
  448. {
  449.     if(commandbuffer[0]==1)         //Set motor 1 position to High and Low value 0 to 1023
  450.     {
  451.         target1=(commandbuffer[1]*256)+commandbuffer[2];
  452.         disable=0;
  453.         return;
  454.     }
  455.     if(commandbuffer[0]==2)         //Set motor 2 position to High and Low value 0 to 1023
  456.     {
  457.         target2=(commandbuffer[1]*256)+commandbuffer[2];
  458.         disable=0;
  459.         return;
  460.     }
  461.  
  462.     if(commandbuffer[0]==200)       //Send both analogue feedback raw values
  463.     {
  464.         SendAnalogueFeedback(currentanalogue1, currentanalogue2);
  465.         return;
  466.     }
  467.     if(commandbuffer[0]==201)       //Send PID count
  468.     {
  469.         SendPidCount();
  470.         return;
  471.     }
  472.     if(commandbuffer[0]==202)       //Send Firmware Version
  473.     {
  474.         SendFirmwareVersion();
  475.         return;
  476.     }
  477.     if(commandbuffer[0]==203)       //Write EEPROM
  478.     {
  479.         EEPROM.write(commandbuffer[1],uint8_t(commandbuffer[2]));
  480.         return;
  481.     }
  482.     if(commandbuffer[0]==204)       //Read EEPROM
  483.     {
  484.         EEPromToSerial(commandbuffer[1]);
  485.         return;
  486.     }
  487.     if(commandbuffer[0]==205)       //Clear EEPROM
  488.     {
  489.         ClearEEProm();
  490.         return;
  491.     }
  492.     if(commandbuffer[0]==206)       //Reread the whole EEPRom and store settings into fitting variables
  493.     {
  494.         ReadEEProm();
  495.         return;
  496.     }
  497.     if(commandbuffer[0]==207 || commandbuffer[0]==208)      //Disable power on both motor
  498.     {
  499.         analogWrite(PWMPinM1,     0);
  500.         UnsetMotor1Inp1();
  501.         UnsetMotor1Inp2();
  502.         analogWrite(PWMPinM2,     0);
  503.         UnsetMotor2Inp1();
  504.         UnsetMotor2Inp2();
  505.         disable=1;
  506.         return;
  507.     }
  508.     if(commandbuffer[0]==209 || commandbuffer[0]==210)      //Enable power on both motor
  509.     {
  510.         analogWrite(PWMPinM1,     128);
  511.         UnsetMotor1Inp1();
  512.         UnsetMotor1Inp2();
  513.         analogWrite(PWMPinM2,     128);
  514.         UnsetMotor2Inp1();
  515.         UnsetMotor2Inp2();
  516.         disable=0;
  517.         return;
  518.     }
  519.     if(commandbuffer[0]==211)       //Send all debug values
  520.     {
  521.         SendDebugValues();
  522.         return;
  523.     }
  524. }
  525.  
  526. void FeedbackPotWorker()
  527. {
  528.     currentanalogue1 = analogRead(FeedbackPin1);
  529.     currentanalogue2 = analogRead(FeedbackPin2);
  530.     //Notice: Minimum and maximum scaling calculation is done in the PC plugin with faster float support
  531. }
  532.  
  533. bool CheckChecksum() //Atmel chips have a comport error rate of 2%, so we need here a checksum
  534. {
  535.     byte checksum=0;
  536.     for(int z=0; z < 3; z++)
  537.     {
  538.         byte val=commandbuffer[z];
  539.         checksum ^= val;
  540.     }
  541.     if(checksum==commandbuffer[3]){return true;}
  542.     return false;
  543. }
  544.  
  545. void SerialWorker()
  546. {
  547.     while(Serial.available())
  548.     {
  549.         if(buffercount==-1)
  550.         {
  551.             buffer = Serial.read();
  552.             if(buffer != 'X'){buffercount=-1;}else{buffercount=0;}
  553.         }
  554.         else
  555.         {
  556.             buffer = Serial.read();
  557.             commandbuffer[buffercount]=buffer;
  558.             buffercount++;
  559.             if(buffercount > 3)
  560.             {
  561.                 if(CheckChecksum()==true){ParseCommand();}else{errorcount++;}
  562.                 buffercount=-1;
  563.             }
  564.         }
  565.     }
  566. }
  567.  
  568. void CalculateVirtualTarget()
  569. {
  570.     if(turn360motor1==true)
  571.     {
  572.         virtualtarget1=target1;
  573.         if(currentanalogue1 > int(threequarter1) && target1 < int(quarter1)){virtualtarget1+=FeedbackMax1;}
  574.         else{if(currentanalogue1 < int(quarter1) && target1 > int(threequarter1)){virtualtarget1=0-FeedbackMax1-target1;}}
  575.     }
  576.     else
  577.     {
  578.         virtualtarget1=target1;
  579.     }
  580.     if(turn360motor2==true)
  581.     {
  582.         virtualtarget2=target2;
  583.         if(currentanalogue2 > int(threequarter2) && target2 < int(quarter2)){virtualtarget2+=FeedbackMax2;}
  584.         else{if(currentanalogue2 < int(quarter2) && target2 > int(threequarter2)){virtualtarget2=0-FeedbackMax2-target2;}}
  585.     }
  586.     else
  587.     {
  588.         virtualtarget2=target2;
  589.     }
  590. }
  591.  
  592. void CalculateMotorDirection()
  593. {
  594.     if(virtualtarget1 > (currentanalogue1 + FeedbackPotDeadZone1) || virtualtarget1 < (currentanalogue1 - FeedbackPotDeadZone1))
  595.     {
  596.         if (OutputM1 >= 0)  
  597.         {                                    
  598.             motordirection1=1;              // drive motor 1 forward
  599.         }  
  600.         else
  601.         {                                              
  602.             motordirection1=2;              // drive motor 1 backward
  603.             OutputM1 = abs(OutputM1);
  604.         }
  605.     }
  606.     else
  607.     {
  608.         motordirection1=0;
  609.     }
  610.  
  611.     if(virtualtarget2 > (currentanalogue2 + FeedbackPotDeadZone2) || virtualtarget2 < (currentanalogue2 - FeedbackPotDeadZone2))
  612.     {
  613.         if (OutputM2 >= 0)  
  614.         {                                    
  615.             motordirection2=1;              // drive motor 2 forward
  616.         }  
  617.         else
  618.         {                                              
  619.             motordirection2=2;              // drive motor 2 backward
  620.             OutputM2 = abs(OutputM2);
  621.         }
  622.     }
  623.     else
  624.     {
  625.         motordirection2=0;
  626.     }
  627.  
  628.     OutputM1 = constrain(OutputM1, -255, 255);
  629.     OutputM2 = constrain(OutputM2, -255, 255);
  630. }
  631.  
  632. int updateMotor1Pid(int targetPosition, int currentPosition)  
  633. {
  634.     float error = (float)targetPosition - (float)currentPosition;
  635.     float pTerm_motor_R = proportional1 * error;
  636.     integrated_motor_1_error += error;                                      
  637.     float iTerm_motor_R = integral1 * constrain(integrated_motor_1_error, -GUARD_MOTOR_1_GAIN, GUARD_MOTOR_1_GAIN);
  638.     float dTerm_motor_R = derivative1 * (error - last_motor_1_error);                            
  639.     last_motor_1_error = error;
  640.     return constrain(K_motor_1*(pTerm_motor_R + iTerm_motor_R + dTerm_motor_R), -255, 255);
  641. }
  642.  
  643. int updateMotor2Pid(int targetPosition, int currentPosition)  
  644. {
  645.     float error = (float)targetPosition - (float)currentPosition;
  646.     float pTerm_motor_L = proportional2 * error;
  647.     integrated_motor_2_error += error;                                      
  648.     float iTerm_motor_L = integral2 * constrain(integrated_motor_2_error, -GUARD_MOTOR_2_GAIN, GUARD_MOTOR_2_GAIN);
  649.     float dTerm_motor_L = derivative2 * (error - last_motor_2_error);                            
  650.     last_motor_2_error = error;
  651.  
  652.     return constrain(K_motor_2*(pTerm_motor_L + iTerm_motor_L + dTerm_motor_L), -255, 255);
  653. }
  654.  
  655. void CalculatePID()
  656. {
  657.     OutputM1=updateMotor1Pid(virtualtarget1,currentanalogue1);
  658.     OutputM2=updateMotor2Pid(virtualtarget2,currentanalogue2);
  659. }
  660.  
  661. void SetPWM()
  662. {
  663.     //Calculate pwm offset and maximum
  664.     pwmfloat=OutputM1;
  665.     pwmfloat*=pwm1divider;
  666.     pwmfloat+=float(pwm1offset);
  667.     OutputM1=pwmfloat;
  668.     if(OutputM1 > pwm1maximum){OutputM1=pwm1maximum;}
  669.     pwmfloat=OutputM2;
  670.     pwmfloat*=pwm2divider;
  671.     pwmfloat+=float(pwm2offset);
  672.     OutputM2=pwmfloat;
  673.     if(OutputM2 > pwm2maximum){OutputM2=pwm2maximum;}
  674.  
  675.     //Set hardware pwm
  676.     if(motordirection1 != 0)
  677.     {
  678.         analogWrite(PWMPinM1, int(OutputM1));
  679.     }
  680.     else
  681.     {
  682.         analogWrite(PWMPinM1, 0);
  683.     }
  684.     if(motordirection2 != 0)
  685.     {
  686.         analogWrite(PWMPinM2, int(OutputM2));
  687.     }
  688.     else
  689.     {
  690.         analogWrite(PWMPinM2, 0);
  691.     }
  692. }
  693.  
  694. //Direct port manipulation, change here your port code
  695.  
  696. void SetMotor1Inp1()
  697. {
  698.     portdstatus |= 1 << ControlPinM1Inp1;
  699.     PORTD = portdstatus;
  700. }
  701.  
  702. void UnsetMotor1Inp1()
  703. {
  704.     portdstatus &= ~(1 << ControlPinM1Inp1);
  705.     PORTD = portdstatus;
  706. }
  707.  
  708. void SetMotor1Inp2()
  709. {
  710.     portdstatus |= 1 << ControlPinM1Inp2;
  711.     PORTD = portdstatus;
  712. }
  713.  
  714. void UnsetMotor1Inp2()
  715. {
  716.     portdstatus &= ~(1 << ControlPinM1Inp2);
  717.     PORTD = portdstatus;
  718. }
  719.  
  720. void SetMotor2Inp1()
  721. {
  722.     portdstatus |= 1 << ControlPinM2Inp1;
  723.     PORTD = portdstatus;
  724. }
  725.  
  726. void UnsetMotor2Inp1()
  727. {
  728.     portdstatus &= ~(1 << ControlPinM2Inp1);
  729.     PORTD = portdstatus;
  730. }
  731.  
  732. void SetMotor2Inp2()
  733. {
  734.     portdstatus |= 1 << ControlPinM2Inp2;
  735.     PORTD = portdstatus;
  736. }
  737.  
  738. void UnsetMotor2Inp2()
  739. {
  740.     portdstatus &= ~(1 << ControlPinM2Inp2);
  741.     PORTD = portdstatus;
  742. }
  743.  
  744. void SetHBridgeControl() //With direct port manipulation for speedup the arduino framework!
  745. {
  746.     //Motor 1
  747.     if(motordirection1 != oldmotordirection1)
  748.     {
  749.         if(motordirection1 != 0)
  750.         {
  751.             if(motordirection1 == 1)
  752.             {
  753.                 SetMotor1Inp1();
  754.                 UnsetMotor1Inp2();
  755.             }
  756.             else
  757.             {
  758.                 UnsetMotor1Inp1();
  759.                 SetMotor1Inp2();
  760.             }
  761.         }
  762.         else
  763.         {
  764.             UnsetMotor1Inp1();
  765.             UnsetMotor1Inp2();
  766.         }
  767.         oldmotordirection1=motordirection1;
  768.     }
  769.  
  770.     //Motor 2
  771.     if(motordirection2 != oldmotordirection2)
  772.     {
  773.         if(motordirection2 != 0)
  774.         {
  775.             if(motordirection2 == 1)
  776.             {
  777.                 SetMotor2Inp1();
  778.                 UnsetMotor2Inp2();
  779.             }
  780.             else
  781.             {
  782.                 UnsetMotor2Inp1();
  783.                 SetMotor2Inp2();
  784.             }
  785.         }
  786.         else
  787.         {
  788.             UnsetMotor2Inp1();
  789.             UnsetMotor2Inp2();
  790.         }
  791.         oldmotordirection2=motordirection2;
  792.     }
  793. }
  794.  
  795. void loop()
  796. {
  797.     //Read all stored PID and Feedback settings
  798.     ReadEEProm();
  799.     //Program loop
  800.     while (1==1) //Important hack: Use this own real time loop code without arduino framework delays
  801.     {
  802.         FeedbackPotWorker();
  803.         SerialWorker();
  804.         CalculateVirtualTarget();
  805.         CalculatePID();
  806.         CalculateMotorDirection();
  807.         if(disable==0)
  808.         {
  809.             SetPWM();
  810.             SetHBridgeControl();
  811.         }
  812.         pidcount++;
  813.     }
  814. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement