• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Использование ESP-12 в связке с DRV8833 и электромоторчиком, и ITR9606

MeMagic

New member
Есть такое задание: управление электромоторчиком используя в том числе и ограничитель.
В качестве элементов используются перечисленные в заголовке, плюс два понижающих резистора для оптопары - 100Ohm последовательно с диодом и 10kOhm развязка от эмиттера на землю, параллельно входу в ESP. Питание: для двигателя и DRV8833 - 12V через преобразователь в 5V, для ESP и оптопары - 3.3V от nodeMCU. Всё это разложено на печеньке небольшой макетки.
IMG_20200516_211840.jpg
Стоит заметить, что электродвигатель мелкий и оснащён редуктором примерно 1:1000, один оборот происходит в течении около 4-5 секунд. Оптопара у меня вскрыта, так как я её готовлю для установки в ограниченное пространство, однако опыты были проведены так же и с оригинальной оптопарой.

Задача: произвести калибровку двигателя путём вращения двигателя в одну сторону до перекрытия оптопары; вращение в другую сторону до перекрытия оптопары с регистрацией времени от старта до останова; ещё одна смена направления и снова вращение до перекрытия оптопары с регистрацией времени от старта до останова; вычисление среднего времени для одного цикла; очередная (на этот раз, демонстрационная) смена направления и вращение в течение 1/4 времени полного цикла. Цель - вращение грубо на четверть оборота.

Код следующий:
Код:
byte FwdPin = 12;
byte BkwPin = 13;
byte OpcPin = 14;
unsigned long TargetTimer = 0;

byte System_NonCalibrated = 0;
byte System_CalibrationStarted = 1;
byte System_InitExtremeFound = 2;
byte System_FindFwdExtreme = 3;
byte System_ForwExtremeFound = 4;
byte System_FindBkwExtreme = 5;
byte System_BckwExtremeFound = 6;
byte System_AvgCcleTimeFound = 7;
byte System_Calibrated = 8;

byte System_State = 0;
byte System_PrevState = -1;
byte OC_State = 0;
byte OC_Prev = -1;
byte Motor_State = 0;
unsigned long System_StartFwdMtn = -1;
unsigned long System_EndFwdMtn = -1;
unsigned long System_StartBkwMtn = -1;
unsigned long System_EndBkwMtn = -1;

byte Motor_StopSignal = LOW;
byte Motor_RunSignal = HIGH;
byte Motor_RunForwd = 2;
byte Motor_RunBackw = 3;

byte OC_Covered = LOW;
byte OC_NonCovered = HIGH;
byte OC_CoverCount = 0;

unsigned long Motor_AvgCcleTime = 0;

bool debug = true;

void setup() {
  // put your setup code here, to run once:
  pinMode(OpcPin, INPUT);
  pinMode(FwdPin, OUTPUT);
  pinMode(BkwPin, OUTPUT);
  Serial.begin(115200);
  Serial.println();
  Serial.println("   Let's ROCK!");
  Serial.println();
  Serial.println();
}

void debug_print(char str1[], unsigned long str2, char str3[]) {
  if (!debug) return;
  if (str1 != "") Serial.print(str1);
  if (str2 != 0) Serial.print(str2);
  if (str3 != "") Serial.print(str3);
  Serial.println();
}

void Motor_Stop()
{
  digitalWrite(FwdPin, Motor_StopSignal);
  digitalWrite(BkwPin, Motor_StopSignal); 
  Motor_State = Motor_StopSignal;
}

void Motor_StartForward()
{
  Motor_Stop();
  digitalWrite(FwdPin, Motor_RunSignal);
  Motor_State = Motor_RunForwd;
}

void Motor_StartBackward()
{
  Motor_Stop();
  digitalWrite(BkwPin, Motor_RunSignal);
  Motor_State = Motor_RunBackw;
}

