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.

The strange object at the back sporting a propeller is simply a load which can be tipped out of the way. In theory this should make the motor turn faster, because there is less work to do. The control program must detect this and reduce the speed to its previous value. The motor is connected to my single motor PWM module described elsewhere. This is controlled by the PWM1 output of the Velleman K8055 board. The output of the generator is connected to the ADC2 input of the K8055 board. A 1000F parallel capacitor smoothes the output of the generator to an acceptable DC level. There is also a 1k resistor in parallel with the capacitor as a load. The small circuit board containing those components can be seen on the bottom right of the photograph below.  Please note that the ADC input should be set to 5V. This means that the link SK3 is removed, resistor R9 is not fitted and the potentiometer ATT2 is turned clockwise all the way. Not doing these things causes some strange behaviour of the set-up.

The tacho generator project

Circuit diagram
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 program

The 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:


Here is a video of the project

   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
   90 PROCK8055_init
  100 SYS K8055_CloseDevice%,0
  110 SYS K8055_OpenDevice%, 0
  120 ON ERROR PROCerror
  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"
  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)
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%)
  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
  710 DEFPROCfeedback(pwm%,V%)
  720 PRINTTAB(2,8)"PWM seed = ";pwm%;"      ADC voltage = ";V%;"   "
  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"
  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
 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
 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
 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

Tudor with sign