CR: What a code loaded video! The ATOMIC_BLOCK and template aspect were unknown to me; shows how DYI I am. You have elevated my understanding substantially for a lawn cart project which will takes its drive input from a joystick controller communicating with HC-12 transceivers. The joystick forward/reverse axis will be straight at +/- speed and the left/right will be radius of curvature of a turn. You use SimplePID which may require a library but I don't see yet where you set the PID compute rate; it may just be the loop() itself.
Yes, the PID control signal (and consequently the PWM value) is updated whenever the loop function triggers (so the sample time is determined by how often the loop function executes). I didn't use a library, the "SimplePID" is just a class written into the code.
@@curiores111 I did read your code and saw that in loop() you do the PID compute. Regarding SimplePID libary, while I saw in your code that you didn't include any library, there is a SimplePID library so I was confused. However, that I didn't understand that you were using a class highlights my weak coding skills in C++. As a physicist, computations are numerical mostly so DYI Arduino coding is new. Finally, thank you for your prompt reply because my knowledge gained from you is HUGE!
I've used motors very similar to those in the video (great video). Like many inexpensive motors, the same power settings to not result in the same motor speed. The PID speed controller will run the motors at the same speed after an initial speed up time. During that time, the motors will not be turning at the same speed and the robot will not run straight. It's easier with four wheels because the friction keeps the robot from moving cross track. For a differential drive robot to run straight, the motors need different initial pwm values.
Can you clarify what you mean? I've considered that issue - PID with individual motors doesn't seem to account for the initial acceleration phase - meaning that the robot will often turn and then go in a straight line. Is there a way to fix this?
There are several ways to address this. 1) Experiment by trial and error with the initial motor driver inputs, whether duty cycles or PWM, whatever the motor driver takes as inputs to find values for each motor that will cause the robot to run straight. 2) Another way, is to make a series of measurements by running the motors at different input PWM, no speed control, and recording both the time duration, 5 seconds is plenty, and the encoder counts. Using the wheel diameter, calculate the speed of each wheel in cm/s. Make the measurements for a variety of motor control inputs. Plot the results of speed vs inputs. I use Excel and fit a least squares quadratic equation for each motor. Now you have motor equations that relate speed to motor driver inputs. For a selected speed, determine and use the corresponding driver inputs for each motor. Now when the robot starts it will tend to go straight and PID can be used for further control. 3) If you have a good way to measure the robot orientation, yaw angle, use the deviation from a straight line, or the cross-track error, and/or the angle to the goal to make path corrections while the robot is in motion. Do that by keeping one wheel speed constant and varying the speed of the other wheel. John-
Stepper motor position is directly controllable; you don't need a feedback loop since you can simply assign the number of steps to take. That's based on the fundamental differences between how DC motors and stepper motors function.
I absolutely love your videos. The way you explain things is perfect. I am using your code in a robotic project and believe I understand the feedback loop. My robot is running mecanum wheels. What I am scratching my head on is how to change directions. With mecanum wheels, I can rotate in place, move left/right, and so on. But apparently my intellect is having a hard time incorporating this into your code.
Hard for me to say without knowing the details of what you're trying to accomplish. I'd suggest starting with a button tutorial (maybe look at OneButton?) and then adjusting the target conditionally based on the state of the button (or intermediate variable).
@@curiores111 What I want is that when I activate the code the motors do not move to any position, until I press the button the motors rotate to the designated position, for example target 2400
@@danielmartinez-mk6iu Sure, so, register a OneButton, "btn". github.com/mathertel/OneButton Then, use a conditional so that if the button is pressed, the target is changed and the PID control is activated. Here's an example pseudocode: OneButton btn(); bool mode = false; setup(){ // register btn // register changeMode function } loop(){ // tick btn if(!mode){ // set motors off } else{ // proceed as usual } } void changeMode(){ mode = !mode; }
Hi, I'm building an obstacle-avoiding robot with an ultrasonic sensor. How can I integrate the PID control into the robot I am doing? (I don't know much about coding and Arduino. I'm trying to do this project to get through class.)
What motor driver is it? If that's the case, it's probably not bidirectional. If it's not bidirectional, it will be harder to control (you won't be able to reverse directions). You would have to slightly edit the setMotor function to make sense with the control code.
@@Luxigaming Oh well that's good then. Look at the truth table for control logic on the spec sheet. You can adjust the setmotor function so that it matches those conditions. (In other words, you remove one input the setmotor function, and then change the logic inside based on the truth table for a single direction pin, rather than 2).
Hello Curio Res, I found your example on RUclips that interests me a lot because I have two reduced motors with encoder and I would like to know if it is possible to synchronize the two motors to have the same speed so the same count on the two encoders. I have two ballasts is they have two pistons to fill them or empty them with water, my problem is that I have a faster ballast than the other, I saw your code and I modified it but I hold a little, can you help me to recover the value of the encoder from the right engine and that of the syncronized left engine in order to display them on an LCD? I use an L298N .... Thanks for your help.. Alfred
The video is nice, but it doesn't adequately address basic questions. When I have a vehicle with 4 motors, each motor typically requires its own set of constants for PID control in control engineering. If the vehicle is supposed to move at a certain speed, the desired speed is set as the setpoint for all motors. For synchronization, the speeds of the 4 motors are not compared, but rather the differences in pulses are compared, and based on the deviations, new output signals are calculated using PID control. If one wants to achieve perfection, deceleration is also calculated using PID control. In this case, the actual pulses are counted to determine the desired new speed (cascade control). There is nothing wrong with the video, but the implementation was somewhat oversimplified by the presenter.
I hear comments like this occasionally. It's valid -- not everything is covered, and certainly the methodology is not optimal. But that's the intention -- its not meant to cover everything, and its not meant to be optimal. Generally, my videos are intended to make more complicated engineering concepts accessible to a wider audience. Getting deeper into the details is another step, and not accessible or useful in an introductory video.
instead of the "A-Star 32U4 Mini SV" controller can I use 2 Arduino Uno/ 2 mega / Arduino due/ 2 Arduino nano v3. I guess I need to have a total of 8 digital pins for the same right? Please Suggest, Thank You.
I am using Arduino Mega with 4 encoder motors and 1 L298d Motor driver shield, I am giving the power of 12 V and each motor side the power is getting 10.7 V. But my all motors are not running at constant speed, how can i fix this?
are you driving all four motors with a single driver? For now I'll assume you have separate driver for each motor. There's nothing that guarantees that the motors will run at the same speed. This is one good reason to use feedback control. In general, you'll want to ramp the position slowly enough so that all the motors can get there at (nearly) the same time. Alternatively, you could try controlling the speed directly. In either case, you'll have to make sure that you adjust your speeds slowly enough that the transients are not causing your motors to get out of sync.
Glad to watch the video , just one question can I do the same by replacing Arduino with Raspberry pi as a control device ? If not which motor controller are used for pi to control dc motors with same type of encoders used in this video.
Yes, you can... but I think there may be some issues with slow interrupts because there is a lot going on in a raspberry pi. I am not familiar enough to know how well it would perform, but I'm guessing not that well. I would myself prefer to do the control loop on a microcontroller and then have the pi doing other tasks, like computer vision and path planning.
Nice! Very detailed and helpful. Anyway i have a question what if i dont have a leader and follower (not familiar with it), and i just have to used L298N motor driver with motor encoder, do i have to delete the line number 102 (send long) and 109(receive long)? and if i delete that lines does the result will be the same distance travel of the motor from previous motor with leader and follower?. Thanks for the reply Curio res.
Hi Aoji! Sorry I didn't get to your comment sooner, (long week). So yes no problem if you don't use the leader and follower strategy. You can delete the send and receive functions. You just need to extend all the pin arrays and function calls to four motors (or however many motors you are using). But you also have to have enough interrupt pins available. For the distance of travel to be the same, you need a control loop for each motor (individually). If you use one control loop to control two motors, then you can't actually control the position directly.
the real question is how to implement two different target positions for one motor, governed by time with function millis()? that is at t1 motor achive position 1 and at t2 position 2 . do somebody have answers?
hello. can I ask you 2 small question: 1.pls explain this small part og your code float deltaT = ((float) (currT - prevT))/( 1.0e6 ) why are you divide by 1.0e6. 2.t = fmod(t,12) maybe if you are explain 1 question, no need to explain last question.
Hi Andrew! The currT and prevT are recorded in microseconds, so dividing by 1.0e6 produces the time in seconds. So "float deltaT = ((float) (currT - prevT))/( 1.0e6 )" produces the time difference between the two iterations of the loop function in seconds. For me, this is useful as it's easier for me to think in terms of seconds rather than microseconds. The part that says "t = fmod(t,12)" causes the code to repeat every 12 seconds. The fmod function is the floating point modulus (remainder after division). You can find information about it here: www.tutorialspoint.com/c_standard_library/c_function_fmod.htm
This video is great. I don't know anything about programmable movements for my project however In theory can I add a thousand motors and programe each rotation to stop exactly on a calculated axis degree for example 141 degrees and then another on 25 degrees and so on for all the 1000 motors at either the same time or in a specific order and what would I need to contol that kind of set up wirelessly? Thanks
Oooh, I like how you used a template function (readEncoder) to essentially pass an argument, since attachInterrupt doesn't give you a way to have it pass arguments to the interrupt service routine. Hopefully, I'll remember that trick for later. (I've used closures which bind that kind of parameter at runtime, but this looks like compile time -- two different copies of readEncoder are generated.)
Thanks! I love using templates in Arduino coding, because they allow you to workaround some of the Arduino restrictions at compile time. I haven't used closures to bind at runtime. I'd be interested to take a look. Have a simple reference handy?
@@curiores111 They're really easy in Python. Here's a pretty good explanation: . Python can also use bound methods, which basically captures "self" and returns a callable object that can be used like an ordinary function. Many languages have them. Apple extended C/C++/ObjC in the Clang compiler, calling it "blocks," notably for use with Grand Central Dispatch (threading helper library). I happen to like the blocks syntax, but it is non-standard. Later, the C++ standards committee added closures; I've not used them in C++, so I don't have a handy reference. And I'm not sure if C++ closures can be used where a pointer-to-function is expected (which is probably what attachInterrupt uses).
You can use any encoder motor/microcontroller/motor driver combination. There are plenty of cheap microcontrollers, like knock-off nanos...but I guess now those aren't nearly as cheap as they used to be. As far as encoder motors go, I found it hard to find anything decent for very cheap. Cheap standard motor driver is l298n h-bridge.
Hi, thank you for your informative video! I have 2 incremental encoders with 2 dc motors, but the encoders have 4 outputs each (2 additional differential signals notA to A and notB to B) how can I use and add these to the code?
Glad to hear that. 😊 Sure, you can use any standard motor driver. The pololu drivers use H-bridge ICs. That's pretty standard for bi-directional DC motor drivers. Their motor drivers are more efficient/better protected than something like an L298N. :)
Do you have any recommendations or resources for how to learn about the mechanical/physical parts of making projects like these? I'm generally good at code, so-so at electronics, and poor at the mechanical/physical parts. I wouldn't know how to choose a chassis, motor, wheels, or how to mount them to each other.
Of course! I use a lot of different components while making projects like these. My best friend is my 3D printer. It fills in the gaps that invariably arise in fitting the model together (this model's chassis is 3d printed with petg). I like to model components in fusion360, although I recently started doing a few in blender. Usually I'll download the STEP files for the purchased components, put them together in a model, and then add in some 3D printed parts as needed to make things fit together. I usually purchase the mechanical components (gears, belts, lead screws, wheels, and so forth) from pololu and/or gobuilda (metric)/servo city. Generally, if you buy multiple parts from the same brand they will fit together nicely, so it makes it easier to put together a working prototype (and they usually have STEP files so I can build the mechanism before actually purchasing the parts. For example here's the model I used for this build: imgur.com/a/gegIMN9 ). I'll buy cheaper amazon parts if I can find something that looks decent (and need to save money). Also, there are a lot of standard sizes. For example, these are 37D motors which you can find mounts/attachments for from various brands. The motor shafts are 6mm-D shaft which is again, pretty standard. You can then use a hub (or wheel mount) with a 6mm shaft to connect to a moving part (e.g., a wheel). I just added these mecanum wheels ( www.gobilda.com/96mm-mecanum-wheel-set-70a-durometer-bearing-supported-rollers/ ) to this model and I'm excited to see how accurately I can drive it. Sorry about the long reply. I don't usually get asked this question. ;) References... hmm. I guess it depends on what you're trying to build. Anything specific in mind?
@@curiores111 Nothing specific. It's a general, "I wish I knew how to do something like that" moment. I'd like to experiment and learn about affecting the word with a microcontroller (beyond lights and sounds). Something that moves would probably be fun. I'd like to experiment with PID. A balancing robot is probably too ambitious for a first project. I've seen people put a ball in a grooved channel and balance it or keep it at a specific distance (servo with mechanical linkages?). Maybe a fan levitating a ping pong ball, trying to keep the ball at a specific height (though I'd need to contain it so it stays above the fan, not flying off sideways).
@@markday3145 Those are good ones to start with. I am sure you can find projects on arduino.cc for the ball and beam. It seems like people like a two bar linkage for that one ruclips.net/video/FidxDZ7X6OI/видео.html . Very easy to put together. I'd like to see the fan project. My initial thought would be three cheap computer fans arranged in a circle. It would be fun to attach them to small servos to tilt their angle along with adjusting their speed. No idea if it would work to levitate a ping pong ball but it would be fun. (although of course you could just stick the whole thing in a plastic tube and then it would work right off the bat). I don't have any references for these types of projects, some youtube videos and maker projects should be fine. For control theory I like the UMich tutorials, e.g.: ctms.engin.umich.edu/CTMS/index.php?example=BallBeam§ion=ControlPID
I think I'm fairly close to replicating your functionality. I get that I have to calculate pulsesperturn and pulsespermeter based on my hardware. I think I have calculated those two correctly. My question is: for setTarget(currT/1.0e6,deltaT) how do you decide on the parameters to setTarget()? From watching the complete video, I don't think the parameters are arbitrary. Thanks in advance, JD.
thanks for the tutorial. I have a question, how about using 3 motors with encoders? what should i add in the program? without Atomic. I'm new to Arduino :), I'm using Arduino Mega 2560. thanks in advance.
Great video. Was wondering though, is there anyway this can be controlled to start other than turning on the Arduino? The function relies on the rtc of the loop which of course starts at 0 when power is first applied and thrn after 10 secs the car changes direction. Is there a way to trigger the first 10 secs direction other than reinitialising the loop? Thanks
Thanks Andrew! Certainly, there are plenty of ways you could trigger a start. You could add a remote or RF kit and start when a particular signal is received. You could add a button and start when the button is pressed. You could restart or stop under any of the above conditions. All you have to do is add your peripherals and adjust the control flow of the code to match your use cases.
Hello curio, It was great video indeed. Would please tell me from where you have installed atomic library? I have downloaded two of them but is not getting compiled properly throwing back some error
So far I haven't been able to identify why some users can't access atomic.h. From what I have read, it's based on your microcontroller. I added an alternative code that does not use ATOMIC_BLOCK -- it's up on the GitHub repository. github.com/curiores/ArduinoTutorials
Thanks Cilynx. I use Camtasia to generate animations. For the wiring diagram on this one I made an SVG in layers, separated it into several images, and then used crop animations. It's too many wires to animate by hand.
Would it be possible to have the code not use the interrupts? Arduino mega only has 6 interrupt pins and I am trying to operate 4 DC encoder motors without using multiple boards.
Well you need interrupts to read the position... so I would say you can't complete this tutorial without interrupts. But if you have 6 interrupt pins that should be enough. You only need 4 interrupts for this particular strategy. You don't need to use two microcontrollers. Although if you use a lot of interrupts on one controller you might find that you miss some of the interrupts.
@@curiores111 Hi I purchased an Arduino Due which allow interrupts on all pins. Im going to try to operate 4 DC motors off of it using your PID control. I will let you know how it goes.
Could you please help me find out where i went wrong? If you could give me your mail id, I can mail the code to you or you may let me know your preferred method also.
You have to make sure "receiveLong" is declared before it is used. In C/C++ you would often declare all the functions in a header file to make sure that this doesn't happen (I didn't turn this into a library, so there is no header with declarations) . The way that I ordered the code "receiveLong" is declared before it is used. My email is curiores@gmail.com if you'd like to email something.
@@ดํารงศักดิ์รัตนชัยจันทร์ Sure you can use ESP 32 (might need some logic shifting?). Are you coding in the arduino IDE for the ESP 32? [if so the libraries should still be there]
Cool video 👍 I think, that speed control with encoders is more difficult. I thought of measuring the time between interrupts and dividing the rotation angle by it, but there may be acceleration between the hall ticks, which introduces an error.
Thanks! Yes, it is more difficult to control speed directly. There are a couple of issues to watch out for. I have worked through it before and am planning a video, but just haven't had the time yet.
In industry the motion controllers are usually given commands from a PLC( programmable logic controller). Some motion controllers can work by themselves and can be programmed with a series of commands.
Finally, i found what i wanted! Just had a question, Is there any motor driver which converts provides proper DC voltage based on PWM signal from arduino? Because I am working on project where motor has to rotate at very low speeds of about 10 rpm. And my 50 rpm motor just produces a beeep at PWM values
Hi Hrishikesh -- that's a limitation of the motor -- it will never run at lower speeds. Generally speaking, if you want to rotate at slower speeds, you would use a higher gear ratio. For example, these 150:1 gear motors: www.pololu.com/product/2828 have a maximum speed of 67 RPMS. They would probably work just fine at 10 RPMS. Here's some information on a wiki page about gear ratios: hades.mech.northwestern.edu/index.php/Choosing_a_Motor_and_Gearing_Combination -edit- Oh I see that I may have misinterpreted your question a bit, and you may already know the answer that I gave. Sorry if that's the case. I find it interesting that you had a different behavior using a pot rather than just a PWM driver. In general lowering the duty cycle of the PWM driver should do the same thing as lowering the voltage across the motor, so you shouldn't need a secondary circuit. In general the most important thing here is the motor and the gear ratio, rather than how you reduce the voltage.
@@curiores111 Wait, I think you got it wrong so when I need to run low steps obviously there is a low PWM signal. So during a low PWM signal there is high frequency which makes motor's coil resonate instead of rotating itself. So I found another way to lower speed. I hooked up a buck converter to output of motor driver which intern is connected to motor and I desolder the pot on buck converter which controls voltage and soldered the emmiter of a transistor to the center pin and connected its collecter to +ve of battery. Then i connected arduino PWM signal to transistor. This way I can run at very low speeds of even at maybe 5 or 6 rpm. But circuit got very big. So I had a question does there exsist such a motor driver which based on arduino's PWM gives a linear DC voltage? Did you get the question?
@@hrishikeshgawas4579 To answer your question: no, I haven't seen any non-pwm motor drivers. It sounds like you're basically using your buck converter (which most likely has a switching MOSFET) as a motor driver. This is not recommended, as it probably doesn't have the necessary protection against current spikes that can occur if there's a rapid direction reversal of the motor. If the PWM signal is causing an issue, have you considered trying to add a filter (e.g. correctly rated ceramic capacitors) to the output of the motor driver? That should amount to something similar to what you're doing (filtering the output of the switching mosfet), but with safer components. In any case, I'm not an electrical engineer by trade, so that's about as far as my thoughts go on this topic. I think filtering the output and/or finding motors with a higher gear ratio are your best bet.
@@curiores111 Okay I will try filtering the output with a capacitor. Thank you; Yes I agree its not safe but was just trying to prove the point that motor can go on at low speeds but PWM causes problems. I will try it with capacitor and let you know. Thanks 😊.
Hi Curio Res. By the way, I have been looping thru this video and I want to share with you something I encountered. When the variable "pos" and "posi" reach 0 and it overflows by going under zero in an operation 0-1 = overflow, the system starts to get some weird behaviour. When there is like a jump from positive values to negative values. Can you tell us how to solve this issue? Thanks by the way for the great content.
Hi Osvaldo, I an sorry that I haven't gotten back to you yet. I want to look at the code and see if I could identify any possible issues. If the variables are indeed outside their limits, then you would definitely see undefined behavior. However, because the variables are integers, you can perform operations like 0-1, which would give you a position of "-1". This by itself would not cause an overflow. However, if you had pos go over 32,678, that could cause an overflow. In that situation you could consider using a long. If it's not actually a problem with an overflow, it could be a problem with the controller. However, I wouldn't be able to say more without seeing the problem for myself.
@@curiores111 Thank you very much. I understand. Now I'm working on a program to make a robot go straight, because is constantly turning one way, using ESP32 and MPU6050. I hope you take on this challenge with me.
Hi Curio Res... I'll really love if you could make an example of how to completely control 2 DC motors to move up front, back, left and right in sync or with the same speed. Because I'm having troubles trying to move to motors with almost same speed. By the way, incredible content. I subscribed.
Hi Curio, I'm currently using a Mega 2560 to controll 3 DC motors with encoders through L298n for each motors, I need these motors to run at the same speed, but when I provide 255 PWM signal, the velocity measured are 180/178/170 RPM. Does it need PID in this situation or are there any ways to control 3 motors at same speed? Thank you.
I like your use of "Leader"/"Follower". I'm doing a somewhat similar project, and since I prefer Python I'm trying the RaspBerry pi Pico board and it seems to read encoders well. Things start getting complicated once you add individual wheel steering and want to calculate distances and angles with that.
Thanks, I've also heard it called "controller"/"peripheral", but I find that a little strange considering that they're both "controllers" and neither one is a "peripheral" (in my mind). For general i2c though, that terminology makes sense. I just got my pico this week! Haven't had a chance to get it running yet though. I also enjoy python (although to be fair I'll code in just about anything).
Hey! thank's so much for this video. Very explanatory and I love your commitment to clean code! I have a question, in getting the motor to move a certain pulses per second, can that be done for just one motor, and how would you go about having different pid loops for two different motors in the same sketch if you did not want them to be in sync?
Certainly, and thank you for noticing. I love clean code! The way this is set up each motor has an independent PID calculation. To set different rates for each motor, you just set the targets differently. To operate only one motor, you would just create one instance of the PID calculation class. Here, I've put everything in arrays for convenience.
Hi Curio! I am deeply impressed by your videos! Please forgive me for asking you a simple question: I noticed that your int b in readEncoder functions shares the same value when the array changes to number 0 or 1 in your case. I assume this setting is to make the two motors rotate in the same speed and direction? Thus, if I change the single int b to int b[array], will the motor's position will be calculated independently? Thanks again for the sharing! :-)
Int b is a local variable for the duration of one call to readEncoder. It doesn't persist past each individual call. The arrays encb and posi persist past this though - they are global variables.
Its as dry and boring as a video you were forced to watch in high school. Only tells half the story. You assume everyone is on the same level. You say what you do but not how or why you knew to do it.
This is nice. Even the quality of the sound is on another level. Not what I was expecting from a smaller chanel. Great work!
Just stumbled upon your channel, and I hope you keep it going. Great videos, I really appreciate everything you do. Thank you for sharing!
Sure and thanks for the kind words. Working on another video today as it so happens. :)
This channel should have millions of subscribers it's great!
de lo mejor que he visto en la red, felicidades
CR: What a code loaded video! The ATOMIC_BLOCK and template aspect were unknown to me; shows how DYI I am. You have elevated my understanding substantially for a lawn cart project which will takes its drive input from a joystick controller communicating with HC-12 transceivers. The joystick forward/reverse axis will be straight at +/- speed and the left/right will be radius of curvature of a turn. You use SimplePID which may require a library but I don't see yet where you set the PID compute rate; it may just be the loop() itself.
Yes, the PID control signal (and consequently the PWM value) is updated whenever the loop function triggers (so the sample time is determined by how often the loop function executes). I didn't use a library, the "SimplePID" is just a class written into the code.
@@curiores111 I did read your code and saw that in loop() you do the PID compute. Regarding SimplePID libary, while I saw in your code that you didn't include any library, there is a SimplePID library so I was confused. However, that I didn't understand that you were using a class highlights my weak coding skills in C++. As a physicist, computations are numerical mostly so DYI Arduino coding is new. Finally, thank you for your prompt reply because my knowledge gained from you is HUGE!
I've used motors very similar to those in the video (great video). Like many inexpensive motors, the same power settings to not result in the same motor speed. The PID speed controller will run the motors at the same speed after an initial speed up time. During that time, the motors will not be turning at the same speed and the robot will not run straight. It's easier with four wheels because the friction keeps the robot from moving cross track. For a differential drive robot to run straight, the motors need different initial pwm values.
Can you clarify what you mean?
I've considered that issue - PID with individual motors doesn't seem to account for the initial acceleration phase - meaning that the robot will often turn and then go in a straight line.
Is there a way to fix this?
There are several ways to address this.
1) Experiment by trial and error with the initial motor driver inputs, whether duty cycles or PWM, whatever the motor driver takes as inputs to find values for each motor that will cause the robot to run straight.
2) Another way, is to make a series of measurements by running the motors at different input PWM, no speed control, and recording both the time duration, 5 seconds is plenty,
and the encoder counts. Using the wheel diameter, calculate the speed of each wheel in cm/s. Make the measurements for a variety of motor control inputs. Plot the results of speed vs inputs. I use Excel and fit a least squares quadratic equation for each motor. Now you have motor equations that relate speed to motor driver inputs. For a selected speed, determine and use the corresponding driver inputs for each motor. Now when the robot starts it will tend to go straight and PID can be used for further control.
3) If you have a good way to measure the robot orientation, yaw angle, use the deviation from a straight line, or the cross-track error, and/or the angle to the goal to make path corrections while the robot is in motion. Do that by keeping one wheel speed constant and varying the speed of the other wheel.
John-
Thanks for the video!! I have a question . Can we control stepper motor in the same if hallow encoder fixed at end of shaft of motor?
Stepper motor position is directly controllable; you don't need a feedback loop since you can simply assign the number of steps to take. That's based on the fundamental differences between how DC motors and stepper motors function.
I absolutely love your videos. The way you explain things is perfect. I am using your code in a robotic project and believe I understand the feedback loop. My robot is running mecanum wheels. What I am scratching my head on is how to change directions. With mecanum wheels, I can rotate in place, move left/right, and so on. But apparently my intellect is having a hard time incorporating this into your code.
Can you tell me what power supply are you using, I am making the same robot as you thanks.
If I wanted to activate the target with a push button, what modifications would I have to make?
Hard for me to say without knowing the details of what you're trying to accomplish. I'd suggest starting with a button tutorial (maybe look at OneButton?) and then adjusting the target conditionally based on the state of the button (or intermediate variable).
@@curiores111 What I want is that when I activate the code the motors do not move to any position, until I press the button the motors rotate to the designated position, for example target 2400
@@danielmartinez-mk6iu
Sure, so, register a OneButton, "btn". github.com/mathertel/OneButton
Then, use a conditional so that if the button is pressed, the target is changed and the PID control is activated. Here's an example pseudocode:
OneButton btn();
bool mode = false;
setup(){
// register btn
// register changeMode function
}
loop(){
// tick btn
if(!mode){
// set motors off
}
else{
// proceed as usual
}
}
void changeMode(){
mode = !mode;
}
Great to see a new video Curio!! That is perfect as others.
Thanks :)
I appreciate that and also thanks for stopping by Omer!
@@curiores111 You are welcome, I am a big fan of you!!
Hi, I'm building an obstacle-avoiding robot with an ultrasonic sensor. How can I integrate the PID control into the robot I am doing? (I don't know much about coding and Arduino. I'm trying to do this project to get through class.)
How do I turn left and right???
Can we do speed control for 4 DC MOTORS like this.
Hi
How can I make a 6 amp driver to turn the DC motor into a servo motor so that the Arduino treats it like a real servo motor?
thank you
My motor driver has only PWM1 and IN1, do i just remove IN2 in the setMotor part of the code?
What motor driver is it? If that's the case, it's probably not bidirectional. If it's not bidirectional, it will be harder to control (you won't be able to reverse directions). You would have to slightly edit the setMotor function to make sense with the control code.
@@curiores111 Its actually known as MDDA 10 Cytron dual channel motor driver
@@Luxigaming Oh well that's good then. Look at the truth table for control logic on the spec sheet. You can adjust the setmotor function so that it matches those conditions. (In other words, you remove one input the setmotor function, and then change the logic inside based on the truth table for a single direction pin, rather than 2).
@@curiores111 Thank you so much for ur help!!
Hello Curio Res, I found your example on RUclips that interests me a lot because I have two reduced motors with encoder and I would like to know if it is possible to synchronize the two motors to have the same speed so the same count on the two encoders.
I have two ballasts is they have two pistons to fill them or empty them with water, my problem is that I have a faster ballast than the other, I saw your code and I modified it but I hold a little, can you help me to recover the value of the encoder from the right engine and that of the syncronized left engine in order to display them on an LCD?
I use an L298N ....
Thanks for your help..
Alfred
The video is nice, but it doesn't adequately address basic questions.
When I have a vehicle with 4 motors, each motor typically requires its own set of constants for PID control in control engineering.
If the vehicle is supposed to move at a certain speed, the desired speed is set as the setpoint for all motors.
For synchronization, the speeds of the 4 motors are not compared, but rather the differences in pulses are compared, and based on the deviations, new output signals are calculated using PID control.
If one wants to achieve perfection, deceleration is also calculated using PID control. In this case, the actual pulses are counted to determine the desired new speed (cascade control).
There is nothing wrong with the video, but the implementation was somewhat oversimplified by the presenter.
I hear comments like this occasionally. It's valid -- not everything is covered, and certainly the methodology is not optimal. But that's the intention -- its not meant to cover everything, and its not meant to be optimal. Generally, my videos are intended to make more complicated engineering concepts accessible to a wider audience. Getting deeper into the details is another step, and not accessible or useful in an introductory video.
instead of the "A-Star 32U4 Mini SV" controller can I use 2 Arduino Uno/ 2 mega / Arduino due/ 2 Arduino nano v3. I guess I need to have a total of 8 digital pins for the same right? Please Suggest, Thank You.
Sure, any of those options seem reasonable to me. Two megas would probably be overkill in terms of pins.
I am using Arduino Mega with 4 encoder motors and 1 L298d Motor driver shield, I am giving the power of 12 V and each motor side the power is getting 10.7 V.
But my all motors are not running at constant speed, how can i fix this?
are you driving all four motors with a single driver?
For now I'll assume you have separate driver for each motor. There's nothing that guarantees that the motors will run at the same speed. This is one good reason to use feedback control. In general, you'll want to ramp the position slowly enough so that all the motors can get there at (nearly) the same time. Alternatively, you could try controlling the speed directly. In either case, you'll have to make sure that you adjust your speeds slowly enough that the transients are not causing your motors to get out of sync.
@@curiores111 yes, I am using a single motor driver, L298d Motor driver shield has 4 different ports for 4 motors
Glad to watch the video , just one question can I do the same by replacing Arduino with Raspberry pi as a control device ?
If not which motor controller are used for pi to control dc motors with same type of encoders used in this video.
Yes, you can... but I think there may be some issues with slow interrupts because there is a lot going on in a raspberry pi. I am not familiar enough to know how well it would perform, but I'm guessing not that well. I would myself prefer to do the control loop on a microcontroller and then have the pi doing other tasks, like computer vision and path planning.
Nice! Very detailed and helpful. Anyway i have a question what if i dont have a leader and follower (not familiar with it), and i just have to used L298N motor driver with motor encoder, do i have to delete the line number 102 (send long) and 109(receive long)? and if i delete that lines does the result will be the same distance travel of the motor from previous motor with leader and follower?. Thanks for the reply Curio res.
Hi Aoji! Sorry I didn't get to your comment sooner, (long week). So yes no problem if you don't use the leader and follower strategy. You can delete the send and receive functions. You just need to extend all the pin arrays and function calls to four motors (or however many motors you are using). But you also have to have enough interrupt pins available. For the distance of travel to be the same, you need a control loop for each motor (individually). If you use one control loop to control two motors, then you can't actually control the position directly.
How do you know your A star 32U4 Mini SV could handle 2 motors?
the real question is how to implement two different target positions for one motor, governed by time with function millis()? that is at t1 motor achive position 1 and at t2 position 2 . do somebody have answers?
hello. can I ask you 2 small question: 1.pls explain this small part og your code float deltaT = ((float) (currT - prevT))/( 1.0e6 ) why are you divide by 1.0e6. 2.t = fmod(t,12) maybe if you are explain 1 question, no need to explain last question.
Hi Andrew! The currT and prevT are recorded in microseconds, so dividing by 1.0e6 produces the time in seconds. So "float deltaT = ((float) (currT - prevT))/( 1.0e6 )" produces the time difference between the two iterations of the loop function in seconds. For me, this is useful as it's easier for me to think in terms of seconds rather than microseconds. The part that says "t = fmod(t,12)" causes the code to repeat every 12 seconds. The fmod function is the floating point modulus (remainder after division). You can find information about it here: www.tutorialspoint.com/c_standard_library/c_function_fmod.htm
That's really cool. Learnt a lot.
Thanks for sharing!
This video is great. I don't know anything about programmable movements for my project however In theory can I add a thousand motors and programe each rotation to stop exactly on a calculated axis degree for example 141 degrees and then another on 25 degrees and so on for all the 1000 motors at either the same time or in a specific order and what would I need to contol that kind of set up wirelessly? Thanks
Oooh, I like how you used a template function (readEncoder) to essentially pass an argument, since attachInterrupt doesn't give you a way to have it pass arguments to the interrupt service routine. Hopefully, I'll remember that trick for later.
(I've used closures which bind that kind of parameter at runtime, but this looks like compile time -- two different copies of readEncoder are generated.)
Thanks! I love using templates in Arduino coding, because they allow you to workaround some of the Arduino restrictions at compile time.
I haven't used closures to bind at runtime. I'd be interested to take a look. Have a simple reference handy?
@@curiores111 They're really easy in Python. Here's a pretty good explanation: . Python can also use bound methods, which basically captures "self" and returns a callable object that can be used like an ordinary function.
Many languages have them. Apple extended C/C++/ObjC in the Clang compiler, calling it "blocks," notably for use with Grand Central Dispatch (threading helper library). I happen to like the blocks syntax, but it is non-standard. Later, the C++ standards committee added closures; I've not used them in C++, so I don't have a handy reference. And I'm not sure if C++ closures can be used where a pointer-to-function is expected (which is probably what attachInterrupt uses).
@@markday3145 Ah, interesting. Feels more like a scripting language construct than something you'd find in C++. Thanks for the reference.
Great video! Can you recommend alternative inexpensive components that can accomplish the same results or will this work only with Pololu components?
You can use any encoder motor/microcontroller/motor driver combination. There are plenty of cheap microcontrollers, like knock-off nanos...but I guess now those aren't nearly as cheap as they used to be. As far as encoder motors go, I found it hard to find anything decent for very cheap. Cheap standard motor driver is l298n h-bridge.
How can i control the target of 4 dc motors separately rather than following.
Hi, thank you for your informative video! I have 2 incremental encoders with 2 dc motors, but the encoders have 4 outputs each (2 additional differential signals notA to A and notB to B) how can I use and add these to the code?
Great video! Very helpful to us mechatronics engineering students, by the way can i used h bridge driver alternative for your driver you used?
Glad to hear that. 😊 Sure, you can use any standard motor driver. The pololu drivers use H-bridge ICs. That's pretty standard for bi-directional DC motor drivers. Their motor drivers are more efficient/better protected than something like an L298N. :)
Tooo good ✨
Do you have any recommendations or resources for how to learn about the mechanical/physical parts of making projects like these?
I'm generally good at code, so-so at electronics, and poor at the mechanical/physical parts. I wouldn't know how to choose a chassis, motor, wheels, or how to mount them to each other.
Of course! I use a lot of different components while making projects like these. My best friend is my 3D printer. It fills in the gaps that invariably arise in fitting the model together (this model's chassis is 3d printed with petg). I like to model components in fusion360, although I recently started doing a few in blender. Usually I'll download the STEP files for the purchased components, put them together in a model, and then add in some 3D printed parts as needed to make things fit together.
I usually purchase the mechanical components (gears, belts, lead screws, wheels, and so forth) from pololu and/or gobuilda (metric)/servo city. Generally, if you buy multiple parts from the same brand they will fit together nicely, so it makes it easier to put together a working prototype (and they usually have STEP files so I can build the mechanism before actually purchasing the parts. For example here's the model I used for this build: imgur.com/a/gegIMN9 ). I'll buy cheaper amazon parts if I can find something that looks decent (and need to save money).
Also, there are a lot of standard sizes. For example, these are 37D motors which you can find mounts/attachments for from various brands. The motor shafts are 6mm-D shaft which is again, pretty standard. You can then use a hub (or wheel mount) with a 6mm shaft to connect to a moving part (e.g., a wheel). I just added these mecanum wheels ( www.gobilda.com/96mm-mecanum-wheel-set-70a-durometer-bearing-supported-rollers/ ) to this model and I'm excited to see how accurately I can drive it.
Sorry about the long reply. I don't usually get asked this question. ;)
References... hmm. I guess it depends on what you're trying to build. Anything specific in mind?
@@curiores111 Nothing specific. It's a general, "I wish I knew how to do something like that" moment.
I'd like to experiment and learn about affecting the word with a microcontroller (beyond lights and sounds). Something that moves would probably be fun. I'd like to experiment with PID. A balancing robot is probably too ambitious for a first project. I've seen people put a ball in a grooved channel and balance it or keep it at a specific distance (servo with mechanical linkages?). Maybe a fan levitating a ping pong ball, trying to keep the ball at a specific height (though I'd need to contain it so it stays above the fan, not flying off sideways).
@@markday3145 Those are good ones to start with. I am sure you can find projects on arduino.cc for the ball and beam. It seems like people like a two bar linkage for that one ruclips.net/video/FidxDZ7X6OI/видео.html . Very easy to put together. I'd like to see the fan project. My initial thought would be three cheap computer fans arranged in a circle. It would be fun to attach them to small servos to tilt their angle along with adjusting their speed. No idea if it would work to levitate a ping pong ball but it would be fun. (although of course you could just stick the whole thing in a plastic tube and then it would work right off the bat).
I don't have any references for these types of projects, some youtube videos and maker projects should be fine. For control theory I like the UMich tutorials, e.g.: ctms.engin.umich.edu/CTMS/index.php?example=BallBeam§ion=ControlPID
I think I'm fairly close to replicating your functionality. I get that I have to calculate pulsesperturn and pulsespermeter based on my hardware. I think I have calculated those two correctly. My question is: for setTarget(currT/1.0e6,deltaT) how do you decide on the parameters to setTarget()? From watching the complete video, I don't think the parameters are arbitrary. Thanks in advance, JD.
Could i control 6 DC motors like this one???
Indeed, you could.
In industry there is sometimes a need to control over 30 motors. This requires more processing power thought.
Explained extremely well!
thanks for the tutorial. I have a question, how about using 3 motors with encoders? what should i add in the program? without Atomic. I'm new to Arduino :), I'm using Arduino Mega 2560. thanks in advance.
Great video. Was wondering though, is there anyway this can be controlled to start other than turning on the Arduino? The function relies on the rtc of the loop which of course starts at 0 when power is first applied and thrn after 10 secs the car changes direction. Is there a way to trigger the first 10 secs direction other than reinitialising the loop? Thanks
Thanks Andrew!
Certainly, there are plenty of ways you could trigger a start.
You could add a remote or RF kit and start when a particular signal is received.
You could add a button and start when the button is pressed.
You could restart or stop under any of the above conditions.
All you have to do is add your peripherals and adjust the control flow of the code to match your use cases.
Hello curio,
It was great video indeed. Would please tell me from where you have installed atomic library? I have downloaded two of them but is not getting compiled properly throwing back some error
So far I haven't been able to identify why some users can't access atomic.h. From what I have read, it's based on your microcontroller. I added an alternative code that does not use ATOMIC_BLOCK -- it's up on the GitHub repository. github.com/curiores/ArduinoTutorials
Very clear and valuable as always. What software are you using for the wiring diagram animations?
Thanks Cilynx. I use Camtasia to generate animations. For the wiring diagram on this one I made an SVG in layers, separated it into several images, and then used crop animations. It's too many wires to animate by hand.
Amazing knowledge u are sharing!!
Would it be possible to have the code not use the interrupts? Arduino mega only has 6 interrupt pins and I am trying to operate 4 DC encoder motors without using multiple boards.
Well you need interrupts to read the position... so I would say you can't complete this tutorial without interrupts. But if you have 6 interrupt pins that should be enough. You only need 4 interrupts for this particular strategy. You don't need to use two microcontrollers. Although if you use a lot of interrupts on one controller you might find that you miss some of the interrupts.
@@curiores111 Hi I purchased an Arduino Due which allow interrupts on all pins. Im going to try to operate 4 DC motors off of it using your PID control. I will let you know how it goes.
@@CryingNeutrons Sounds awesome, looking forward to hearing about it.
@@curiores111 Btw I got an arduino due to control 4 dc motors ising your multiple encoders code for velocity control
@@CryingNeutrons well done! I haven't used that myself yet for several motors, so you're ahead of me.😉
I had doubt, in your follower sketch should it be void recieveLong(), because I got compilation errors.
error states , " 'recieveLong' was not declared in this scope "
Could you please help me find out where i went wrong? If you could give me your mail id, I can mail the code to you or you may let me know your preferred method also.
You have to make sure "receiveLong" is declared before it is used. In C/C++ you would often declare all the functions in a header file to make sure that this doesn't happen (I didn't turn this into a library, so there is no header with declarations) . The way that I ordered the code "receiveLong" is declared before it is used.
My email is curiores@gmail.com if you'd like to email something.
no it should be long, because it returns a long.
Hmm i get a error stating the recieveLong() isnt declared in scope for a statement under void loop(). Anyways i have mailed my code. 😊
Hi ,
Can you share the robot chassis frame
I would but I can't stand that one anymore. If I make a new, improved one, I'll share it.
Where can I download this library ?
That's part of Arduino's built in library. No need to acquire it.
@@curiores111 Can only be used with Arduino? Can it be used with ESP32?
@@ดํารงศักดิ์รัตนชัยจันทร์ Sure you can use ESP 32 (might need some logic shifting?). Are you coding in the arduino IDE for the ESP 32? [if so the libraries should still be there]
@@curiores111
I'm perplexed to change the logic from Uno to ESP32.Do you have an example?
@@ดํารงศักดิ์รัตนชัยจันทร์ I don't have an example, but I'm sure there are plenty of tutorials for ESP32 out there. Good luck!
Great video, will be very useful for my project
Great job, thank you!
Very good video, thank you very much!
Cool video 👍 I think, that speed control with encoders is more difficult. I thought of measuring the time between interrupts and dividing the rotation angle by it, but there may be acceleration between the hall ticks, which introduces an error.
Thanks! Yes, it is more difficult to control speed directly. There are a couple of issues to watch out for. I have worked through it before and am planning a video, but just haven't had the time yet.
@@curiores111 Great, I will wait for the new video.
I love your channel! Please keep going :)
what application do you control it with?
In industry the motion controllers are usually given commands from a PLC( programmable logic controller). Some motion controllers can work by themselves and can be programmed with a series of commands.
I hope to see "How to speed control of DC motor with encoder"
it's coming...whenever I find the time... thank you for the encouragement.
Eres Maravillosa, Mil Gracias...You are amazing, Thanks a lot.
Nicely explained 👍
Thank you for sharing.
This is a great tutorial 😊
Thank you very much. your tutorial is very helpful for me. your tutorial is what I am looking for.
Finally, i found what i wanted! Just had a question, Is there any motor driver which converts provides proper DC voltage based on PWM signal from arduino? Because I am working on project where motor has to rotate at very low speeds of about 10 rpm. And my 50 rpm motor just produces a beeep at PWM values
Hi Hrishikesh -- that's a limitation of the motor -- it will never run at lower speeds. Generally speaking, if you want to rotate at slower speeds, you would use a higher gear ratio. For example, these 150:1 gear motors: www.pololu.com/product/2828 have a maximum speed of 67 RPMS. They would probably work just fine at 10 RPMS. Here's some information on a wiki page about gear ratios: hades.mech.northwestern.edu/index.php/Choosing_a_Motor_and_Gearing_Combination
-edit-
Oh I see that I may have misinterpreted your question a bit, and you may already know the answer that I gave. Sorry if that's the case.
I find it interesting that you had a different behavior using a pot rather than just a PWM driver. In general lowering the duty cycle of the PWM driver should do the same thing as lowering the voltage across the motor, so you shouldn't need a secondary circuit. In general the most important thing here is the motor and the gear ratio, rather than how you reduce the voltage.
@@curiores111 Wait, I think you got it wrong so when I need to run low steps obviously there is a low PWM signal. So during a low PWM signal there is high frequency which makes motor's coil resonate instead of rotating itself. So I found another way to lower speed. I hooked up a buck converter to output of motor driver which intern is connected to motor and I desolder the pot on buck converter which controls voltage and soldered the emmiter of a transistor to the center pin and connected its collecter to +ve of battery. Then i connected arduino PWM signal to transistor. This way I can run at very low speeds of even at maybe 5 or 6 rpm. But circuit got very big. So I had a question does there exsist such a motor driver which based on arduino's PWM gives a linear DC voltage? Did you get the question?
Resonate in the sense the coil just makes a sound like beeeeeep
@@hrishikeshgawas4579 To answer your question: no, I haven't seen any non-pwm motor drivers.
It sounds like you're basically using your buck converter (which most likely has a switching MOSFET) as a motor driver. This is not recommended, as it probably doesn't have the necessary protection against current spikes that can occur if there's a rapid direction reversal of the motor.
If the PWM signal is causing an issue, have you considered trying to add a filter (e.g. correctly rated ceramic capacitors) to the output of the motor driver? That should amount to something similar to what you're doing (filtering the output of the switching mosfet), but with safer components.
In any case, I'm not an electrical engineer by trade, so that's about as far as my thoughts go on this topic. I think filtering the output and/or finding motors with a higher gear ratio are your best bet.
@@curiores111 Okay I will try filtering the output with a capacitor. Thank you; Yes I agree its not safe but was just trying to prove the point that motor can go on at low speeds but PWM causes problems. I will try it with capacitor and let you know. Thanks 😊.
Ultimate video .thank you .
Thank you for explanation.
Hi Curio Res. By the way, I have been looping thru this video and I want to share with you something I encountered. When the variable "pos" and "posi" reach 0 and it overflows by going under zero in an operation 0-1 = overflow, the system starts to get some weird behaviour. When there is like a jump from positive values to negative values. Can you tell us how to solve this issue? Thanks by the way for the great content.
Hi Osvaldo, I an sorry that I haven't gotten back to you yet. I want to look at the code and see if I could identify any possible issues. If the variables are indeed outside their limits, then you would definitely see undefined behavior.
However, because the variables are integers, you can perform operations like 0-1, which would give you a position of "-1". This by itself would not cause an overflow. However, if you had pos go over 32,678, that could cause an overflow. In that situation you could consider using a long.
If it's not actually a problem with an overflow, it could be a problem with the controller. However, I wouldn't be able to say more without seeing the problem for myself.
@@curiores111 Thank you very much. I understand. Now I'm working on a program to make a robot go straight, because is constantly turning one way, using ESP32 and MPU6050. I hope you take on this challenge with me.
Hi Curio Res... I'll really love if you could make an example of how to completely control 2 DC motors to move up front, back, left and right in sync or with the same speed. Because I'm having troubles trying to move to motors with almost same speed. By the way, incredible content. I subscribed.
Hi Osvaldo, thank you for the suggestion! Yes, syncing the motors can be a challenge. Hope that it is working out for you.
Можно ли использовать обычную Arduino uno?
да
This is an amazing video. Thank you very much. We need mooore!!! Hahahaha
Thanks! I'll see what I can do. 😅
Dios mío, que calidad de video, gracias!!! :D
Hi Curio, I'm currently using a Mega 2560 to controll 3 DC motors with encoders through L298n for each motors, I need these motors to run at the same speed, but when I provide 255 PWM signal, the velocity measured are 180/178/170 RPM. Does it need PID in this situation or are there any ways to control 3 motors at same speed? Thank you.
I like your use of "Leader"/"Follower". I'm doing a somewhat similar project, and since I prefer Python I'm trying the RaspBerry pi Pico board and it seems to read encoders well. Things start getting complicated once you add individual wheel steering and want to calculate distances and angles with that.
Thanks, I've also heard it called "controller"/"peripheral", but I find that a little strange considering that they're both "controllers" and neither one is a "peripheral" (in my mind). For general i2c though, that terminology makes sense.
I just got my pico this week! Haven't had a chance to get it running yet though. I also enjoy python (although to be fair I'll code in just about anything).
Hey! thank's so much for this video. Very explanatory and I love your commitment to clean code!
I have a question, in getting the motor to move a certain pulses per second, can that be done for just one motor, and how would you go about having different pid loops for two different motors in the same sketch if you did not want them to be in sync?
Certainly, and thank you for noticing. I love clean code!
The way this is set up each motor has an independent PID calculation. To set different rates for each motor, you just set the targets differently. To operate only one motor, you would just create one instance of the PID calculation class. Here, I've put everything in arrays for convenience.
@@curiores111 Thank you so much for your help. You're amazing!
Hi Curio! I am deeply impressed by your videos! Please forgive me for asking you a simple question: I noticed that your int b in readEncoder functions shares the same value when the array changes to number 0 or 1 in your case. I assume this setting is to make the two motors rotate in the same speed and direction? Thus, if I change the single int b to int b[array], will the motor's position will be calculated independently?
Thanks again for the sharing! :-)
Int b is a local variable for the duration of one call to readEncoder. It doesn't persist past each individual call. The arrays encb and posi persist past this though - they are global variables.
thank you !
Is great!!!!!
Thank you!
Thanks
just woow😲
Thank you. Clearly explained. Very well done. Helped in my robotics application.
so glad to hear that, thanks Thomas!
Its as dry and boring as a video you were forced to watch in high school. Only tells half the story. You assume everyone is on the same level. You say what you do but not how or why you knew to do it.
Thanks for the feedback Daniel (albeit a little rude ;)
Thank you☺
Hi Curio Res... I need some help in a similar kind of project, please share email to connect with you...thanks!!
Very nicely and neatly explained. Thank you!! :)