So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By MeMagic
#86976 Gents!
I'm working on a project that includes an ESP-12 (just core due to space restrictions) controling an N20 motor using an ITR9608 opto interrupter. So far, I was able to program motor rotation forward and backward. Further I succeeded with reading signals from ITR9608. But when I went to combine those two parts, I felt into some errors I can't afford. Thus, asking you for help.
First of all, the power in my schema is taken from computer's USB3 and converted by an AMS1117. Am using YP-02 USB2TTL. There pins used from the YP-02 are RX, TX and GND, so the power is taken from the AMS1117.
The schema for connecting opto interrupter is as follows. 3.3V through a 100Ohm goes to LED and further to the Ground. On the other side +12V is driven to Emitter and the result is pulled down through a 10 kOhm to Ground and going to ESP-12. ITR 9608 looks like it has a 1.1-1.2V Relative Forward Voltage, max 1.5V, while the current is 20mA. When connected it showed about 3V on the pin connected to the ESP-12. The schema is like taken from here: Image
The motor is driven by a DRV8833 Motor Driver Module Board. The board has connected to it the power 3.3V and two signal wired from ESP-12, and the motor on the other side.
The PINs used for peripherals are 12 and 13 as OUTPUT to motor and 14 as INPUT from the ITR9608. In Run mode I had connected Enable and VCC to +3.3, GND and GPIO15 to Gnd.
Software used is Arduino IDE 1.8.12 and the board defined as Generic ESS8266 Module.

I'm affraid that I have burned the PIN14 that has input from the ITR, but using another PIN (12 or 13) gave me the same result, even with the motor disconnected. I don't know exactly how to operate voltages in case that I have to INPUT a signal.

Any help is appreciated.
User avatar
By MeMagic
#87018 Unbelievable!
Continuing the Saga. I have tested the ESP-12 on a NodeMCU with this code:
Code: Select allint FwdPin = 13;    /*  Forward command for motor drive  */
int BkwPin = 12;    /*  Reverse command for motor drive  */
int OpcPin =  4;    /*  Opto coupler feedback pin  */

bool CalibrationStarted = false;
bool Calibrated = false;
bool Aligned = false;
bool debug = true;

int StopState = LOW;    /* Forward command for motor drive   */
int RunState = HIGH;    /* Forward command for motor drive   */

int Covered = LOW;
int NonCovered = HIGH;

int StartFwdMtn = -1;   //  here are the vars for measuring the time needed for engine
int EndFwdMtn = -1;    //   to rotate between extreme positions
int StartBkwMtn = -1;   //   these values later are used to calculate an average time
int EndBkwMtn = -1;    //   and rotate the shaft to some degree.

void setup()
{
  pinMode(FwdPin, OUTPUT);
  pinMode(BkwPin, OUTPUT);
  pinMode(OpcPin, INPUT);
  Serial.begin(115200);
  Serial.println("   Let's ROCK!");
  Serial.println();
  Serial.println();
  Serial.println("Cover the opto interrupter to start calibration");
}

void stopEngine()
{
  digitalWrite(FwdPin, StopState);
  digitalWrite(BkwPin, StopState);
}

void startEngineForward()
{
  stopEngine();
  digitalWrite(FwdPin, RunState);
}

void startEngineBackward()
{
  stopEngine();
  digitalWrite(BkwPin, RunState);
}

void WaitToStop()
{
  if (digitalRead(OpcPin) == Covered) {    //   if the Opto Interrupter was covered when starting moving,
    while (digitalRead(OpcPin) == Covered) {    //  let it move until gets uncovered
    }
  }
  while (digitalRead(OpcPin) != Covered) {   //  here is a loop until the Opto Interrupter gets covered
  }
  stopEngine();    //   finally stop the motor
}

bool Calibration()
{
  bool ThisResult = false;
  if (debug) Serial.println("Going to stop the engines right now!");
  stopEngine();   //  if moving
  delay(3000);     //  have you seen it?

  if (debug) Serial.println("Signal to align the engine to the most Bkw position");
  startEngineBackward();
  Aligned = false;

  while (digitalRead(OpcPin) == Covered) {   // we have to let the motor rotate a while to get the OI uncovered
  }
  while (digitalRead(OpcPin) != Covered) {   // since it is not covered, let it rotate until the OI gets covered
  }
  stopEngine();
  if (debug) Serial.println("Engine got Backward position.");
  delay(3000);

  if (debug) Serial.println("Going to start Forward engine");
  StartFwdMtn = millis();
  startEngineForward();
  if (debug) Serial.println("Guess Forward engine started. Now waiting for it to get to the limit");

  WaitToStop();
  EndFwdMtn = millis();
  if (debug) Serial.println("Guess Forward engine stopped. Is the OC uncovered?");
  delay(3000);

  if (debug) Serial.println("Going to start Backward engine");
  StartBkwMtn = millis();
  startEngineBackward();
  if (debug) Serial.println("Guess Backward engine started. Now waiting for it to get to the limit");

  WaitToStop();
  EndBkwMtn = millis();
  if (debug) Serial.println("Guess Backward engine stopped. Is the OC uncovered?");
  delay(3000);

  if (debug) Serial.println("Going to check acquired data.");
  if ((StartBkwMtn < EndBkwMtn) and (StartFwdMtn < EndFwdMtn)) {
    if (debug) Serial.println("Calibration successfully performed! Let's get out of here!");
    ThisResult = true;
  }
  if (!(StartBkwMtn < EndBkwMtn) or !(StartFwdMtn < EndFwdMtn)) {
    if (debug) Serial.println("Unfortunately calibration failed. Need to rerun.");
    ThisResult = false;
  }
  return ThisResult;
}

void loop()
{
  if (!Calibrated) Calibrated = Calibration();
// --  In case calibration was successful the motor shall rotate to 30 degrees from an extreme position
  if (Calibrated and !Aligned) {
    int SecsToRotate = int((EndFwdMtn - StartFwdMtn + EndBkwMtn - StartBkwMtn) / 4 * 0.3)
    startEngineForward();
    delay(SecsToRotate);
    stopEngine();
    if (debug) Serial.println("Calibration successfuly performed. Engine aligned to 30 degrees forward.");
    Aligned = true;
  }
// ---   In case we want to repeat calibration just put the flag into the Opto Interrupter (OpcPin)
  if (Aligned and (digitalRead(OpcPin) == Covered)) {
    while (digitalRead(OpcPin) == Covered) {
    }
    delay(200);
    Calibrated = false;
    if (debug) Serial.println("Calibration reset.");
  }
}


The result is as follows:

Code: Select all   Let's ROCK!


Cover the opto interrupter to start calibration
Going to stop the engines right now!
Signal to align the engine to the most Bkw position

Soft WDT reset

>>>stack>>>

ctx: cont
sp: 3ffffdc0 end: 3fffffc0 offset: 01a0
3fffff60:  402014d4 00000000 3ffe84e0 4020122a 
3fffff70:  3fffdad0 0000002f 3ffee5f0 402016fc 
3fffff80:  3fffdad0 3ffe84f4 3ffee5f0 3ffee658 
3fffff90:  3fffdad0 00000000 3ffee5d1 402013a9 
3fffffa0:  3fffdad0 00000000 3ffee618 40201d18 
3fffffb0:  feefeffe feefeffe 3ffe850c 40100c4d 
<<<stack<<<

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3656, room 16
tail 8
chksum 0x0c
csum 0x0c
v9c56ed1f
~ld
   Let's ROCK!

(the motor rotates for about 2 sec and ESP resets over and over, why?)

Tp be mentioned that the above result I had with the Opto Interrupter disconnected from NodeMCU. With the OI connected the program runs very different. Here it is below.

Code: Select all   Let's ROCK!


Cover the opto interrupter to start calibration
Going to stop the engines right now!
Signal to align the engine to the most Bkw position
Engine got Backward position.
Going to start Forward engine
Guess Forward engine started. Now waiting for it to get to the limit
Guess Forward engine stopped. Is the OC uncovered?
Going to start Backward engine
Guess Backward engine started. Now waiting for it to get to the limit
Guess Backward engine stopped. Is the OC uncovered?
Going to check acquired data.
Calibration successfully performed! Let's get out of here!
Calibration successfuly performed. Engine aligned to 30 degrees forward.
Calibration reset.
Going to stop the engines right now!
Signal to align the engine to the most Bkw position
Engine got Backward position.
Going to start Forward engine
Guess Forward engine started. Now waiting for it to get to the limit
Guess Forward engine stopped. Is the OC uncovered?
Going to start Backward engine
Guess Backward engine started. Now waiting for it to get to the limit
Guess Backward engine stopped. Is the OC uncovered?
Going to check acquired data.
Calibration successfully performed! Let's get out of here!
Calibration successfuly performed. Engine aligned to 30 degrees forward.
Calibration reset.
Going to stop the engines right now!
Signal to align the engine to the most Bkw position
Engine got Backward position.
Going to start Forward engine
Guess Forward engine started. Now waiting for it to get to the limit

Soft WDT reset

>>>stack>>>

ctx: cont
sp: 3ffffdb0 end: 3fffffc0 offset: 01a0
3fffff50:  3ffee5c8 3ffe84d8 3ffee5f0 40201724 
3fffff60:  3ffee5c8 3ffe84d8 3ffe84e0 40201290 
3fffff70:  00000000 00000012 3ffee5f0 40201700 
3fffff80:  00000000 00000000 00000001 3ffee658 
3fffff90:  3fffdad0 00000000 3ffee5d1 402013ad 
3fffffa0:  3fffdad0 00000000 3ffee618 40201d1c 
3fffffb0:  feefeffe feefeffe 3ffe850c 40100c4d 
<<<stack<<<

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 3656, room 16
tail 8
chksum 0x0c
csum 0x0c
v9c56ed1f
~ld
   Let's ROCK!


In this case I was covering the Opto Interrupter looking for some rules in getting the results from the schema. The motor rotated uncontrollable. And, strange thing, the ESP again resets...

To be mentioned, when I cut the program into separate sequences for reading the opto interrupter and for simple rotating the motor forward and backward, it executes correctly over and over, without issues.

So I'm really frustrated, because (as an IT guy that used to code scripts and etc.) I'm expecting the schema to have a certain, predictable behavior. What am I missing? Is it because of connections between ESP and peripherals - the motor driver and opto interrupter?
User avatar
By schufti
#87022 empty while loops like

Code: Select all  while (digitalRead(OpcPin) == Covered) {   // we have to let the motor rotate a while to get the OI uncovered
  }
  while (digitalRead(OpcPin) != Covered) {   // since it is not covered, let it rotate until the OI gets covered
  }
or
    while (digitalRead(OpcPin) == Covered) {
    }

are a big NONO on esp!
At least place one yield() into each loop to get rid of the wdt resets.
User avatar
By MeMagic
#87023
schufti wrote:empty while loops like

Code: Select all  while (digitalRead(OpcPin) == Covered) {   // we have to let the motor rotate a while to get the OI uncovered
  }
  while (digitalRead(OpcPin) != Covered) {   // since it is not covered, let it rotate until the OI gets covered
  }
or
    while (digitalRead(OpcPin) == Covered) {
    }

are a big NONO on esp!
At least place one yield() into each loop to get rid of the wdt resets.

Thanks mate for suggestion. Will you please make it clear to me what means that yield()? I have inserted it in all the empty loops and the result is following:
Code: Select allCover the opto interrupter to start calibration
Going to stop the engines right now!
Signal to align the engine to the most Bkw position

It will start the motor but will never stop. Perhaps I have to learn about linking of opto interrupter and DRV8833 to the ESP-12 (with or without MCU).

Update. I have found some information about ESP and yield(), - it is very interesting. But still can not make the ESP work both with the Opto Interrupter and the DRV8833. It makes me crazy! As an idea, shall I define all the possible states of the circuit and process the signals one by one in each loop() iteration, so I will avoid long loops? It makes sense, but loses the elegance.