void System_Calibration()
{
  switch (System_State) {
    case 0:
      debug_print("System not calibrated. Starting initial rotation backward.", 0, "");
      Motor_StartBackward();
      System_State = System_CalibrationStarted;
      System_StartFwdMtn = 0;
      System_StartBkwMtn = 0;
      System_EndFwdMtn = 0;
      System_EndBkwMtn = 0;
      break;
    case 1:
      if (OC_State == OC_Covered) {
        Motor_Stop();
        System_State = System_InitExtremeFound;
        TargetTimer = millis() + 2000;
        debug_print("Initial extreme found. What next?", 0, "");
      }
      break;
    case 2:
      TargetTimer = millis() + 400;
      Motor_StartForward();
      System_StartFwdMtn = millis();
      System_State = System_FindFwdExtreme;
      debug_print("Started measurement rotation forward. Start forward time = ", System_StartFwdMtn, "");
      break;
    case 3:
      if (OC_State == OC_Covered) {
        System_EndFwdMtn = millis();
        Motor_Stop();
        System_State = System_ForwExtremeFound;
        TargetTimer = millis() + 2000;
        debug_print("Measurement rotation forward stopped. End forward time = ", System_EndFwdMtn, "");
      }
      break;
    case 4:
      TargetTimer = millis() + 400;
      Motor_StartBackward();
      System_StartBkwMtn = millis();
      System_State = System_FindBkwExtreme;
      debug_print("Started measurement rotation backward. Start backward time = ", System_StartBkwMtn, "");
      break;
    case 5:
      if (OC_State == OC_Covered) {
        System_EndBkwMtn = millis();
        Motor_Stop();
        System_State = System_BckwExtremeFound;
        debug_print("Measurement rotation backward stopped. End backward time = ", System_EndBkwMtn, "");
      }
      break;
    case 6:
      Motor_AvgCcleTime = (System_EndFwdMtn - System_StartFwdMtn + System_EndBkwMtn - System_StartBkwMtn) / 2;
      TargetTimer = millis() + int(Motor_AvgCcleTime / 4);
      Motor_StartForward();
      System_State = System_AvgCcleTimeFound;
      debug_print("Average circle time calculated - ", Motor_AvgCcleTime, " millisecs.");
      break;
    case 7:
      System_State = System_Calibrated;
      debug_print("System calibrated?", 0, "");
      break;
  }
}

void loop() {
  OC_State = digitalRead(OpcPin);
 
  if (System_State < 0 or System_State > 8) System_State = System_NonCalibrated;
  if (System_State != System_PrevState) {
      debug_print("Current system state - ", System_State, "");
      System_PrevState = System_State;
  }
  if (OC_Prev != OC_State) {
    if (OC_State == OC_Covered) {
      debug_print("Opto interrupter covered. Time: ", millis(), "");
      if (System_State == System_Calibrated) OC_CoverCount++;
      if (OC_CoverCount > 5) {
        OC_CoverCount = 0;
        if (System_State == System_Calibrated) System_State = System_NonCalibrated;
      }
    }
    else {
      debug_print("Opto interrupter not covered. Time: ", millis(), "");
    }
    OC_Prev = OC_State;
  }
  if (TargetTimer < millis()) if (System_State < System_Calibrated) {
    System_Calibration();
  }
  if (System_State == System_Calibrated and Motor_AvgCcleTime <= 0) {
    System_State = System_NonCalibrated;
    debug_print("Average circle time corrupted, going to run calibration. Average circle: ", Motor_AvgCcleTime, ".");
  }

  yield();
}
При полностью отключенном питании на двигатель, после заливки кода получаем следующий аутпут:
Let's ROCK!


