Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Can someone explain this code?

SharpTeeth

Junior Member level 2
Junior Member level 2
Joined
Feb 8, 2025
Messages
22
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
247
Can some help define what this is going to do?
This is coding for an ESP to control a motor. I am trying to make the forward motion the same as the reverse motion. Someone wrote this for me but I am not sure why they would not be the same equation?
frdCounter = MC + 1;
bkdCounter = (MC * 2) + 2;
 
Nobody can answer your question without knowing what 'MC' is. I would guess it is some number telling us where the motor currently is but we don't even know what kind of motor it is. Is it a stepper motor perhaps and MC is an indication of its current angle?

Can you explain what kind of motor it controls and show the rest of the software so we can put the variables into context.

Brian.
 
Hi,

I agree with Brian. You miss to provide context.

***
But I´ve seen your other thread. There I can see these lines.

Didn´t you write the code on your own?

What it does:
It sets the limits / threshods for forward and backwards movement of your motor.

Example:
You want 150 steps forward
you want go back to the same position = plus another 150steps backwards = 300 steps. Why they add the value of 2 ... may be because of the reasons I shoed in the ther thread.

Since the STEP_Counter always counts UP - independent of motor direction -
the software runs forward until the counter is at 150.
then it stops
waits for some time
runs backwards until the counter is 300 (or 302)
then stops
then waits

Klaus
 
Missing CODE or SYNTAX tags [ Added by moderator ]
I did not write the code. Someone did it for me but we are having trouble getting the motor to stop at the exact same spot each time. It unwinds out and then unwinds in stopping at the same spot in the cord one time (sometimes) then after a few times it's usually about 20 inches off. Often stopping too soon when reeling in the cord.

The motor is from a company called MY Lifter. It's a bluetooth garage hoist that we are controlling using an ESP and IR sensors.

Here is the set up and picture of the motor below. And also the code. Keep in mind in line 174 of the code we were playing with a delay to try and get the in and out to line up but as mentioned -- for some reason it is still not stopping in the same spot.

Any help in getting this thing to stop in the same spot each time would be GREATLY appreciated!

MyLifter circuit diagram esp32.png


IMG_1835.jpg


Code C++ - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
 
#define RPWM 27        // RPWM pin of HiLetgo BTS7960 board to esp 27
#define LPWM 26       // LPWM pin of HiLetgo BTS7960 board to esp 26
#define R_EN 25       // Right Enable pin of HiLetgo BTS7960 board to esp 25
#define L_EN 33       // Left Enable pin of HiLetgo BTS7960 board to esp 33
#define IrSensor 14   // connect IR sensor pin to esp pin 14 for motor start
#define IrSensor2 15  // connect IR sensor pin to esp pin 15  for gear count
#include <EEPROM.h>
const int eeprom1 = 0;
const int eeprom2 = 4;
const int eeprom3 = 8;
const int eeprom4 = 12;
const int eeprom5 = 16;
int FMS = 150;    //Forward Motor Run time   ///
int MPT = 10000;  //Middel Pause Time    ///
int RMS = 150;    //Reverse Motor Speed   //
int EPT = 10000;  //End Pause time   ///
int MC = 05;      // Motor Counter
volatile int whiteCount = 0;
bool countFlag = false;
 
