Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.55 KB | None | 0 0
  1. #define REMOTEXY_MODE__SOFTSERIAL
  2. #include <SoftwareSerial.h> //джойстик блютуз
  3. #include <RemoteXY.h> //джойстик блютуз
  4. #include <Wire.h>//библиотека работы с цап
  5. #include <SPI.h>
  6.  
  7. const int ENCODER_PIN_A = 10;    //Пин, к которому подключен энкодер.  
  8. const int ENCODER_PIN_B = 11;    //Пин, к которому подключен энкодер.  
  9. const int ENCODER_PIN_C = 15;
  10. const int SERVO_DIRECTION_PIN = 20;//Направление серво.
  11.  
  12. const int PWM_PIN_A = 17;//ПИНЫ управления углами поворота ШИМ
  13. const int PWM_PIN_B = 18;
  14. const int PWM_PIN_C = 19;
  15.  
  16. const int alpha=86; //максимальный угол поворота серва 30 град
  17. const int beta=71;//макимальный угол 25 град
  18. const int gamma=86;//максимальный угол поворота серва 30 град
  19. //T=20ms
  20. const int PWM_A=50;//10ms
  21. const int PWM_B=40;//8ms работает 12 отдыхет
  22. const int PWM_C=50;
  23. #define PCF8591 0x48//адрес подцепления ЦАП
  24. #define PCF8591_2 0x27//адрес подцепления второго ЦАП
  25. // настройки соединения  
  26. #define REMOTEXY_SERIAL_RX 10 //работа с bluetooth
  27. #define REMOTEXY_SERIAL_TX 11 //работа с bluetooth
  28. #define REMOTEXY_SERIAL_SPEED 9600
  29. #pragma pack(push, 1)
  30. uint8_t RemoteXY_CONF[] =
  31.   { 255,3,0,0,0,22,0,8,13,0,
  32.   5,0,10,16,30,30,2,26,31,1,
  33.   0,70,23,12,12,2,31,88,0 };
  34.    
  35. // структура определяет все переменные вашего интерфейса управления  
  36. struct {
  37.  
  38.     // input variable
  39.   int8_t joystick_1_x; // =-100..100 координата x положения джойстика
  40.   int8_t joystick_1_y; // =-100..100 координата y положения джойстика
  41.   uint8_t button_1; // =1 если кнопка нажата, иначе =0
  42.  
  43.     // other variable
  44.   uint8_t connect_flag;  // =1 if wire connected, else =0
  45.  
  46. } RemoteXY;
  47. #pragma pack(pop)
  48.  
  49. /////////////////////////////////////////////
  50. //           END RemoteXY include          //
  51. /////////////////////////////////////////////
  52.  
  53.  
  54. // в сантиметрах (distance threshold) Пороги расстояний до препятствия
  55. // Если ближе, то стоп
  56. const int DST_STOP = 20;
  57. boolean SAFE_DISTANCE = true; // измерение дистанции и безопасное движение. Если впереди близко препятствие, то стоп
  58. int distance = 0;
  59.  
  60. /* пины для подключения HC-SR04 Ultrasonic Module Distance Measuring
  61.  * 13, 2 цифровые пины
  62.  * 14, 15 аналоговые пины A0 и A1 соответственно
  63.  */
  64. #define SONIC_PIN_TRIG 14 //вывод на парктроник
  65. #define SONIC_PIN_ECHO 15 //вывод на парктроник
  66. #define SONIC_PIN_TRIG_BACK 16 //вывод на парктроник
  67. #define SONIC_PIN_ECHO_BACK 17// вывод на парктроник
  68. #define PIN_BUTTON_STOP 13//вывод кнопки тормоза
  69. // Detection distance: 2cm--450cm
  70. const int SONIC_DISTANCE_MAX = 450;
  71. const int SONIC_DISTANCE_MIN = 2;
  72.  
  73. // для управления по блютуз
  74. char btCommand = 'S';
  75. // счетчики для определения потери связи с блютуз
  76. unsigned long btTimer0 = 2000;  //Stores the time (in millis since execution started)
  77. unsigned long btTimer1 = 0;     //Stores the time when the last command was received from the phone
  78. const int in_1 = 22;//управление направления двигателя
  79. const int in_2 = 23;//управление направления двигателя
  80.  
  81.  
  82. //ЦАП 0..255
  83. //0В-0
  84. //5В-255
  85. //ЦАП покоя двигателя 0.66В прим. 34
  86. //Минимальная скорость 0.8В прим 41
  87. //Максимальная скорость 2.7В прим 137
  88. void setDAC(byte val){ //функция установления напряжения
  89.    Wire.beginTransmission(PCF8591);         // соединяемся с PCF8591
  90.    Wire.write(0x40);                        // включаем DAC    
  91.    Wire.write(val);                         // пишем в DAC значение
  92.    Wire.endTransmission();                  // завершаем соединение
  93. }
  94. void setDAC_2(byte val){ //функция установления напряжения
  95.    Wire.beginTransmission(PCF8591_2);         // соединяемся с PCF8591
  96.    Wire.write(0x40);                        // включаем DAC    
  97.    Wire.write(val);                         // пишем в DAC значение
  98.    Wire.endTransmission();                  // завершаем соединение
  99. }
  100.  
  101.  
  102. /******************************************
  103.   Main program
  104. ******************************************/
  105.  
  106. void setup() {
  107.   Wire.begin();
  108.   RemoteXY_Init ();  
  109.   pinMode (PIN_BUTTON_STOP, OUTPUT);
  110.   Serial.begin(9600);
  111.   pinMode(SONIC_PIN_TRIG, OUTPUT);
  112.   pinMode(SONIC_PIN_ECHO, INPUT);
  113.   pinMode(SONIC_PIN_TRIG_BACK, OUTPUT);
  114.   pinMode(SONIC_PIN_ECHO_BACK, INPUT);
  115.   pinMode(SERVO_DIRECTION_PIN, OUTPUT);
  116.   pinMode(ENCODER_PIN_A, OUTPUT);
  117.   pinMode(ENCODER_PIN_B, OUTPUT);
  118.   pinMode(ENCODER_PIN_C, OUTPUT);
  119.   analogWrite(PWM_PIN_A, PWM_A);
  120.   analogWrite(PWM_PIN_B, PWM_B);
  121.   analogWrite(PWM_PIN_C, PWM_C);
  122.   encoderInit();
  123.   motorInit();
  124. }
  125.  
  126.  
  127. void loop() {
  128.   RemoteXY_Handler ();
  129.   if (Serial.available() > 0) {
  130.     btTimer1 = millis();//засекаем время одного цикла
  131.    // ЕСЛИ ТОРМОЗ НЕ НАЖАТ
  132.    if (RemoteXY.button_1==0)
  133.    {
  134.       LeftRight(RemoteXY.joystick_1_x);
  135.       UpDown(RemoteXY.joystick_1_y);
  136.    }
  137.    else
  138.    {
  139.       motorStop();
  140.    }
  141.     btTimer0 = millis();  //Get the current time (millis since execution started).
  142.     //Check if it has been 500ms since we received last btCommand.
  143.     if ((btTimer0 - btTimer1) > 1500)   {
  144.       //если прошло больше 1500мс после последней команды, останавливаем
  145.       motorStop();
  146.     }
  147.   }
  148. }
  149.  
  150. /******************************************
  151.   Functions
  152. ******************************************/
  153. void encoderInit()
  154. {
  155.   SPI.begin();
  156.   digitalWrite(ENCODER_PIN_A, 1);
  157.   digitalWrite(ENCODER_PIN_B, 1);
  158.   digitalWrite(ENCODER_PIN_C, 1);
  159.   SPI.setClockDivider(SPI_CLOCK_DIV32);
  160. }
  161.  
  162. // инициализация моторов
  163. void motorInit()  {
  164.   setDAC(34);
  165.   motorStop();
  166. }
  167.  
  168. // безопасно ли ехать вперед?
  169. boolean isSafeDistance(bool z) {
  170.     if ( SAFE_DISTANCE )  {
  171.         // замер расстояния
  172.         if(z==false)
  173.         {
  174.           distance = measureDistanceBefore();
  175.         }
  176.         else if(z==true)
  177.         {
  178.           distance = measureDistanceAfter();
  179.         }
  180.         // препятствие так близко что надо ехать назад ?
  181.         if ( distance < DST_STOP ) {
  182.             return false;
  183.         }
  184.     } else {
  185.         return true;
  186.     }
  187. }
  188. // стоп
  189. void motorStop()  {
  190.  
  191. }
  192. // Возвращает расстояние до препятствия в сантиметрах
  193. int measureDistanceBefore()  {
  194.   long duration;
  195.   int  distance;
  196.   /* Для запуска передатчика нужно подать на Trig сигнал, длительностью 10мкс.
  197.    * Передатчик который посылает 8 коротких импульсов с частотой 40kHz.
  198.    * Приемник получает отраженный сигнал и на входе Echo генерируется сигнал,
  199.    * длительность которого равна времени прохождения звукового сигнала.
  200.    */
  201.   digitalWrite(SONIC_PIN_TRIG, LOW); // инициализация перед замером
  202.   delayMicroseconds(5); // 3
  203.   digitalWrite(SONIC_PIN_TRIG, HIGH);
  204.   delayMicroseconds(12); // 10
  205.   digitalWrite(SONIC_PIN_TRIG, LOW);
  206.  
  207.   duration = pulseIn(SONIC_PIN_ECHO, HIGH);
  208.   // Скорость звука 340 м/с или 29 микросекунд на сантиметр.
  209.   // Звук идет вперед и возвращается назад, таким образом время нужно делить на два
  210.   distance = duration / 58; // = microseconds / 29 / 2
  211.  
  212.   if (distance < SONIC_DISTANCE_MIN )  // out of range
  213.     return SONIC_DISTANCE_MIN;
  214.   if (distance > SONIC_DISTANCE_MAX )  // out of range
  215.     return SONIC_DISTANCE_MAX;
  216.  
  217.   return distance;
  218. }
  219. int measureDistanceAfter()  {
  220.   long duration;
  221.   int  distance;
  222.   /* Для запуска передатчика нужно подать на Trig сигнал, длительностью 10мкс.
  223.    * Передатчик который посылает 8 коротких импульсов с частотой 40kHz.
  224.    * Приемник получает отраженный сигнал и на входе Echo генерируется сигнал,
  225.    * длительность которого равна времени прохождения звукового сигнала.
  226.    */
  227.   digitalWrite(SONIC_PIN_TRIG_BACK, LOW); // инициализация перед замером
  228.   delayMicroseconds(5); // 3
  229.   digitalWrite(SONIC_PIN_TRIG_BACK, HIGH);
  230.   delayMicroseconds(12); // 10
  231.   digitalWrite(SONIC_PIN_TRIG_BACK, LOW);
  232.  
  233.   duration = pulseIn(SONIC_PIN_ECHO_BACK, HIGH);
  234.   // Скорость звука 340 м/с или 29 микросекунд на сантиметр.
  235.   // Звук идет вперед и возвращается назад, таким образом время нужно делить на два
  236.   distance = duration / 58; // = microseconds / 29 / 2
  237.  
  238.   if (distance < SONIC_DISTANCE_MIN )  // out of range
  239.     return SONIC_DISTANCE_MIN;
  240.   if (distance > SONIC_DISTANCE_MAX )  // out of range
  241.     return SONIC_DISTANCE_MAX;
  242.  
  243.   return distance;
  244. }
  245. void UpDown (int Y)
  246. {
  247. // изменение на джойстике 4..100 = изменение в байтах для ЦАП 41..137 (+37)
  248. if (Y>100) Y=100;
  249. if (Y<-100) Y=-100;
  250. if (Y>4)
  251. {
  252.   if(isSafeDistance(true)==true)
  253.   {
  254.     digitalWrite(in_1,HIGH);
  255.     digitalWrite(in_2,LOW);
  256.     setDAC(Y+37);
  257.     setDAC_2(Y+37);
  258.     delay(1000);//1сек
  259.   }
  260.   else
  261.   {
  262.     motorStop();  
  263.   }
  264. }
  265. else if (Y<-4)
  266. {
  267.   if(isSafeDistance(false)==true)
  268.   {
  269.     digitalWrite(in_1,LOW);
  270.     digitalWrite(in_2,HIGH);
  271.     Y*=-1;//берем по модулю
  272.     setDAC_2(Y+37);
  273.     setDAC(Y+37);
  274.     delay(1000);//1сек едет
  275.   }
  276.   else
  277.   {
  278.     motorStop();
  279.   }
  280. }
  281. else
  282. {
  283.   digitalWrite(in_1,LOW);
  284.   digitalWrite(in_2,LOW);
  285.   setDAC(34);// Если джойстик по вертикальной оси не двигается, то состояние покоя 0.66В
  286. }
  287. }
  288.  
  289. void LeftRight (int X)// 86 71 86
  290. {
  291.   if (X>100) X=100;
  292.   if (X<-100) X=-100;
  293.   if (X>4)
  294.   {
  295.     Right(ENCODER_PIN_A, PWM_PIN_A, 86, X);
  296.     Right(ENCODER_PIN_B, PWM_PIN_B, 71, X);
  297.     Right(ENCODER_PIN_C, PWM_PIN_C, 86, X);
  298.     delay(10);
  299.   }
  300.   else if(X<-4)
  301.   {
  302.     X*=-1;
  303.     Left(ENCODER_PIN_A, PWM_PIN_A, 86, X);
  304.     Left(ENCODER_PIN_B, PWM_PIN_B, 71, X);
  305.     Left(ENCODER_PIN_C, PWM_PIN_C, 86, X);
  306.     delay(10);
  307.   }
  308.   else
  309.   {//при отпускании руля нужно вычислить значение угла, чтобы привести его к нулю
  310.     ToNull(ENCODER_PIN_A, PWM_PIN_A, PWM_A);
  311.     ToNull(ENCODER_PIN_B, PWM_PIN_A, PWM_B);
  312.     ToNull(ENCODER_PIN_C, PWM_PIN_A, PWM_C);
  313.   }
  314. }
  315.  
  316. void ToNull(int ENCODER_PIN, int PWM_PIN, int PWM)
  317. {
  318.     digitalWrite(ENCODER_PIN, 0);
  319.     byte a = SPI.transfer(0);
  320.     byte b = SPI.transfer(1);
  321.     digitalWrite(ENCODER_PIN, 1);
  322.     int angle = (a << 8) | b;
  323.     while(angle!=0)
  324.     {
  325.      
  326.       if ((angle<512)&&(angle>10))
  327.       {
  328.         digitalWrite(SERVO_DIRECTION_PIN, 0);//обратное направлние
  329.         analogWrite(PWM_PIN, PWM);
  330.         delay(10);
  331.       }
  332.       else if ((angle>512)&&(angle<1013))
  333.       {
  334.         digitalWrite(SERVO_DIRECTION_PIN, 1);
  335.         analogWrite(PWM_PIN, PWM);
  336.         delay(10);
  337.       }
  338.      
  339.       else if((angle<512)&&(angle<10))//ДЛЯ ИЗБЕЖАНИЯ ЛИШНИХ КОЛЕБАНИЙ КОЛЕС В ЛЕВО ВПРАВО ПРИ МАЛЕНЬКИХ УГЛАХ
  340.       {
  341.         digitalWrite(SERVO_DIRECTION_PIN, 0);
  342.         analogWrite(PWM_PIN, 100);
  343.       }
  344.       else //ДЛЯ ИЗБЕЖАНИЯ ЛИШНИХ КОЛЕБАНИЙ КОЛЕС В ЛЕВО ВПРАВО ПРИ МАЛЕНЬКИХ УГЛАХ
  345.       {
  346.         digitalWrite(SERVO_DIRECTION_PIN, 1);
  347.         analogWrite(PWM_PIN, 100);
  348.       }
  349.       delay(2);
  350.     }
  351.     analogWrite(PWM_PIN, 0);
  352. }
  353. void Right(int ENCODER_PIN, int PWM_PIN, int MAXANGLE, int X)
  354. {
  355.     digitalWrite(SERVO_DIRECTION_PIN, 0);
  356.     digitalWrite(ENCODER_PIN, 0);
  357.     byte a = SPI.transfer(0);
  358.     byte b = SPI.transfer(1);
  359.     digitalWrite(ENCODER_PIN, 1);
  360.     int angle = (a << 8) | b;//склейка из двух байтов числа int от 0 до 1023
  361.     if(X*MAXANGLE/100<=angle)
  362.     analogWrite(PWM_PIN, 0);
  363. }
  364. void Left(int ENCODER_PIN, int PWM_PIN, int MAXANGLE, int X)
  365. {
  366.     digitalWrite(SERVO_DIRECTION_PIN, 1);
  367.     digitalWrite(ENCODER_PIN, 0);
  368.     byte a = SPI.transfer(0);
  369.     byte b = SPI.transfer(1);
  370.     digitalWrite(ENCODER_PIN, 1);
  371.     int angle =1023- (a << 8) | b;//отсчет в обратную сторону
  372.     if(X*MAXANGLE/100<=angle)
  373.     analogWrite(PWM_PIN, 0);
  374. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement