Sensor ADC 16F877a picbasic

Hallo,

Mijn naam is Daan Zeeuwe en ik heb een raar probleem met mijn 16F877a.
Ik ben bezig met de ADC functie van de 16F877a en ik gebruik de volgende code.

Device 16F877A

;CONFIG HS_OSC,PWRTE_ON,CP_OFF,WDT_OFF,BODEN_ON ;, MCRLE_OFF
Config CP_OFF , CPD_OFF , WDT_OFF , HS_OSC , PWRTE_ON , BODEN_OFF , LVP_OFF , DEBUG_OFF
All_Digital TRUE

Xtal=20

Declare LCD_Type 0
Declare LCD_Interface 4 ' 4-bit Interface
Declare LCD_Lines 4

Declare LCD_ENPin PORTC.1
Declare LCD_RSPin PORTC.0
Declare LCD_DTPin PORTB.0

'Read the value from channel 0 of the ADC and place in variable VAR1.
Adin_Res = 8 ;ADC resolutie
Adin_Tad = FRC ;de clock voor de adc extern / intern
Adin_Stime = 40;De conversie tijd

; 76543210
TRISA = %00000001
ADCON1= %01000000 ;adc instellen op de goede poorten RTFM
TRISB = %00000000 ;
TRISC = %11111100 ;

Dim adin1 As Word ;variabelen
Dim waardebuffer As Word

Clear

While 1=1
adin1 = ADIn 0
If waardebuffer <> adin1 Then ;tegen het nutteloos opnieuw op het display schrijven.
Cls
Print At 1,1, Dec adin1, " "
DelayMS 100
waardebuffer = adin1
EndIf
If adin1 > 30 And adin1 < 50 Then
DelayMS 500
ElseIf adin1 > 50 Then
DelayMS 500
EndIf ;20mSec = 50Hz, eventueel wijzigen bij ander type motor
Wend

End

Zelfs als ik de sensor niet aangesloten heb op de 16F877a PORTA.0 dan komt er al een waarde van rond de 110 op te staan en dan gaat hij langzamerhand naar beneden.
Mijn vraag is hoe komt dat en hoe kan ik dit voorkomen.
Kan dit liggen aan de condesatoren 22 uF en 0.1 uF condensator.
Of door mijn schakeling?
http://s1211.photobucket.com/albums/cc426/daanz1/?action=view&curr…
Ik heb trouwens ook de servo's even voor de zekerheid losgekopelt.

Weet iemand altublieft wat ik moet doen, want ik kom er niet meer uit.

Hoogachtend,
Daan Zeeuwe

Op 4 januari 2012 11:00:22 schreef dazes:
Hallo,

Mijn naam is Daan Zeeuwe en ik heb een raar probleem met mijn 16F877a.
Ik ben bezig met de ADC functie van de 16F877a en ik gebruik de volgende code.

Device 16F877A

;CONFIG HS_OSC,PWRTE_ON,CP_OFF,WDT_OFF,BODEN_ON ;, MCRLE_OFF
Config CP_OFF , CPD_OFF , WDT_OFF , HS_OSC , PWRTE_ON , BODEN_OFF , LVP_OFF , DEBUG_OFF
All_Digital TRUE

Xtal=20

Declare LCD_Type 0
Declare LCD_Interface 4 ' 4-bit Interface
Declare LCD_Lines 4

Declare LCD_ENPin PORTC.1
Declare LCD_RSPin PORTC.0
Declare LCD_DTPin PORTB.0

'Read the value from channel 0 of the ADC and place in variable VAR1.
Adin_Res = 8 ;ADC resolutie
Adin_Tad = FRC ;de clock voor de adc extern / intern
Adin_Stime = 40;De conversie tijd

; 76543210
TRISA = %00000001
ADCON1= %01000000 ;adc instellen op de goede poorten RTFM
TRISB = %00000000 ;
TRISC = %11111100 ;

Dim adin1 As Word ;variabelen
Dim waardebuffer As Word

Clear

