Sinus calculating !


Results 1 to 30 of 30

Threaded View

  1. #20
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    Here we go... third method of getting accurate Sines... no DIV32 statements, accuracy to at least three decimal places and 99% of the time you'll get four decimal places... near instant calculation etc etc... also brews Cappuccino, Late and Expresso on the side...

    Yes, with simple PBP we take an ANGLE to TWO DECIMAL PLACES (what? decimal places with integers?) and produce an example of SINE to FOUR DECIMAL PLACES... who need floats when you've got integers?...

    Example 1.

    Sine of 135.57 Degrees
    Result 0.7000
    Actual 0.700037341

    Example 2.

    Sine of 45.25 Degrees
    Result 0.7101
    Actual 0.710185375

    Example 3.

    Sine of 186.66 Degrees
    Result -0.0638
    Actual -0.063836616

    Do NOT get worried about the size of this code... the ONLY important bit is the CalculateSine subroutine and the EEPROM statements, the rest is window-dressing to make pretty displays and for easy data-entry.


    Code:
    	'	Sine Calculation - Interpolated Method
    	'	======================================
    	'	Melanie Newman
    	'	15/Sept/2004
    
    	'	Program demonstrates SINE calculation 
    	'	using a simple interpolative method. 
    	'	Input Angles valid from 0-359.99 degrees
    	'	Output SINE to four decimal places ie 1.0000
    
    	'	Display is on 2-line LCD with 3 buttons
    	'	Same circuit layout as per 'Olympic Timer' previously posted.
    
    	'
    	'	PIC Defines
    	'	===========
    	'
    	'	Change these defines to suit your chosen PIC
    	'	Your PIC must have 180 Bytes of EEPROM
    	'
    	@ DEVICE pic16F876, XT_OSC
    	@ DEVICE pic16F876, WDT_ON
    	@ DEVICE pic16F876, PWRT_ON
    	@ DEVICE pic16F876, BOD_ON
    	@ DEVICE pic16F876, LVP_OFF
    	@ DEVICE pic16F876, CPD_OFF
    	@ DEVICE pic16F876, PROTECT_OFF
    	@ DEVICE pic16F876, WRT_OFF
    
    	'
    	'	Hardware Defines
    	'	================
    		'
    		' 	LCD Display
    		'	-----------
    		'	Adjust these to suit your chosen LCD pinout
    		'
    	Define LCD_DREG PORTC	' Port for LCD Data
    	Define LCD_DBIT 4	' Use upper 4 bits of Port
    	Define LCD_RSREG PORTC	' Port for RegisterSelect (RS) bit
    	Define LCD_RSBIT 0	' Port Pin for RS bit
    	Define LCD_EREG PORTC	' Port for Enable (E) bit
    	Define LCD_EBIT 3	' Port Pin for E bit
    	Define LCB_BITS 4	' Using 4-bit bus
    	Define LCD_LINES 2	' Using 2 line Display
    	Define LCD_COMMANDUS 2000
    				' Command Delay (uS)
    	Define LCD_DATAUS 50	' Data Delay (uS)
    
    		'
    		'	Control Buttons/Lines
    		'	---------------------
    	ButtonUp var PortB.0		' Take this pin low momentarily to INCREMENT
    	ButtonDown var PortB.1		' Take this pin low momentarily to DECREMENT
    	ButtonSet var PortB.2		' Take this pin low momentarily to SET
    
    	'
    	'	Software Defines
    	'	----------------
    	Angle var WORD			' Input angle 0-36000 representing 0.00-360.00 degrees
    	CounterA var BYTE
    	KeyBut var BYTE			' Keyboard Button Code
    	Sine var WORD			' Sine value 0-10000 representing 0-1.0000
    	SineMax var WORD		' High-end of Lookup
    	SineMin var WORD		' Low-end of Lookup
    	SineNeg var BIT			' Flag indicating Negative answer
    	TempA var WORD
    	TempB var BYTE
    	UserData var BYTE[5]		' User-Entry Edit Field
    	UserMax var BYTE		' Variable to keep numeric entry within integer limitations
    	UserPos var BYTE		' User Entry Field Position
    
    	'
    	'	EEPROM Presets
    	'	--------------
    	Data @0,$00,$AF			'   1 =  175 (Sine of 1 Degree = 0.0175)
    	Data $01,$5D			'   2 =  349 (Sine of 2 Degrees - 0.0349)
    	Data $02,$0B			'   etc, etc
    	Data $02,$BA
    	Data $03,$68
    	Data $04,$15
    	Data $04,$C3
    	Data $05,$70
    	Data $06,$1C
    	Data $06,$C8
    	Data $07,$74
    	Data $08,$1F
    	Data $08,$CA
    	Data $09,$73
    	Data $0A,$1C
    	Data $0A,$C4
    	Data $0B,$6C
    	Data $0C,$12
    	Data $0C,$B8
    	Data $0D,$5C
    	Data $0E,$00
    	Data $0E,$A2
    	Data $0F,$43
    	Data $0F,$E3
    	Data $10,$82
    	Data $11,$20
    	Data $11,$BC
    	Data $12,$57
    	Data $12,$F0
    	Data $13,$88
    	Data $14,$1E
    	Data $14,$B3
    	Data $15,$46
    	Data $15,$D8
    	Data $16,$68
    	Data $16,$F6
    	Data $17,$82
    	Data $18,$0D
    	Data $18,$95
    	Data $19,$1C
    	Data $19,$A1
    	Data $1A,$23
    	Data $1A,$A4
    	Data $1B,$23
    	Data $1B,$9F
    	Data $1C,$19
    	Data $1C,$92
    	Data $1D,$07
    	Data $1D,$7B
    	Data $1D,$EC
    	Data $1E,$5B
    	Data $1E,$C8
    	Data $1F,$32
    	Data $1F,$9A
    	Data $20,$00
    	Data $20,$62
    	Data $20,$C3
    	Data $21,$20
    	Data $21,$7C
    	Data $21,$D4
    	Data $22,$2A
    	Data $22,$7D
    	Data $22,$CE
    	Data $23,$1C
    	Data $23,$67
    	Data $23,$AF
    	Data $23,$F5
    	Data $24,$38
    	Data $24,$78
    	Data $24,$B5
    	Data $24,$EF
    	Data $25,$27
    	Data $25,$5B
    	Data $25,$8D
    	Data $25,$BB
    	Data $25,$E7
    	Data $26,$10
    	Data $26,$35
    	Data $26,$58
    	Data $26,$78
    	Data $26,$95
    	Data $26,$AF
    	Data $26,$C5
    	Data $26,$D9
    	Data $26,$EA
    	Data $26,$F8
    	Data $27,$02
    	Data $27,$09
    	Data $27,$0E
    
    	'
    	'	Start Program
    	'	=============
    
    		'
    		'	Initialise Processor
    		'	--------------------
    	TRISA=%00000001
    	TRISB=%11111111
    	TRISC=%00000000
    	OPTION_REG.7=0			' Enable Pull-Up's
    	Pause 1000
    	Angle=0
    	'
    	'	Enter Data
    	'	----------
    	'	This section gets variable ANGLE
    	'	ANGLE is a value 0-36000 where 36000 represents 360.00 Degrees.
    	'	Press UP/DOWN Buttons to set the Angle 0-360, then Press SET to Accept the value
    	'
    Loop:
    	LCDOut $FE,$01,$FE,$0E,"Angle "
    	Gosub DisplayAngle
    	LCDOut " Deg"
    	UserPos=0
    	Gosub UserEntry
    	If Angle>35999 then 
    		LCDOut $FE,1,"Angle must be",$FE,$C0,"less than 360.00"
    		Pause 1000
    		goto Loop
    		endif
    
    	'
    	'	Calculate & Display SINE
    	'	------------------------
    	' 	This section gets and Displays the resultant variable SINE
    	'
    	Gosub CalculateSine
    	LCDout $FE,$C0,"Sine "
    	If SineNeg=1 then LCDOut "-"
    	LCDOut #SINE DIG 4,".",#SINE DIG 3,#SINE DIG 2,#SINE DIG 1,#SINE DIG 0
    	'
    	'	Loop around again (Press SET to Continue)
    	'	-----------------------------------------
    	While KeyBut<>3:Gosub GetKey:Wend
    	LCDOut $FE,1
    	While KeyBut<>7:Gosub GetKey:Wend
    	Goto Loop
    
    	'
    	'	Subroutine Calculates Sine
    	'	--------------------------
    CalculateSine:
    	SineNeg=0			
    	If ANGLE>18000 then SineNeg=1	' Determine if negative Result
    	TempA=Angle			' Reduce angle to 1st Quadrant (0-90 degrees only)
    	If TempA>17999 then TempA=TempA-18000
    	If TempA>9000 then TempA=9000-(TempA-9000)
    		'
    		'	Load Low-End of Lookup
    		'	----------------------
    	CounterA=TempA/100
    	If CounterA=0 then
    		SineMin=0
    		else
    		If CounterA=90 then
    			SineMin=10000
    			else
    			TempB=CounterA*2-2:Read TempB,SineMin.Highbyte
    			TempB=TempB+1:Read TempB,SineMin.Lowbyte
    			endif
    		endif
    		'
    		'	Load High-End of Lookup
    		'	-----------------------
    	CounterA=CounterA+1
    	If CounterA=>90 then
    		SineMax=10000
    		else
    		TempB=CounterA*2-2:Read TempB,SineMax.Highbyte
    		TempB=TempB+1:Read TempB,SineMax.Lowbyte
    		endif
    		'
    		'	Determine the Decimal Fraction (Interpolation) Bit
    		'	--------------------------------------------------
    	TempB=TempA-((TempA/100)*100)
    	Sine=SineMin+(((SineMax-SineMin)*TempB)/100)
    	Return
    	
    	'
    	'	Subroutine Reassembles User-Entered Angle
    	'	-----------------------------------------
    ReassembleAngle:
    	Angle=UserData(0)*10000
    	Angle=Angle+(UserData(1)*1000)
    	Angle=Angle+(UserData(2)*100)
    	Angle=Angle+(UserData(3)*10)
    	Angle=Angle+UserData(4)
    	'
    	'	subroutine Displays Angle
    	'	-------------------------
    DisplayAngle:
    	LCDOut $FE,$86,$FE,$0C
    	If Angle>9999 then 
    		LCDOut #ANGLE DIG 4 
    		else 
    		LCDOut " "
    		endif
    	If Angle>999 then 
    		LCDOut #ANGLE DIG 3 
    		else 
    		LCDOut " "
    		endif
    	LCDOut #ANGLE DIG 2,".",#ANGLE DIG 1,#ANGLE DIG 0
    	Return
    
    	'
    	'	Subroutine Scans Buttons
    	'	------------------------
    		' KeyBut - 0 = Invalid (SET+UP+DOWN Pressed)
    		'	 - 1 = Invalid (SET+UP Pressed)  
    		'	 - 2 = Invalid (SET+DOWN Pressed)
    		'	 - 3 = SET Pressed
    		'	 - 4 = Invalid (UP+DOWN Pressed)
    		'	 - 5 = UP Pressed
    		'	 - 6 = DOWN Pressed
    		'	 - 7 = No Buttons Pressed
    GetKey:
    	KeyBut=0			' Zero any previous Result First
    	KeyBut.0=ButtonDown		' Read Input Buttons
    	KeyBut.1=ButtonUp
    	KeyBut.2=ButtonSet
    	Pause 100			' Allows for 10cps auto-repeat
    	Return
    
    	'
    	'	Subroutine performs User Numeric Field Entry
    	'	--------------------------------------------
    UserEntry:
    	For CounterA=0 to 4
    		UserData(CounterA)=Angle DIG (4-CounterA)
    		Next CounterA
    UserEntryLoop:
    	CounterA=$86+UserPos
    	If UserPos>2 then CounterA=CounterA+1
    	LCDOut $FE,CounterA,$FE,$0E
    UserEntryLoopSkip:
    	Gosub GetKey
    	UserMax=9
    	If UserPos=0 then UserMAX=3
    	If KeyBut=5 then
    		UserData(UserPos)=UserData(UserPos)+1
    		If UserData(UserPos)>UserMAX then UserData(UserPos)=0
    		gosub ReassembleAngle
    		goto UserEntryLoop
    		endif
    	If KeyBut=6 then
    		If UserData(UserPos)=0 then 
    			UserData(UserPos)=UserMAX
    			else 
    			UserData(UserPos)=UserData(UserPos)-1
    			endif
    		gosub ReassembleAngle
    		goto UserEntryLoop
    		endif
    	If KeyBut<>3 then goto UserEntryLoopSkip
    	While KeyBut<>7:Gosub GetKey:Wend
    	UserPos=UserPos+1
    	If UserPos<5 then goto UserEntry
    	Return
    	
    	End
    There you go... with only 178 EEPROM statements you've got 36,000 points on your Sine graph.

    Have fun...

    Melanie
    Attached Images Attached Images  

Similar Threads

  1. picbasic-l Calculating the day of Week from a date
    By Melanie in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 3rd August 2012, 00:09
  2. Calculating elapsed time, how?
    By Eng4444 in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 1st June 2006, 09:00
  3. Replies: 0
    Last Post: - 26th March 2006, 00:13
  4. calculating arc tangent
    By mischl in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 14th July 2005, 07:29
  5. Sinus generation with PIC
    By martarse in forum mel PIC BASIC Pro
    Replies: 13
    Last Post: - 16th August 2004, 16:10

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts