Σελίδα 1 από 2 1 2 ΤελευταίαΤελευταία
Εμφάνιση αποτελεσμάτων : 1 έως 10 από 11

Θέμα: LED Bar οδηγηση με pic

  1. #1
    Μέλος Το avatar του χρήστη Airwolf30
    Όνομα
    Παράσχος
    Εγγραφή
    Nov 2008
    Περιοχή
    Ηράκλειο - Κρήτης
    Μηνύματα
    71

    Προεπιλογή LED Bar οδηγηση με pic

    Γεία σας και πάλι. Έχω σχεδιάσει κύκλωμα με PIC16F877 το οποίο οδηγεί ενα led bar που ακολουθεί μια αναλογική τιμή. Παρακάτω παραθέτω το πρόγραμμα σε C. Θα ήθελα την άποψη σας σχετικά με το τμήμα του κώδικα που είναι μέσα στη while με τον οποίο φτιάχνω τα όρια στα οποία θα ενεργοποιείται το κάθε led. Υπάρχει καλύτερος τρόπος για να την οδήγηση του led bar; Δοκίμασα με switch case αλλά παρατήρησα οτι τα led έχουν διακυμάνσεις. Με το παρακάτω κώδικα είναι πιο σταθερά.
    Ευχαριστώ.

    void main()
    {
    unsigned int value;
    TRISC=0X00;
    //ADC Configuration
    ADCON1=0B10001110;
    ADCON0=0B00000101;
    adc_init();


    while(1)
    {
    value=adc_read(0);
    if(value==0) portc=0x00;
    if(value==12 portc=0x01;
    if(value==256) portc=0x03;
    if(value==384) portc=0x07;
    if(value==512) portc=0x0f;
    if(value==640) portc=0x1f;
    if(value==76 portc=0x3f;
    if(value==896) portc=0x7f;
    if(value==1023) portc=0xff;
    }
    }

    0 Not allowed! Not allowed!
    If you don't like the answer, don't ask.

  2. #2
    Μέλος Το avatar του χρήστη klik
    Όνομα
    just a click away
    Εγγραφή
    Oct 2009
    Περιοχή
    Θεσσαλλλονίκη
    Μηνύματα
    2.555

    Προεπιλογή

    Στον κώδικα σου θα έπρεπε να έχεις ελέγχους με if(value < xxx) .. else ...

    Έστι όπως το έχεις δεν ελέγχεις όλες τις τιμές αλλά μόνο 8 από τις 1023.

    Ο γρηγορότερος και συντομότερος κώδικας που μου ρθε στο μυαλό, είναι η παρακάτω μαυρισμένη και υπογραμμισμένη γραμμή που αντικαθιστά όλα τα if που έχεις.
    Το αν θα το καταλάβεις είναι άλλο θέμα!

    Κώδικας:
           ...
           while(1){
                   value = ... εδώ ίσως θέλεις κάποιον έλεγχο για σφάλματα μέτρησης (φευγάτες τιμές σε σχέση με τις προηγούμενες)
                   PORTC = ~(0xff << (value>>7));
    
     // το value>>7 δίνει αριθμό από 0(value=0 έως και 127) έως 7 (value=896 έως 1023)
    
    // το 0xff << (value>>7) δίνει άσους στα bit πάνω από αυτά που θέλεις να ανάψουν (αν value>>7 είναι 3, θα δώσει 11111000)
    
    // το ~ κάνει την αντιστροφή των bit και έχεις αυτό που θέλεις.
           ...


    υγ. αν αλλάξεις το βήμα σε 113 από 128, θα έχεις και τις 9 επιλογές (0led έως 8led).
    Τότε θα κάνεις διαιρέση αντί για >>7

    Κώδικας:
    PORTC = ~(0xff << (value/113));

    0 Not allowed! Not allowed!
    Τελευταία επεξεργασία από το χρήστη klik : 06-06-12 στις 02:40 Αιτία: επεξηγήσεις*3

  3. #3
    Μέλος Το avatar του χρήστη Airwolf30
    Όνομα
    Παράσχος
    Εγγραφή
    Nov 2008
    Περιοχή
    Ηράκλειο - Κρήτης
    Μηνύματα
    71

    Προεπιλογή

    Λοιπόν, με αρκετή προσπάθεια κατάλαβα τι παίζει, τελικά. Στο πρώτο παράδειγμα διαιρείς τη τιμή της value / 128 παίρνοντας απο τη διάρεση το ακαίρεο μέρος το οποίο στη συνεχεια το χρησιμοποιείς για να μεταφέρεις τόσες αντιστοιχες προς τ' αριστερά θέσεις τον αριθμο 0b11111111 και τέλος αντιστρέφεις το τελικό απότελεσμα.

    Αντίστοιχη διαδιακασία γίνεται και στο 2ο παράδειγμα μόνο που εδώ έχεις αλλάξει το βήμα να αλλάζει ανα 113 step αντί 128 που ήταν πριν. Στη δική μου περίπτωση έχω ενα led bar με 10 led και για αυτό το λόγο άλλαξα το step σε 102 (1024/10LED=102,4) με αυτό το τρόπο μπορώ να ελέγξω 10 led αλλά έχω κολλήσει στο πωςθα οδηγώ τα δύο τελευταία bit στα bit0-1 της portc.

    Ομολογώ οτι ήταν δύσκολο αλλά μέσα απο αυτή τη διαδιακασία κατάλαβα περισσότερο τη χρήση του >> και <<. Θα μπορούσα να πώ οτι είναι το αντίστοιχο της διαίρεσης ή του πολλαπλασιασμού αντίστοιχα.

    παρόμοια διαδιακασία έχω την εντύπωση οτι χρησιμοποιώ και στην εμφάνηση χαρακτήρων σε LCD, δλδ:

    text[3]=value/1000 + '0';
    text[2]=(value/100)%10 + '0';
    text[1]=(value/10)%10 + '0';
    text[0]=value%10 + '0';

    lcd_out(1,1,text);

    **αν κάνω λάθος διόρθωσε με, άλλωστε απο τα λάθη μαθαίνουμε.

    0 Not allowed! Not allowed!
    If you don't like the answer, don't ask.

  4. #4
    Μέλος Το avatar του χρήστη picdev
    Όνομα
    akis
    Εγγραφή
    Jul 2007
    Περιοχή
    ____
    Μηνύματα
    7.381

    Προεπιλογή

    ρε klik τι κώδικας ήταν αυτός, δεν θα το σκεφτόμουν και 2 χρόνια να το ψαχνα, πολύ έξυπνο μπράβο
    ολόκληρο πρόγραμμα το έκανες 2 γραμμές, βάζω στοίχημα ότι είναι από την εποχή που έγραφες σε assembly

    0 Not allowed! Not allowed!

  5. #5
    Μέλος Το avatar του χρήστη klik
    Όνομα
    just a click away
    Εγγραφή
    Oct 2009
    Περιοχή
    Θεσσαλλλονίκη
    Μηνύματα
    2.555

    Προεπιλογή

    Παράθεση Αρχικό μήνυμα από Airwolf30 Εμφάνιση μηνυμάτων
    Λοιπόν, με αρκετή προσπάθεια κατάλαβα τι παίζει, τελικά....
    ωραία

    Παράθεση Αρχικό μήνυμα από Airwolf30 Εμφάνιση μηνυμάτων
    Στη δική μου περίπτωση έχω ενα led bar με 10 led και για αυτό το λόγο άλλαξα το step σε 102 (1024/10LED=102,4) με αυτό το τρόπο μπορώ να ελέγξω 10 led αλλά έχω κολλήσει στο πωςθα οδηγώ τα δύο τελευταία bit στα bit0-1 της portc.
    λάθος, το βήμα σου είναι 1024/11 και όχι 1024/10 διότι έχεις 11 τιμές
    {κανένα led,1,2,3,4,5,6,7,8,9,10}
    Οι εντολές είναι:
    Κώδικας:
            const unsigned short divisor = 1024/11; //το βήμα σου
            unsigned short value = adc_read ...;//η μετρούμενη τιμή
             unsigned short leds = ~(0x3ff << (value / divisor));//η 10bit value για τα led
            PORTB = leds; //βαλε τα 8 (lsb) bits στην portB
            PORTC &= 0xfc;//σβήσε τα 2 bit της portC αφήνοντας τα υπόλοιπα ανεπηρέαστα
            PORTC |= (leds >> 8) & 0x03; //βάλε τα 2 (msb) bit των led στην portC (bit0,1)
    Παράθεση Αρχικό μήνυμα από Airwolf30 Εμφάνιση μηνυμάτων
    Ομολογώ οτι ήταν δύσκολο αλλά μέσα απο αυτή τη διαδιακασία κατάλαβα περισσότερο τη χρήση του >> και <<. Θα μπορούσα να πώ οτι είναι το αντίστοιχο της διαίρεσης ή του πολλαπλασιασμού αντίστοιχα.
    όχι πάντα. Αντιστοιχεί με πολλαπλασιασμό και διαίρεση μόνο όταν έχεις να πολλαπλασιάσεις/διαιρέσεις με δυνάμεις του 2 και μόνο. Η εντολή >> ή << παίρνει πολύ λιγότερο χρόνο από μια διαίρεση (συνήθως 1 με 2 κύκλους ρολογιού) ενώ η διαίρεση μπορεί να θέλει αρκετές δεκάδες εντολών. Μερικές φορές ο compiler κάνει βελτιστοποίηση από μόνος του όταν έχεις πάρε δώσε με δυνάμεις του 2.

    Παράθεση Αρχικό μήνυμα από Airwolf30 Εμφάνιση μηνυμάτων
    παρόμοια διαδιακασία έχω την εντύπωση οτι χρησιμοποιώ και στην εμφάνηση χαρακτήρων σε LCD, δλδ:

    text[3]=value/1000 + '0';
    text[2]=(value/100)%10 + '0';
    text[1]=(value/10)%10 + '0';
    text[0]=value%10 + '0';

    lcd_out(1,1,text);
    Όχι βρε, μόνο η διαίρεση είναι κοινή εδώ.
    Σημείωση στον παραπάνω κώδικα: ο κώδικας αυτός τρώει πολλές εντολές κώδικα και πολύ RAM.
    Να κάνεις ένα loop με μια / και ένα % μόνο. Πίνακας RAM δεν θα χρειαστεί.

    0 Not allowed! Not allowed!

  6. #6
    Μέλος Το avatar του χρήστη klik
    Όνομα
    just a click away
    Εγγραφή
    Oct 2009
    Περιοχή
    Θεσσαλλλονίκη
    Μηνύματα
    2.555

    Προεπιλογή

    Παράθεση Αρχικό μήνυμα από picdev Εμφάνιση μηνυμάτων
    ρε klik τι κώδικας ήταν αυτός, δεν θα το σκεφτόμουν και 2 χρόνια να το ψαχνα, πολύ έξυπνο μπράβο
    ολόκληρο πρόγραμμα το έκανες 2 γραμμές, βάζω στοίχημα ότι είναι από την εποχή που έγραφες σε assembly
    Δεν ξέρω αν κέρδισες το στοίχημα! Δεν μπορώ να θυμηθώ τι έμαθα (ικανοποιητικά) πρώτο: C ή Assembly...
    Αλλα γιατί λες δυο γραμμές;
    Κώδικας:
    while(1) PORTC = ~(0xff << (adc_read(0)>>7));
    αφού μία είναι!

    0 Not allowed! Not allowed!

  7. #7
    Μέλος Το avatar του χρήστη Airwolf30
    Όνομα
    Παράσχος
    Εγγραφή
    Nov 2008
    Περιοχή
    Ηράκλειο - Κρήτης
    Μηνύματα
    71

    Προεπιλογή

    λοιπόν σε κάθε απάντηση με βάζεις σε άλλο τρυπάκι. Στην απάντηση σχετικά με την διαίρεση και τη μετατόπιση bit έπεξα με αρκετές τυχαίες τιμές για να καταλάβω τι εννωείς. Τελικά, οκ. Όταν είναι δυνάμεις του 2 (2^7=128, 2^3=8 κοκ) μπορώ να χρησιμοποιώ τις πράξεις << ή >>, ενώ όταν δεν είναι δυνάεις του 2 πχ 100, 102, 113 (παίρνω τα πιο πρόσφατα παραδείγματα) πρέπει να χρησιμοποιούμε διάρεση. Σωστά;

    Στο παράδειγμα του κώδικα που παρέθεσα τελευταία έκανες μία παρατήρηση. Έλεγα να το προσπαθήσω λίγο μόνος μου αλλά δεν μου βγαίνει. Μπορείς σε παρακαλώ να δώσεις ένα σχετικό κώδικα για δύο χαρακτήρες ας πούμε και θα προσπαθήσω να το επεκτίνω.
    Ευχαριστώ...

    0 Not allowed! Not allowed!
    If you don't like the answer, don't ask.

  8. #8
    Μέλος Το avatar του χρήστη Airwolf30
    Όνομα
    Παράσχος
    Εγγραφή
    Nov 2008
    Περιοχή
    Ηράκλειο - Κρήτης
    Μηνύματα
    71

    Προεπιλογή

    [QUOTE=klik;529701] ωραία

    λάθος, το βήμα σου είναι 1024/11 και όχι 1024/10 διότι έχεις 11 τιμές
    {κανένα led,1,2,3,4,5,6,7,8,9,10}
    Οι εντολές είναι:
    [code]
    const unsigned short divisor = 1024/11; //το βήμα σου
    unsigned short value = adc_read ...;//η μετρούμενη τιμή
    unsigned short leds = ~(0x3ff << (value / divisor));//η 10bit value για τα led
    PORTB = leds; //βαλε τα 8 (lsb) bits στην portB
    PORTC &= 0xfc;//σβήσε τα 2 bit της portC αφήνοντας τα υπόλοιπα ανεπηρέαστα
    PORTC |= (leds >> & 0x03; //βάλε τα 2 (msb) bit των led στην portC (bit0,1)

    Μια ερώτηση. Στο σημείο όπου PORTB = leds; μήπως θα έπρεπε να γράψω καλύτερα PORTB = ~leds; διότι ακριβώς πριν τα πρώτα 9 bit τις value αντικαθίστανται με 0 οπότε πρέπει να αντιστραφούν για να ανάψουν. Τι λές;

    0 Not allowed! Not allowed!
    If you don't like the answer, don't ask.

  9. #9
    Μέλος Το avatar του χρήστη Airwolf30
    Όνομα
    Παράσχος
    Εγγραφή
    Nov 2008
    Περιοχή
    Ηράκλειο - Κρήτης
    Μηνύματα
    71

    Προεπιλογή

    μη λάβεις υπόψη σου το τελευταίο post, παρατήρησα μετά οτι κάνει αντιστροφή στην προηγούμενη ακριβώς γραμμή. Εγώ κάνω διπλή αντιστρφή, δλδ, τπτ.

    0 Not allowed! Not allowed!
    If you don't like the answer, don't ask.

  10. #10
    Μέλος Το avatar του χρήστη klik
    Όνομα
    just a click away
    Εγγραφή
    Oct 2009
    Περιοχή
    Θεσσαλλλονίκη
    Μηνύματα
    2.555

    Προεπιλογή

    Κώδικας:
    byte print_uword(word n){
        byte digits_printed = 0;
        word divisor;
        for(divisor = 10000 ; divisor!=0 ; divisor /= 10){
            byte value = n / divisor;
            if(value!=0 || digits_printed){
                digits_printed++;
                lcd_write(value + '0');
            }
            n %= divisor;
        }
        return digits_printed;
    }
    Μια απλή περίπτωση. Τυπώνει αγνοώντας αρχικά μηδενικά.
    Επιστρέφει αριθμό χαρακτήρων που τυπώθηκαν.
    Φυσικά μπορεί να περνάς παράμετρο το αρχικό divisor (αν θέλεις π.χ. να τυπώνεις μόνο τα 3 τελευταία ψηφία ενός αριθμού), θα μπορούσες να περνάς την lcd_write με pointer ώστε με την ίδια συνάρτηση προσπέλασης αριθμών να μπορείς να τυπώσεις σε οθόνη-rs232-δικτυο κλπ

    0 Not allowed! Not allowed!

Σελίδα 1 από 2 1 2 ΤελευταίαΤελευταία

Παρόμοια Θέματα

  1. Οδηγηση led με mosfer βοηθεια
    By gourtz in forum Μικροελεγκτές
    Απαντήσεις: 13
    Τελευταίο Μήνυμα: 11-06-17, 02:26
  2. Οδηγηση LED απο 220
    By Scotty in forum Κυκλώματα Εικόνας-'Ηχου & Φωτισμού
    Απαντήσεις: 11
    Τελευταίο Μήνυμα: 22-02-13, 09:17
  3. Προβλημα με οδηγηση LED 3W
    By mralex1111 in forum Εξαρτήματα & Datasheets
    Απαντήσεις: 4
    Τελευταίο Μήνυμα: 28-10-12, 19:45
  4. Ερωτηση για οδηγηση Bi-color LED
    By andrewsweet4 in forum Γενικά
    Απαντήσεις: 15
    Τελευταίο Μήνυμα: 29-11-11, 14:24
  5. οδηγηση LED 1w
    By pavlakis in forum Κυκλώματα Τροφοδοτικών
    Απαντήσεις: 2
    Τελευταίο Μήνυμα: 20-08-11, 20:27

Δικαιώματα - Επιλογές

  • Δημιουργία θεμάτων: Όχι
  • Υποβολή μηνυμάτων: Όχι
  • Σύναψη αρχείων: Όχι
  • Επεξεργασία μηνυμάτων: Όχι
  •  
  • BB code: σε λειτουργία
  • Smilies: σε λειτουργία
  • [IMG]: σε λειτουργία
  • [VIDEO] code is σε λειτουργία
  • HTML: εκτός λειτουργίας