' {$STAMP BS2} ' {$PBASIC 2.5} ' ' Experiments with Wind Turbines ' Electrical Parameters and RPM ' Version 1.0, Program Listing 1.0 ' File: Parallax_Wind_RPM_Exp.bs2 ' Copyright: LearnOnLine, Inc. ' Author: J. Gavlik ' Last Updated: 06-30-2009 ' '------------------------------------------------------------------ ' Declarations '------------------------------------------------------------------ ' ' General VARs ' i VAR Nib filteredDC VAR Word oneOhmDrop VAR Word current VAR Word rpm VAR Word loLimit CON 100 hiLimit CON 200 loLimitFlag VAR Bit ckSum VAR Byte delay VAR Byte 'ms of delay between samples ' ' VARs for MCP3208 8 channel, 12 bit multiplexed A/D Converter ' a2dClk CON 0 'clock (P0) a2dDout CON 1 'data out (P1) a2dDin CON 2 'data in (P2) a2dCs CON 3 'chip select (P3) a2dId0 CON %1000 'A/D Channel 0 ID a2dId1 CON %1001 'A/D Channel 1 ID a2dId2 CON %1010 'A/D Channel 2 ID a2DId3 CON %1011 'A/D Channel 3 ID a2dId4 CON %1100 'A/D Channel 4 ID a2dId5 CON %1101 'A/D Channel 5 ID a2dId6 CON %1110 'A/D Channel 6 ID a2DId7 CON %1111 'A/D Channel 7 ID a2dIdShiftOut VAR Nib 'A/D Channel ID to shift out a2dResult VAR Word '16-bit result of A/D conversion '------------------------------------------------------------------ ' RPM Wind Experiment Algorithm '------------------------------------------------------------------ ' Take samples of the rectified DC voltage and voltage drop across the ' 1 ohm sense resistor which is used to compute current ' Average 16 samples to smooth out the ripples on these waveforms ' Convert the raw count to millivolts ' Test to see if the input voltage > voltage drop across the 1 ohm resistor ' if so, ingore readings and loop back to top for more ' if not, continue ' Convert the 1 ohm voltage drop to current in milliamps ' Measure the RPM by syncing to phase 1 and measuring the time delay from ' the start of one cycle to the start of the next cycle. Use this time to ' compute the RPM by multiplying the delay time by the number of cycles per revolution ' Compute the checksum and transmit the data to the computer ' Repeat '------------------------------------------------------------------ ' Main Loop '------------------------------------------------------------------ Wind_3Phase_Exp: GOSUB Take_Samples GOSUB Measure_RPM GOSUB Transmit_Data_To_PC GOTO Wind_3Phase_Exp '------------------------------------------------------------------ ' Take Samples ' Acquire a2d readings for rectified DC and oneOhmDrop ' Average 16 readings and compute current '------------------------------------------------------------------ Take_Samples: filteredDC = 0 oneOhmDrop = 0 FOR i = 0 TO 15 a2dIdShiftOut = a2dId0 GOSUB A2d filteredDC = filteredDC + a2dResult a2dIdShiftOut = a2dId5 GOSUB A2d oneOhmDrop = oneOhmDrop + a2dResult NEXT filteredDC = filteredDC / 16 oneOhmDrop = oneOhmDrop / 16 filteredDC = filteredDC */ $0138 oneOhmDrop = oneOhmDrop */ $0138 IF (filteredDC > oneOhmDrop) THEN current = (filteredDC - oneOhmDrop)/ 1 ENDIF RETURN '------------------------------------------------------------------ ' Measure RPM '------------------------------------------------------------------ Measure_RPM: GOSUB Wait_For_Phase1_Zero_Volts GOSUB Wait_For_Phase1_New_Peak delay = 0 Measure_RPM_Delay: PAUSE 1 delay = delay + 1 GOSUB Test_For_Next_Peak IF (delay > 0) THEN GOTO Measure_RPM_Delay ENDIF RETURN '------------------------------------------------------------------ ' Transmit Data To PC ' 1. The raw a2d readings are converted to millivolts by multiplying each count by 1.22 mv/count ' using the Multiply Middle Operator */ where the fraction of 0.22 is converted to ' a hex number that represents 0.22 x 256 = 56.32 = $38. The integer 1 forms the other ' part of the total hex number $0138. ' ' 2. The checksum (cksum) is computed as a one-byte value ' ' 3. The entire data stream is transmitted to the computer using the Debug instruction @ 9600 baud ' '------------------------------------------------------------------ Transmit_Data_To_PC: cksum = filteredDC.HIGHBYTE + filteredDC.LOWBYTE + current.HIGHBYTE + current.LOWBYTE + rpm.HIGHBYTE + rpm.LOWBYTE DEBUG 0, 0, 0, 0, 0, 0, 0, 0 DEBUG filteredDC.HIGHBYTE, filteredDC.LOWBYTE, current.HIGHBYTE, current.LOWBYTE, rpm.HIGHBYTE, rpm.LOWBYTE, cksum RETURN '------------------------------------------------------------------ ' A/D Converter Routine ' Enter with a2dIdShiftOut as the channel to convert ' Return with 12-bit result in a2dResult - right shifted '------------------------------------------------------------------ A2D: 'Initialize signals HIGH a2dCs 'Disable A/D chip select HIGH a2dDin 'Initial state of data in LOW a2dClk 'Initial state of clock a2dResult = 0 'Clear the 10-bit result A2D_Start_Conversion: 'Start the conversion process LOW a2dCs 'Enable A/D chip select A2D_Shift_Out_Channel_ID: 'Shift out the Channel ID value PULSOUT a2dClk,10 'Send first clock with Din high SHIFTOUT a2dDin,a2dClk,MSBFIRST,[a2dIdShiftOut\4] A2D_Shift_In_Result: 'Shift in the result PULSOUT a2dClk,10 'clock out null bit PULSOUT a2dClk,10 'clock out null bit SHIFTIN a2dDout,a2dClk,MSBPRE,[a2dResult\12] A2D_End_Conversion: HIGH a2dCs 'Disable A/D chip select A2D_End: RETURN 'Return to calling routine '------------------------------------------------------------------ ' Wait_For_Phase1_Zero_Volts ' Loop until phase1 voltage is below a minimum a2d count ' indicating that it is at the bottom of its voltage cycle '------------------------------------------------------------------ Wait_For_Phase1_Zero_Volts: a2dIdShiftOut = a2dId1 GOSUB A2D IF (a2dResult < loLimit) THEN RETURN ELSE GOTO Wait_For_Phase1_Zero_Volts ENDIF RETURN '------------------------------------------------------------------ ' Wait_For_Phase1_New_Peak ' Loop until phase1 voltage is above a minimum a2d count ' indicating that it is just beginning to rise again '------------------------------------------------------------------ Wait_For_Phase1_New_Peak: a2dIdshiftOut = a2dId1 GOSUB A2D IF (a2dResult > hiLimit) THEN RETURN ELSE GOTO Wait_For_Phase1_New_Peak ENDIF RETURN '------------------------------------------------------------------ ' Test For Next Peak ' First detect next lolimit - set flag ' Next detect following hilimit - clear flag and compute rpm '------------------------------------------------------------------ Test_For_Next_Peak: a2dIdShiftOut = a2dId1 GOSUB A2D IF (a2dresult < loLimit) THEN 'we're back into the zero volt area loLimitFlag = 1 ENDIF IF (a2dResult> hiLimit) AND (loLimitFlag = 1) THEN 'we've started a new peak loLimitFlag = 0 rpm = 10000 /(12*delay) delay = 0 ENDIF RETURN