Интернет-лаборатория роботов ZiZiBOT.RU

Проектирование и разработки в области робототехники и автоматизации технологических процессов. Производство готовых роботов и конструкторов для творчества. Консультации и обучение по электронике и программированию.

г. Юрга,
ул.Ленинградская 38/83

+7 923-503-6074

Разберемся, почему использование GPIO 12 и/или 2 в ESP32 может привести к неработосопособности модуля и как совмещать 3 и 5 вольтовую логику

 

Добрый день!

С некоторых пор мы предпочитаем использовать контроллеры ESP32 обычным AVR контроллерам вроде ATMega328 (arduino nano/uno). Причина тому в функциональности ESP32 при схожей стоимости. 

Гикие возможности программирования прерываний и высокая скорость работы (240МГц против 16 МГц, 32 разряда против 8 разрядов) дает просто огромный выигрыш в производительности: (240/16)*(32/8) = 60 раз, грубый подсчет говорит о том, что ESP32 производительнее ATMega328 в 60 раз, но это весьма грубо. Без учета других особенностей, например, энергопотребление, которое может быть значительно выше при работе с беспроводными интерфейсам.

ESP32 поделка китайских мастеров и как все восточное несет некоторую таинственность, недосказаннность, неопределенность.

Мы расскажем о подводных камнях, с которыми столкнулись и о которых нужно сообщить, дабы Конструктора не начали сходить с ума от непредсказуемого поведения ESP32, как при попытках прошивки, так и при работе.

Потребовалось нам для стола большого 3d-принтера, имеющего два ходовых винта и пару шаговых подъемных моторов сконструировать систему выравнивания положения.  Дело в том, что использование пары несвязанных жестко ходовых винтов на подъем стола обязательно приведет к ппоявлению отклонений в положении осей, так как после отключения драйверов оси можно свободно вращать отдельно, а это приводит к вероятному наклону поверхности стола относительно печатного сопла (в сторону одной из подъемных осей), а при больших смещениях к даже заклиниванию стола.

подъем оси Z 3d принтера

Стандартные платы 3d принтеров имеют только один выход (набор выходных сигналов) для управления осью Z, что позволяет поднимать и опускать ось, но не дают возможности управлять подъемными моторами отдельно. Обычно пару моторов включают так, что их драйвера управляются параллельно (сигналы STEP, DIR, ENABLE приходят на оба драйвера с одних контактов управления), китайские умельцы "научились" управлять парой моторов от одного драйвера, подключая обмотки моторов последовательно, в этом случае пара моторов как-бы становится одним, деля мощность между собой, но отдельное управляемое перемещение осей в этих случаях также не осуществляется, а вот неуправляемый скос/разбаланс осей вполне вероятен.

Но кто может нам помешать самостоятельно сделать систему выравнивания осей. Главное, чтобы основная плата управления не имела препятствий в управлении перемещением стола при печати, а вот если в свободное от печати время мы будем иметь возможность автоматически проверить и выровнять стол, это хорошо и удобно.

В качество драйверов для шаговых моторов были использованы драйверы средней мощности HY-DIV268N-5А

HY-DIV268N

А для управление через ESP32 был использован конвертер уровней, хотя управление можно было осуществить проще, используя возможности использования GPIO ESP32 в режиме с открытым коллектором. Но режим "с отрытым коллектором" может быть небезопасен для контроллера, ведь подача ничем неограниченного даже небольшого напряжения в этом режиме вполне может сжечь ESP32.

Двунаправленные конвертеры уровней очень удобная вещь, но если входы находяться в неопределенном состоянии, то как поведет себя данная пара BX-AX предсказать трудно. В наше случае, при подключении конверторов уровней на GPIO по схеме изображенной ниже, модуль перестал загружаться, веренее ушел в постоянную перезгрузку, указывая на ошибку памяти через UART. 

Причина оказалась в том, что на GPIO12, после подачи напряжения питания схемы, выставлялся высокий уровень сигнала от конвертера уровней, что приводило к уходу ESP32 в бесконечный ребут.

Решение проблемы состоит в неиспользовании данного GPIO или контролю, за тем, чтобы при включении и до загрузки ESP32, на данном GPIO (GPIO12 GPIO2) был/эмулировался разрыв - отсутствие подключения к GND или питанию. Для этого мы подтянем к GND контакты 0E конвертеров, отвечающие за их включение и будем отдельно управлять включением конвертеров тогда, кода нам это поребуется в программе. Мы подключили управление к GPIO33, теперь следует не забыть в программе перевести GPIO33 в состояние OUTPUT и до использования конвертора уровней подать на GPIO33 высокий уровень сигнала digitalWrite(33,HIGH); 

 

ESP32 схема

Программа тестирования  функциональности созданной схемы приведена ниже. 

Мы имеем три кнопки S1,S2,S3, которые подтянуты через различные по номиналу резисторы (R1 R2 R3) к земле. С другой стороны замыкающего контакта кнопки подтянуты к питанию через резистор R4. Сигнал снимается между резисторами и, за счет того что при змыкании определенной кнопки потенциал на GPIO32 будет отличаться, мы считывая его (analogRead(BUTTON_GPIO);)  получаем информацию о том, какая кнопка нажата.

Аналогично, но в цифровом виде, мы снимаем информацию с оптических концевых датчиков fc-03, они подключены к GPIO19 и GPIO15. 