int frdCounter = 0;
int bkdCounter = 0;
BLEServer* pServer;
BLECharacteristic* pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"            // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"  // UART RX characteristic UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"  // UART TX characteristic UUID
class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic* pCharacteristic) {
    String value = pCharacteristic->getValue();
    Serial.println(value.c_str());
    if (value.length() > 0) {
      Serial.print("Received: ");
      Serial.println(value.c_str());
      int numValue = atoi(value.substring(1).c_str());
      switch (value[0]) {
        case 'A': EEPROM.put(eeprom1, numValue); break;  // A Forward Motor Run time   ///
        case 'B': EEPROM.put(eeprom2, numValue); break;  // B Middel Pause Time
        case 'C': EEPROM.put(eeprom3, numValue); break;  // Reverse Motor Speed
        case 'D': EEPROM.put(eeprom4, numValue); break;  // End Pause time
        case 'E': EEPROM.put(eeprom5, numValue); break;  // End Pause time
      }
      EEPROM.commit();
      Serial.print("numValue ");
      Serial.println(numValue);
      Serial.println("Value saved in EEPROM");
    }
  }
};
class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    BLEDevice::startAdvertising();
  };
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};
void setup() {
  Serial.begin(9600);
  Serial.println("Connect to MyESP32");
  pinMode(IrSensor, INPUT_PULLDOWN);
  pinMode(IrSensor2, INPUT_PULLDOWN);
  pinMode(RPWM, OUTPUT);
  pinMode(LPWM, OUTPUT);
  pinMode(R_EN, OUTPUT);
  pinMode(L_EN, OUTPUT);
  digitalWrite(R_EN, HIGH);
  digitalWrite(L_EN, HIGH);
  delay(10);
  EEPROM.begin(32);
  EEPROM.put(eeprom1, FMS);
  EEPROM.put(eeprom2, MPT);
  EEPROM.put(eeprom3, RMS);
  EEPROM.put(eeprom4, EPT);
  EEPROM.put(eeprom5, MC);
  FMS = EEPROM.get(eeprom1, FMS);  //
  MPT = EEPROM.get(eeprom2, MPT);  //
  RMS = EEPROM.get(eeprom3, RMS);  //
  EPT = EEPROM.get(eeprom4, EPT);  //
  MC = EEPROM.get(eeprom5, MC);
  Serial.print("FMS");
  Serial.println(FMS);
  Serial.print("MPT");
  Serial.println(MPT);
  Serial.print("RMS");
  Serial.println(RMS);
  Serial.print("EPT");
  Serial.println(EPT);
  BLEDevice::init("Mylifter Motor");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService* pService = pServer->createService(SERVICE_UUID);
  pTxCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID_TX,
    BLECharacteristic::pROPERTY_NOTIFY);
  pTxCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic* pRxCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID_RX,
    BLECharacteristic::pROPERTY_WRITE);
  pRxCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  BLEAdvertising* pAdvertising = pServer->getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->start();
  frdCounter = MC + 1;
  bkdCounter = (MC * 2) + 2;
}
 
 
void loop() {
  if (digitalRead(IrSensor) == LOW) {
    int currentState = digitalRead(IrSensor2);
    Serial.print("sensor");
    Serial.println(digitalRead(IrSensor2));
    if (currentState == LOW && !countFlag) {
      whiteCount++;
      countFlag = true;
      delay(200);
    }
    if (currentState == HIGH) {
      countFlag = false;
    }
    if (whiteCount < frdCounter) {  //this will count and unwound the rope
      analogWrite(RPWM, FMS);       // analogWrite(RPWM, FMS);  //Forward Motor Speed
      analogWrite(LPWM, 0);         // analogWrite(LPWM, 0);
      Serial.print("foward");
    } else if (whiteCount == frdCounter) {  // when counting is 25 so it will pause for middle pause time and then start wounding
      analogWrite(RPWM, 0);
      analogWrite(LPWM, 0);
      Serial.print("middle pause");
      delay(MPT);  //middle pause time
      whiteCount++;
    } else if (whiteCount > frdCounter && whiteCount < bkdCounter) {  // when counting is 50 so it will pause for end pause time and then start unwounding and make count 0
      analogWrite(RPWM, 0);
      analogWrite(LPWM, RMS);  //Backward Motor Speed
      Serial.print("backward");
    } else if (whiteCount >= bkdCounter) {
      delay(350);
      analogWrite(RPWM, 0);
      analogWrite(LPWM, 0);
      Serial.print("Stop");
      delay(EPT);
      whiteCount = 0;  // Reset for next cycle
    }
    Serial.print("White count: ");
    Serial.print(whiteCount);
  }
}

 
Last edited by a moderator:
Keep in mind in line 174
use the [ C O D E ] button when inserting code. It´s especially here for you ;-)

