- 1. A learning experience
- 2. For the fun of it
- 3. To develop the software, sensing technique, and mechanical considerations that will be used when constructing a much larger one.
Code:
'************************************************* ***************************** '* Name : SOLAR_TRACKER.BAS * '* A SMALL SOLAR TRACKER / CHARGER FOR CHARGING NiMh BATTERIES * * '* Author : KEN STUEMPGES * '* Date : 7/11/2011 * '* Version : 1.0 * '* Notes : MY VERSION OF A PIC - BASED SOLAR TRACKER * '* IT USES A PIC 16F876A (CAUSE I HAVE LOTS OF THEM). THE SENSORS * '* ARE 10 MM CLEAR LENSE GREEN LED'S. THE ONES I USED WILL * '* OUTPUT AS MUCH AS 1.6 VOLTS IN FULL SUNLIGHT. * '* I USED A SERIAL LCD BACKPAK FOR TROUBLESHOOTING PURPOSES * '************************************************* ***************************** ' ' INCLUDE "DT_INTS-14.bas" INCLUDE "ReEnterPBP.bas" ' DEFINE OSC 4 DEFINE ADC_BITS 10 DEFINE ADC_CLOCK 3 DEFINE ADC_SAMPLEUS 100 ' ADCON1 = 000010 ' RIGHT JUSTIFY TRISC = 001111 TRISA = 111111 TRISB = 110000 ' wsave var byte $70 SYSTEM east var word ' EAST FACING LED, CATHODE TO GROUND, ANODE TO A.0 west var word ' WEST FACING LED, CATHODE TO GROUND, ANODE TO A.1 DIFFERENCE VAR WORD ' used in LCD routine for testing X var WORD ' counter for delay time between readings CHK_POSITION VAR Bit ' TELLS US WHEN TO SAMPLE VIA TIMER INTERRUPT LS_ERROR VAR byte ' TRAVEL LIMIT SWITCH HAS BEEN CLOSED volts1 var word ' used to calculate actual voltage in MV volts2 var word ' ditto conv1 con 4 ' units result of 5000/1024 conv2 con 88 ' hundreths result of 5000/1024 ' EnableMotor var PORTB.2 ' Enables H-Bridge driver RotateWest var PORTB.1 ' H-Bridge input to Rotate motor toward west RotateEast VAR PORTC.6 ' H-Bridge input to Rotate Motor toward east GoWest var PORTC.0 ' Toggle switch to rotate panel west GoEast var PORTC.1 ' Toggle switch to rotate panel east StopWest var PORTC.2 ' Limit Switch to stop West rotation StopEast var PORTC.3 ' Limit Switch to stop East rotation Tx var PORTC.4 ' TRANSMIT TO SERIAL LCD BACKPAK ' EnableMotor = 0 RotateWest = 0 RotateEast = 0 CHK_POSITION = 0 x = 0 LS_ERROR = 0 ' ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler TMR1_INT, _TIME_COUNTER, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM ' T1CON = $31 ; Prescaler = 8, TMR1ON @ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts '********************** goto main '************************************************* ************** '************************************************* ************* '' MoveEast: ' move off travel limit switch @ INT_DISABLE TMR1_INT ' DISABLE TIMER1 INTERRUPT WHILE MOVING while stopwest = 0 'LIMIT SWITCH CLOSED ? EnableMotor = 1 RotateEast = 1 ' MOVE PANEL OFF LIMIT SWITCH wend pause 8000 ' move panel until it is nearly parallel with earth eNABLEmOTOR = 0 rOTATEEast = 0 @ INT_ENABLE TMR1_INT RETURN MoveWest: ' MOVE OFF TRAVEL LIMIT SWITCH @ INT_DISABLE TMR1_INT ' DISABLE TIMER1 INTERRUPT WHILE MOVING while stopeast = 0 ' LIMIT SWITCH CLOSED ? EnableMotor = 1 RotateWest = 1 wend pause 8000 'move panel until it is nearly parallel with earth eNABLEmOTOR = 0 rOTATEWest = 0 @ INT_ENABLE TMR1_INT RETURN ' AutoEast: if stopeast = 0 then ' TRAVEL LIMIT SWITCH CLOSED ls_error = 1 ' FLAG THE ERROR GOTO EXIT_EAST ' LIMIT SWITCH CLOSED - GET OUT ENDIF EnableMotor = 1 ' ELSE MOVE THE PANEL NORMALLY FOR ADJUSTMENT RotateEast = 1 pause 100 'give it time to move the panel some (THIS SEEMS TO BE THE ' OPTIMUM TIME FOR MOVING THE PANEL APROX 1 DEGREE) EXIT_EAST: eNABLEmOTOR = 0 rOTATEEast = 0 RETURN ' AutoWest: if stopwest = 0 then ' TRAVEL LIMIT SWITCH CLOSED ls_error = 1 ' FLAG THE ERROR GOTO EXIT_WEST 'LIMIT SWITCH CLOSED - GET OUT ENDIF EnableMotor = 1 ' ELSE MOVE PANEL NORMALLY FOR ADJUSTMENT RotateWest = 1 pause 100 ' give it time to move some EXIT_WEST: eNABLEmOTOR = 0 rOTATEWest = 0 RETURN ' ' MOVE THE PANEL USING THE TOGGLE SWITCH ManualWest: @ INT_DISABLE TMR1_INT ' DISABLE TIMER INTERRUPT WHILE MOVING MANUALY While GoWest = 0 EnableMotor = 1 RotateWest = 1 wend EnableMotor = 0 RotateWest = 0 @ INT_ENABLE TMR1_INT return ManualEast: ' MOVE THE PANEL USING THE TOGGLE SWITCH @ INT_DISABLE TMR1_INT ' DISABLE TIMER INTERRUPT WHILE MOVING MANUALY while GoEast = 0 EnableMotor = 1 RotateEast = 1 wend EnableMotor = 0 RotateEast = 0 ' @ INT_ENABLE TMR1_INT return ' Measure: ' NOW CHECK THE POSITION LED SENSORS ' @ INT_DISABLE TMR1_INT ' DISABLE THE TIMER INTERUPT DURING POSITION CHECK / AUTO MOVE ' READ THE ANALOG PORTS ' Automatically move the panel East or West to track the Sun ' IF LS_ERROR = 1 THEN GOTO HERE ' GET OUT IF TRAVEL LIMIT SWITCH IS CLOSED Measure1: ' ENTRY POINT FOR ADJUSTING PANEL ' IF LS_ERROR = 1 THEN GOTO HERE ' GET OUT IF TRAVEL LIMIT SWITCH IS CLOSED ' ADCIN 0,east 'LED'S OUTPUT UP TO 1.5 VOLTS WHEN FULLY EXPOSED TO LIGHT pause 50 ' Convert west LED Millivolt value volts1 = east * conv1 volts2 = east * conv2 volts2 = volts2/100 east = volts1 + volts2 'actual millivolt value of west LED ' Convert the east LED Millivolt value adcin 1,west pause 50 ' volts1 = west * conv1 volts2 = west * conv2 volts2 = volts2/100 west = volts1 + volts2 'actual millivolt value of east LED '************************************************* ****************** ' THIS IS JUST FOR TROUBLESHOOTING USING THE LCD ' the pause 1000 in the serial routine should be replaced in the ' read_east / read_west to provide some delay between movements IF east > west then difference = east - west if west > east then difference = west - east SEROUT2 Tx, 84,[254,192,"EAST: ", dec east] 'DISPLAY THE DECIMAL MV VALUE pause 50 serout2 Tx,84,[254,148,"WEST: ",DEC west] PAUSE 50 serout2 Tx,84,[254,212,"DIFFERENCE ",DEC DIFFERENCE] pause 1000 SEROUT2 Tx,84,[254,$01] ' clears the display '************************************************* ********************** ' IF DIFFERENCE EAST THEN GOTO READ_WEST ' Panel is relatively aligned with the Sun at this point ' Now wait till next reading via the timer interrupt HERE: EAST = 0:WEST=0:DIFFERENCE = 0 CHK_POSITION = 0 ' @ INT_ENABLE TMR1_INT RETURN '************************************************* *********** '************************************************* *************** Main: ' CHECK FOR A MANUAL MOVE If GoWest = 0 then gosub ManualWest ' If GoEast = 0 then gosub ManualEast ' ' CHECK FOR LIMIT SWITCH CLOSED if StopWest = 0 then gosub MoveEast ' move panel off the limit switch loop1: ' *** COULD ADD CHECKING A PUSHBUTTON HERE TO CLEAR ERROR*** goto loop1 ' loop here till power cycle- - panel is in horizontal position endif 'and stopped which indicates a limit switch error ' if StopEast = 0 then gosub MoveWest 'move panel off limit switch loop2: ' *** COULD ADD CHECKING A PUSHBUTTON HERE TO CLEAR ERROR*** goto loop2 'loop here till power cycle- - panel is in horizontal position endif 'and stopped which indicates a limit switch error ' ' IS IT TIME TO READ THE LED SENSORS ? IF CHK_POSITION = 1 THEN GOSUB Measure ' goto Main '---[TMR1 - interrupt handler]-------------------------------------------------- TIME_COUNTER: X = X + 1 ' THE LCD DISPLAY IS FOR TROUBLESHOOTING IF NEEDED ' INDICATES THE TIMER INTERRUPT IS EXECUTING BY DISPLAYING THE COUNT ' SEROUT2 Tx, 84,[254,128,"X ", dec X] 'DISPLAY THE TIMER COUNT IF X = 120 THEN CHK_POSITION = 1 ' sample aprox once a minute IF X >= 122 THEN ' Give it 2 more ticks and start over X = 0 CHK_POSITION = 0 SEROUT2 Tx,84,[254,$01] ' clears the display ENDIF @ INT_RETURN GOTO MAIN ' end
Best Tips for Keeping PIC BASIC Projects Reliable?
Hi all,
WonderNom Today, 09:30I’ve been working on a few small PIC BASIC projects lately — mostly simple automation and sensor modules. I’m trying to make them as stable and reliable as possible, especially when they run...