Current system state -
Opto interrupter not covered. Time: 61
System not calibrated. Starting initial rotation backward.
Current system state - 1
Opto interrupter covered. Time: 4927
Initial extreme found. What next?
Current system state - 2
Opto interrupter not covered. Time: 4927
Opto interrupter covered. Time: 4928
Started measurement rotation forward. Start forward time = 6928
Current system state - 3
Measurement rotation forward stopped. End forward time = 7329
Current system state - 4
Opto interrupter not covered. Time: 7678
Started measurement rotation backward. Start backward time = 9330
Current system state - 5
Opto interrupter covered. Time: 11689
Measurement rotation backward stopped. End backward time = 11689
Current system state - 6
Average circle time calculated - 1380 millisecs.
Current system state - 7
System calibrated?
Current system state - 8
Opto interrupter not covered. Time: 17653
Opto interrupter covered. Time: 20302
Opto interrupter not covered. Time: 20302
Opto interrupter covered. Time: 20302
Opto interrupter not covered. Time: 22919

После окончания калибровки происходит просто регистрация факта закрытия/открытия оптопары. Однако, если система в состоянии "Откалибровано", после пятого открытия оптопары происходит сброс состояния и снова производится калибровка. Это сделано для проверки многократной системной отработки (короче, - для пущего тестирования).
Можно заметить в окне вывода, что открытие/закрытие оптопары происходит до странности многократно при одном движении флажка (флажок в данном случае кусочек картонки подносимый рукой). Почему это происходит следует понять, потому что это никак не сходится с задачей.

Далее, если подать питание на цепь управления двигателя, происходят чудеса - оптопара сама по себе срабатывает по многу раз в секунду, двигатель крутит то туда, то сюда вообще бессистемно.

Прошу просветить: Что я делаю не так?

ПЫС. Изначально код имел совсем другую структуру и включал переизбыток пауз. После указания со стороны о недопустимости перехвата цепи обработки процессов на долгое время, было решено перевести в формат отработки как можно меньших шагов и их обработки в дискретные значения времени. Таким образом получилось избавиться от постоянных перезагрузок контроллера. С той же целью был включен оператор yield(), но при текущем построении алгоритма, его использование оказалось избыточным.
 

MeMagic

New member
Ну, уважаемые, нет никого-никого, кто разбирается в электротехнике ESP8266. Аж неловко стало, что задаю такие вопросы... :)))
Мне-то всего-то надо, чтобы кто-то подсказал как правильно подключать между собой следующие компоненты:
1589826602241.png 1589826700572.png 1589826777174.png

Исходя из моих нескромных опыта и знаний электроники, я вышел на следующую схему:
1589827398173.png

Вот здесь я застрял. Так как при вместе подключенных оптопаре и драйвера мотора у меня дребезг на входе ESP12 со стороны оптопары, и как следствие код исполняется абсолютно невпопад. На данный момент с оптопары приходят совсем неправильные сигналы. А именно, если я просто отслеживаю оптопару, я получаю открыто/закрыто. Если же я отправляю сигнал на соседние GPIO 12 и/или 13 (управление мотором вперёд/назад), у меня начинается котовасия на входе с оптопары (GPIO14).
Что я делаю не так?
ЗЫ. Не знаю правильно ли я отобразил схему подключения оптопары, но согласно её лэйауту (на втором рисунке) я подключил масу к катоду и к эмиттеру, к эмиттеру через резистор 10к. К эмиттеру же подключил ногу ESP.
 

MeMagic

New member
Подайте питание на мотор от другого источника питания.
Питание на мотор подаётся с источника питания в 12В, пониженного до 5В через Kis-3r33. Питание на ESP и соответственно оптопару подаётся от компьютера через microUSB.
 

CodeNameHawk

Moderator
Команда форума
Далее, если подать питание на цепь управления двигателя, происходят чудеса - оптопара сама по себе срабатывает по многу раз в секунду,
Вы уверены, что она срабатывает по многу раз в секунду, а не вы просто успеваете столько раз ее считать.
Смотреть на код, в котором нет коментариев для чего нужна каждая переменная, что должен делать этот код, нет желания.
 

A_D

Active member
Ну, уважаемые, нет никого-никого, кто разбирается в электротехнике ESP8266. Аж неловко стало, что задаю такие вопросы... :)))
Мне-то всего-то надо, чтобы кто-то подсказал как правильно подключать между собой следующие компоненты:
Посмотреть вложение 9225 Посмотреть вложение 9226 Посмотреть вложение 9227