*****
A timed delay is probably the worst precise solution...

****
As already written: One needs an clear error description... To understand what really happens.
When you write "20 inches off" it means nothing. I don´t knw what this means in time nor what this means in pulses...
But the software only works with time and pulses.

***
I don´t rewrite your copied code.
You say you want to learn... but if I write code for you, you don´t learn nothing. ;-)


Klaus
 
Lol. Yes I understand what you mean about learning Klaus-- but this has been going for 5 months and my exhibition is coming up. I can't learn too much more at this point. When I first started posting on forums for advice they told me to forget it. I know nothing. But I still kept trying to learn. Now I am up against time. That is something you cannot control.

But at the least I will use the code button in the future.... ;)

Some more info from the person who wrote the code:
Mc means the user defined motor rotation counterSo frdCounter means the cord will go out, so motor will run till MC frdCounter=MC+1 and when MC+1 then the motor will get stop, then it will start running in backward (means the cord will go in) this way bkdCounter= (MC*2)+2 this equation will work, which means the counter move in forward directionFor example:MC is 10 So motor will move in forward till 10 count and the count will be 11 so it will get stop, then it will start moving in backward (Mc*2) +2, (10*2)+2= 22 so this way the motor will move till 22 in backward direction and this strategy is used to make it precise, the motor forward counter and backward counter will be same

___________________________

I value your time and understand if you can't adjust my code. It seems the person I am working with needs to learn more too but here we are.
 
From your 'schematic' it seems you are using PWM to control a reversible two terminal motor but have no feedback loop. In essence you are expecting the motor to stop in the same position by just controlling the power to it. I wouldn't describe that as impossible but it is certainly impractical because it doesn't take the motor stalling current, mass and the mass of the load into consideration. Think of it as riding a bicycle and expecting it to stop exactly on target by stopping pedaling at the right time.

Brian.
 
From your 'schematic' it seems you are using PWM to control a reversible two terminal motor but have no feedback loop. In essence you are expecting the motor to stop in the same position by just controlling the power to it. I wouldn't describe that as impossible but it is certainly impractical because it doesn't take the motor stalling current, mass and the mass of the load into consideration. Think of it as riding a bicycle and expecting it to stop exactly on target by stopping pedaling at the right time.

Brian.
I see. Here is the motor as it is switched on and off. It seems to be built more precisely than most but obviously not stopping on a dime. Powers on and moves right away-- stopping it takes a second. Can there be a clear code adjustment made for that?

--- Updated ---

More info--- We are using a DC motor which has no hall effect sensor and cannot give feedback
--- Updated ---

IMG_1843 2.JPG

So I think we found the problem. After uploading new coding the counter wants to start at 1. But only the first time. Every time after in winds out it begins at 0.
Any thoughts on why this could be happening?

Is there a way to put something in the code that says always to start at 0?

Powering on and off the system also starts it at 1. After that is goes back to starting at 0.
 
Last edited:
There is no definite solution to this but there are some things you can try:

1. if the motor or whatever it attaches to has a mechanical stop, you can initialize your counter by driving it against that stop and setting to zero. This will re-calibrate it which will help but it still doesn't overcome system inertia.

2. This takes some doing, especially if you are in a rush but the motor current almost certainly fluctuates as the commutator makes and breaks connection. The fluctuation will be at some multiple of the rotational speed, how much so depends on how many 'splits' it has. With some current sensing it would be possible to tell how many times it has rotated so you can calculate its absolute angle of rotation. What complicates this is driving it with PWM as the applied voltage will already have variation in it. If you can find the angle you can control the speed it rotates based on target position and present position so you can decelerate and stop more accurately.

