Als eerste A/D project tracht ik de spanning van een 4,8V batterij te meten en aldus te bewaken. Spanning komt binnen op GP0 en referentie van 2,5V via zener diode op GP1. Ik stuur twee LED's aan op GP2 en GP3 als de spanning gelijk of hoger is dan 2,4V (spanningsdeler)
brandt de groene LED, als de spanning lager of gelijk is dan 2,35V pinkt de rode led en lager dan 2,3V blijft de rode led branden.
Na inlezen van het programma gebeurt er uiteraard niets... het is bij deze nogal blind werken en heb zelf geen programmeer ervaring.
Kan iemand mij hier door helpen...
Device = 12F675
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, MCLRE_OFF
XTAL = 4
DECLARE ADIN_RES 10 ' 10-bit resultaat
DECLARE ADIN_TAD FRC ' interne OSC geselecteerd
DECLARE ADIN_STIME 50 ' selecteer 50µs sample tijd
TRISB = %00000011 ' Configure AN0 (PORTB.0 and 1) as an input
ADCON0 = %10000000 ' Set analogue input on PORTA.0
DIM VAR1 as WORD
Dim AD_RESULT as ADRESL.WORD ' Convert the ADRESL register into a WORD variable
' ADCON0 register's bits
Symbol GO_DONE = ADCON0.1 ' ADC Conversion status/ plus enable conversion-bit
Symbol ADON = ADCON0.0 ' ADC Enable bit: 1 = enabled, 0 = disabled.
Symbol LEDG = Portb.2 ' groene LED is output 2
Symbol LEDR = portb.3 ' rode LED is output 3
Delayms 500 ' Wait for the PICmicro to stabilise
Goto OVER_ADC_SUBS ' Jump over the subroutines
'---[START ADC CONVERSION]---
GET_ADC:
ADON = 1 ' Enable the ADC
Delayus 50 ' Wait for sample/hold capacitors to charge
GO_DONE = 1 ' Start conversion
While GO_DONE = 1 : Wend ' Poll the GO_DONE flag for completion of conversion
ADON = 0 ' Disable the ADC, to save power
Return
'---[INITIALISE THE ADC REGISTERS]---
' Standard procedures for setting up the ADC
OVER_ADC_SUBS:
TRISIO = %11111111 ' All pins set for input
Ansel.4 = 1 ' Setup ADC's clock for FRC (ADCS0)
ANSEL.5 = 1 ' Setup ADC's clock for FRC (ADCS1)
ANSEL.6 = 0 ' Setup ADC's clock for FRC (ADCS2)
ADCON0.6 = 1 ' VREF is set to extern zener diode (VCFG)
ADCON0.7 = 1 ' Right justify the ADC resul (ADFM)
ANSEL.0 = 0 ' Set AN0 (GPIO.0) as Digital input
ANSel.1 = 0 ' Set AN1 (GPIO.1) as Digital input
ANSEL.2 = 1 ' Set AN2 (GPIO.2) as Analogue input
ANSEL.3 = 1 ' Set AN3 (GPIO.3) as Analogue input
'---[MAIN PROGRAM LOOP STARTS HERE]---
While 1 = 1 ' Create an infinite loop
VAR1 = AD_Result
VAR1 = VAR1 * (0.006/100)
IF VAR1 >= 240 Then LEDG = 1
IF VAR1 >= 235 AND VAR1 < 240 Then LEDR = 1
DelayMS 250
IF VAR1 >= 235 Then LEDR = 0
IF VAR1 < 230 Then LEDR = 1
Delayms 50 ' Wait for another conversion
Wend
[Bericht gewijzigd door Henry S. op (0%)]
hadv
Just find out what you like and let it kill you
Weet je zeker dat je een 12F675 gebruikt?
Ik zie nl TRISB staan en deze uC kent alleen TRISIO.
Commentaar als PORTB en PORTA zal wel van een ander programma zijn geknipt en geplakt.
Vervolgens zet je met TRISIO alles op input, maar je zegt dat er led's aan moeten gaan. Dat gaat dus niet werken.
GET_ADC wordt overigens nergens aangeroepen, dus AD_Result zal een onvoorspelbare waarde hebben.
Ik heb het programma even gecompileerd...
Blijkt dat Proton PORTB gewoon herkent en implementeert als GPIO en TRISB als TRISIO.
Je programma doet het wel in de Sim van MPLab, maar noppes aan ADC.
In GPIO staan alle pinnen op input (logisch, dat heb je zelf zo aangezet).
Beste hadv, alvast bedankt voor uw antwoord, het is wel degelijk een 12F675 ik gebruik deze omdat ik de gratis versie van PROTON IDE gebruik. Ik heb enkele aanpassingen uitgevoerd, maar bezit niet de mogelijkheid om te testen, als het louter digitaal is lukt het allemaal vrij goed, maar ADC, eerlijk gezegd is misschien iets te hoog gegrepen. Alvast hieronder een nieuwe poging;
Device = 12F675
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, MCLRE_OFF
XTAL = 4
DECLARE ADIN_RES 10 ; 10-bit resultaat
DECLARE ADIN_TAD FRC ; interne OSC geselecteerd
DECLARE ADIN_STIME 50 ; selecteer 50µs sample tijd
TRISB = %00000011 ' Configure AN0 (PORTB.0 and 1) as an input
ADCON0 = %10000000 ' Set analogue input on PORTA.0
DIM VAR1 as WORD
Dim AD_RESULT as ADRESL.WORD ' Convert the ADRESL register into a WORD variable
' ADCON0 register's bits
Symbol GO_DONE = ADCON0.1 ' ADC Conversion status/ plus enable conversion-bit
Symbol ADON = ADCON0.0 ' ADC Enable bit: 1 = enabled, 0 = disabled.
Symbol LEDG = Portb.2 ' groene LED is output 2
Symbol LEDR = portb.3 ' rode LED is output 3
Delayms 500 ' Wait for the PICmicro to stabilise
Goto OVER_ADC_SUBS ' Jump over the subroutines
'---[START ADC CONVERSION]---
GET_ADC:
ADON = 1 ' Enable the ADC
Delayus 50 ' Wait for sample/hold capacitors to charge
GO_DONE = 1 ' Start conversion
While GO_DONE = 1 : Wend ' Poll the GO_DONE flag for completion of conversion
ADON = 0 ' Disable the ADC, to save power
Return
'---[INITIALISE THE ADC REGISTERS]---
' Standard procedures for setting up the ADC
OVER_ADC_SUBS:
Ansel.4 = 1 ' Setup ADC's clock for FRC (ADCS0)
ANSEL.5 = 1 ' Setup ADC's clock for FRC (ADCS1)
ANSEL.6 = 0 ' Setup ADC's clock for FRC (ADCS2)
ADCON0.6 = 1 ' VREF is set to extern zener diode (VCFG)
ADCON0.7 = 1 ' Right justify the ADC resul (ADFM)
ANSEL.0 = 0 ' Set AN0 (GPIO.0) as Digital input
ANSel.1 = 0 ' Set AN1 (GPIO.1) as Digital input
ANSEL.2 = 1 ' Set AN2 (GPIO.2) as Analogue input
ANSEL.3 = 1 ' Set AN3 (GPIO.3) as Analogue input
'---[MAIN PROGRAM LOOP STARTS HERE]---
While 1 = 1 ' Create an infinite loop
ADCON0 = ADCON0 | (2 << 2) ' Select the channel to read
Gosub GET_ADC ' Perform an ADC conversion
VAR1 = AD_Result
VAR1 = VAR1 * (0.006/100)
IF VAR1 >= 240 Then LEDG = 1
IF VAR1 < 238 AND VAR1 > 236 Then LEDR = 1
DelayMS 250
IF VAR1 >= 235 Then LEDR = 0
IF VAR1 < 230 Then LEDR = 1
Delayms 50
Wend
[Bericht gewijzigd door Henry S. op (0%)]
Device = 12F675
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, MCLRE_OFF
XTAL = 4
Dit klopt al niet, je zegt dat je de interne clock gebruikt maar je zet er XTAL = 4 bij.
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %001011 ; in en uitgangen
Je poorten zet je zo neer.
;76543210 ; hulpregel controlregister
ADCON0 = %00000001 ; A/D control register
Zo zet je je adcon neer.
Je hebt nu in je programma gedifinieerd dat je tien bits gebruikt, is dat nodig. Met acht bits werkt dit net zo goed, dan heb je 0.0196078 / V per stapje.
hadv
Just find out what you like and let it kill you
Goed, de volgende ronde...
Wat doet de volgende regel?
ADCON0 = ADCON0 | (2 << 2) ' Select the channel to read
Het ziet er naar uit dat je twee verschillende kanalen wilt gebruiken. Eerlijk gezegd krijg ik jeuk van dit soort C constructies omdat ik nooit precies weet hoe het werkt. Bovendien vraag ik me af of je wel bitwise mag shiften op een constante...waar moet de compiler het resultaat laten?
En zelfs al zou het kunnen, wat is het effect?
De kanalen zitten op bits 2 en 3 van het ADCON0 register en je verandert ook de rest van het ADCON0 register...
Ik zie overigens nergens code die iets met de referentie doet en de code die je gebruikt doet dus voor beide kanalen het zelfde...
Wat doet de volgende regel?
VAR1 = VAR1 * (0.006/100)
Let op: VAR1 is een Word, maar je gebruikt een float berekening. Zou zomaar helemaal niet goed kunnen gaan.
Stel, ADRESL bevat 255 en stel dat Proton dat in runtime gewoon floating point uitrekent...255 * 0,006 / 100 = 0,0153.
Zeg maar 0.
Wat doet de volgende regel?
IF VAR1 < 238 AND VAR1 > 236 Then LEDR = 1
If VAR1 = 237 then LEDR = 1
Wat doet de while-wend 1=1 lus?
Haal de Analoge waarde op
Maak er een heeeeeel klein getal van
Laat LEDG misschien branden (die blijft wsl altijd uit)
Laat LEDR misschien branden (idem)
wacht effekes
Zet LEDR aan of uit (dat wordt wsl altijd aan)
wacht heel effekes
...en weer van voor af aan
Het effect is een knipperende LEDR zonder enige relatie met de ingangsspanning.
ADC testen zonder bv een display is best lastig, maar er zijn wel trucjes voor.
De manier waarop jij dat doet is overigens een prima voorbeeld van zo'n trucje.
Om zeker te zijn dat je de boel goed hebt aangesloten en geconfigureerd kun je het volgende doen:
Sluit een potmeter aan met de ene kant aan de 5v en de andere kant aan de gnd. Hang de loper aan de AD-ingang.
Onderdruk even alle instellingen van het ADCON0 register zodat Proton de zaak kan instellen.
Pas je mainloop zodanig aan dat je bv 3 ledjes laat branden afhankelijk van de AD-waarde, bv
while 1 = 1
Led1 = 0
Led2 = 0
Led3 = 0
VAR1 = ADIN x ; de x is het kanaal dat je gebruikt
select VAR1
case 0 - 85: Led1 = 1
case 86 - 170: Led2 = 1
case 171 - 255: Led3 = 1
endselect
whend
draai aan de as van de pot om te zien of het zaakje het doet.
hier heb je een voorbeeld:
Device 12F675 ; processor type
XTAL 10 ; crystal 10 Mhz
Config WDT_OFF,_ ; WatchDog Timer uit
PWRTE_ON,_ ; Power-up Timer Enable aan
MCLRE_OFF,_ ; Externe Master Reset Enable uit
HS_OSC ; X-tal groter dan 4MHz
ALL_DIGITAL true ; alle poorten digitaal
Symbol aan = 1 ; 1 is hoog
Symbol uit = 0 ; 0 is laag
Symbol led = GPIO.2 ; led op poort_2
Declare ADIN_RES = 8 ; resolutie 8 bits
Declare ADIN_TAD = frc ; Set rc osc
Declare ADIN_STIME = 50 ; sample tijd 5
Dim potmeter As Byte ; variabele potmeter
Clear ; wis geheugen
DelayMS 1000 ; stabilisering
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %000001 ; poort I/O
;76543210 ; hulpregel control register
ADCON0 = %00000001 ; A/D control register
run: ; run programma
potmeter = ADIn 0 ; potmeter op analoog_0
If potmeter > 250 Then ; als potmeter groter is als 250 dan
led = aan ; led is aan
If potmeter < 200 Then ; als potmeter kleiner is dan 200 dan
led = uit ; led is uit
EndIf ; einde als
EndIf ; einde als
GoTo run ; ga naar run programma
End ; einde programma
Probeer dit eest eens aan de praat te krijgen, en dan kan je er je eigen aanvulling aan geven.
En zorg er voor dat pin_4 (MCLRE) van je 12F675 via een 10K weerstand aan de 5VDC ligt. En deze pin kan alleen als ingang of als reset gebruikt worden.
Je XTAL en je Config even aanpassen natuurlijk.
Beste Lambiek en hadv ik ga achter een potmeter van 10K en probeer dit alvast uit, ik begrijp dus als ik de potmeter vervang door de spanning van de batterij via een spanningsdeler in te lezen dat ik in feite hetzelfde resultaat krijg.
Ik laat iets weten...
hadv
Just find out what you like and let it kill you
Op 16 januari 2012 21:27:27 schreef Lambiek:
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, MCLRE_OFF XTAL = 4Dit klopt al niet, je zegt dat je de interne clock gebruikt maar je zet er XTAL = 4 bij.
Lambiek, dat klopt wel. Ook al gebruik je een interne oscillator, dan nog moet je Proton laten weten op welke snelheid deze draait omdat deze waarde wordt gebruikt voor alle tijd-gerelateerde berekeningen.
4MHz wordt automatisch aangenomen als je geen waarde opgeeft.
If the Declare is not used in the program, then the default frequency is 4MHz.
Het is voor de duidelijkheid wel handig altijd de Xtal declaratie te gebruiken.
Hallo hier ben ik terug schakeling gemaakt met pot de LED gaat aan maar gaat dan niet meer uit, als ik de spanning weghaal en opnieuw begin is het net hetzelfde moet ik ergens het geheugen niet resetten er staat ergens een clear commando maar moet dat niet in het RUN programma staan en wat doen beide endif daar... alvast het ding werkt nu analoog in en digitaal uit wat ben ik blij... hoe configureer ik dit signaal naar bijvoorbeeld de helft van de voedingsspanning
Die endif was er teveel aan... en XTAL = 4 toch terug geplaatst hieronder het aangepast programma.
Device 12F675 ; processor type
XTAL = 4
Config WDT_OFF,_ ; WatchDog Timer uit
PWRTE_ON,_ ; Power-up Timer Enable aan
MCLRE_OFF,_ ; Externe Master Reset Enable uit
INTRC_OSC_NOCLKOUT ; Gebruik interne klok
ALL_DIGITAL true ; alle poorten digitaal
Symbol aan = 1 ; 1 is hoog
Symbol uit = 0 ; 0 is laag
Symbol led = GPIO.2 ; led op poort_2
Declare ADIN_RES = 8 ; resolutie 8 bits
Declare ADIN_TAD = frc ; Set rc osc
Declare ADIN_STIME = 50 ; sample tijd 50µs
Dim pot1 As Byte ; variabele potmeter
Clear ; wis geheugen
DelayMS 1000 ; stabilisering
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %000001 ; poort I/O
;76543210 ; hulpregel control register
ADCON0 = %00000001 ; A/D control register
run: ; run programma
pot1 = ADIn 0 ; potmeter op analoog_0
If pot1 > 250 Then led = aan ; als potmeter groter is als 250 dan led is aan
If pot1 < 200 Then led = uit ; als potmeter kleiner is dan 200 dan led is uit
GoTo run ; ga naar run programma
End ; einde programma
Mod-edit: De edit en code-tags gebruiken, zie de FAQ.
[Bericht gewijzigd door Henry S. op (66%)]
Stan1
Read the fuc.... manual and read the fuc.... datasheet! {Proton IDE: V2.0.1.2 / Proton Compiler: V3.5.4.5}
Waarschijnlijk schommelt de waarde een beetje en blijft deze hoger dan 200 en dan zal deze nooit uit gaan, pak een weerstandje van bijvoorbeeld 10K en trek de AD ingang naar gnd.
@ Stan1,
Dat kan natuurlijk niet, als je de potmeter goed aansluit dan wordt de waarde op de loper groter of kleiner. Je draaid hem naar de plus of de gnd.
@ Flaybaby,
Dit moet werken zo, hier werkt het ook.
hadv
Just find out what you like and let it kill you
Stan1
Read the fuc.... manual and read the fuc.... datasheet! {Proton IDE: V2.0.1.2 / Proton Compiler: V3.5.4.5}
Op 17 januari 2012 22:24:05 schreef Lambiek:
@ Stan1,
Dat kan natuurlijk niet, als je de potmeter goed aansluit dan wordt de waarde op de loper groter of kleiner. Je draaid hem naar de plus of de gnd.
Dat ben ik met je eens, alleen heeft de TS vermoedelijk de pot alleen aan de Vcc hangen.
De potmeter is tussen VCC en GND aangesloten de schakeling werkt met het laatste programma nu heb ik nog één vraag i.v.m. ADC.
Kan ik een tweede spanning aan bv. GP1 aansluiten en hoe ziet dan het programma er uit:
TRISIO = %000011 ; poort I/O
;76543210 ; hulpregel control register
ADCON0 = %00000011 ; A/D control register
run: ; run programma
pot1 = ADIn 0 ; potmeter op analoog_0
pot2 = ADIn 1 ; potmeter op analoog_1
If pot1 > pot2 Then led = aan
enz....
Ik zie reeds een klein lichtje aan het eind van de tunnel...
Probeer het zo eens, zo moet het zeker werken.
run:
potmeter = ADIn 0
If potmeter > 250 Then
led = aan
endif
potmeter = ADin 0
If potmeter < 100 Then
led = uit
EndIf
GoTo run
End
EDIT:
En in jou geval erbij zetten:
Else led = uit
Hey Lambiek, het werkt, heb je mijn vorige en laatste vraag gezien i.v.m. een tweede ADIN op poort 1...
De EndIf geeft een fout bij compilen als ik hem gebruik zoals in uw voorbeeld; onderstaande werkt wel. Nu nog een tweede ADIN, is onderstaande mogelijk.?
pic basic code:
Device 12F675 ; processor type
XTAL = 4
Config WDT_OFF,_ ; WatchDog Timer uit
PWRTE_ON,_ ; Power-up Timer Enable aan
MCLRE_OFF,_ ; Externe Master Reset Enable uit
INTRC_OSC_NOCLKOUT ; Gebruik interne klok
ALL_DIGITAL true ; alle poorten digitaal
Symbol aan = 1 ; 1 is hoog
Symbol uit = 0 ; 0 is laag
Symbol ledr = GPIO.2 ; ledr op poort_2
Symbol ledg = GPIO.3 ; ledg op poort_3
Declare ADIN_RES = 8 ; resolutie 8 bits
Declare ADIN_TAD = frc ; Set rc osc
Declare ADIN_STIME = 50 ; sample tijd 50µs
Dim pot1 As Byte ; variabele potmeter 1
Dim pot2 As Byte ; variabele potmeter 2
Clear ; wis geheugen
DelayMS 1000 ; stabilisering
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %000011 ; poort I/O
;76543210 ; hulpregel control register
ADCON0 = %00000011 ; A/D control register
run: ; run programma
pot1 = ADIn 0 ; potmeter op analoog_0
If pot1 > 250 Then ledr = aan ENDIF ; als potmeter groter is als 250 dan led is aan
If pot1 < 200 Then ledr = uit EndIf ; als potmeter kleiner is dan 200 dan led is uit
pot2 = ADIn 1
If pot2 > 250 Then ledg = aan ENDIF ; als potmeter groter is als 250 dan led is aan
If pot2 < 200 Then ledg = uit EndIf ; als potmeter kleiner is dan 200 dan led is uit
GoTo run ; ga naar run programma
End
[Bericht gewijzigd door Henry S. op (88%)]
zo zou het moeten werken
TRISIO = %000011
;76543210
ADCON0 = %00000011
run:
pot1 = ADIn 0
pot2 = ADIn 1
If pot1 > pot2 Then
led = aan
else led = uit
eindif
end
Dringend verzoek aan de TS de FAQ eens te gaan lezen!
Als ik VREF wil gebruiken moet ik het ADCON0 = %01000001 aldus definiëren maar moet ik dan ook het TRISIO = % 00000011 als analoog input definiëren ik denk van wel maar ben niet zeker.
Wat doe ik verkeerd... ik wil absoluut GPIO3 als analoge ingang gebruiken kan iemand mij hier verder helpen
Device 12F675 ; processor type
XTAL = 4 ; crystal 4Mhz
Config WDT_OFF,_ ; WatchDog Timer uit
PWRTE_ON,_ ; Power-up Timer Enable aan
MCLRE_OFF,_ ; Externe Master Reset Enable uit
HS_OSC ; X-tal groter dan 4MHz
ALL_DIGITAL true ; alle poorten digitaal
Symbol aan = 1 ; 1 is hoog
Symbol uit = 0 ; 0 is laag
Symbol led = GPIO.2 ; led op poort_2
Declare ADIN_RES = 8 ; resolutie 8 bits
Declare ADIN_TAD = frc ; Set rc osc
Declare ADIN_STIME = 50 ; sample tijd 5
Dim potmeter As Byte ; variabele potmeter
Clear ; wis geheugen
DelayMS 1000 ; stabilisering
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %000000 ; poort I/O
ANSEL = %001000
;76543210 ; hulpregel control register
ADCON0 = %00000001 ; A/D control register ;
run: ; run programma
potmeter = ADIn 3 ; potmeter op analoog_0
If potmeter > 250 Then ; als potmeter groter is als 250 dan
led = aan ; led is aan
If potmeter < 200 Then ; als potmeter kleiner is dan 200 dan
led = uit ; led is uit
EndIf ; einde als
EndIf ; einde als
GoTo run ; ga naar run programma
End ; einde programmaJe zet dit neer:
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %000000 ; poort I/O
ANSEL = %001000
Bij TRISIO heb je alles als uitgang staan, je moet AN3 wel als ingang zetten natuurlijk.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Het moet zo worden:
;543210 ; hulpregel
GPIO = %000000 ; maak poort laag
TRISIO = %010000 ; poort I/O
;76543210 ; hulp regel
ANSEL = %00001000 ; ansel register
;76543210 ; hulpregel control register
ADCON0 = %00000001 ; A/D control
[Bericht gewijzigd door Lambiek op (15%)]
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com