Работоспособность схемы проверяется сигналом светодиода WS2812, для которого компания Adafruit предлагает библиотеку Adafruit_NeoPixel.h. Нажимая на разные кнопки или перекрывая световой поток в оптодатчике мы даем команду светодиоду светить определеным-разным светом.

Тестирование схемы прошло успешно, теперь нужно написать программу управления шаговыми моторами и получения внешних команд.


Тестовая программа опробована в Arduino IDE
 

  1. #include   < Adafruit_NeoPixel.h >
  2.  
  3. #define LED_PIN 17
  4.  
  5. // How many NeoPixels are attached to the Arduino?
  6. #define LED_COUNT 1
  7.  
  8. // NeoPixel brightness, 0 (min) to 255 (max)
  9. #define BRIGHTNESS 50
  10.  
  11. #define BUTTON_GPIO 32
  12. #define white_GPIO_BUTTON 1860
  13. #define blue_GPIO_BUTTON 208
  14. #define red_GPIO_BUTTON 1120
  15. #define dX 40
  16.  
  17. #define SENSOR_1_GPIO 15
  18. #define SENSOR_2_GPIO 19
  19.  
  20. #define STEP_1_GPIO 25
  21. #define DIR_1_GPIO 26
  22. #define EN_1_GPIO 27
  23.  
  24. #define STEP_2_GPIO 14
  25. #define DIR_2_GPIO 12
  26. #define EN_2_GPIO 13
  27.  
  28.  
  29. #define EN_CONVERTOR_GPIO 33
  30.  
  31.  
  32. Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);
  33. // Argument 1 = Number of pixels in NeoPixel strip
  34. // Argument 2 = Arduino pin number (most are valid)
  35. // Argument 3 = Pixel type flags, add together as needed:
  36. // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
  37. // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
  38. // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
  39. // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
  40. // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
  41.  
  42. void setup() {
  43.  
  44. pinMode(EN_CONVERTOR_GPIO, OUTPUT); //
  45. digitalWrite(EN_CONVERTOR_GPIO, LOW); //Выключаем конверторы уровней.
  46. strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  47. strip.show(); // Turn OFF all pixels ASAP
  48. strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
  49. pinMode(BUTTON_GPIO, INPUT); //button
  50. pinMode(SENSOR_1_GPIO, INPUT); //sens 1
  51. pinMode(SENSOR_2_GPIO, INPUT); //sens 1
  52.  
  53. pinMode(STEP_1_GPIO, OUTPUT);
  54. pinMode(DIR_1_GPIO, OUTPUT);
  55. pinMode(EN_1_GPIO, OUTPUT);
  56.  
  57. pinMode(STEP_2_GPIO, OUTPUT);
  58. pinMode(DIR_2_GPIO, OUTPUT);
  59. pinMode(EN_2_GPIO, OUTPUT);
  60.  
  61. digitalWrite(STEP_1_GPIO, LOW);
  62. digitalWrite(DIR_1_GPIO, LOW);
  63. digitalWrite(EN_1_GPIO, LOW);
  64.  
  65. digitalWrite(STEP_2_GPIO, LOW);
  66. digitalWrite(DIR_2_GPIO, LOW);
  67. digitalWrite(EN_2_GPIO, LOW);
  68.  
  69. Serial.begin(115200);
  70. digitalWrite(EN_CONVERTOR_GPIO, HIGH); //Включаем конверторы уровней.
  71. }
  72.  
  73. void loop() {
  74. int X = analogRead(BUTTON_GPIO);
  75.  
  76. if (((white_GPIO_BUTTON - dX) < X) && ((white_GPIO_BUTTON + dX) > X))
  77. {
  78. strip.setPixelColor(0, strip.Color(155, 155, 155));
  79. strip.show();
  80. }
  81. else if (((blue_GPIO_BUTTON - dX) < X) && ((blue_GPIO_BUTTON + dX) > X))
  82. {
  83. strip.setPixelColor(0, strip.Color(0, 0, 255));
  84. strip.show();
  85. }
  86. else if (((red_GPIO_BUTTON - dX) < X) && ((red_GPIO_BUTTON + dX) > X))
  87. {
  88. strip.setPixelColor(0, strip.Color(255, 0, 0));
  89. strip.show();
  90. }
  91. else if (digitalRead(SENSOR_1_GPIO) == 1)
  92. {
  93. strip.setPixelColor(0, strip.Color(155, 155, 0));
  94. strip.show();
  95. }
  96. else if (digitalRead(SENSOR_2_GPIO) == 1)
  97. {
  98. strip.setPixelColor(0, strip.Color(155, 0, 155));
  99. strip.show();
  100. }
  101. else
  102. {
  103. strip.setPixelColor(0, strip.Color(0, 0, 0));
  104. strip.show();
  105. }
  106.  
  107.  
  108.  
  109. Serial.println(X);
  110. delay(30);
  111. return;
  112. }

ОСТАВИТЬ КОММЕНТАРИЙ

Форма авторизации

ВОЙТИ С ПОМОЩЬЮ:
ИЛИ Авторизация на сайте:

или



X

Написать сообщение:

Укажите свой номер телефона или e-mail для обратной связи
- e-mail
ИЛИ
- номер телефона

Текст сообщения: