'Declarations symbol pwm_max = w3 symbol rpm_delta = w4 symbol rpm_ave = w5 symbol rpm_set = w6 symbol tach_in = w7 symbol tach_ave = w8 symbol tach_delta = w9 symbol rpm_tach_delta = w10 symbol pwm_value = w11 symbol current_in = w12 symbol current_ave = w13 symbol current_delta = w14 symbol baud = N4800_32 'communication with OLED module reprogrammed for 32MHz init: rpm_set=0 rpm_ave=0 tach_in=0 tach_delta=0 let b0=0 low B.7 ' switch-off motor supply relay setfreq m32 'set internal frequency at 32MHz pwmout C.5, 255, 0 'set 31.3kHz PWM at pin 5 at zero (100% value = 1023) pause 4000 serout B.2,baud,(254,1) ' clear OLED display pause 1000 main: readadc10 B.1, rpm_set 'rpm input reading rpm_set = rpm_set*62/21 'make rmp_set 3023rpm at 1024 input 'average the rpm_set reading (not too much to avoid reading lag if rpm_set > rpm_ave then rpm_delta=rpm_set-rpm_ave rpm_delta=rpm_delta/2 rpm_ave=rpm_ave+rpm_delta endif if rpm_set < rpm_ave then rpm_delta=rpm_ave-rpm_set rpm_delta=rpm_delta/2 rpm_ave=rpm_ave-rpm_delta endif pwm_max = rpm_set*21/62+400 max 1020 ' calculate dynamic max value of pwm based on speed setting if pinB.6=0 then ' check if on-off switch is OFF pwmduty C.5,0 'pwm output at zero low B.7 ' switch-off motor supply relay tach_delta=0 tach_ave=0 current_ave=0 pwm_value=0 let b0=0 serout B.2,baud,(254,128) serout B.2,baud,("STOPPED ") serout B.2,baud,(254,192) serout B.2,baud,("RPM SET:") serout B.2,baud,(254,200) serout B.2,baud,(#rpm_ave," ") 'show the RPM set value goto main endif if rpm_set < 2 then ' check whether rpm setting is below minimum threshold low B.7 ' switch-off motor relay pwmduty C.5,0 'pwm output at zero tach_delta=0 tach_ave=0 current_ave=0 pwm_value=0 let b0=0 serout B.2,baud,(254,128) serout B.2,baud,("STOPPED ") serout B.2,baud,(254,192) serout B.2,baud,("INCR RPM ") 'warning message that RPM setting is too low goto main endif high B.7 'switch-on motor supply relay count C.3, 16, tach_in 'tacho reading 2msec gives 50 counts max tach_in=tach_in*60 ' make 50 counts = 3000 rpm 'average tach reading if tach_in > tach_ave then tach_delta=tach_in-tach_ave tach_delta=tach_delta/5 tach_ave=tach_ave+tach_delta endif if tach_in < tach_ave then tach_delta=tach_ave-tach_in tach_delta=tach_delta/5 tach_ave=tach_ave-tach_delta endif readadc10 B.0, current_in 'current input reading current_in=current_in*25/256 'make 100% at 1024 input 'average current reading if current_in > current_ave then current_delta=current_in-current_ave current_delta=current_delta/5 current_ave=current_ave+current_delta endif if current_in < current_ave then current_delta=current_ave-current_in current_delta=current_delta/5 current_ave=current_ave-current_delta endif 'calculate error between rpm and tach input if rpm_ave > tach_in then rpm_tach_delta=rpm_ave-tach_in rpm_tach_delta=rpm_tach_delta/15 max 10 'set max value to get soft-start pwm_value=pwm_value+rpm_tach_delta max pwm_max ' avoid too high duty-cycles endif if tach_in > rpm_ave then rpm_tach_delta=tach_in-rpm_ave rpm_tach_delta=rpm_tach_delta/15 max 10 'set max value to get soft-start pwm_value=pwm_value min rpm_tach_delta - rpm_tach_delta min 1 ' avoid underflow when motor is turned at zero rpm_set endif 'sertxd(#rpm_ave," ",#tach_in," ",#pwm_value," ",#tach_ave," ",#current_ave,13,10) if current_ave > 90 then overcurrent 'trigger overcurrent protection at ~18Amp if tach_ave < 4 and current_ave > 40 then stall 'trigger stall protection when RPM is too low at ~5Amp pwmduty C.5, pwm_value 'pwm output b0=b0+1 if b0=20 then 'send display every 10 cycles serout B.2,baud,(254,128) serout B.2,baud,("RUNNING~") serout B.2,baud,(254,192) serout B.2,baud,("RPM:") serout B.2,baud,(254,196) serout B.2,baud,(#tach_ave," ") ' display average RPM serout B.2,baud,(254,201) serout B.2,baud,("TORQ:") serout B.2,baud,(254,206) serout B.2,baud,(#current_ave," ") ' display average current b0=0 endif goto main overcurrent: pwmduty C.5,0 low B.7 ' switch-off motor supply relay serout B.2,baud,(254,128) serout B.2,baud,("Overcurrent") tach_delta=0 tach_ave=0 current_ave=0 pwm_value=0 if pinB.6=1 then overcurrent 'keep in this state until switch is in stop position goto main stall: pwmduty C.5,0 low B.7 ' switch-off motor supply relay serout B.2,baud,(254,128) serout B.2,baud,("Stall ") tach_delta=0 tach_ave=0 current_ave=0 pwm_value=0 if pinB.6=1 then stall 'keep in this state until switch is in stop position goto main