3. if possible, add some external rotation sensor to the motor, a slotted wheel and opto-coupler or a 'starburst' printed on clear plastic moving through a slotted opto-coupler works well.

I have a project in development here that uses a DC motor and massive gearing to convert high motor speed to low speed high torque screw mechanism to push large objects and it has to stop instantly if a jam occurs. I am designing the stop system and the motor has no connections I can easily reach. I've done something similar to my suggestion above, printing black stripes across a narrow strip of 'sticky backed' white vinyl paper and fixing it around a rotating gear wheel. A reflective opto switch picks up the passing stripes and feeds them to a small processor (PIC10F220) which times them and produces the shut off signal to the motor driver if the opto sensor level doesn't change within a few milliseconds.

Brian.
 
There is no definite solution to this but there are some things you can try:

1. if the motor or whatever it attaches to has a mechanical stop, you can initialize your counter by driving it against that stop and setting to zero. This will re-calibrate it which will help but it still doesn't overcome system inertia.

2. This takes some doing, especially if you are in a rush but the motor current almost certainly fluctuates as the commutator makes and breaks connection. The fluctuation will be at some multiple of the rotational speed, how much so depends on how many 'splits' it has. With some current sensing it would be possible to tell how many times it has rotated so you can calculate its absolute angle of rotation. What complicates this is driving it with PWM as the applied voltage will already have variation in it. If you can find the angle you can control the speed it rotates based on target position and present position so you can decelerate and stop more accurately.

3. if possible, add some external rotation sensor to the motor, a slotted wheel and opto-coupler or a 'starburst' printed on clear plastic moving through a slotted opto-coupler works well.

I have a project in development here that uses a DC motor and massive gearing to convert high motor speed to low speed high torque screw mechanism to push large objects and it has to stop instantly if a jam occurs. I am designing the stop system and the motor has no connections I can easily reach. I've done something similar to my suggestion above, printing black stripes across a narrow strip of 'sticky backed' white vinyl paper and fixing it around a rotating gear wheel. A reflective opto switch picks up the passing stripes and feeds them to a small processor (PIC10F220) which times them and produces the shut off signal to the motor driver if the opto sensor level doesn't change within a few milliseconds.

Brian.
Thank you Brian for your detailed solutions. I will read them over carefully a few times before deciding what direction to go but a couple of questions based on your answers--

1- The motor is used as a hoist. The hoist cable will attach to a mannequin-like figure. When you say a "mechanical stop" I'm not exactly sure how that would work. Can you give me an example?

2- Would the IR sensor I already have connected to the exterior of the motor work in a way you suggested for the #3 solution?

Your own project in development sounds like it has a bit of overlap with mine for sure. I am worried about my sensor or some programming issue occurring and the hoist cable sucking into the motor and busting everything. Big fear of mine. And I have no fail safe at the moment. This project of mine has to run continuously all day by itself too.

This motor I am working on attaches to another motor that is connected to a rail system. The idea is that the rail motor moves the figure from one room to another then gets lowered by my second motor when it hits a sensor point. This is supposed to happen all day. Not having it lower and raise precisely each time means that over the course of a day the hoist cable could lbecome longer and leave the mannequin dragging along the floor or worse get shorter and go into to the motor itself.
 
The IR sensor may work, it will let you know how many times the motor has turned and that is a great help but it doesn't guide the motor to any particular spot. Counting revolutions to move it between two positions is notoriously hard when the motor will not start instantly and stop instantly and it may have a varying mass attached to it.

By mechanical stop I mean something that physically prevents it passing a certain place. You can use that as a reference position by driving a short way beyond the stop so you are sure where travel ended. It may temporarily overload the motor/driver when it is powered but can't rotate but it should be able to withstand that for a moment.

