Notifications
Clear all

Fully Electronic Speed Control of a DC Motor

22 Posts
8 Users
17 Likes
1,688 Views
(@emilyq1)
Member
Joined: 1 year ago
Posts: 7
Topic starter  

@zander That is what I was attempting to do, but the encoder value changes every second, which makes it difficult to continuously increase/decrease to maintain the desired speed. Is an encoder supposed to be so variable?


   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2504
 

@emilyq1 

What Ron is telling you is that you need to use the encoder's result to adjust your motorPwm value each time through the loop. The encode is variable because it's tracking the speed of the motor and that's what's changing. Ron is telling you that you need to use the encoder's result to control the otor speed.

As your sketch stands now, you set the power sent to the motor by calculating

motorPwm = map(analogRead(speedcontrol), 0, 1023, 0, 255);

and then send that value to the motor controller.

The problem that you see is the motor is slowing down under load, but that never gets better because the power isn't being adjusted upwards when the motor slows and downwards when it speeds up (which may happen when the load on the motor decreases). You're always looking at where the potentiometer is set instead.

What Ron is saying is that you'll need to use the encoder's results to see when the motor is rotating slower and raise (or lower) the calculated value of motorPwm.

For a start, you should move the calculation of rpm (and degspeed and radspeedif you really need them) before the calculation of motorPwm. You can then check the calculated rpm and decide what to do with powerPwm accordingly. So, if the rpm calculated is below your target speed, increase motorPwm a bit. Concvsrsely, if your calculated rpm is higher than your target, then reduce motorPwm a bit.

In other words, adjust the power based on the speed calculated and not the speed control potentiometer. You only need to use it to provide a starting valuebefore you enter the loop(). You should start off making small increments and decrements to the powerPwm value until you get a feeling for how much variation is needed to handle the load on the motor. Being too aggressive changing the power may damage your motor or make it run erratically as it swings back and forth between too much and too little power.

Anything seems possible when you don't know what you're talking about.


   
Emily reacted
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6662
 

@emilyq1 I think @will captured my thinking quite well.

I would like to give you some guidance from a very old programmer to a newbie. First format your code, or use the IDE Auto Format under the Tools menu. If I can't easily read your code I simply move on to the next request for help.

Instead of #define, use const. Several reasons for this and even the arduino authors recommend it.

Check your functions for full syntax, the millis() function returns 'unsigned long'. Storing that in a long could be interesting.

Also a millisecond for the modern processor is a long time, maybe try micros(), and it also returns unsigned long.

Lastly, I am a big believer in using google to find several similar articles or even code samples to see what others have done. I find this one from the Arduino Hub particularly informative

https://create.arduino.cc/projecthub/curiores/how-to-control-a-dc-motor-with-an-encoder-d1734c

Good luck.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2037
 

@emilyq1 

From what the others have commented maybe you need to convert the POT reading to a desired_speed value not a PWM value. Compare that desired_speed value to the actual_speed value and adjust the PWM up or down accordinaly.

Maybe the PID algorithm might be useful here to determine by how much the PWM should be changed according the amount of difference between the desired speed and the actual speed?  The utube video suggested by @zander seems to be doing just that to control speed.

Another thing I have noticed in some other people's code is during computations the interrupt is turned off and then turned back on again when the computations have finished.


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2037
 

@emilyq1 

For a nice formatted listing if you are using the old Arduino IDE as I am or the IDE you have can save as HTML then that is a good option. Just select all and save as HTML. Then in your post hit the Enter a few times to make some lines where you want to insert the source code. Then in your forum post select the source code button {;}

A window will pop up so paste between the Ps and hit enter.

scWindow

   
ReplyQuote
(@davee)
Member
Joined: 3 years ago
Posts: 1608
 

Hi @emilyq1,

  I don't know if you have solved your fluctuating motor speed problem yet, but in case you haven't, I offer a suggestion on how to look for the problem. Unfortunately, it is fairly dependent on a piece of test equipment, so it may not be that easy for you.

I note others have provided helpful suggestions of providing a speed feedback control, and that may be a useful direction for the complete project, but at the moment, your printout is suggesting that the speed is varying, whilst the motor control signal is a constant value. Assuming the load is constant, then this implies a problem that needs to be identified before proceeding with a feedback system. If your speed measurement system is flawed, then attaching a feedback system will only make the problem much worse!

----------

The first difficulty is establishing what is actually happening. Listing some of the usual suspects for the reading varying, as shown in your chart (in no particular order):

  1. The motor speed is continually changing
  2. Your timing period of 1 second (you specified) to count pulses is varying
  3. The encoder to Arduino interface is adding and/or losing pulses

Unfortunately, in the absence of test equipment to give an independent measurement, it is tricky to eliminate any of these. Your best bet is to acquire an oscilloscope and methodically go through the suspects, checking their alibis. (Sorry, I watch too many 'whodunnit' programs! 🙄 )

  • A/ Bill's video showed the neat pulses from his encoder on his oscilloscope. That would be the first (easiest) to check out. You don't say which motor/encoder you have acquired, so I couldn't look at the data sheet. It is possible it needs some changes to the interface connections.
    • Check that the voltages ... below about 0.4V when low, above about 4V when high, as well as the timing, assuming a 5V Arduino system.
  •  
  • B/ Assuming, it is producing neat pulses, then you can use the 'scope to directly check the motor speed.
  •  
  • C/ By adding a 2-3 lines of code to your program, you could arrange to output a digital signal from one of the spare Arduino pins, which changed state at the start of each 1 second timing period, so that it would be high for 1 second, then low for 1 second, and so on. Again, the 'scope could verify the accuracy of these pulses. (I think I have read somewhere that using interrupts can upset some of the Arduino timing routines, but I don't recall the details.)

I appreciate getting hold of an oscilloscope may be a bit tricky, but hopefully you could borrow one for an hour or so, if you haven't already got access to one.

If that really isn't possible, then consider using a second Arduino to perform the same (or equivalent) timing measurements. Try to use very simple code based on millis() or micros() functions, and no interrupts. The easiest to check would be "C/", as is a single digital input. "B/" could rigged up in some way .. maybe a pointer or reflector attached to the motor shaft, with a LED light source and photo detector. "C/" would be the hardest .. there are 'oscilloscope' style Arduino projects on the web, but they involve a fair bit of preparation ... also note the 'usual' Arduinos like UNO only have fairly slow analogue to digital converter provision ... so others like ESPs or Picos might be better.

Of course, identifying the suspect will not in itself fix the problem, but it would enable you to focus your attention in the right area ... and you can always ask a follow up question with your new evidence.

Good luck with your project, Dave


   
ReplyQuote
(@hilldweller)
Member
Joined: 1 year ago
Posts: 111
 

There is a standard algorithm for speed control, tried and tested, you need to look up Motor PID control. Basically it calculates how much power is needed to maintain speed based on the the last few seconds of movement. Just as if you were pushing a wheel barrow, you quickly work out how hard to push as you go up and down a gradient.

 

Search:  arduino motor PID


   
Ron reacted
ReplyQuote
Page 2 / 2