Ik gebruik een pic16f877A om:
* een ADC uit te lezen
* temperatuur te meten met een DS1820
* een fan aan te sturen (digitaal met een lm317)
* fan toerental uit te lezen (met pulsin commando)
* vervolgens het gemeten voltage, temperatuur en fan snelheid op een lcd te printen
Dit werkt in principe allemaal prima, alleen is het programma te traag.
De adc waarde verspringt maar langzaam op het lcd.
D.m.v weglaten van delen code heb ik het idee dat vooral het meten van het toerental met pulsin en de if statements voor het instellen van de fan snelheid veel tijd kosten.
Wie kan mij tips geven over het optimaliseren van het programma?
Device 16F877A
'Config WDT_Off, PWRTE_Off, XT_OSC, LVP_off
Config WDT_OFF, PWRTE_Off, XT_OSC, LVP_OFF, CP_OFF, DEBUG_OFF, WRT_OFF, CPD_OFF, BODEN_ON
PORTB_PULLUPS On
XTAL 4
ADIN_RES = 10 ;ADC resolutie
ADIN_TAD = FRC ;de clock voor de adc extern / intern
ADIN_STIME = 50;De conversie tijd
ALL_DIGITAL = True
Symbol EN1 = PORTC.7 ;Uitgang voor LCD Enable 1
Symbol EN2 = PORTD.5 ;Uitgang voor LCD Enable 2
Symbol dq = PORTD.0 ; inlees poort ds1820
Symbol R0K = PORTD.2 ; lm317 res to ground
Symbol R5K = PORTD.3 ; lm317 res to ground
Symbol R1K = PORTC.4 ; lm317 res to ground
;76543210
TRISA = %01000000
ADCON1= %11000001 ;adc instellen op de goede poorten
Print $FE,$40,$0E,$0A,$0E,$00,$00,$00,$00,$00 '' voor graden symbool
Clear
Cls
;Variabele declareren
Dim Waarde As Float
Dim VAR1 As Word
Dim VAR2 As Word
Dim TPL As Word
Dim Rpm As Float
Dim Rpm1 As Word
Dim Temp As Word ' Holds the temperature value
Dim C As Byte ' Holds the counts remaining value
Dim CPerD As Byte ' Holds the Counts per degree C value
Hoofdprogramma:
;; TEMPERATURE MEASUREMENT
OWrite dq, 1, [$CC, $44] ' Send Calculate Temperature command
Repeat '
ORead dq, 4, [C] ' Keep reading low pulses until
Until C <> 0 ' the DS1820 is finished.
OWrite dq, 1, [$CC, $BE] ' Send Read ScratchPad command
ORead dq, 2,[Temp.LowByte,Temp.HighByte, C, C, C, C, C, CPerD]
' Calculate the temperature in degrees Centigrade
Temp = (((Temp >> 1) * 100) - 25) + (((CPerD - C) * 100) / CPerD)
;; FAN SPEED
If Temp < 3000 Then GoSub SPEED0
If Temp > 3000 Then GoSub SPEED1
If Temp > 4000 Then GoSub SPEED2
If Temp > 5000 Then GoSub SPEED3
; RPM MEASUREMENT
VAR1 = PulsIn PORTC.5 , 0
VAR2 = PulsIn PORTC.5 , 1
TPL = (VAR1 * 2) + (VAR2 * 2)
Rpm = 6000000/TPL
Rpm1 = Rpm
If TPL < 100 Then Rpm1=0
;; ADC uitlezen
Waarde = ADIn 6
Waarde = (Waarde * 5) / 341
;; Print op LCD
GoSub Derde
Print At 1, 1, "Heatsink Temp: ", Dec Temp / 100, ".", DEC1 Temp," ", 0,"C " ;Zet tekst op regel 1
Print At 2,1, "Fan Speed: ", Dec Rpm1, " rpm "
GoSub Eerste
Print At 1,1, "Vout: ",DEC2 Waarde, " V "
GoTo Hoofdprogramma ;Doe het voorbeeld steeds weer opnieuw
Derde:
High EN1 ;geef regel 1 en 2 vrij
Low EN2 ;blokkeer regel 3 en 4
Return
Eerste:
Low EN1 ;blokkeer regel 1 en 2
High EN2 ;geef regel 3 en 4 vrij
Return
SPEED0:
DelayMS 1
High R0K
High R5K
High R1K
DelayMS 1
Return
SPEED1:
DelayMS 1
Low R0K
Low R5K
High R1K
DelayMS 1
Return
SPEED2:
DelayMS 1
Low R0K
High R5K
Low R1K
DelayMS 1
Return
SPEED3:
DelayMS 1
Low R0K
Low R5K
Low R1K
DelayMS 1
Return
End
theove
Take care to get what you like or you will be forced to like what you get
Fredjuhh
"Ben nog een N00B, maar dat is al aan het veranderen ;)
DelayMS 1000 ' Wait until conversion is complete
Hier mis ik een until, want dat doet delayms niet: die wacht gewoon telkens een seconde.
Dus een rondje van je main kost minimaal 1 seconde: lekker traag 
[EDIT] te laat
oeps, foutje bij opschonen code voor het posten.
die had ik er (uiteraard
) al tussenuit gehaald.
code blijft te traag naar mijn zin....
Fuzzbass
Mijn echte naam: Joris | Mijn elektronica website: Fuzzcraft.com
De DS1820 doet er ook iets van 750msec. over om tot een resultaat te komen. Misschien kun je beter de DS1820 pollen in plaats van wachten. Dus gewoon je rondje doen totdat hij klaar is, dan pas de temperatuur uitlezen en verwerken.
Persoonlijk zou ik al die tijdvretende dingen in een interrupt afhandelen.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Stan1
Read the fuc.... manual and read the fuc.... datasheet! {Proton IDE: V2.0.1.2 / Proton Compiler: V3.5.4.5}
Beter kan je one-wire sensoren zoals de DS1820 niet gebruiken, zijn traag en in combinatie met interrupts levert dit geheid problemen op.
Gebruik of I2C of AD (bijvoorbeeld de LM35 of de LM335AZ) sensoren.
De 16F877A heeft 8x 10-BIT ADC, dus daar kan je zo een LM35 aan hangen!
Je gebruikt ook tweemaal float, (daar ontkom je waarschijnlijk niet aan) maar daar wordt het niet echt sneller van.
De controller draaid nu op 4MHz, die kan ook naar 20MHz dat scheeld ook weer.
;; FAN SPEED
If Temp < 3000 Then GoSub SPEED0
If Temp > 3000 Then GoSub SPEED1
If Temp > 4000 Then GoSub SPEED2
If Temp > 5000 Then GoSub SPEED3Bij een temp > 5000 gaat hij eerst naar SPEED1, dan SPEED2 en dan pas naar SPEED3
Ik zou het zo neerzetten:
If Temp > 5000 Then GoSub SPEED3
elseif Temp > 4000 Then GoSub SPEED2
elseif Temp > 3000 Then GoSub SPEED1
else GoSub SPEED0
Endif
En waarom zit er bij elke SPEED subroutine 2 maal een waitms 1 in?
Tinus016
www.tinuselectronics.nl Because DIY Electronics Matters!!!!
I.p.v. High en Low, Aan en Uit gebruiken. wel even aan en uit definiëren.
symbol AAN = 1
symbol Uit = 0
Dit boven staande stukje code moet boven in je programma staan.
Edit, zo is het misschien duidelijker.
Derde:
EN1 = Aan ;geef regel 1 en 2 vrij
EN2 = Uit ;blokkeer regel 3 en 4
Return
Eerste:
EN1 = Uit ;blokkeer regel 1 en 2
EN2 = Aan ;geef regel 3 en 4 vrij
Return
SPEED0:
DelayMS 1
R0K = Aan
R5K = Aan
R1K = Aan
DelayMS 1
Return
SPEED1:
DelayMS 1
R0K = Uit
R5K = Uit
R1K = Aan
DelayMS 1
Return
SPEED2:
DelayMS 1
R0K = Uit
R5K = Aan
R1K = Uit
DelayMS 1
Return
SPEED3:
DelayMS 1
R0K = Uit
R5K = Uit
R1K = Uit
DelayMS 1
Return
End
Stan1
Read the fuc.... manual and read the fuc.... datasheet! {Proton IDE: V2.0.1.2 / Proton Compiler: V3.5.4.5}
Of zo:
Select Temp
Case < 3001
GoSub SPEED0
Case 3000 To 4000
GoSub SPEED1
Case 4000 To 5000
GoSub SPEED2
Case > 5000
GoSub SPEED3
End Select
Waar waarom een snelheid via vaste waardes regelen en niet via PWM?
[Bericht gewijzigd door Stan1 op (13%)]
Frits Kieftenbelt
Ohm sweet Ohm | www.picbasic.nl
Op 30 oktober 2011 15:48:51 schreef Tinus016:
I.p.v. High en Low, Aan en Uit gebruiken. wel even aan en uit definiëren.symbol AAN = 1 symbol Uit = 0
Dat is niet het enige, je moet dan ook TRIS instellen.
Frits Kieftenbelt
Ohm sweet Ohm | www.picbasic.nl
Bij iedere HIGH en LOW wordt ook steeds de poort als uitgang gedefinieerd.
Het is beter om dit eenmalig bovenaan in je programma te doen met TRIS.
Lees hiervoor het begin van cursus deel 3:
www.picbasic.nl/beginners3.htm
winjohan
When you think you have it dummy proof they come up with a better dummy!
Richard,
om de meting van de ds te versnellen, heb ik de code voor het uitlezen in 2 gehakt!
' ****************** temp meting ds18s20 *******************************
ds_1820:
Output DQbin ' maak Pin Output
DQbin=0 ' OneWire lijn Laag
PauseUs 480 ' 480 µS laag houden
Input DQbin ' Maak Pin Input
PauseUs 70 ' wacht 70 µS
If DQbin=1 then ' geen pulzen van DS1820
v = 1200 ' op display 20,0 graden
Return
EndIf
OWOut DQbin, 1, [$CC, $44] ' Start temperatuur conversie
return
Wachtlus_bin:
led2 = 1
OWIn DQbin, 4, [resterend_tellen] ' controlle nog steeds bezig controleren
If resterend_tellen = 0 Then wachtlus_bin ' Bezig
OWOut DQbin, 1, [$CC, $BE] ' lees de temperatuur
OWIn DQbin, 0, [Temperatuur.LowByte, Temperatuur.HighByte, Skip 4, resterend_tellen, tellen_per_C]
Temperatuur = (((Temperatuur >> 1) * 100) - 25) + (((tellen_per_C - resterend_tellen) * 100) / tellen_per_C)
if Temperatuur > 32767 then '32767 controleer als bit 12=1
Temperatuur= ~Temperatuur
V= (10000 - Temperatuur )/10 ' 25 C = 1250 0 C= 1000 -10 C =900
else
V= (10000 + Temperatuur)/10
EndIf
led2= 0
Tekenbit_bin = $2b '2b="+"
If v >= 1000 then ' boven 0 C.
Temp_bin=V-1000
Else
Temp_bin=1000-V ' onder 0 C.
Tekenbit_bin=$2d '2d = -"
EndIf
returnik gebruik een iets andere versie van picbasic maar ik vermoed dat het wel duidelijk is
Eerst met de sub ds_1820 de conversie starten, en ik ga 1 seconden later de sub Wachtlus_bin aanroepen en zodoende heb ik om de 2 seconden een nieuwe temperatuur en tussendoor kan de up andere dingen doen ! Dus hij zit niet te wachten todat de ds de temparatuur conversie heeft gedaan.
Succes Johan
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com