Speed control using a tacho generator and the K8055
I'm the first person to admit that this project is of
no practical use whatsoever. It was written to demonstrate the
principle and - surprisingly - it does this rather well. The basic idea
is simple and well known. A generator is driven by an electric motor .
As the voltage generated by the generator is proportional to the speed,
this can be used to control the speed of the motor. The aim of this
project was to let the motor turn with the same speed, no matter what
the load.
The rather archaic looking arrangement can be admired
on the left. The motor is at the front, driving the generator via two
equal sized cogwheels. |
|
![]() |
This set-up works rather well, but because the Velleman
K8055 board has a rather slow response time - each command takes 20ms
to execute - the system reacts rather ponderously to any change in
load. As a result the motor takes a few seconds to catch and even when
conditions do not change it tends to slowly change between a
top and a bottom speed. A contributing factor to this behaviour is the
fact that the ADC inputs have only an 8-bit resolution. However, as a
demonstration of the principles involved this behaviour is very
instructive.The programThe heart of the program are the lines below: 510
SYS K8055_ReadAnalogChannel%,2 TO V%
520 SYS "Sleep",40 530 IF State$="Running" THEN 540 IF V%< TargetVolt% PWM%-=1 :IF PWM%<0 PWM%=0 550 IF V%>TargetVolt% +1PWM%+=1 : IF PWM%>255 PWM%=255 560 SYS K8055_OutputAnalogChannel%,1,PWM% 570 SYS "Sleep",40 580 ENDIF Line 510 reads the voltage at the analogue to digital converter. Line 520 waits for this number to appear. I experimented with various values but this one seems to do the trick best. Lines 540 and 550 check that this value lies in between two points above and below the target value and increase the variable PWM% accordingly. This variable is the seed for the pulse width modulation generator on the K8055 board. This program and am executable file are in the archive below: K8055_speedcon.zip |
10 REM
K8055_Speed-con 20 REM Control one dc motor using pulse width modulation with the Velleman K8055 USB interface 30 REM Version 1.3 40 REM Jochen Lueg 50 REM http://roevalley.com 60 REM February 2012 70 80 90 PROCK8055_init 100 SYS K8055_CloseDevice%,0 110 SYS K8055_OpenDevice%, 0 120 ON ERROR PROCerror 130 140 PROCwindow(450,200) 150 SYS "SetWindowText",@hwnd%,"Tachogenerator Control with the K8055" 160 OFF 170 PWM%=255 180 TargetVolt%=60 190 State$="Stopped" 200 SYS K8055_OutputAnalogChannel%,1,PWM% 210 PRINT 220 PRINT " On - Off . . . . C - X" 230 PRINT " Faster - slower . . . . < - >" 240 PRINT 250 PRINT " Quit the program . . . . Q" 260 270 REPEAT 280 Key$=INKEY$(0) 290 REPEAT UNTIL INKEY(0)=-1 300 IF (Key$="c" OR Key$="C") AND State$ = "Stopped" PROCstart 310 IF (Key$="x" OR Key$="X") AND State$= "Running" PROCstop 320 REM Slower 330 IF Key$="," OR Key$="<" THEN 340 TargetVolt%-=1 :PWM%+=1 350 IF TargetVolt%<0 TargetVolt%=0 360 IF PWM%>255 PWM%=255 370 SYS K8055_OutputAnalogChannel%,1,PWM% 380 SYS "Sleep",22 390 REPEAT UNTIL INKEY(0)=-1 400 ENDIF 410 REM Faster 420 IF Key$="." OR Key$=">" THEN 430 TargetVolt%+=1:PWM-=1 440 IF TargetVolt%>255 TargetVolt%=255 450 IF PWM%<0 PWM%=0 460 SYS K8055_OutputAnalogChannel%,1,PWM% 470 SYS "Sleep",22 480 REPEAT UNTIL INKEY(0)=-1 490 ENDIF 500 REM Constant speed (or so they would have you believe) 510 SYS K8055_ReadAnalogChannel%,2 TO V% 520 SYS "Sleep",40 530 IF State$="Running" THEN 540 IF V%< TargetVolt% PWM%-=1 :IF PWM%<0 PWM%=0 550 IF V%>TargetVolt% +1PWM%+=1 : IF PWM%>255 PWM%=255 560 SYS K8055_OutputAnalogChannel%,1,PWM% 570 SYS "Sleep",40 580 ENDIF 590 PROCfeedback(PWM%,V%) 600 610 UNTIL Key$="q" OR Key$="Q" 620 PROCstop 630 SYS K8055_ClearAllDigital% 640 SYS K8055_OutputAnalogChannel%,1,255 650 SYS K8055_CloseDevice% 660 SYS "FreeLibrary",K8055_Board% 670 *QUIT 680 END 690 700 710 DEFPROCfeedback(pwm%,V%) 720 PRINTTAB(2,8)"PWM seed = ";pwm%;" ADC voltage = ";V%;" " 730 ENDPROC 740 750 760 DEFPROCstart 770 LOCAL CurrentVolt% 780 SYS K8055_SetDigitalChannel%,8 790 PWM%=180 800 REPEAT 810 SYS K8055_ReadAnalogChannel%,2 TO CurrentVolt% 820 SYS "Sleep",22 830 IF CurrentVolt%< TargetVolt% PWM%-=2 : IF PWM%<0 PWM%=0 840 IF CurrentVolt%>TargetVolt% PWM%+=2 850 SYS K8055_OutputAnalogChannel%,1,PWM% :IF PWM%>255 PWM%=255 860 SYS "Sleep",22 870 PROCfeedback(PWM%,CurrentVolt%) 880 UNTIL CurrentVolt%<TargetVolt%+3 AND CurrentVolt%>TargetVolt%-3 890 State$="Running" 900 ENDPROC 910 920 930 DEFPROCstop 940 FOR J%= PWM% TO 255 950 SYS K8055_OutputAnalogChannel%,1,J% 960 PROCfeedback(J%,0) 970 NEXT 980 SYS K8055_ClearDigitalChannel%,8 990 TargetVoltage%=0 1000 State$="Stopped" 1010 PWM%=255 1020 ENDPROC 1030 1040 1050 DEFPROCwindow(ScreenWidth%,ScreenHeight%) 1060 COLOUR 128 1070 CLS 1080 COLOUR 15 1090 SYS "SetWindowPos",@hwnd%,-1,0,0,ScreenWidth%,ScreenHeight%,0 1100 VDU 26 1110 ENDPROC 1120 1130 1140 DEFPROCerror 1150 PRINT REPORT$;" at line ";ERL : 1160 SYS K8055_ClearAllDigital%,1 1170 SYS K8055_ClearAllAnalog%,1 1180 SYS K8055_CloseDevice%,1 1190 SYS "FreeLibrary",K8055_Board% 1200 END 1210 ENDPROC 1220 1230 1240 DEFPROCK8055_init 1250 REM These are all the system calls in the order found in the manual 1260 SYS"LoadLibrary","K8055D.dll" TO K8055_Board% 1270 SYS"GetProcAddress",K8055_Board%,"OpenDevice" TO K8055_OpenDevice% 1280 SYS"GetProcAddress",K8055_Board%,"CloseDevice" TO K8055_CloseDevice% 1290 SYS"GetProcAddress",K8055_Board%,"ReadAnalogChannel" TO K8055_ReadAnalogChannel% 1300 SYS"GetProcAddress",K8055_Board%,"ReadAllAnalog" TO K8055_ReadAllAnalog% 1310 SYS"GetProcAddress",K8055_Board%,"OutputAnalogChannel" TO K8055_OutputAnalogChannel% 1320 SYS"GetProcAddress",K8055_Board%,"OutputAllAnalog" TO K8055_OutputAllAnalog% 1330 SYS"GetProcAddress",K8055_Board%,"ClearAnalogChannel" TO K8055_ClearAnalogChannel% 1340 SYS"GetProcAddress",K8055_Board%,"ClearAllAnalog" TO K8055_ClearAllAnalog% 1350 SYS"GetProcAddress",K8055_Board%,"SetAnalogChannel" TO K8055_SetAnalogChannel% 1360 SYS"GetProcAddress",K8055_Board%,"SetAllAnalog" TO K8055_SetAllAnalog% 1370 SYS"GetProcAddress",K8055_Board%,"WriteAllDigital" TO K8055_WriteAllDigital% 1380 SYS"GetProcAddress",K8055_Board%,"ClearDigitalChannel" TO K8055_ClearDigitalChannel% 1390 SYS"GetProcAddress",K8055_Board%,"ClearAllDigital" TO K8055_ClearAllDigital% 1400 SYS"GetProcAddress",K8055_Board%,"SetDigitalChannel" TO K8055_SetDigitalChannel% 1410 SYS"GetProcAddress",K8055_Board%,"SetAllDigital" TO K8055_SetAllDigital% 1420 SYS"GetProcAddress",K8055_Board%,"ReadDigitalChannel" TO K8055_ReadDigitalChannel% 1430 SYS"GetProcAddress",K8055_Board%,"ReadAllDigital" TO K8055_ReadAllDigital% 1440 SYS"GetProcAddress",K8055_Board%,"ResetCounter" TO K8055_ResetCounter% 1450 SYS"GetProcAddress",K8055_Board%,"ReadCounter" TO K8055_ReadCounter% 1460 SYS"GetProcAddress",K8055_Board%,"SedtCounterDebouceTime" TO K8055_SetCounterDebounceTime% 1470 ENDPROC |
Return
to the interfacing index Back to the Limavady home page ![]() |