DC motor speed control.

Billyde16

Member
Hi guys,
I have a small DC motor which I want to control the speed of using a 10K pot as an input.

I would normally go about this by using a 555 timer circuit, but we are in lockdown at the moment and I don’t have any on hand. My idea is to use the 14m2 that I have and PWM control to control the speed based on the value of my pot.

However this is where I need help as I wasn’t able to find any circuits with that setup.

The components I have available right now are... a 10k pot, various resistors, Picaxe 14m2, ULN2003A motor driver, Various NPN and PNP transistors, a few power diodes, an irfz44 mosfet and of course the small DC motor I am using.

I am planning to power the motor and Picaxe chip from a 3.7V Lipo battery.

If someone could suggest how I could make this work with a schematic and code that would be fantastic and much appreciated as I am a novice with Picaxe still.
Cheers
 

premelec

Senior Member
You might just try READADC from pot wiper and use that value to control PULSOUT length in a loop... put a capacitor in parallel with motor to reduce sparky stuff... and back connected diode across drive transistor - depending on size of motor and transistor [may not need any protection].
 

Buzby

Senior Member
Welcome to the forum !.

The circuits you need are in Manual 3 ( https://picaxe.com/docs/picaxe_manual3.pdf Output device 6 and Input device 2 )

The pot is wired like this : 24095

As the pot is rotated the voltage on the analogue pin varies from 0 to 5 volts. This voltage is read using a READADC command, which will return a value from 0 to 255.

Get this part working first, them move on to the motor.

The motor will be wired like this :24096

( Your IRFZ44 should work in place of the IRL520, and put a small value ceramic cap across the motor to reduce noise. )

Now you can control the motor with PWM, or PULSEOUT in a loop, as already mentioned.

Depending on the current draw of your motor, you might have issues driving both the motor and the PICAXE from the same 3.7v battery. Do your initial testing with a nice solid 5v supply, then change to the LiPo when you are sure the code is working OK.

Good Luck,

Buzby
 

Billyde16

Member
Welcome to the forum !.

The circuits you need are in Manual 3 ( https://picaxe.com/docs/picaxe_manual3.pdf Output device 6 and Input device 2 )

The pot is wired like this : View attachment 24095

As the pot is rotated the voltage on the analogue pin varies from 0 to 5 volts. This voltage is read using a READADC command, which will return a value from 0 to 255.

Get this part working first, them move on to the motor.

The motor will be wired like this :View attachment 24096

( Your IRFZ44 should work in place of the IRL520, and put a small value ceramic cap across the motor to reduce noise. )

Now you can control the motor with PWM, or PULSEOUT in a loop, as already mentioned.

Depending on the current draw of your motor, you might have issues driving both the motor and the PICAXE from the same 3.7v battery. Do your initial testing with a nice solid 5v supply, then change to the LiPo when you are sure the code is working OK.

Good Luck,

Buzby
Thanks heaps for the detailed explanation. I will try it out later and let you know how I get on.
Billy.
 

Billyde16

Member
Hi,
I have tested my speed control circuit with interesting results. Here is the circuit I built up including a ceramic cap (104) across the motor as Buzby suggested.

I am using a perfectly regulated 5V from a 8.4V Lipo through an LM7805 for my initial tests. I have got my 10K pot connected to C.0 and am using readadc to get a value of 0-255. I’ve tested this with a debug and it is working well.

I am also using pulsout to control my motor which is controlled by my IRFZ44N MOSFET on C.2. I have set the length of pulse to adc_C.0 and unit of pulse length to 1ms.

with this setup the motor is receiving about 4V and the speed does vary from very slow and gets a bit faster, but only reaches about half the speed it did before (when directly connected to my 3.7V Lipo battery.) It also has far less torque then before too. The current to the motor ranges from 2mA - 100mA depending on the position of the pot. I also noticed that the motor stops and starts a lot when on the faster end Before when connected to the 3.7V Lipo it would draw 200mA, with good torque.

If I remove the 5V supply and try connecting the 3.7V Lipo (actually about 4V) as originally planned, then the motor doesn’t turn at all. This surprised me given that I measured 3.3V at the motor so only about half a volt less than before. I also measured the current from this setup at 60mA.

This leaves me with a few questions...

Why is the current to the motor so much lower with this setup compared to the direct battery?

Is there a problem with my code?

Have I wired something wrong?

Is the a way so increase motor current/torque/speed? (Maybe adding a transistor array such as my ULN2003A driver)

What is causing the jerkiness of my motor at the faster end?

I have also included a shot of my code, using flowcharts as I’m still new and find it much more intuitive.

Sorry for all my annoying questions guys, this probably doesn’t make sense but you’re help is much appreciated.
Thanks,
Billy.
 

Buzby

Senior Member
Not sure if the images attached properly
They didn't !.

We need to see your code and circuit.

Just 'drag and drop' the .plf file from your local folder into the forum where you are editing your message.

You can do the same with image files.



24100
Cheers,

Buzby
 

Attachments

AllyCat

Senior Member
Hi,

IMHO it's better to show programs within [ code] [/code] tags, so that we can look at them immediately, or load them directly into the Simulator. However, you mention using PULSOUT (i.e. not setting up a PWMOUT channel), but also DEBUG. The DEBUG command takes a long time to execute when presumably there will be no pulses? Using SERTXD ... is generally far preferable to Debug, and the dedicated PWM hardware in preference to PULSOUTs.

Cheers, Alan.
 

AllyCat

Senior Member
Hi,

You should be able to delete the "corrupt" post #9.

However, I think you have an error in your code. You have PULSOUT C.2 , ADC_C.0 (it's a pain not being able to cut and paste directly from between code tags) ; I don't know what ADC_C.0 is supposed to do (I'm surprised it's not flagged as a syntax error) but I think you should be using PULSOUT C.2 , VarA .

Personally, I can see some advantages with "Blockly", but is that flow chart really any easier to understand than : ?
Code:
symbol VarA = b0   ; Optional, to make the variable as horrible/useless as in the flowchart.   :-)
do
   readadc c.0 , VarA
   pulsout  c.2 , VarA
loop
... especially as you could create a symbol rather more meaningful than "VarA" , and the flowchart compiles to program code twice the size of the Basic (23 versus 11 bytes).

EDIT: Hmm, it appears that the Readadc c.0 , VarA cell is unnecessary (not used) and the Pulsout c.2 , adc_c.0 cell expands to:
Code:
    readadc C.0, varTEMPBYTE3
    let varTEMPWORD1 = varTEMPBYTE3 * 100
    pulsout C.2, varTEMPWORD1
so each pulse might be as long as 255 ms (1/4 second). Is that really more intuitive?

Cheers, Alan.
 
Last edited:

Billyde16

Member
Hi,

You should be able to delete the "corrupt" post #9.

However, I think you have an error in your code. You have PULSOUT C.2 , ADC_C.0 (it's a pain not being able to cut and paste directly from between code tags) ; I don't know what ADC_C.0 is supposed to do (I'm surprised it's not flagged as a syntax error) but I think you should be using PULSOUT C.2 , VarA .

Personally, I can see some advantages with "Blockly", but is that flow chart really any easier to understand than : ?
Code:
symbol VarA = b1   ; Optional, to make the variable as horrible/useless as in the flowchart.   :-)
do
   readadc c.0 , VarA
   pulsout  c.2 , VarA
loop
... especially as you could create a symbol rather more meaningful than "VarA" , and the flowchart compiles to program code twice the size of the Basic (23 versus 11 bytes).

Cheers, Alan.
Just tried swapping ADC_C.0 for VarA but that works even worse. Motor barely rotates at all.
 

lbenson

Senior Member
Another issue which might or might not be a factor is that your IRFZ44N is not a "logic level" mosfet--full on at 5V--(the IRLZ44N +is+). Especially if you are using PWM or strings of PULSOUTs, the MOSFET may not reach full on and might both overheat and underpower.
 

Billyde16

Member
I know that FET isn't ideal, but its the only FET I had on hand. its attached to a heat sink and isn't getting hot to touch but you might be right about the under power issue. I guess the only way i'll know for sure is to get a different one. The schematic calls for an IRL520.
 

AllyCat

Senior Member
Hi,

Sorry, I didn't realise that you'd replied, I've recently edited my post at #11. I don't know if the FlowChart is able to "support" PWM outputs, but I doubt if that *100 is going to help the motor run smoothly. Certainly the FET shouldn't "get hot" at currents of less than 1A, what NPN transistors do you have?

Cheers, Alan.
 

Billyde16

Member
Hi,

Sorry, I didn't realise that you'd replied, I've recently edited my post at #11. I don't know if the FlowChart is able to "support" PWM outputs, but I doubt if that *100 is going to help the motor run smoothly. Certainly the FET shouldn't "get hot" at currents of less than 1A, what NPN transistors do you have?

Cheers, Alan.
What do you mean by flowchart not supporting PWM outputs?
The FET is not hot at all, but isn't logic level as pointed out before. I have a BD139, a BC550B, a BC547.

I was also able to find a 40n03gp MOSFET as well as a p60nf06 MOSFET if they are any better?

Don't know enough about semiconductors to know myself.

Thanks for the help.
 

AllyCat

Senior Member
Hi,

Apologies, I missed the "isn't" (getting hot).

You're likely to get better PWM motor control using the PWMOUT (hardware) command method rather than PULSOUT, but I don't know how (or if) that can be coded into the flowchart. A problem with these "assisted" methods of code generation is that some of the necessary "fine detail" is not available. It was only when I (accidentally) introduced an error into the flowchart that it listed the code that was being created, which showed that the PULSEOUT cell was reading an ADC value and multiplying it by 100 before generating a pulse. That makes the pulse width compatible with the PAUSE (1ms units), but is certainly not "intuitive".

One problem is that a variable pulse width cannot create PWM (pseudo-analogue) control without a complementary PAUSE period. The normal (Basic) PULSOUT command would give a pulse of 0 - 2.5 ms, with a "dead space" (Pause) of a few ms during the Readadc and closure of the loop. So that should at least give a predictable PWM duty cycle over a range from about 0 to 50 %. However, if the pulse is multiplied up to a range of 0 - 255 ms, then the duty cycle will be greater than 90% for all but the lowest 10% of the potentiometer range. If the motor is not turning rapidly, suggests that the FET is not driving it correctly:

Personally I "dislike" (through-hole) FETs in low-voltage circuits, because they often seem to need a higher gate voltage than expected. Even "Logic Level" normally refers to 5 volts, so they might struggle on a single 3.7 volt cell. Bipolar transistors do of course require a significant base current, but for a motor up to about 500 mA, I'd try the BD139 with a base resistor of about 330 ohms driven by a PICaxe output pin. Alternatively try the ULN2003A , but beware that Darlington drivers do always "lose" about a volt of drive from the supply rail. As for the Program, try the following compromise, until we can identify what can be done with the flowchart software (or we can persuade you to use the native programming language). ;)

Code:
do
   readadc c.0 , b0
   w1 = b0 * 10
   pulsout  c.2 , w1   ; A pulse of up to 25 ms
   w1 = 2550 - w1
   pause w1            ; A gap (pause) down from 25 ms
loop
Cheers, Alan.
 

Billyde16

Member
Hi,

Apologies, I missed the "isn't" (getting hot).

You're likely to get better PWM motor control using the PWMOUT (hardware) command method rather than PULSOUT, but I don't know how (or if) that can be coded into the flowchart. A problem with these "assisted" methods of code generation is that some of the necessary "fine detail" is not available. It was only when I (accidentally) introduced an error into the flowchart that it listed the code that was being created, which showed that the PULSEOUT cell was reading an ADC value and multiplying it by 100 before generating a pulse. That makes the pulse width compatible with the PAUSE (1ms units), but is certainly not "intuitive".

One problem is that a variable pulse width cannot create PWM (pseudo-analogue) control without a complementary PAUSE period. The normal (Basic) PULSOUT command would give a pulse of 0 - 2.5 ms, with a "dead space" (Pause) of a few ms during the Readadc and closure of the loop. So that should at least give a predictable PWM duty cycle over a range from about 0 to 50 %. However, if the pulse is multiplied up to a range of 0 - 255 ms, then the duty cycle will be greater than 90% for all but the lowest 10% of the potentiometer range. If the motor is not turning rapidly, suggests that the FET is not driving it correctly:

Personally I "dislike" (through-hole) FETs in low-voltage circuits, because they often seem to need a higher gate voltage than expected. Even "Logic Level" normally refers to 5 volts, so they might struggle on a single 3.7 volt cell. Bipolar transistors do of course require a significant base current, but for a motor up to about 500 mA, I'd try the BD139 with a base resistor of about 330 ohms driven by a PICaxe output pin. Alternatively try the ULN2003A , but beware that Darlington drivers do always "lose" about a volt of drive from the supply rail. As for the Program, try the following compromise, until we can identify what can be done with the flowchart software (or we can persuade you to use the native programming language). ;)

Code:
do
   readadc c.0 , b0
   w1 = b0 * 10
   pulsout  c.2 , w1   ; A pulse of up to 25 ms
   w1 = 2550 - w1
   pause w1            ; A gap (pause) down from 25 ms
loop
Cheers, Alan.
Hello Alan,
I have the BD139 (in place of the FET) with a 330ohm R on the base as you suggested. Along with the code you supplied. Again I have some interesting results to share.

First off your code in combination with the IRFZ44N didn't work at all, howeve once I swapped the FET for a BD139 it worked quite well. When using my 5V supply the motor was getting 4V at its peak and aroud 100mA which gave it much more talk than my first setup. It would appear that the speed drops down quite quickly in the 1st quarter turn of the pot and then decreases much more gradually over the remaining turn. (I don't know what is causing that or if there is a way to correct for it?)

Next I switched over to my 3.7V (actually around 4V) lipo cell and to my suprise that also worked well, with very similar performace. Interestingly I recored the max voltage to the motor to be 3.5 volt, so the is only a half volt drop with the Lipo Vs a 1V drop with the 5V supply.

A final thing I noticed is that the connection to the pot seemed a bit dodgy because the speed wasn't stable unless it squeezed it slightly. I tried new wires and a new pot but it did the same thing. (they are probably just badly made)

I think with this setup I might actually have enought torque for the project, its really just the non linear speed changing thing now.
Cheers.
 

AllyCat

Senior Member
Hi,

It looks as if the FET had too high a threshold voltage, there may be better ones available, but for a few hundred mA from a 3.7 volt battery, I'd stay with Bipolar transistors. BC are "low power" and BD "medium power" which is why I chose the 139 (and I have used them occasionally). It's not a great transistor (even the BD131 is a little better) but should be good enough up to about 200 mA, with 10 mA base current. My 330 ohms was a little cautious, you could probably drop the base resistance to 150 or 100 ohms to see if it helps. Ohms Law will tell you the base current, but remember the base voltage is around 700 mV above ground (0v) and the PICaxe output stage will drop at least that much again down from the supply rail.

You do have a diode connected from the motor/transistor junction up to the supply rail? That's quite important for PWM. Are you measuring the voltage directly across the motor? Note that when the transistor is off (i.e. the "pause" period), there is a small reverse voltage across the motor (~ 700 mV) which will lower the average voltage being measured across the motor.

For testing, it's worthwhile to put a SERTXD (#b0," ") (or whatever variable is read from the Pot / ADC) to check what value is actually being read. Ask if you need more of an explanation about this. But note that this will add to the "dead time" of the PWM output which will reduce the motor drive (but not as much as the DEBUG command). You could also add or change the SERTXD to report the pulse/gap widths, etc., that are being generated.

The "normal" way to use PWM is at fixed frequency, which is why my program introduced and reduces the pause period when the pulse period increases. However, the overall pause cannot be reduced to zero, because there is always the "dead time" of the other instructions in the program loop. There must be a compromise with PULSOUT, the narrower we make the pulse, the proportionally longer is the off/space time, but the longer the pulse, the lower the frequency becomes. The ADC byte value * 10 seemed about right, but you could try * 5 or * 20 (but the zero pulse starting values would become 1275 or 5100). You could also reduce the dead time (or increase the frequency) with for example a SETFREQ M16.

However, the best way to get a full range of speeds is to use the on-chip hardware, controlled by the PWMSETUP and PWMOUT commands, but it is rather more complex and can be used only on certain pins. The advantage is that it is a "background" process, so you can add much more program code (e.g. READADC and SERTXD reports) without affecting the actual duty cycle of the PWM.

If you're happy to continue programming the PICaxe from Basic, then we can suggest some more features, but I'm afraid that the possibiities with the flowchart might be quite limited (if only because most of us never use it).

Cheers, Alan.
 

Billyde16

Member
Hi again, I have swapped the base R for a 100ohm and that’s working fine. To answer you’re question, yes I was measuring the voltage directly across the motor.

You will have to forgive me as some of your code suggestions are going over my head, but yes I’m open to learning some basic.

another thing I thought I’d mention is that I found a small ESC unit for brushed motors (these are normally used in radio control cars). I thought there might be someway to control it using the Picaxe and my pot, as I believe they too operate off PWM. I’ve seen some vids on how to control them using Arduino but haven’t got it working on the Picaxe yet. Just thought it might be a good way of doing it?

Thanks,
Billy.
 

AllyCat

Senior Member
Hi,

Yes, you should be able to control the ESC from a PICaxe, but it uses a "different type" of PWM. So far, you have been directly controlling the power applied to the motor by effectively reducing the average voltage (by switching it ON and OFF quickly). However, the ESC will probably have a separate power connection directly to the battery (Supply and Earth) and the PICaxe will only signal the required speed by the width of a pulse on a third wire. That is done by the SERVO pin , value command, which sends quite a narrow pulse (around 1.5 ms) once every 20ms to indicate how (far) the "servo motor" should drive forwards or backwards (or in the case of an ESC, how fast). The pulses are quite narrow so that a sequence of them can be sent over the same radio channel with the pulses being distributed in sequence to the various Servos and/or ESCs, in a repeating cycle of 20ms.

The SERVO command (like the PWMSETUP / PWMOUT commands that I described earlier is a "background" or automatic task, you only need to issue the instruction once and the PICaxe will continue to send the pulses until you instruct it to change or stop. In the case of an ESC, you might set the pulse to a value around 150 (1.5ms = "in between forwards and backwards") or actually turn the pulse off (SERVO pin , OFF).

Most of the commands I've discussed can be found from the PICAXE > BASIC Commands link at the top of this forum page, for example this one. Normally you would put them in a "polling loop" to repatedly read ADC (Pot) values and generate pulse widths, but the polling speed is not critical.

Cheers, Alan.
 

Eng460

Well-known member
In a radio control system, the ESC plugs into the receiver in the same way as any other servo, as Alan has described. The transmitter and receiver do not know or care whether they are controlling a servo or an ESC or other device, so just use the standard servo controls, and use the Picaxe program to calculate and modify the pulse length you want for the speed required, instead of the radio control system. The ESC does have a separate connection to a battery to power the motor, and many then also include an internal voltage regulator (or battery eliminator circuit) to get the five volt receiver supply. This eliminates the receiver battery, an important weight saving function in a flying model, or space saving in model cars and boats. I don’t know if this is sufficiently close to that required for a Picaxe, you would have to measure it.

So the project then reduces to three steps, read ADC to get a desired speed input, some basic maths (of the Picaxe integer type) to change the figure received by Readadc to the pulse length required by the servo command, and finally use the servo and servopos commands to control the ESC. You may need to experiment to find the minimum pulse length that will allow the motor to run, as it will likely over heat if you leave it sitting with a short a duty cycle that is too short to allow it to run. The servo command requires a number between 75 and 225 (and hence what the ESC is expecting) to determine the servo position so only 150 possible integer number inputs so you don’t need the finer resolution of the readadc10 command. You may only need say 120 to 225 to run the motor. Use pwm pin, off followed by pin high or low to run full speed or stop.

If you need reverse, it may be best to follow the examples in section 3 which use relays, although if you are up for some heavy reading, the hpwm commands can handle forward and reverse on each of two separate motors, but it is definitely more complex, and probably kept as a second stage of your project development after you have the pwmduty and pwmout commands working.

Like others, I don’t use the flow sheets, but looking through the manual, it only has “pseudo pwm” command which works in short bursts. It does not support the pwmout and duty commands which will run your motor continuously in the background while the program works on in its own time. If you use the pwmout and pwmduty commands programmed in basic, you won’t need the ESC.

Using pulse out means you have to maintain a continuous steam of pulses with appropriate gaps between and I suggest a much more difficult way to go, unless you have some special requirements that can’t be handled with pwmout and pwmduty. I always prefer to start simple and try the commands in section 2 as they seem to be intended. You can always try more advanced techniques later if you run into a limitation.

Eng460
 
Top