Исходя из моих нескромных опыта и знаний электроники, я вышел на следующую схему:
Посмотреть вложение 9229

Вот здесь я застрял. Так как при вместе подключенных оптопаре и драйвера мотора у меня дребезг на входе ESP12 со стороны оптопары, и как следствие код исполняется абсолютно невпопад. На данный момент с оптопары приходят совсем неправильные сигналы. А именно, если я просто отслеживаю оптопару, я получаю открыто/закрыто. Если же я отправляю сигнал на соседние GPIO 12 и/или 13 (управление мотором вперёд/назад), у меня начинается котовасия на входе с оптопары (GPIO14).
Что я делаю не так?
ЗЫ. Не знаю правильно ли я отобразил схему подключения оптопары, но согласно её лэйауту (на втором рисунке) я подключил масу к катоду и к эмиттеру, к эмиттеру через резистор 10к. К эмиттеру же подключил ногу ESP.
у оптопары поменяйте местами 3 \ 4 выводы, так она работать не будет.
 

MeMagic

New member
Вы уверены, что она срабатывает по многу раз в секунду, а не вы просто успеваете столько раз ее считать.
Смотреть на код, в котором нет коментариев для чего нужна каждая переменная, что должен делать этот код, нет желания.
Здесь привожу адаптированную выдержку из кода. Адаптированную, чтобы выделить только искомый момент.
Код:
int OpcPin = 14;      //   адрес GPIO для входа с оптопары
int OC_State = 0;     //   переменная для считывания сигнала с оптопары
int OC_Prev = 0;      //   вспомогательная переменная для хранения сигнала с оптопары независимо от цикла
int OC_Covered = HIGH;   //   константа для контроля значения сигнала оптопары  -  удобочитаемый флаг, избыточная переменная

void loop() {
  OC_State = digitalRead(OpcPin);    //  Здесь у нас считывание входа с оптопары

  if (OC_Prev != OC_State) {       //  Здесь у нас контроль изменения состояния. Вывод на печать производится только при переключении, а не в каждом цикле

    if (OC_State == OC_Covered) {       //  Здесь мы просто определяем состояние по значению флага int OC_Covered = HIGH;
      Serial.println("Opto interrupter covered. Time: ", millis(), "");     //   Вывод на печать времени от начала исполнения 
                                                                            //    кода до текущего переключения сигнала оптопары
    }
    else {
      Serial.println("Opto interrupter not covered. Time: ", millis(), "");     //   Вывод на печать времени от начала исполнения 
                                                                                //   кода до текущего переключения сигнала оптопары
    }
    OC_Prev = OC_State;   //   установка значения предыдущей величины, логический результат = переключение отработано
  }
}    //    Здесь у нас заканчивается код и происходит выход из программы.
А здесь у нас вывод.
Код:
Opto interrupter not covered. Time: 141525
Opto interrupter covered. Time: 141525
Opto interrupter not covered. Time: 141525
Opto interrupter covered. Time: 141525
Opto interrupter not covered. Time: 141528
Opto interrupter covered. Time: 141573
Opto interrupter not covered. Time: 141606
Opto interrupter covered. Time: 141628
Opto interrupter not covered. Time: 150657
Из вывода следует, что срабатывание происходит не просто по многу раз в секунду, а по многу раз за тысячную секунды.
 

MeMagic

New member
у оптопары поменяйте местами 3 \ 4 выводы, так она работать не будет.
Я попробую поменять и отпишусь.
Но меня всё же гложет другое. А именно то, что дребезг происходит тогда, когда я шлю сигнал на ноги управления мотором. Как пример:
Код:
   Let's ROCK!


