# Συζήτηση Κυκλωμάτων > Ψηφιακά Κυκλώματα > Μικροελεγκτές >  >  millivolts reading με PIC

## billtech

καλησπερα παιδια,
 προσπαθω με εναν pic18452 να διαβασω την πτωση τασης πανω σε μια αντισταση αλλα οταν πατω το button και το αφηνω για να παει να κανει μετρηση καθε φορα διαβαζει διαφορετικη ταση.
σαν vref εχω βαλει εξωτερικη σταθερη στα 1.25V
για να εχω καλυτερη αναλυση.
δλδ να ειναι 1.25V/1023 = 0,001222 volts βημα.
πως να το κανω να διαβαζει σταθερα την ιδια τιμη? αφου το ρευμα που περνα απο την αντισταση ειναι σταθερο και σεταρισμενο?

----------


## SV1JRT

> καλησπερα παιδια,
>  προσπαθω με εναν pic18452 να διαβασω την πτωση τασης πανω σε μια αντισταση αλλα οταν πατω το button και το αφηνω για να παει να κανει μετρηση καθε φορα διαβαζει διαφορετικη ταση.
> σαν vref εχω βαλει εξωτερικη σταθερη στα 1.25V
> για να εχω καλυτερη αναλυση.
> δλδ να ειναι 1.25V/1023 = 0,001222 volts βημα.
> πως να το κανω να διαβαζει σταθερα την ιδια τιμη? αφου το ρευμα που περνα απο την αντισταση ειναι σταθερο και σεταρισμενο?




 Για ανέβασε κώδικα και κύκλωμα βρε Bill να δούμε τι εχεις κάνει....
 Ετσι χωρίς να έχουμε ιδέα, πώς να σε βοηθήσουμε ??

----------


## billtech

αυτος ο απλος κωδικας ειναι 




```
program ref

' Declarations section 

dim res,res1,res2 as float
dim txt as string[20]
    Text,Text1 as string[10]

main:
'   Main program
 ADCON1     = $81                       ' configure VDD as Vref, and analog channels
      TRISA      = $FF                       ' designate porta as input
      UART1_Init(9600)
      TrisB = 255
      portB = 255
      Text  =  "Voltage:  "                     ' assign text to string a
      Text1  = "Resistor: "                    ' assign text to string a

      UART1_Write_text("Ready")
      UART1_Write(10)                      ' Line Feed
      UART1_Write(13)                      ' Carriage Return

while(1)
     if PortB.4 = 1 then
        while portb.4=1 wend
          res=ADC_read(2)    'TIMES APO 0 EOS 1023 //Read ADC value from channel #2 (res E [0..1023])

          res1= (res*1.25)/1023.      'METATREPOUME SE Volt  //Scale res to [0..0.55]
'          res1 = res1/1000
          floattostr(res1,txt)     ' Convert float to string
          txt[6]=0             ' Truncate string to 3 decimals

          UART1_Write_text(Text)
          UART1_Write_text(txt)
          UART1_Write_text("V")
          UART1_Write(10)                      ' Line Feed
          UART1_Write(13)                      ' Carriage Return

    end if
    delay_ms(100)
wend
end.
```

----------


## SV1JRT

Bill,  απο ότι βλέπω στα γρήγορα, δεν έχεις ρυθμίσει τις πορτες σου ώς αναλογικές.
Χρησημοποίησε την εντολή ANSEL και ANSELH για να ορίσεις ποιά pin είναι αναλογικά.
Το datasheet του PIC πρέπει να σου δινει τις τιμές για τις δύο εντολές.
 Αν δεν βγάλεις ακρη, θα το κοιτάξω πάλι αυριο που θα έχω περισσότερο χρόνο.

----------


## billtech

μα αφου το κανω ηδη εδω

ADCON1     = $81

και επισης η κατασκευη δουλευει. μα διαβαζει διαφορετικες τιμες σε κα8ε μετρηση.
δηλαδη ας πουμε θα διαβασει τωρα 0.0112 μετα θα διαβασει 0.097 μετα 0.0132 καπως ετσι

----------


## SV1JRT

> μα αφου το κανω ηδη εδω
> 
> ADCON1     = $81
> 
> και επισης η κατασκευη δουλευει. μα διαβαζει διαφορετικες τιμες σε κα8ε μετρηση.
> δηλαδη ας πουμε θα διαβασει τωρα 0.0112 μετα θα διαβασει 0.097 μετα 0.0132 καπως ετσι



Η ADCON1     = $81 ανοίγει το ADC στον PIC, αλλα δέν ρυθμίζει την πόρτα που θές εσύ σαν αναλογική. Ολες οι πόρτες είναι by default ψηφιακές. Το οτι διαβάζει τυχαίες τιμές είναι ένδειξη ότι το αναλογικό κομμάτι δεν παίζει.
Τέλος πάντών, δεν χάνεις τίποτα να το δοκιμάσεις.
Αυριο θα έχω χρόνο να το δώ πιο αναλυτικά.

----------


## spiroscfu

Με basic δεν έχω ασχοληθεί και δεν μπορώ να σχολιάσω το κώδικα,
αλλά επειδή δεν έχεις βάλει το κύκλωμα να κάνω μια ερώτηση, το ρεύμα που θέλεις να μετρήσεις είναι παλμικό, εναλλασσόμενο ή καθαρό dc ?

----------


## somone

billtech το πρόβλημά σου είναι οτι παίρνεις γενικά τυχαίες τιμές ή οτι οι τιμές που πέρνεις είναι σωστές αλλά υπάρχει μια μικρή διακύμανση απο μέτρηση σε μέτρηση;; Από τον κώδικα φαίνεται φαίνεται οτι έχεις ρυθμίσει γενικά σωστά τον A/D (Vref+ απο το ποδαράκι AN3, Vref- στη γη και όλες οι πόρτες αναλογικές) οπότε αν η ADC_read() κάνει αυτό που υπόσχετε θα έπρεπε τουλάχιστον να παίρνεις μια τιμή γενικά σωστή. Τώρα για να εξαλήψεις τον "θόρυβο" από τις μετρήσεις σου μπορείς να μελετήσεις λίγο το datasheet και να ρυθμίσεις το clock convertion απο τον ADCON0 και ADCON1, επίσης μπορείς να βάλεις και κάποιο low pass φιλτρό (είτε software είτε στο κύκλωμα) ώστε να έχεις πιο σταθερές τιμές.

----------


## billtech

*SW1JRT* θα δοκιμασω και αυτο που ειπες μα δεν το νομιζω γτ για να ειναι αναλογικες το δηλωνω μεσα στον ADCON0.

somone πως ειναι τα φιλτρα τα low pass με software τροπο? ναι τις περισσοτερες φορες ειναι παραπλησια της πραγματικης τιμης η μετρηση αλλα εχει καποια ψηφια διαφορα..εχει διακυμανση...

----------


## SV1JRT

> *SW1JRT* θα δοκιμασω και αυτο που ειπες μα δεν το νομιζω γτ για να ειναι αναλογικες το δηλωνω μεσα στον ADCON0.
> 
> somone πως ειναι τα φιλτρα τα low pass με software τροπο? ναι τις περισσοτερες φορες ειναι παραπλησια της πραγματικης τιμης η μετρηση αλλα εχει καποια ψηφια διαφορα..εχει διακυμανση...