While 1=1
adin1 = ADIn 0
If waardebuffer <> adin1 Then ;tegen het nutteloos opnieuw op het display schrijven.
Cls
Print At 1,1, Dec adin1, " "
DelayMS 100
waardebuffer = adin1
EndIf
If adin1 > 30 And adin1 < 50 Then
DelayMS 500
ElseIf adin1 > 50 Then
DelayMS 500
EndIf ;20mSec = 50Hz, eventueel wijzigen bij ander type motor
Wend

End

Zelfs als ik de sensor niet aangesloten heb op de 16F877a PORTA.0 dan komt er al een waarde van rond de 110 op te staan en dan gaat hij langzamerhand naar beneden.
Mijn vraag is hoe komt dat en hoe kan ik dit voorkomen.
Kan dit liggen aan de condesatoren 22 uF en 0.1 uF condensator.
Of door mijn schakeling?
Of aan de BAT85?
http://s1211.photobucket.com/albums/cc426/daanz1/?action=view&curr…
Ik heb trouwens ook de servo's even voor de zekerheid losgekopelt.

Weet iemand altublieft wat ik moet doen, want ik kom er niet meer uit.

Hoogachtend,
Daan Zeeuwe

Lambiek

Special Member

Zet je adcon eens zo neer.

pic basic code:


         ;76543210                     ; Hulp regel analoog
ADCON0 = %00000001                     ; Analooge ingang 

En ik hang altijd een pulldown weerstand van 100K naar de gnd.
(Van je sensor signaal naar de gnd.)

Als je haar maar goed zit, GROETEN LAMBIEK.

Ik heb 22k ohm, de grootste die ik heb, gehangen van porta.1 naar de ground.
De ADCON0 heb ik toegevoegd, maar nu geeft hij alleen maar 1 of 0 aan.

Op 4 januari 2012 11:45:24 schreef dazes:
Ik heb 22k ohm, de grootste die ik heb, gehangen van porta.1 naar de ground.
De ADCON0 heb ik toegevoegd, maar nu geeft hij alleen maar 1 of 0 aan.

porta.0, pardon

Arco

Special Member

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

een afstandsensor van conrad
Overige technische gegevens:Uitgang: (positief, analoog) 0.4 - 1,9 V
Tolerantie:0,5 cm
Type: GP2Y0A21YK0F
Meetbereik:(detectiebereik) 10 - 80 cm
Conform RoHS:Ja
Voedingsspanning:5 V/DC

Arco

Special Member

De uitgangsweerstand van de sensor moet wel <= 2.5K zijn, anders werkt de D/A converter niet goed.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ik heb een 2,2 k ohm en 1k ohm weerstand geprobeerd, maar niets helpt.
Als ik er helemaal geen weerstand in doe dat zit de waarde steeds tussen de 255 en de 0.

M-i-c-h-e-l

Golden Member

Goeiedag, welkom op het forum.

Even het datasheetje erbij.

Je routine klopt van geen kanten.
Even hoofdstuk 11 van de datasheet erbij nemen.

Initialiseer port a (bit 0 = input)
Initialiseer adc
* ADCON0 Bit 3, 4 en 5 = 0 (adc channel 0)
* ADCON0 Bit 6 en 7 -> clock conversion
ADCON1 Bit 6 -> clock conversion
* ADCON0 Bit 2 -> GO/DONE-bit = Flag om te pollen of conversie klaar is
* ADCON0 Bit 0 -> ADON-bit Deze moet worden aangezet om uberhaupt een conversie te kunnen doen.

* ADCON1 Bit 3, 2, 1 en 0 = 0 -> je referentie is de spanning tussen Vss en Vdd
* ADCON1 Bit 7 -> resultaat links of rechts uitlijnen.

Je start je conversie door ADON = 1
Wanneer de conversie klaar is: GO/DONE-bit = 0
Het resultaat staat in ADRESH en ADRESL.
De volgende conversie start je door GO/DONE = 1
Weer pollen totdat ie 0 wordt, etc.

Het makkelijkst is om even een potmetertje aan de ingang te hangen, dan kun je even testen of je de gewenste spanning terugvindt in je gemeten resultaat.

Als je de ingang open laat, kun je willekeurige waardes verwachten om dat de ingang dan zweeft.

Wat raar dat dit zelfde het gister nog deed.
Als eerste deze om porta.0 te initialiseren.
TRISA = %00000001
Dan moet ik het volgende doen om clock conversion te krijgen, go/done-bit te activeren en adon-bit aanzetten om uberhaupt iets te kunnen converseren.
ADCON0= %11000101
Dan hoef ik niets met de adcon1 te doen, omdat het toch niet uitmaakt of je het links dan wel rechts uitlijnt.

dus in de while zet ik dan als eerst adon = 1 om de sensor uit te lezen.
Dan moet deze op nul gezet worden, GO/DONE-bit = 0 om te beginnen met uitlezen.
Hoe laat ik vervolgens dan de waarde uitlezen??? Moet ik dan zeggen waarde = ADRESH???
DE volgende uitlezen doe ik met GO/DONE = 1.

Dus de code moet alsvolgt zijn:

Device 16F877A

;CONFIG HS_OSC,PWRTE_ON,CP_OFF,WDT_OFF,BODEN_ON ;, MCRLE_OFF
Config CP_OFF , CPD_OFF , WDT_OFF , HS_OSC , PWRTE_ON , BODEN_OFF , LVP_OFF , DEBUG_OFF
All_Digital TRUE

Xtal=20

Declare LCD_Type 0
Declare LCD_Interface 4 ' 4-bit Interface
Declare LCD_Lines 4

Declare LCD_ENPin PORTC.1
Declare LCD_RSPin PORTC.0
Declare LCD_DTPin PORTB.0

'Read the value from channel 0 of the ADC and place in variable VAR1.
Adin_Res = 8 ;ADC resolutie
Adin_Tad = FRC ;de clock voor de adc extern / intern
Adin_Stime = 100;De conversie tijd

; 76543210
TRISA = %00000001
ADCON0= %11000101
TRISB = %00000000 ;
TRISC = %11111100 ;

Dim waarde As Word ;variabelen
Dim waardebuffer As Word

Clear

adon = 1 ; om te kunnen converseren

While 1=1
GO/DONE = 0 ; om een converseren te starten
waarde = ADRESH ; om de sensor uit te lezen
GO/DONE = 1 ; om het converseren te stoppen
If waardebuffer <> waarde Then
Cls
Print At 1,1, Dec adin1, " "
DelayMS 100
waardebuffer = waarde
EndIf
Wend

End

Toch ?!

Device 16F877A

;CONFIG HS_OSC,PWRTE_ON,CP_OFF,WDT_OFF,BODEN_ON ;, MCRLE_OFF
Config CP_OFF , CPD_OFF , WDT_OFF , HS_OSC , PWRTE_ON , BODEN_OFF , LVP_OFF , DEBUG_OFF
All_Digital TRUE

Xtal=20

Declare LCD_Type 0
Declare LCD_Interface 4 ' 4-bit Interface
Declare LCD_Lines 4

Declare LCD_ENPin PORTC.1
Declare LCD_RSPin PORTC.0
Declare LCD_DTPin PORTB.0

'Read the value from channel 0 of the ADC and place in variable VAR1.
Adin_Res = 8 ;ADC resolutie
Adin_Tad = FRC ;de clock voor de adc extern / intern
Adin_Stime = 100;De conversie tijd

; 76543210
TRISA = %00000001
ADCON0= %11000001
TRISB = %00000000 ;
TRISC = %11111100 ;

Dim waarde As Word ;variabelen
Dim waardebuffer As Word

Clear

While 1=1
ADCON0= %11000101 ; om een converseren te starten
waarde = ADRESH ; om de sensor uit te lezen
ADCON0= %11000001 ; om het converseren te stoppen
If waardebuffer <> waarde Then
Cls
Print At 1,1, Dec waarde, " "
DelayMS 100
waardebuffer = waarde
EndIf
Wend

End

