Introduction: Electronic Motor Control Using Optical Pick Up.

The first instructable I did was the build of a really nice DC motor. This is kind of a second part. It adds electronic control of the motor and gets rid of the brush and cam which limit the original motor.

Basically the design uses a slotted disc and an optical pickup to measure the time then depending on the pots adjusts the magnet timing and duration using a logic level mosfet to switch the magnet.

Simple really!!!

Step 1: PCB Build and Components List.

So the main part of this modification to the original build is the PCB with a MicroChip PIC12F675 at its heart.

It took a few revisions to get to the final PCB you see in the pictures here. The design features power supply from a deans plug like before but this time there is a 5Volt regulator to supply the PIC. The PIC receives the pulse from the slotted disc via an optical slot detector. this pulse is then timed and the POT's read before working out when to turn on the magnet and for how long. the magnet is the same as before but this time it is turned on by a logic level mosfet. Two LED's show the presence of 5Volts and indicate when the magnet is turned on.

I am going to do another Instructable about making PCB's but it really isn't that hard to do at home.

Step 2: Fitting It All Together.

So let’s look at the difference from this motor to the original. Firstly the original cam and brush assembly is removed. And the rear shaft support replaced for a different design which has a mount for the optical pickup. The cam is replaced for a disc which has 4 slots cut using a junior hacksaw. So with these new bit you can then detect the time of each section. The really clever bit is the PIC 12F675 which is the brains behind the measuring and control. The rest of the original motor is left untouched, however it is worth noting that the new slotted disc is aligned on the shaft so the slots

Step 3: The Program.

This took a bit of head scratching the most obvious method would be simply to detect the slot then wait a certain TIME then turn the magnet on for another TIME then off then wait for the next slot. But that wasn’t going to work very well because the time changes depending on the speed. SO the method I used was to measure the time then use fractions of the time for the delay and magnet on.

So the programs runs basically like this:-

Wait for a low pulse

Start the tmr1

Wait for a high pulse

Wait for the low pulse again

Stop the tmr1

At this point you need to check if the TMR1 overflowed and if it did start again from the beginning. (flic the rotor faster!) If the pulse was within the 16bit tmr range then the program continues.

The TMR1 value is stored as delay_time (only the 8MSB meaning the value is divided by 256)

The TMR1 is reset and started again

The delay_timing is run depending on the value of the delay pot (scaled to 0-31) multiplied by the delay_time

Then the magnet is turned on

Then the delay_on2 is run depending on the magnet pot (scaled to 0-31) multiplied by the delay_time.

Once the timing delay has completed the magnet turns off.

The Pots are read ready for the next cycle.

Then you wait for the next low pulse and start the cycle again.

The A/D conversion is a 10bit conversion with 8 bits held in one register and the other 2 held in another. You choose where to justify left or right and in my case I chose to only bother with the 8 MSB and ignore the 2 LSB, so in affect I am only reading a 8 bit number. This 8 bit number is then file rotated 3 times to reduce the result to 0 – 31.

10 bit = 0000000000 - 111111111 = 0 – 1023

8 bit = 00000000 – 11111111 = 0 – 255

5 bit = 00000 – 11111 = 0 – 31

Step 4: The Three Adjustments.

You can see in the photos that there are three pot to adjust. The first POT(red) adjusts the pulse duration, if you want more speed and power then you give the motor more pulse. You can see the effect on the Green LED as it will be brighter with more pulse. the Blue pot adjust the timing of when the pulse happens, if you have a small pulse then you need to time it correctly or the motor will stop. if you have a large pulse then the timing has to be correct to stop the magnet being on when the rotor passes it. these two adjustments are the same as rotating the cam for the timing and increasing the tension to increase the pulse duration.

The Last POT (yellow) is what i call a "Hit N' Miss" governor, this was inspired by old stationary engine you sometimes see at steam rallies. these engines have a centrifugal governor when the weights are thrown out and they operate a lever which stops the exhaust valve shutting, then on the next few strokes the engine will just pull in fresh air and then pump it out again and only when the speed has reduced will the exhaust valve shut and the cycle contine. So my circuit looks for a time which is so fast and waits for it to slow down. (fast speed = short time, slow speed = long time) this is adjusted by the Yellow POT.

Step 5: Loading the Program and the Full Listing.

The Program is written in BASIC using MikroElektronika programming environment. You can download this software for free but are limited by the program length. This program is under the maximum length so works fine. But i don't use the MikroElekronika software to load the hex file to the PIC instead i use a small USB programmer from PICCIRCUIT and this connects onto the pins where the POTs connect on the PCB meaning i can program the PIC chip in circuit. The program i use is the PICkit 2 v2.55 program which is also free to download. What is nice about doing it this way is that you can test out different programs without having to remove the chip from the PCB.

program motor
symbol input_pulse = GPIO.4
symbol start_timer1 = T1CON.TMR1ON = 1
symbol stop_timer1 = T1CON.TMR1ON = 0
symbol timer1_flag = PIR1.TMR1IF
symbol timer0_flag = INTCON.T0IF
symbol magnet_on = GPIO.5 = 1
symbol magnet_off = GPIO.5 = 0
dim delay_time as byte
pot01 as byte
pot02 as byte
pot03 as byte
count as byte
tmr1 as word absolute $0e