1. Current system state - 
2. Opto interrupter not covered. Time: 61
3. System not calibrated. Starting initial rotation backward.
4. Current system state - 1
5. Opto interrupter covered. Time: 4927
6. Initial extreme found. What next?
7. Current system state - 2
8. Opto interrupter not covered. Time: 4927
9. Opto interrupter covered. Time: 4928
10. Started measurement rotation forward. Start forward time = 6928
11. Current system state - 3
12. Measurement rotation forward stopped. End forward time = 7329
13. Current system state - 4
14. Opto interrupter not covered. Time: 7678
15. Started measurement rotation backward. Start backward time = 9330
16. Current system state - 5
17. Opto interrupter covered. Time: 11689
18. Measurement rotation backward stopped. End backward time = 11689
19. Current system state - 6
20. Average circle time calculated - 1380 millisecs.
21. Current system state - 7
22. System calibrated?
23. Current system state - 8
24. Opto interrupter not covered. Time: 17653
25. Opto interrupter covered. Time: 20302
26. Opto interrupter not covered. Time: 20302
27. Opto interrupter covered. Time: 20302
28. Opto interrupter not covered. Time: 22919
Алгоритм должен быть таким:
1. Шаги 1-2. Система не откалибрована. Запускаем процесс калибровки.
2. Шаги 3-9. Вращаем моторчик назад (вперёд и назад условные направления, просто противоположные друг другу) до закрытия оптопары (таким образом эмулируем срабатывание ограничителя).
3. Шаги 10-11. Выжидаем 2с. и запускаем вращение вперёд. Выжидаем 0,4с и начинаем мониторить оптопару на предмет срабатывания ограничителя. 0,4с - время в течение которого оптопара должна стать открытой, чтобы был смысл отслеживать её закрытие.
4. Шаги 12-13. При закрытии оптопары фиксируется время и останавливается мотор.
5. Шаги 14-16. Выжидаем 2с и запускаем движение назад: 7329 - 9330 мс.
6. Шаги 17-19. Через 0.4с после запуска мотора назад начинается отслеживание флаг закрытия оптопары. На 11689 мс оптопара закрылась. Мотор остановлен.
7. Шаги 20-21. Вычисление срднего времени вращения между срабатываниями оптопары - почти одного оборота.
8. Шаги 22-23. Вращение двигателя вперёд на четверть одного полного вращения - 90 градусов.
9. Шаг 23. Установка системы в значение откалибровано.
Шаги 24-28 - произвольное закрытие/открытие оптопары рукой. Как видно, на шагах 25, 26 и 27 одно и то же значение времени в мс что может быть следствием либо дребезга (шумов) в системе, либо некачественного закрытия транзистора оптопары, что вообще нонсенс.

Если система некоторое время стоит без сигналов на ного управления мотором, вигнал идущий с оптопары в общем случае стабилен.
 

CodeNameHawk

Moderator
Команда форума
Скорее всего у вас наводки на провода.
Попробуйте земли есп, платы управления и оптопары соединить в одной точке.
Все провода минимальной длины.
Резистор возле оптопары, который на землю, замените на 470 ом.
 

CodeNameHawk

Moderator
Команда форума
Код:
int OpcPin = 14;      //   адрес GPIO для входа с оптопары
int OC_State = 0;     //   переменная для считывания сигнала с оптопары
int OC_Prev = 0;      //   вспомогательная переменная для хранения сигнала с оптопары независимо от цикла
int OC_Covered = HIGH;   //   константа для контроля значения сигнала оптопары  -  удобочитаемый флаг, избыточная переменная

void loop()
{
  OC_State = digitalRead(OpcPin);    //  Здесь у нас считывание входа с оптопары

  if (OC_Prev == HIGH)
  {       //  Здесь у нас контроль изменения состояния. Вывод на печать производится только при переключении, а не в каждом цикле
      Serial.println("Opto HIGH: ", millis(), "");     //   Вывод на печать времени от начала исполнения
  }
  else
  {
      Serial.println("Opto  LOW: ", millis(), "");     //   Вывод на печать времени от начала исполнения
   }
}    //    Здесь у нас заканчивается код и происходит выход из программы.
Покажите, что этот код выдает.
 