From your more detailed description it sounds like you are transporting your mannequin back and forth between two locations by lifting, carrying and lowering it each time. I would suggest a slightly different approach: I would use limit switches, these are just a switch that gets operated when the mechanism reaches a certain position. In conjunction with your software you use the switch to tell the driver circuit to cut the motor power when it has reached the end of its task. For example you put a switch at each end of the rail to detect when the rail motor should stop and you somehow put a switch on the hoist to tell it the mannequin has landed or been lifted far enough.
In other words, you react to the state of the mechanism instead of assuming it has reached the correct position using a timer. This method should always perform properly with no 'slippage' over time. The limit switches can be mechanical or optical to keep things simple.

If you want to be clever, you could still control the motor speed and run at full power for a time you know is less than needed for full travel then taper if off until the limit switch says stop. Doing that reduces overshoot, your mannequin won't swing around on the hoist cable as the rail movement commences and ceases.

You should be thankful you don't have my project. There are two motors in mine but they can both push or pull 0.25 ton objects and they are arranged facing each other. Maximum travel is about 6' (2m) each and the gap when both are in push mode is 0.25" (5mm). It is a death trap if someone gets in the middle when they operate so as soon as motor rotation stops, except when it is supposed to, they have to go into a brief 'back off' mode to release whatever (or whoever!) has blocked them. Reaction time is about 0.2 seconds.

Brian.
 
The IR sensor may work, it will let you know how many times the motor has turned and that is a great help but it doesn't guide the motor to any particular spot. Counting revolutions to move it between two positions is notoriously hard when the motor will not start instantly and stop instantly and it may have a varying mass attached to it.

By mechanical stop I mean something that physically prevents it passing a certain place. You can use that as a reference position by driving a short way beyond the stop so you are sure where travel ended. It may temporarily overload the motor/driver when it is powered but can't rotate but it should be able to withstand that for a moment.

From your more detailed description it sounds like you are transporting your mannequin back and forth between two locations by lifting, carrying and lowering it each time. I would suggest a slightly different approach: I would use limit switches, these are just a switch that gets operated when the mechanism reaches a certain position. In conjunction with your software you use the switch to tell the driver circuit to cut the motor power when it has reached the end of its task. For example you put a switch at each end of the rail to detect when the rail motor should stop and you somehow put a switch on the hoist to tell it the mannequin has landed or been lifted far enough.
In other words, you react to the state of the mechanism instead of assuming it has reached the correct position using a timer. This method should always perform properly with no 'slippage' over time. The limit switches can be mechanical or optical to keep things simple.

If you want to be clever, you could still control the motor speed and run at full power for a time you know is less than needed for full travel then taper if off until the limit switch says stop. Doing that reduces overshoot, your mannequin won't swing around on the hoist cable as the rail movement commences and ceases.

You should be thankful you don't have my project. There are two motors in mine but they can both push or pull 0.25 ton objects and they are arranged facing each other. Maximum travel is about 6' (2m) each and the gap when both are in push mode is 0.25" (5mm). It is a death trap if someone gets in the middle when they operate so as soon as motor rotation stops, except when it is supposed to, they have to go into a brief 'back off' mode to release whatever (or whoever!) has blocked them. Reaction time is about 0.2 seconds.

Brian.
Damn Brian. That's a lot of pressure for your project. No pun intended. And I thought I had pressure.

So you are proposing some very good options for me and I may have to go in that direction eventually but I think I am so close here---

I now have the motor stopping precisely in and out using the IR sensor detecting a white patch on the outside of the motor. The problem is still from time to time for some reason it wants to do one extra rotation. Then it will go back to regular rotation on it's own for the next round of in and out. So for example the first two will be fine. Then the third will change to a new precise spot of one extra rotation. Watching the serial monitor in Arduino shows no difference in the counting.

Is this a sensor issue?

Very frustrating and confusing. And the thought of wiring in anymore switches, etc. might take me over the edge.
 

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top