- 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


Menu
Re: LCDOUT command followed by variable data
no , you can create your alias names for the array address' in the buffer in any way that you prefer or just use array notation and have no alias' at all
richard Yesterday, 23:08