MeMagic

New member
Скорее всего у вас наводки на провода.
Попробуйте земли есп, платы управления и оптопары соединить в одной точке.
Все провода минимальной длины.
Резистор возле оптопары, который на землю, замените на 470 ом.
Если исходить из следующего, у меня подключение было катод на землю и эмиттер через 10к на землю и на МК.
1589914495751.png
Сейчас мне порекомендовали подключить таким образом:
1589915118183.png или 1589915142285.png

Товарищ, который это порекомендовал, сослался на то, что внутренние транзисторы микроконтроллера надо учитывать и оберегать. Правда, опыта с Ардуино или ESP у него нет. Даже не знаю, что пробовать.
Кстати, сам по себе концепт макеток слегка пижонистый - дюпон провода болтаются как в проруби, а длина почти 20см каждого. Это то, что касается соединить земли в одной точке.
 

MeMagic

New member
Код:
int OpcPin = 14;      //   адрес GPIO для входа с оптопары
int OC_State = 0;     //   переменная для считывания сигнала с оптопары
int OC_Prev = 0;      //   вспомогательная переменная для хранения сигнала с оптопары независимо от цикла
int OC_Covered = HIGH;   //   константа для контроля значения сигнала оптопары  -  удобочитаемый флаг, избыточная переменная

void loop()
{
  OC_State = digitalRead(OpcPin);    //  Здесь у нас считывание входа с оптопары

  if (OC_Prev == HIGH)
  {       //  Здесь у нас контроль изменения состояния. Вывод на печать производится только при переключении, а не в каждом цикле
      Serial.println("Opto HIGH: ", millis(), "");     //   Вывод на печать времени от начала исполнения
  }
  else
  {
      Serial.println("Opto  LOW: ", millis(), "");     //   Вывод на печать времени от начала исполнения
   }
}    //    Здесь у нас заканчивается код и происходит выход из программы.
Покажите, что этот код выдает.
Серьёзно? Результат следующий:
Код:
бесконечное 
"Opto  LOW: nnnnnn"
Ничего другого не может быть, т.к. из кода исполняется только считывание, сравнение HIGH и HIGH и печать одного и того же.
Интересно было бы узнать, какова была цель, но опыт интересный.

Изменил предложенный вами код на что-то более смысловое для меня:
C:
int OpcPin = 14;      //   адрес GPIO для входа с оптопары
int OC_State = 0;     //   переменная для считывания сигнала с оптопары
int OC_Prev = 0;      //   вспомогательная переменная для хранения сигнала с оптопары независимо от цикла
int OC_Covered = HIGH;   //   константа для контроля значения сигнала оптопары  -  удобочитаемый флаг, избыточная переменная

void setup() {
  Serial.begin(74880); 
}

void loop()
{
  OC_State = digitalRead(OpcPin);    //  Здесь у нас считывание входа с оптопары

  if (OC_Prev == OC_State) return;

  if (OC_State == HIGH)
  {       //  Здесь у нас контроль изменения состояния. Вывод на печать производится только при переключении, а не в каждом цикле
      Serial.print("Opto HIGH: ");
      Serial.println(millis());     //   Вывод на печать времени от начала исполнения
  }
  else
  {
      Serial.print("Opto  LOW: ");
      Serial.println(millis());     //   Вывод на печать времени от начала исполнения
   }
   OC_Prev = OC_State;
}    //    Здесь у нас заканчивается код и происходит выход из программы.
Результат совсем другой!
Opto HIGH: 61
Opto LOW: 48802
Opto HIGH: 50763
Opto LOW: 53562
Opto HIGH: 54916
Opto LOW: 56203
Opto HIGH: 57154
Opto LOW: 59147
Opto HIGH: 59148
Opto LOW: 59149
Opto HIGH: 64017
Opto LOW: 65428
Opto HIGH: 66881
Opto LOW: 68306
Opto HIGH: 69869
Opto LOW: 71451
Opto HIGH: 72661
Opto LOW: 73790
Opto HIGH: 74503
Opto LOW: 75578
Opto HIGH: 75853
Opto LOW: 85949
Opto HIGH: 85949
Opto LOW: 85950
Opto HIGH: 85950
Opto LOW: 85950
Opto HIGH: 85950
Opto LOW: 85950
Opto HIGH: 85951
Opto LOW: 85953
Opto HIGH: 85955
Opto LOW: 85958
Opto HIGH: 86052
Opto LOW: 86052
............
Opto LOW: 581609
Opto HIGH: 582937
Opto LOW: 583969
Opto HIGH: 584865
Opto LOW: 585732
Opto HIGH: 586704
Opto LOW: 587614
Opto HIGH: 588670
Opto LOW: 589487
Opto HIGH: 590525
Opto LOW: 591332
Opto HIGH: 592380
Opto LOW: 593130
Opto HIGH: 594128
Opto LOW: 594953
Opto HIGH: 595872
....................

Поначалу, оптопара срабатывала (почти, за одним исключением) чётко на каждом шагу. Вплоть до 86-й секунды.... Что там произошло?
Далее попробовал снова. Как видно, дребезга почти нет. Правда, я так же старался чётко открывать/закрывать оптопару. Когда это случилось слегка небрежно, появилось ложное срабатывание.
Полагаю, мне надо пересмотреть значение сопротивления на диоде - думаю, надо уменьшить ток. Нет? Или схема с делителем на коллекторе будет лучше?
 

MeMagic

New member
Предыдущий код с делителем до 2,8В результат (напряжение 0.002 - 2.76В):
Opto LOW: 156021
Opto HIGH: 156021
Opto LOW: 156021
Opto HIGH: 162530
Opto LOW: 178265
Opto HIGH: 178265
Opto LOW: 178266
Opto HIGH: 183626
Opto LOW: 186943
Opto HIGH: 186943
Opto LOW: 186943
Opto HIGH: 189781

Теперь с сопротивлением 430Ом вместо отсутствующего 470Ом (напряжение 0.001 - 2.33В):
Opto LOW: 62076
Opto HIGH: 62076
Opto LOW: 62076
Opto HIGH: 62076
Opto LOW: 62076
Opto HIGH: 63852
Opto LOW: 66170
Opto HIGH: 67233
Opto LOW: 67233
Opto HIGH: 67233
Opto LOW: 68464
Opto HIGH: 69765
Opto LOW: 69765
Opto HIGH: 69765
Opto LOW: 69765
Opto HIGH: 69765
Opto LOW: 72181
Opto HIGH: 72181
Opto LOW: 72181
Opto HIGH: 73357
Opto LOW: 74655
Opto HIGH: 75846
Opto LOW: 77102
Opto HIGH: 77102
Opto LOW: 77102
Opto HIGH: 78242
Opto LOW: 79522
Opto HIGH: 79523
Opto LOW: 79523
Opto HIGH: 80750
Opto LOW: 80750
Opto HIGH: 80750
Opto LOW: 80750
Opto HIGH: 80750
Кажется, ложных срабатываний одинаково. Однако, вариант, когда я пытался воспроизвести горизонтальное движение флажка, вроде как чище отрабатывает.
В общем так, я построю прототип с электромотором с флажком, закреплённом жестко, с пропаянными проводниками и т.д. Тогда уже буду тестировать на живую.
Всё же, может есть вариант изолировать выходные ноги в сторону модуля DRV8833, чтоб не было случайных внутренних шумов?
 

A_D

Active member
Я не особо шарю в ESP, но, думаю, надо копать в сторону прерываний и измерении периода с помощью них - https://circuits4you.com/2017/12/08/esp8266-external-interrupt-example/ , по идее идеально с таймером и в целом, посмотрели бы осциллографом сигналы, убедились сначала в их периодичности и не зашумлёности, а потом отлаживались с кодом уже, если есть сомнения в "ложных срабатываниях".
 

CodeNameHawk