Bill, από οτι βλέπω στο datasheet του 18F452, έχεις ρυθμίσει σωστά την ADCON1 στο 81. Εχεις βάλει AN0, AN1 και ΑΝ4 είναι άναλογικές είσοδοι τα ΑΝ3 στο +Vref, AN2 στο -Vref και τα υπόλοιπα pin σαν digital I/O. Θα έπρεπε να παίζει λογικά. Για κάνε μια αλαγή και βάλε το ADCON1 = FF (όλα τα AN σαν αναλογικές είσοδοι και VREF την τροφοδοσία) να δούμε αν θα σου βγάζει πάλι τυχαίες τιμές....
 Οι ANSEL δεν είναι απαραίτητες τελικά απο ότι είδα στο datasheet. (πάντως εγώ τις βάζω στα προγράμματα μου για κάθε ενδεχόμενο).
 (υποθέτω βέβαια οτι η τάση αναφοράς που έχεις είναι πράγματι σταθερή και χωρίς ανεβοκατεβάσματα.. Δεν είμαστε και χτεσινοί.... ετσι ??)

----------


## billtech

Λοιπον με τον κωδικα που ειχα απο πριν. χωρις να τον αλλαξω. απλα για να δω αν τρεχει οπως ειπε ο σπυρος εκανα ενα τεστ εχω στις φωτο τις τιμες απο το proteus και απο τις real τιμες.
οι τιμες που εβαλα στις αντιστασεις ειναι 2.2Ω
50mA ρευμα

τρελλο δεν ειναι οπως παιζει?

----------


## spiroscfu

Το δοκίμασα και εγώ στο proteus και παίζει μια χαρά





Δεν είχε τον 452 ο compiler μου και έβαλα τον 4520 (το πρόγραμμα είναι αυτά που τσεκάρω τα άλλα είναι headers και setup).



```
while (1)
   {
      a=read_adc();
      delay_ms(100);
      printf("\fADCValue=> %Ld\r",a);
      printf("Voltage=> %.3fV\r",a*0.001222);
      delay_ms(100);
   }
```


Τα delay τα έβαλα για να μην αναβοσβήνει πολύ το virtual terminal,
για να φανούν καλύτερα οι μετρήσεις βάλτο σε 720p

----------


## billtech

τι εννοεις 720p?
αν θες επειδη δεν αλλαζει κατι κανε το σχηματικο που εχω εγω. δλδ να μετρας την πτωση τασης σε μικρη αντισταση. απο 2.2Ω και κατω. οσο παει.

----------


## billtech

με τοσες ωρες που εφαγα πανω του εκανα ενα μεγαααααααααααααααααααααααααλο λαθος που το ανακαλυψα τωρα. μεσα στο προγραμμα δηλωνα σαν Vref τα 1.25 μα εγω εδινα 2.5!!!!!!!!!!!!!!!!! μεγααα λαθος!!!
τωρα πρεπει να παιξω λιγο μαζι του να δω τι κανει.

----------


## billtech

ΟΚ!!!! το εκανα και δουλεψε και στο πραγματικο κομματι.
μετακινησα κατι καλωδια της γειωσης και αλλαξα κατι αλλα βυσματα και δουλεψε. παρακατω σας εχω μια φωτογραφια των μετρησεων με μετρουμενη αντισταση 2.2Ω

τωρα θα βαλω διαφορες αντιστασεις να δω τι τιμες θα μετρησει. και μικρες και λιγο μεγαλυτερες.

----------


## spiroscfu

Α ρε bill, μισό σου κάνω αυτό που είπες.





720p είναι η ανάλυση του βίντεο.

ο κώδικας



```
  while (1)
   {
      a=read_adc();
      delay_ms(100);
      b=a*0.001219;
      c=(5/b)-1;
      c=(20/c)-1;
      printf("\fADCValue=> %Ld\r",a);
      printf("Voltage=> %.3fV\r",b);
      printf("Resistor=> %f Ohms\r",c);
      delay_ms(100);
   }
```

----------


## billtech

λοιπον παιδια ευχαριστω για την βοηθεια. η συνεχεια απο δευτερα. αυριο αναχωρω για χωριο διακοπες....

----------


## SV1JRT

Βλέπω ότι έγινε καλή πρόοδος κατα την απουσία μου  :Wink:  μπράβο παίδια.
Bill καλές διακοπές.

----------

