Faire une double PWM en C avec un Tiny 2313
Répondre à la discussion
Affichage des résultats 1 à 16 sur 16

Faire une double PWM en C avec un Tiny 2313



  1. #1
    Yoruk

    Faire une double PWM en C avec un Tiny 2313


    ------

    Bonjour à tous,

    Je cherche à réaliser une double PWM en hard sur un attiny 2313. Je me suis inspiré d'un exemple donné ici qui le fait pour une sortie (OCOA). J'ai tenté de doubler le code pour pouvoir utiliser une deuxième sortie, OC1A.

    J'ai du malheureusement me planter dans les noms de registre car la seconde ne fonctionne pas. J'ai pourtant bien lu et relu la page de la datasheet du tiny qui en parle (page 72) mais je me mélange un peu les pinceaux entre les différents registres à initialiser, aux bonnes valeurs...

    Si un pro pourrais me mettre sur la piste, voici mon code (qui compile très bien au passage)

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <avr/io.h>
    
    #define F_CPU 1000000UL
    #include <util/delay.h>
    
    void init_timer()
    {
    
    //pin de sortie premiere MLI :  PB2 #14  OC0A   la seconde PB3  #15 OC1A
    
    
    	//premiere MLI : fonctionne
    
    	// set fast PWM mode
    	TCCR0A |= (1<<WGM00) | (1<<WGM01);
    
    	// clear 0C0A (la sortie) on compare
    	TCCR0A |= (1<<COM0A1);
    
    	// start timer, no prescaling
    	TCCR0B |= (1<<CS00);
    
    	//duty cycle 0%
    	OCR0A =0;
    
    
    	//deuxieme MLI : ne fonctionne pas. Les noms de registre ne doivent pas être bons.
    	TCCR1A |= (1<<WGM00) | (1<<WGM01);
    	TCCR1A |= (1<<COM0A1);
    	TCCR1B |= (1<<CS00);
    	OCR1A =0;
    
    }
    
    void init_led()
    {
    	DDRB |= (1<<PB2);         // PB2 
    	DDRB |= (1<<PB3);         // PB3 
    	//DDRB = 0b00001100; //sens sorties
    
    }
    
    
    int main(int argc, char *argv[])
    {
    
    	int i;
    
    	init_led();
    	init_timer();
    
    	while(1) {
    
    		//modification du duty cycle en boucle
    		for (i=0;i<255;i++) {
    			OCR0A=i; //premier rapport cyclique
    
    			OCR1A=i; //deuxieme rapport cyclique
    
    			_delay_ms(10);
    
    		}
    
    		for (i=255;i>0;i--) {
    
    			OCR0A=i;
    			OCR1A=i;
    
    			_delay_ms(10);
    
    		}
    
    	}	
    	return 0;
    }
    J'ai sans doute fait une erreur sur les WGM00 et autres seuils de comparaison...

    Pour mon test, les 2 rapports cycliques sont identiques (OCR0A et OCR1A). La boucle est simple, juste une augmentation puis une diminution du rapport. Mais seule la led branchée sur la première pin fonctionne correctement...?

    Merci d'avance !

    -----
    La robotique, c'est fantastique !

  2. #2
    indri

    Re : Faire une double PWM en C avec un Tiny 2313

    Tu peux changer ca:
    TCCR1A |= (1<<WGM10) | (1<<WGM01);
    TCCR1A |= (1<<COM1A1);
    TCCR1B |= (1<<CS10);

    Mais normalement ca devrait rien changer..

    Sinon les timer1=16bit et timer 0=8bit....donc OCR1A à 255 tu a quazi pas de rapoort cyclique (pas juste ca le problème?)
    Là où va le vent...

  3. #3
    Yoruk

    Re : Faire une double PWM en C avec un Tiny 2313

    Je vais tenter, pas ce weekend je n'aurais pas accès à ma carte de dev'

    Tu veux dire que OCR0A est 8 bits et OCR1A sur 16 ? Aouch, c'est pas logique pour moi...

    Je veux juste faire 2 fois la PWM proposée, rien de bien méchant... Si l'une est à 8 et l'autre 16 bits, ça se complique.
    La robotique, c'est fantastique !

  4. #4
    indri

    Re : Faire une double PWM en C avec un Tiny 2313

    Oui OCR0A c'est 8 bits et OCR1A c'est 16 (regarde le datasheet y'a deux timers différents )
    sinon tu peux juste mettre n'utiliser que OCR1AH (mais egalement divisé la fréquence par 256)
    ou configuré le timer1 non plus en fast pwm mais en PWM normal et mettre la "butée" à 255 (ICR1 si je me trompe pas) (cette solution serait plus "correct" je crois pour pas changer le reste de ton code)
    Là où va le vent...

  5. A voir en vidéo sur Futura
  6. #5
    ftorama

    Re : Faire une double PWM en C avec un Tiny 2313

    C'est pourtant indiqué dans la datasheet. Le Timer 0 est un 8 bits, le Timer 1 est un 16 bits.

    Puisque ton PWM sur OCR0A fonctionne, utilise donc OCR0B, la deuxième sortie PWM du timer 0. Il faudra évidemment modifier les bits COM0Bx (comme tu as fait pour COM0A1) et utiliser le registre OCR0B pour régler ton second PWM
    Quand un homme a faim, mieux vaut lui aprendre à pecher que de lui donner un poisson.

  7. #6
    Yoruk

    Re : Faire une double PWM en C avec un Tiny 2313

    La manipulation des registres est quelque chose de nouveau pour moi, désolé si j'ai un peu de mal.

    Mon premier timer 8 bits est donc OCR0A. Il va de 0 à 255. Il contient mon rapport cyclique. Le second que je souhaite utiliser est OCR0B.

    TCCR0A est configuré (COM0A1 à 1 et COM0A0 à 0 ) de façon à ce que j'ai "Clear OC0A on Compare Match, set OC0A at TOP"

    Pour la seconde, je dois avoir "Clear OC0B on Compare Match, set OC0B at TOP", soit COM0B1 à 1 et COM0B0 à 0, toujours pour TCCR0A (page 78 de la datasheet)

    Comment alors régler le fast PWM pour OC0B ?

    Ensuite, concernant TCCR0B (page 80 et 81) si je comprends bien, je n'ai pas de prescaling. Certes, mais ce réglage est valable pour les 2 ?

    Je vais lire ce tuto en attendant, qui semble mieux expliquer le rôle des différents registres.
    La robotique, c'est fantastique !

  8. #7
    zibuth27

    Re : Faire une double PWM en C avec un Tiny 2313

    hello,

    Les compteurs fonctionnent de la même manière pour les AT90S 2313 et AT tiny 2313

    extrait doc 2313
    Timer/Counter1 and Timer/Counter0 share the same prescaler module, but the Timer/Counters
    can have different prescaler settings. The description below applies to both Timer/Counter1 and
    Timer/Counter0.

    c'est la même horloge de base qui entre dans le prédiviseur. On choisit le taux de prédivision individuellement pour chaque timer, ils sont donc multiples l'un de l'autre.


    TCCR0B contient les bits CS00 à CS02 qui programment le prédiviseur pour Timer0 (bits 0 à 2)
    TCCR1B contient les bits CS10 à CS12 qui programment le prédiviseur pour Timer1 (bits 0 à 2)

    saluts

  9. #8
    zibuth27

    Re : Faire une double PWM en C avec un Tiny 2313

    d'accord avec Indri,

    TCCR1B |= (1<<CS00); ton compilateur (c'est quoi?) devrait le signaler
    tu demande à programmer un bit du Timer1 (TCCR1B) avec un nom de prédivision du Timer 0 : CS00


    je mettrais donc
    TCCR1B |= (1<<CS10);

    saluts
    saluts

  10. #9
    Yoruk

    Re : Faire une double PWM en C avec un Tiny 2313

    @zibuth27 -> Non j'ai faux, je ne veux pas utiliser le timer 1 justement, j'aimerai rester sur du 8 bits.

    Je compile avec Atmel Studio, mais je transfère avec avrdude en ligne de commande, mon programmateur n'étant pas supporté par le soft d'Atmel.

    Ok pour le prescaler, j'aimerai rester sur le même type de division. Mais je ne comprends toujours pas comment on diffère le prescaling pour OCR0A et OCR0B ? La table 41 ne semble pas faire de différence ?

    Je commence à douter de la faisabilité de ma demande... Est-il possible, avec le timer 0 (8 bits), de gérer deux fasts PWM sur 2 pins différentes avec 2 rapports cycliques différents ?
    La robotique, c'est fantastique !

  11. #10
    Yoruk

    Re : Faire une double PWM en C avec un Tiny 2313

    Bon je pense avoir trouvé un exemple qui semble faire ce que je veux. Je vais décortiquer tout ça...
    La robotique, c'est fantastique !

  12. #11
    zibuth27

    Re : Faire une double PWM en C avec un Tiny 2313

    hello,

    syntaxe des commandes de Timers

    TCCR0A = Timer Counter Control Timer0 registreA
    T = Timer
    C = Counter
    C = Control
    0 = timer 0 devient 1 pour le Timer 1
    A = registre A devient B pour le registre B

    COM0A1 Compare Output Match timer 0 bit 1 = changement d'état dès que la valeur "matche" (est égale à {OCR0A}) , selon la valeur de WGM ce sont deux bits de commande dans le registre TCCR0A (TCCR1A)
    C = Compare
    O = Output
    M = Match
    0 = timer 0, devient 1 pour le timer 1
    A = sortie A le timer 0 (ou B) a deux sorties 0C0A et OC0B qui changent d'état dès que le compteur atteint OCR0A (ou OCR1A) la réponse (waveform) est contrôlée par COMxYz
    1 = 1er bit du COM0A, 2eme bit = COM0A1

    (attention, j'ai vu des docs Atmel où COM0Ax se trouvait dans la description du timer1, copier/coller excessif, ça arrive même chez Atmel)

    le timer 0 sort sur les pins OCxA et OCxB
    O = Output
    C = Compare match output
    0 = timer 0
    A = sortie normale 5 = sortie complémentée)
    OC0A = PB2 pin 14
    OC0B = PD5 pin 9 (attention portD)
    OC1A = PB3 pin 15
    OC1B = PB4 pin 16



    le timer 0 a son prédiviseur dans le registre TCCR0B : les bits CS00 à CSO2
    C = Counter
    S = preScaler
    0 = timer 0
    1 à 2 = chacun des trois bits de CS

    pour le timer 1 c'est dans le registre TCCR1B et les bits s'appellent CS10 à CS12
    C
    S
    1 = timer 1
    0 à 2 = bits de CS


    l'exemple que tu viens de donner se contente de limiter la comparaison à 255 max (le compteur cycle sur 65535), je n'ai pas vu dans l'extrait la limitation du compteur pour qu'il cycle à 255. Ou bien j'ai lu trop vite

    Pour un PWM 8 bits, il te faut un mode PWM dont le TOP ne soit pas MAX (OxFFFF) mais un des modes limités à FF = mode 1 (PWM phase correct 8 bits), ou mode 5(fast PWM 8 bit) dans la table 46

    le mode est controlé par les bits WGM10 à WGM13 (Waveform Generation Mode) qui sont répartis dans les deux registres TCCR
    WGM10 et WGM11 dans TCCR1A
    WGM12 et WGM13 dans TCCR1B

    pour le timer 0, ces bits s'appellent WGM00 à WGM02 (pas de WGM03) et se trouvent dans les registres TCCR0A et TCCR0B

    j'espère t'avoir fait voir éclairer le fond

    saluts

  13. #12
    Yoruk

    Re : Faire une double PWM en C avec un Tiny 2313

    Ok merci, c'est tout à fait le type d'explications dont j'avais besoin. Si avec ça je ne comprends pas...

    Deux petites questions :

    La valeur physique du timer est elle accessible ?

    Le pré-diviseur sert juste à diminuer la gamme de fréquence de la PWM ?
    La robotique, c'est fantastique !

  14. #13
    zibuth27

    Re : Faire une double PWM en C avec un Tiny 2313

    Oops

    le timer 0 sort sur les pins OCxA et OCxB
    O = Output
    C = Compare match output
    0 = timer 0
    A = sortie normale 5 = sortie complémentée)
    OC0A = PB2 pin 14
    OC0B = PD5 pin 9 (attention portD)
    OC1A = PB3 pin 15
    OC1B = PB4 pin 16


    il fallait comprendre A=sortie normale, B=sortie complémentée
    le lecteur averti l'aura compris de lui-même (de mon temps, c'était un futur antérieur)

  15. #14
    zibuth27

    Re : Faire une double PWM en C avec un Tiny 2313

    @Yoruk #12

    valeur instantané du timer accessible dans les registres TCNT0 ou TCNT1H et TCNT1L
    TCNT0 registre 8 bits du timer0
    TCNT1H registre 8 bits du timer1, octet de poids fort : Hi byte
    TCNT1L registre 8 bits du timer1, octet de poids faible : Low byte

    Si tu cherches à lire la valeur du timer, n'oublies pas de prendre en compte le temps de lecture / comparaison, whatsoever, temps pendant lequel le compteur évolue. Pas facilement utilisable à faible taux de prédivision, il faut lister les instructions assembleur de sortie de compilation (option de ton compilateur ou makefile à placer, sortie parfois en "nomdefichier".l, désolé je ne pratique que avr-gcc sous minux) Boulot classique si tu pratiques l'assembleur, c'est autre chose si elle ne compile que le c.

    prédiviseur: il donne le PAS de comptage, le compteur incrémente d'un pas à ce rythme. Une fois atteint le maximum du compteur (256 pas en compteur 8 bits) le compteur recycle à zéro, en générant les interruptions éventuelles.

    saluts

  16. #15
    Yoruk

    Re : Faire une double PWM en C avec un Tiny 2313

    Ok !

    Bon je ne cherche pas forcément à exploiter la valeur physique du timer. Avec toutes ces infos, je devrais m'en sortir.

    Merci !
    La robotique, c'est fantastique !

  17. #16
    zibuth27

    Re : Faire une double PWM en C avec un Tiny 2313

    n'utilises pas un compteur 16 bits en limitant seulement OCR à 255, le compteur continuera jusqu'à son MAX avant de reboucler, il faut limiter le MAX lui-même en choisissant un mode PWM 8bit

Discussions similaires

  1. Ajout d'un port programmation ICSP sur un ATTINY 2313
    Par Yoruk dans le forum Électronique
    Réponses: 3
    Dernier message: 25/03/2013, 09h59
  2. Calcul intégrale double avec double changement de variable
    Par inviteef80dea9 dans le forum Mathématiques du supérieur
    Réponses: 4
    Dernier message: 21/10/2012, 11h07
  3. problème avec Jtagkey tiny/openocd et lpc1766
    Par eldudo dans le forum Électronique
    Réponses: 0
    Dernier message: 12/06/2011, 22h52
  4. Tn 2313
    Par invite2b4da655 dans le forum Électronique
    Réponses: 16
    Dernier message: 20/05/2006, 12h14
  5. Comment faire pour insoler du double face avec une insoleuse
    Par zanzeoo dans le forum Électronique
    Réponses: 1
    Dernier message: 20/07/2003, 13h41
Découvrez nos comparatifs produits sur l'informatique et les technologies.