er komt nu helemaal niets op het scherm te staan :(

M-i-c-h-e-l

Golden Member

Ik denk dat de beheerder van dit forum niet blij is dat je telkens een nieuwe post maakt. Je kunt je post ook editen (=bewerken).

Ik zou als ik jou was, eenvoudig beginnen.
PIC, een ledje aan een uitgang, en een potmeter aan een ingang.

Doe je adcmeting, en als je gemeten waarde groter is dan bijvoorbeeld 10, laat dan de led 1x knipperen.
Als de waarde groter is dan 50, laat 'm dan 2x knipperen. etc.
Zo kun je eerst testen of je adc goed werkt.

Als dat werkt, kun je je gaan bezighouden met je lcd-display. En kijken of je de gemeten waarde op je display krijgt.

----
Over die adc, ik zal een stuk code invoegen (wel in de taal c) dat goed werkt.

Het is de bedoeling dat je gaat begrijpen wat je doet, anders kom je niet ver ben ik bang.

code:


int adc_measure(char channel)
{  
//ga ervan uit: het 16bits getal is rechts uitgelijnd (ADFM=1)

  int retval=0;
  adcon0.GO_DONE = 1;	
  // Wait until it is done
  while(adcon0.GO_DONE);

  retval = (short)adresh;       //haal adresh op
  retval = retval << 8;         //schuif het naar links in het integer
  retval |= adresl;             //zet adresl op z'n plek
  //retval>>=2;
  retval &= 0b0000001111111111; //maak de eerste 6 bits "0"
  return retval;	
}

void main(void){
trisa=0;
porta=0;
trisb=0;            //outputs
portb=0;
trisc=0b10000000;   //bit7 = input voor analoge input 9, rest outputs
portc=0;

unsigned char adc;

int ADCMeting=0;

//Initialise ADC
set_bit( anselh, ANS9 );   //configureer AN0 als analoge ingang
set_bit( adcon0, ADFM );   // AD resultaat rechts uitgelijnd (over de 2 bytes) 

set_bit( adcon1, ADCS0 );  //Fosc/8
clear_bit( adcon1, ADCS1 );
clear_bit (adcon1, ADCS2 );

set_bit( adcon0, CHS0 );   // Channel AN9
clear_bit( adcon0, CHS1 );         
clear_bit( adcon0, CHS2 ); 
set_bit( adcon0, CHS3 );   

clear_bit( adcon0, VCFG ); //Reference voltage = Vdd
volatile bit adc_on @ ADCON0 . ADON; //definieer ADON-bit
volatile bit adc_go @ ADCON0 . GO;   //defineer go-bit
adc_on = 1;                          //enable adc


//-------------------------------------------------------------------
while(1){

    adc_go=1;                           //start conversie
    ADCMeting = adc_measure( 9 );

}

Device 16F877A

;CONFIG HS_OSC,PWRTE_ON,CP_OFF,WDT_OFF,BODEN_ON ;, MCRLE_OFF
Config CP_OFF , CPD_OFF , WDT_OFF , HS_OSC , PWRTE_ON , BODEN_OFF , LVP_OFF , DEBUG_OFF
All_Digital TRUE

Xtal=20

Declare LCD_Type 0
Declare LCD_Interface 4 ' 4-bit Interface
Declare LCD_Lines 4

Declare LCD_ENPin PORTC.1
Declare LCD_RSPin PORTC.0
Declare LCD_DTPin PORTB.0

'Read the value from channel 0 of the ADC and place in variable VAR1.
Adin_Res = 8 ;ADC resolutie
Adin_Tad = FRC ;de clock voor de adc extern / intern
Adin_Stime = 50;De conversie tijd

; 76543210
TRISA = %00000001
ADCON0= %11001001
TRISB = %00000000 ;
TRISC = %11111100 ;
TRISD = %00000001

Dim waarde As Word ;variabelen

Clear

While 1=1
waarde = ADIn 0 ; om de sensor uit te lezen
If waarde > 100 Then
Low PORTD.0
DelayMS 500
High PORTD.0
DelayMS 500
ElseIf waarde < 100 Then
Low PORTD.0
DelayMS 100
High PORTD.0
DelayMS 100
EndIf
Wend

End

Ik heb dit met een potentiometer geprobeerd en dan gaat het uitstekend.
Maar als ik de sensor, zonder weerstand, erin doe, duurt het erg lang voordat hij doorheeft dat mijn in de buurt van de camera zit of dat ik allang weer mijn hand heb weggehaald. Dit duurt ongeveer 5 seconde.
ADON = 0 is voor mij denk ik de enige manier hoe ik de ADC functie kan gebruiken.
Ik gebruik geen weerstand bij de sensor omdat dit niet helpt, ik krijg dan gewoon geen signaal.
Kan iemand mij verder helpen waarom het met de sensor niet gaat en met de potentiometer wel?

M-i-c-h-e-l

Golden Member

Goed bezig.

Je ADC-routine werkt dus.
Kun je ook waarden op je lcd-display weergeven? Zodat je zeker weet dat de aansturing van het display goed werkt?

Wat is de impedantie van je sensor?
Klopt dat met de ingangsimpedantie van je analoge ingang van de picf877?
Wat geeft de datasheet van de sensor aan, voor de reactiesnelheid?
Ofwel: welke tijd moet je minimaal verwachten om een verandering waar te nemen?

Overige technische gegevens:Uitgang: (positief, analoog) 0.4 - 1,9 V
Tolerantie:0,5 cm
Type: GP2Y0A21YK0F
Meetbereikdetectiebereik) 10 - 80 cm
Conform RoHS:Ja
Voedingsspanning:5 V/DC
Distance measuring operation : 38.3 ms +- 9.6 ms.

Ik zal even kijken wat er op de lcd komt te staan.

Hij blijft tussen de 255 en 0 dwarrelen.
Ik snap nog steeds niet wat ik precies met de signaal van de sensor moet doen, moet ik er een potentiometer aan schakelen of juist niet, en hoe dan???

[Bericht gewijzigd door dazes op woensdag 4 januari 2012 20:02:04 (25%)

Ik denk dat het niet aan mij ligt maar aan de sensor, waarschijnlijk is hij kapot want hij blijft maar tussen de 0 en 255 hangen en als ik het signaal door een led heen haal zie ik niets, waarschijnlijk omdat hij te snel spanningswisselingen zijn.
Ik ga twee nieuwe sensoren bestellen en dan zie ik wel verder.

Ik wil de volgende personen bedanken die me hebben geholpen:
M-i-c-h-e-l
Arco
Lambiek

Bedankt voor jullie hulp en hopelijk zie ik jullie weer eens op het forum.

Hoogachtend,
Daan Zeeuwe

M-i-c-h-e-l

Golden Member

Als je iets wilt leren, lees dan even mee.
Hier vind je bijvoorbeeld de datasheet van je sensor.
Zo'n datasheet vertelt je alles wat je nodig hebt om die sensor goed te laten werken.

Dan zie je:
* Hij heeft voeding nodig. Dat zit goed in jou schakeling.
* Aansluitingen: 3=voeding, 2=ground, 1=uitgang.
Volgens mij heb je de pennen 1 en 2 omgewisseld.
Zet die eens goed en meet dan nog 's?

Ik hoop voor je dat je sensor en pic deze fout overleefd hebben.

Waarschijnlijk heb ik een keer per ongeluk de sensor verkeerd aangesloten, want deze doet het niet.
Gelukkkig doet mijn 16F877a het nog wel.

M-i-c-h-e-l

Golden Member

Dat zou jammer zijn.

Weet je zeker dat ie kaduuk is?
(even los aansluiten op voeding en de output aan een multimeter hangen)

ja de sensor is echt stuk. 0.00 volt door een weerstand.

Maar alle nogmaals bedankt voor jullie hulp.

M-i-c-h-e-l

Golden Member

Graag gedaan.
Ik hoor graag van je of het je alsnog gaat lukken je sensor uit te meten met de controller.