A light follower using the Velleman K8055 interfacing board

A simple light follower

Circuit diagram

The circuit diagram of this project is very simple - consisting of two LDRs and two 3k resistors - seen on the right outside the dashed box. In order to understand what follows, I have included the input circuitry of one of the two ADC channels. Notice that the 100k potentiometer will always be in the circuit and hence allows us to adjust the input voltage to the circuit. Notice also the broken link to the internal 5V line and the tap diverting  this voltage to the light sensing circuit.

The ADC input sectionFurthermore notice resistances R8  and R9. These two  components determine the gain of the input stages and Velleman supply two values with their kit.  It is vital that these resistors have the same value for both channels. If they don't this project won't work, as I found out after a long puzzled evening.

A word of warning here. The two internal potentiometers are still connected to the analogue inputs even when the internal link is disconnected. This affects the level of the ADC output. My program allows you to monitor the brightness of the surrounding. Adjust the top potentiometer for the best reading.

Also notice the red wire soldered to one side of a link connector and attached to one of the pins. This is a handy way of getting a 5V supply. But remember, this voltage comes from the USB port so treat the connection with respect - your computer is at the other end.

The projectThe two LDRs

On the right is my way of mounting the two LDRs. They need to point away from each other at a small angle, because the program works by turning the assembly in the direction of the sensor exposed to the brighter light.

I used bits and pieces from a Fischertechnik kit but other arrangements will do the job just as well. Make sure that the leads connected to the sensor head are long enough to wrap around the axle a few times. My software does not allow for very short leads!

The light follower projectOn the left is the complete project. The above sensor assembly is directly mounted to a stepper motor. The only other components needed are the two resistors for the light detection voltage divider. I picked a value of 3k, but this depends on the type of LDR used. The resistors are mounted on the small Vero board.

The outputs and the 0V line are connected to the ADC section of the K8055 Velleman interface board. Take care that the left sensor is connected to ADC1 and the right sensor to ADC2. If you get this wrong,  this project will turn out to be a light avoider, rather than a light follower!

The stepper motor is connected to the board via my higher current interface explained elsewhere in these pages. If your motor uses little current it can of course be connected directly. Additionally, my motor has a step angle of only 1.8 degrees, which is much smaller than most run-of-the-mill stepper motors can boast.

The program

To help set up the system, the program gives various adjustment options. Pressing 'A' will display the output of both ADC channels side by side. This makes it easy to adjust the output levels of the two channels so that they are more or less the same. This is done by adjusting the two potentiometers on the K8055. Either one should not be larger than the other by more than 1 or 2.

Pressing 'L' will produce one complete turn of the motor and print the light values measured to the screen. If you see a lot of 0s or 255s then there is something wrong. Either you turned the potentiometers too far in either direction or you are in total darkness or you live under a bright tropical sun. Readjusting the pots should fix the problem.

Pressing 'Z' or 'C' will turn the motor either left or right. Use this option if you find that the lead has wrapped itself around the shaft several times and is running out of slack.  Pressing 'S' will cause the program to perform one complete revolution and then reverse and point towards the brightest spot it has found. This duplicates my earlier light seeker project.

Finally comes the light follower option. After pressing 'F' and shining a moveable light towards the assembly, the motor should turn until it points towards that light. Moving the light left or right will make the motor turn in the same direction. This is done with the following few lines of basic:

  640   SYS K8055_ReadAnalogChannel%,1 TO ADC1%
  650   SYS K8055_ReadAnalogChannel%,2 TO ADC2%
  660   IF ADC1%<ADC2%+3 AND ADC1%<ADC2%-3 THEN
  670     Turn%-=1
  680     Coil%-=1 :IF Coil%<1 Coil%=4
  690     SYS K8055_WriteAllDigital%,FullStep%(Coil%)
  700     Key$=INKEY$(0)
  710   ENDIF
  720   IF ADC2%<ADC1%-3 AND ADC2%<ADC1%+3 THEN
  730     Turn%+=1
  740     Coil%+=1 :IF Coil%>4 Coil%=1
  750     SYS K8055_WriteAllDigital%,FullStep%(Coil%)
  760     Key$=INKEY$(0)
  770   ENDIF

Lines 640 and 650 read the two ADC channels and store their value in ADC1% and ADC2%.  Line 660 finds out whether ADC1% is smaller than ADC2% - with s tolerance of +/- 3. If it is, line 690 will turn the motor by one full step.

Lines 720 to 750 do the same thing in the other direction. If you do this project  and run into problems, drop me a line and I'll do my best to help.

As usual I supply a zip archive with the BBC BASIC for Windows listing and an executable file which will run the program even if you don't have BBC BASIC for Windows installed.


YouTube video of the project

Below is the same thing for the K8061


       10 REM Light follower
   20 REM For The Velleman K8055 USB interface
   30 REM Play with tow LDRs and a stepper motor
   40 REM Jochen Lueg
   50 REM http://roevalley.com/newsbrowser/v-projects/v-index.htm
   60 REM Version 1.1
   70 REM February 2012
  100 PROCK8055_init
  110 SYS K8055_CloseDevice%
  120 SYS K8055_OpenDevice%,0
  130 SYS K8055_ClearAllDigital%
  140 PROCinit
  150 PROCprintout
  170 REM Main loop
  180 REPEAT
  190   Key$=INKEY$(0) : REPEAT UNTIL INKEY(0)=-1
  200   IF Key$="a" OR Key$="A" PROCadjust
  210   IF Key$="l" OR Key$="L" PROClight_levels
  220   IF Key$="f" OR Key$="F" PROCfollow_light
  230   IF Key$="s" OR Key$="S" PROCbright_spot
  240   IF Key$="=" OR Key$="+" Dir$="Finished"
  250   IF Key$="h" OR Key$="H" Dir$="Halt"
  260   IF Key$="c" OR Key$="C"  THEN
  270     Coil%-=1:IF Coil%<1 Coil%=8
  280     SYS K8055_WriteAllDigital%,HalfStep%(Coil%)
  290   ENDIF
  300   IF Key$="z" OR Key$="Z" THEN
  310     Coil%+=1:IF Coil%>8 Coil%=1
  320     SYS K8055_WriteAllDigital%,HalfStep%(Coil%)
  330   ENDIF
  340 UNTIL Dir$="Finished"
  360 PRINTTAB(1,16)"All good things come to an end.                                     "
  370 SYS K8055_ClearAllDigital%
  380 SYS K8055_CloseDevice%
  390 REPEAT UNTIL INKEY(0)=-1 :REM Clear keyboard buffer
  400 END
  430 DEFPROCbright_spot
  440 LOCAL Bright%,B%
  450 Turn%=0
  460 Bright%=0
  470 FOR J%=1 TO 400
  480   SYS K8055_ReadAnalogChannel%,1 TO ADC1%
  490   SYS K8055_ReadAnalogChannel%,2 TO ADC2%
  500   B%=ADC1%+ADC2%
  510   IF Bright%<B% Bright%=B%:Turn%=J%
  520   Coil%+=1: IF Coil%>8 Coil%=1
  530   SYS K8055_WriteAllDigital%,HalfStep%(Coil%)
  540 NEXT
  550 FOR J%=1 TO Turn%
  560   Coil%-=1:IF Coil%<1 Coil%=8
  570   SYS K8055_WriteAllDigital%,HalfStep%(Coil%)
  580 NEXT
  590 SYS K8055_ClearAllDigital%
  620 DEFPROCfollow_light
  630 Turn%=0
  640 Rot%=0
  650 ADC1%=0
  660 ADC2%=0
  670 REPEAT
  680   SYS K8055_ReadAnalogChannel%,1 TO ADC1%
  690   SYS K8055_ReadAnalogChannel%,2 TO ADC2%
  700   IF ADC1%<ADC2%+3 AND ADC1%<ADC2%-3 THEN
  710     Turn%-=1
  720     Coil%-=1 :IF Coil%<1 Coil%=8
  730     SYS K8055_WriteAllDigital%,HalfStep%(Coil%)
  740     Key$=INKEY$(0)
  750   ENDIF
  760   IF ADC2%<ADC1%-3 AND ADC2%<ADC1%+3 THEN
  770     Turn%+=1
  780     Coil%+=1 :IF Coil%>8 Coil%=1
  790     SYS K8055_WriteAllDigital%,HalfStep%(Coil%)
  800     Key$=INKEY$(0)
  810   ENDIF
  820 UNTIL  Key$="h" OR Key$="H"
  840 SYS K8055_ClearAllDigital%
  880 DEFPROCadjust
  890 CLS
  900 REPEAT
  910   SYS K8055_ReadAnalogChannel%,1 TO ADC1%
  920   SYS K8055_ReadAnalogChannel%,2 TO ADC2%
  930   PRINTTAB(1,2) ADC1%,ADC2%
  940   PRINTTAB(1,4)"Press 'H' to return to the menu"
  950   Key$=INKEY$(10) : REPEAT UNTIL INKEY(0)=-1
  960 UNTIL Key$="h" OR Key$="H"
  970 PROCprintout


 1010 DEFPROClight_levels
 1020 Coil%=1
 1030 Turn%=0
 1040 ADC1%=0
 1050 ADC2=0
 1060 CLS
 1070 REPEAT
 1080   SYS K8055_WriteAllDigital%,HalfStep%(Coil%): FOR I%=1 TO T%:NEXT
 1090   Turn%+=1
 1100   Coil%+=1:IF Coil%>8 Coil%=1
 1110   SYS K8055_ReadAnalogChannel%,1 TO ADC1%
 1120   SYS K8055_ReadAnalogChannel%,2 TO ADC2%
 1130   PRINT;ADC1%;"   ";ADC2%;"   ";
 1140 UNTIL Turn%=400
 1150 SYS K8055_ClearAllDigital%
 1160 PRINT
 1170 PRINT
 1180 PRINT" Press 'H' to return to the menu"
 1190 REPEAT
 1200   Key$=INKEY$(20) : REPEAT UNTIL INKEY(0)=-1
 1210 UNTIL Key$="h" OR Key$="H"
 1220 PROCprintout

 1260 DEFPROCprintout
 1270 CLS
 1280 PRINT "You can do the following:"
 1290 PRINT
 1300 PRINT " Adjust input voltages    . . . . . .  A"
 1310 PRINT " Check light levels       . . . . . .  L"
 1320 PRINT " Find the brightest spot  . . . . . .  S"
 1340 PRINT " Follow light             . . . . . .  F"
 1350 PRINT " Turn left                . . . . . .  Z"
 1360 PRINT " Turn right               . . . . . .  C"
 1370 PRINT
 1380 PRINT " Return to menu           . . . . . .  H"
 1390 PRINT " Leave the program        . . . . . .  ="
 1450 DEFPROCinit
 1460 COLOUR 128
 1470 CLS
 1480 COLOUR 15
 1490 Coil%=1: REM Current operational stepper motor coil
 1500 Turn%=0: REM Position within 1 revolution %0 is one complete turn
 1510 Dir$="Halt"
 1530 DIM HalfStep%(8)
 1540 HalfStep%(1)=%00000011
 1550 HalfStep%(2)=%00001111
 1560 HalfStep%(3)=%00001100
 1570 HalfStep%(4)=%00111100
 1580 HalfStep%(5)=%00110000
 1590 HalfStep%(6)=%11110000
 1600 HalfStep%(7)=%11000000
 1610 HalfStep%(8)=%11000011
 1630 DIM FullStep%(4)
 1640 FullStep%(1)=%00000011
 1650 FullStep%(2)=%00001100
 1660 FullStep%(3)=%00110000
 1670 FullStep%(4)=%11000000
 1680 FOR J%=1 TO 4
 1690   SYS K8055_WriteAllDigital%,FullStep%(J%)
 1700 NEXT
 1710 SYS K8055_ClearAllDigital%
 1750 DEFPROCK8055_init
 1760 REM  Typing errors in routine name do not generate an error message - they just hang up the program.
 1770 REM These are all the system calls in the order found in the manual
 1780 SYS"LoadLibrary","K8055D.dll" TO K8055_Board%
 1790 SYS"GetProcAddress",K8055_Board%,"OpenDevice" TO K8055_OpenDevice%
 1800 SYS"GetProcAddress",K8055_Board%,"CloseDevice" TO K8055_CloseDevice%
 1810 SYS"GetProcAddress",K8055_Board%,"ReadAnalogChannel" TO K8055_ReadAnalogChannel%
 1820 SYS"GetProcAddress",K8055_Board%,"ReadAllAnalog" TO K8055_ReadAllAnalog%
 1830 SYS"GetProcAddress",K8055_Board%,"OutputAnalogChannel" TO K8055_OutputAnalogChannel%
 1840 SYS"GetProcAddress",K8055_Board%,"OutputAllAnalog" TO K8055_OutputAllAnalog%
 1850 SYS"GetProcAddress",K8055_Board%,"ClearAnalogChannel" TO K8055_ClearAnalogChannel%
 1860 SYS"GetProcAddress",K8055_Board%,"ClearAllAnalog" TO K8055_ClearAllAnalog
 1870 SYS"GetProcAddress",K8055_Board%,"SetAnalogChannel" TO K8055_SetAnalogChannel%
 1880 SYS"GetProcAddress",K8055_Board%,"SetAllAnalog"  TO K8055_SetAllAnalog%
 1890 SYS"GetProcAddress",K8055_Board%,"WriteAllDigital" TO K8055_WriteAllDigital%
 1900 SYS"GetProcAddress",K8055_Board%,"ClearDigitalChannel" TO K8055_ClearDigitalChannel%
 1910 SYS"GetProcAddress",K8055_Board%,"ClearAllDigital" TO K8055_ClearAllDigital%
 1920 SYS"GetProcAddress",K8055_Board%,"SetDigitalChannel" TO K8055_SetDigitalChannel%
 1930 SYS"GetProcAddress",K8055_Board%,"SetAllDigital"  TO K8055_SetAllDigital%
 1940 SYS"GetProcAddress",K8055_Board%,"ReadDigitalChannel" TO K8055_ReadDigitalChannel%
 1950 SYS"GetProcAddress",K8055_Board%,"ReadAllDigital"  TO K8055_ReadAllDigital%
 1960 SYS"GetProcAddress",K8055_Board%,"ResetCounter"  TO K8055_ResetCounter%
 1970 SYS"GetProcAddress",K8055_Board%,"ReadCounter"  TO K8055_ReadCounter%
 1980 SYS"GetProcAddress",K8055_Board%,"SedtCounterDebouceTime"  TO K8055_SetCounterDebounceTime%

Return to the interfacing index

Back to the Roe Valley index page
  Return sign