Moderator
Команда форума
В коде должно было быть
Код:
  OC_State = digitalRead(OpcPin);    //  Здесь у нас считывание входа с оптопары

  if (OC_State == HIGH)
 

CodeNameHawk

Moderator
Команда форума
Правда, я так же старался чётко открывать/закрывать оптопару. Когда это случилось слегка небрежно, появилось ложное срабатывание.
Важно, что бы не было ложных срабатываний от наводок.
Вам важно поймать первое срабатывание датчика и остановить двигатель, а потом, если программа составлена грамотно, дребезг не должен мешать. От обычной кнопки куча срабатываний и никому особо не мешает.

Или схема с делителем на коллекторе будет лучше?
Можете оставить схему с делителем, а можете верхний выкинуть и сделать так
1589915142285.png
Это обережет есп, если вход есп окажется выходом с низким уровнем, а транзистор будет открыт.
 

MeMagic

New member
В коде должно было быть
Код:
  OC_State = digitalRead(OpcPin);    //  Здесь у нас считывание входа с оптопары

  if (OC_State == HIGH)
Вечером попробую, выпишу результаты. Кстати, а за чем наблюдать при воспроизведении кода? В идеале получится тот же результат, что и в случае с моим кодом. Разве, что не будет фильтра состяния, и "каждый Божий" цикл будет отработан, а это огромное кол-во записей вывода за парочку секунд. Если это и есть то, что мы хотим выследить - не вопрос. Результат чего выписать сюда?
Надо посмотреть в описании какой надо пускать ток через светодиод и рассчитать резистор.
В описании оптопары смотрел, падение напряжения на диоде - 1,2В при токе 20мА. Соответственно и был выбран резистор 100Ом при условии питания 3,3В.
При необходимости, описание можно посмотреть в этом документе.
Важно, что бы не было ложных срабатываний от наводок.
Вам важно поймать первое срабатывание датчика и остановить двигатель, а потом, если программа составлена грамотно, дребезг не должен мешать. От обычной кнопки куча срабатываний и никому особо не мешает.
То есть, в принципе доступно такое поведение и следует всё это ловить и исключать на уровне кода? Програмные паузы я уже исключил, наверное и с этим смогу справиться. Но самый важный момент - ложные срабатывания, то есть дребезг, при подаче сигнала на управление мотором. Конкретно – из-за дребезга я буду ловить первое срабатывание в середине оборота, а не там где оно должно быть, и моя схема окажется неработоспособной.
Можете оставить схему с делителем, а можете верхний выкинуть и сделать так
Посмотреть вложение 9233
Это обережет есп, если вход есп окажется выходом с низким уровнем, а транзистор будет открыт.
Приблизительно это и было задумано. Из-за усталости была допущена ошибка - резистор в последовательности с транзистором должен был быть 100Ом, а суммарно с транзистором - 200Ом. И почему "вход есп окажется выходом с низким уровнем", разве он может быть либо с высоким, либо с низким? Для меня, образно, либо нужное сопротивление есть, либо оно вовсе сгорело.

CodeNameHawk, вам спасибо за участие. Мне очень важно завершить этот проект успешно. Поэтому я благодарен за любую помощь. Лишь бы двигаться вперёд, а не танцевать вокруг макетки.
 

MeMagic

New member
Я не особо шарю в ESP, но, думаю, надо копать в сторону прерываний и измерении периода с помощью них - https://circuits4you.com/2017/12/08/esp8266-external-interrupt-example/ , по идее идеально с таймером и в целом, посмотрели бы осциллографом сигналы, убедились сначала в их периодичности и не зашумлёности, а потом отлаживались с кодом уже, если есть сомнения в "ложных срабатываниях".
Я думал, что работа с данным типом микроконтроллеров будет гораздо проще для той части публики, которая не владеет углублёнными знаниями в электронике и схемотехнике.
Может, если использовать оригинальный Ардуино будет проще? Но ESP в любом случае нужно для включения удалённого управления.
 
Сверху Снизу