sub procedure init
trisio = %00010111 'set input/output 1 = input 0 = output
ansel = %00000111 'set digital or analog 1 = analog 0 = digital
OSCCAL = OSCCAL '
ASM '
bsf STATUS,RP0 '
call 0x3ff '
movwf OSCCAL '
bcf STATUS,RP0 '
END ASM '
cmcon = %00000111 '
t1con = %00000000 '
PIE1.TMR1IE = 1 'tmr1_enable = PIE1.TMR1IE
PIR1.TMR1IF = 0 'tmr1_flag = PIR1.TMR1IF
INTCON.T0IE = 1 'tmr0_enable = INTCON.T0IE
magnet_off '
end sub '
'
sub procedure ad_adquire (dim ad_channel as byte) '
adcon0 = (ad_channel) '
delay_us(20) '
adcon0.1 = 1 'start conversion
lup14: '
if adcon0.1 = 1 then goto lup14 '
end if '
end sub '
'
sub procedure get_ad '
ad_adquire (%00000001) 'AD0 pin 7
pot03 = 255 - adresh  'divide by 32 (from 10bit) value range 0-31
ad_adquire (%00000101) 'AD1 pin 6
pot02 = adresh >>2 'divide by 32 (from 10bit) value range 0-31
ad_adquire (%00001001) 'AD2 pin 5
pot01 = adresh >>3 '8 Bit only
end sub '
sub procedure first_pulse '
magnet_off '
stop_timer1 '
tmr1 = 0 '
lup03: '
if input_pulse = 1 then goto lup03 'check if input pulse is high
end if 'and if it is loop until it goes low
start_timer1 'once it goes low start tmr1
lup04: '
if input_pulse = 0 then goto lup04 'now loop whilst the input pulse is low
end if 'which wont be long as its the gap
lup05: '
if input_pulse = 1 then goto lup05 'now loop until the pulse stops being high
end if '
stop_timer1 'now low again so stop tmr1
end sub '
'
sub procedure set_tmr0(dim option_val as byte) 'this is a timing loop based on the tmr0
tmr0 = 0 'firstly set the timer to zero
timer0_flag = 0 'reset the flag
tmr0 = 255 - delay_time 'load a value into the timer based on max value - delay
option_reg = (option_val) 'set the timer pre scaler
lup26: 'then loop untill the timer overflows
if timer0_flag = 1 then timer0_flag = 0 'and return to the main program
else goto lup26 '
end if '
end sub '

sub procedure delay_timing 'start with a fixed delay time
'set_tmr0(%00000101) 'run the timer with a pre scaler of 1:64
set_tmr0(%00000110) 'run the timer with a pre scaler of 1:32?
count = 0 'reset the counter
lup28: 'Pot02 is pin 6
if count = pot02 then goto lup30 'check if the counter has reached the value of the
end if 'timing pot which has a range from 0 - 31
set_tmr0(%00000000) 'run the timer with a pre scaler of 1:2
count = count + 1 'increment the counter
goto lup28 'loop back to check the value against the pot
lup30: 'and return if the pot value has been reached
end sub '
'
sub procedure delay_on2 'start with a fixed delay time
set_tmr0(%00000011) 'run the timer with a pre scaler of 1:16
count = 0 'reset the counter
lup18: '
if count = pot01 then goto lup20 'check if the counter has reached the value of the
end if 'timing pot which has a range from 0 - 31
set_tmr0(%00000000) 'run the timer with a pre scaler of 1:2
count = count + 1 'increment the counter
goto lup18 'loop back to check the value against the pot
lup20: 'and return if the pot value has been reached
end sub '

main: '
init '
start: '
first_pulse '
if timer1_flag = 1 then timer1_flag = 0 'check if TMR1 has overflowed and if it has
goto start 'reset the flag and return to the start
end if 'first pulse was to slow start again.
lup07: '
delay_time = tmr1h 'delay_time is only the 8 most significate bits of the 16 bit timer
tmr1 = 0 'meaning that its divided by 256
start_timer1 'restart the tmr1 for the next 1/4 rev
if delay_time < pot03 then 'speed limit section
goto lup08 'skip the magnet on section if speed to high
end if '
delay_timing '
magnet_on '
delay_on2 '
magnet_off '
lup08: '
get_ad '
if timer1_flag = 1 then timer1_flag = 0 'check wether the time is too slow and tmr1 has overflowed
goto start 'go back to the start is pulse is to low
end if '
if input_pulse = 1 then goto lup08 'loop whilst the pulse is still high
end if '
stop_timer1 '
goto lup07 '
end. '

Comments

author
Omnivent (author)2016-10-02

Hi,

Extremely nice and well written instructable!

A small FYI. Do _not_ use thermals on the PCB's flood fills for hand soldered jobs, they were only "invented" for machine soldered (e.g. wave soldered) PCBs to assure good joints (when hand soldering, you just use a bit more time on the joints with a large (cooling) copper area to get it done and the thermals represent a higher impedance (albeit not of much consequence in this particular project), so it's a good habit to avoid them when possible.

Regards

author
russ_hensel (author)2016-09-27

See if you can use this:

https://www.instructables.com/id/Put-Your-Code-in-a...

You may need to be a pro ( if so the folks at instructables should fix it ).

author
mr_fid (author)russ_hensel2016-09-27

Thanks for that handy hint, i have given it a go. Mind you my programming skills are very poor anyway! but at least i did comment this program.

author
russ_hensel (author)2016-09-27

hey Instructables feature this!

About This Instructable

3,280views

50favorites

License:

Bio: I love making things. I have for as long as I can remember liked to make stuff. Now days I have two kids (Thomas and ... More »
More by mr_fid:HoverboardSignal Generator Build.Arduino Rotary Switch One Analogue Input
Add instructable to: