ATTINY85 fréquences

Bonjour existe t il une librairie pour modifier la fréquence du PWN pour un attiny85.
Par exemple je souhaite du 20kHz. Y a t il une fonction qui permet facilement de modifier les registres? merci

Bonjour,
Regarde le chapitre 11. 8-bit Timer/Counter0 with PWM de la datasheet de l'ATTINY85

Il n'y a pas de fonction toute faite prévue pour changer la fréquence du PWM. Il faut donc changer soi-même les registres.
Sinon oui on peut facilement changer la valeur d'un registre, par exemple pour changer le registre TCCR0A, il suffit de faire:
TCCR0A = 5;

Dans l'initialisation de base le compteur travaille sur 256 valeurs. Pour donner le pourcentage de PWM il faut donner un nombre entre 0 et 255. Si on prend une fréquence de 20kHz par exemple, et si l'on voulait toujours commander le rapport cyclique avec un octet entre 0 et 255, il faudrait une horloge pour le compteur de 5,12MHz, ce que l'on n'a pas par défaut. Avec un attiny85, on peut facilement utiliser la fréquence F du quartz ou des fréquences F/8, F/64, F/256... Par exemple pour un quartz à MHz, il faudra utiliser une horloge pour le compteur de F/8 soit 1,25 MHz et compter jusqu'à 62. Le réglage du rapport cyclique se fera par un nombre compris entre 0 et 61. on n'a plus 0 à 255. Ce n'est pas forcément très grave, on peut faire une règle de 3, mais on a moins de précision sur le réglage. En utilisant un compteur 16 bits, on va retrouver de la précision.

J'ai écrit une bibliothèque pour faire du PWM avec une Uno/Mega qui a quasiment les mêmes registres, mais je ne pouvais pas utiliser les noms des registres pour pouvoir choisir le timer au cours de l'exécution. Toutefois, je peux t'aider dans le choix du mode et la valeur des registres.
Pour cela il faut savoir quel timer tu souhaite utiliser (8 ou 16 bits), et/ou la broche utilisée, la fréquence du quartz. et si les 20kHz sont fixes ou pas. A partir de là, on peut avoir la valeur des registres.

effectivement. comment peux rajouter le compteur?
Mon ATTINY85 a une horloge de 16,5MHz sauf erreur. lorsque je télécharge cela fonctionne avec le digispark 16,5MHz.

si je prends un prescaler de 8 il faudra donc compter 103
Dans la datasheet je sélectionne fast PWM mode 7
non inverting pour partir du zéro
et je sélectionne le port P0
J ai juste une ligne droite sur l'oscillo.


#include <avr/io.h>



// CPU runs @16,5MHz
// select fast mode => MODE 7 sur datasheet WGM02 WGM01 ET wGM00 @ 1
// non inverting mode pour partir du bottom @ 0 ==>> COM0A1 =1 et COM0A0 = 0
//prescaler = 8

int main(void)
{

TCCR0A |= (1<<WGM01) | (1<<WGM00) | (1<<COM0A1); // mode 7
// start timer at 2,062,500 Hz (16,5 MHz / 8)
   //16 500 000 / 8 = 2,062,500 Hz
  //8 - pre-scaler
  //2,062,500 Hz / 103 ~ 20,000 Hz
TCCR0B |= (1<<CS01)|(1<<WGM02)  ; // prescaler 8 + mode 7
OCR0A=103;   // set TOP to generate ~20,000 kHz
DDRB|=(1<<DDB0) ;/// set P0 PWN

while(1){
  
}
}

Je veux bien ton aide pour y arriver. j'ai un driver pololu DRV8876 et pololu conseille d'utiliser une fréquence de 20kHz.

A priori la configuration des registres me semble bonne. Mais en y regardant de plus près, il y a un petit oubli: Le programme doit faire du PWM avec 0% ou avec 100%.? Dans les deux cas, on obtient bien une droite horizontale à l'oscillo. C'est normal. Mais dans un premier temps, supposons que nous voulons un signal à 50%. Où est programmé de 50% (en fait 51 car 103/2)?

Dans la doc, il y a deux modes fast PWM, le 3 et le 7. Dans l'explication du fast PWM, c'est expliqué pour les deux. Dans le mode 3, le compteur va jusqu'à 255. Dans le mode 7, il va jusqu'à103 (OCR0A).
Pour la sortie PWM, on peut utiliser la sortie OC0A ou OC0B. c'est effectivement possible si on utilise le mode 3, mais dans le mode 7, le registre qui doit contenir 51 ne peut pas être OC0A car il est déjà utilisé pour le max du compteur. Il ne reste plus que OC0B. En mode 3 on peut faire 2 PWM avec OC0A et OC0B (mais avec quelques fréquences), ou un seul PWM avec OC0A mais on eut alors choisir sa fréquence.

Pour le code, il faut sortir sur OC0B et pas sur OC0A:

DDRB|=(1<<DDB1) ;/// set PB1 PWN
TCCR0A |= (1<<WGM01) | (1<<WGM00) | (1<<COM0B1); // mode 7

Et il faut programmer le rapport cyclique dans OCR0B:
OCR0B=51; // Choix du rapport cyclique ou durée d l'impulsion

A propos du programme, le code peut se trouver dans le setup. Mais on pourrait aussi l'exécuter en boucle, cela n'est pas grave.

C'est génial. Cela fonctionne.
J'obtiens 19,82kHz que je mesure a l'oscillo.
L'objectif sera de donner une impulsion de 0,8 seconde à un moteur d'aiguillage de train. Donc un rapport cyclique de 100%.
Conceptuellement mon compteur OCR0A part de 0 pour aller à 103 ==> donc 104 pas? c'est correct?
Le compteur OCROB est 51 ce qui correspond bien à la moitié (0+51 = 52 si je peux me permettre). Pourtant l'oscillo donne une mesure de 52%. Savez-vous d'où vient l'écart?
Dans mon esprit je pars en non-inverting autrement dit de 0.
Un grand merci pour votre temps

La doc n'est pas vraiment explicite dessus, mais si TOP=255, ils font bien la division par 256. Je suppose qu'en mettant 130 cela divise par 104. D'ailleurs 16,5MHz/ 8/19,82kHz donne bien 104!

A priori non. car la sortie bascule lorsque la comparaison est bonne, c'est à dire quand le compteur atteint 51. On est donc dans le premier état de 0 jusqu'à 50, puisque pour 51 on a basculé. On a 51 périodes seulement.

La sortie passe à 1 quand le compteur TCNT0 est à 0 en logique positive. Disons que OCR0A donne la période et OCR0B donne la durée de l'impulsion. On part de 1:


La sortie devrait être à 1 entre 0 et 50 inclus 'à vérifier), ce qui ferait un rapport cyclique de 51/104=49...
C'est plutôt l'inverse de ta mesure.


En utilisant les valeurs que tu as choisies, une erreur de 1 sur un registre se traduit par une erreur de 1% sur le signal. Pour bien voir les choses, il vaut mieux avoir des nombres beaucoup plus faibles, par exemple OCR0A=9 et OCR0B=5. A partir de là c'est plus facile de voir si on a une division par 9 ou par 10 (à cause du prédiviseur par 8, ce sera 16,5MHz/72 ou 16,5MHz/80).
Pus en regardant comment évolue le rapport cyclique quand OCR0B varie. Cela permet de voir comment avoir un rapport cyclique donné.

Je ferai peut être aussi l'essai, mais pas maintenant, j'ai du monde chez moi. Mais si tu fais l'essai, cela m'intéresse.

Je vais regarder. Petite question débutant encore: pour tester le signal j'utilise le PIN PB0. Pourtant le signal PWM devrait sortir sur PB1 non?

Bonjour

L'objectif sera de donner une impulsion de 0,8 seconde à un moteur d'aiguillage de train. Donc un rapport cyclique de 100%

pas besoin de PWM pour ca une sortie permet de faire ca facilement en la mettant a 1 pendant o.8 s.

Bonjour, dans mon esprit je pensais à brancher mon Pololu comme cela en mettant PIN MODE OFF et utiliser PH pour la direction digitalWrite(GPIO, 1/0), puis un analogWrite(PWM,100%) avec un delay(800). Et peut-être rajouter un condensateur en amont de 16V 100uf. c'est sur une toute petite période alors je ne pense pas que mon circuit sera beaucoup sollicité. Je n'ai pas encore mon Pololu. pas encore testé. Tu penses que je peux encore plus rationaliser? Sinon j'ai trouvé la réponse à ma question plus haut. Le timer0 est sur la broche P0. Mais je ne vois pas pourquoi on set up PB1 comme PWM.

Le timer a deux sorties P0 et P1 (ou PB0 et PB1) et P0 sort le signal OC0A et p1 est pour OC0B. Normalement la sortie PWM est sur OC0B, et devrait être sur P1 et pas sur P0.
Tu es sûr que c'est bien P0?

oui c'est bien P0: je relie le GND au GND de l'oscillo, le + de l'oscillo sur P0 et j'ai le signal.
Ensuite si je switche sur P1 il n'y a rien.
voilà ce que j'envoie

#include <avr/io.h>
#include <util/delay.h>


int main(void)
{


TCCR0A |= (1<<WGM01) | (1<<WGM00) | (1<<COM0B1); // mode 7
TCCR0B |= (1<<CS01)|(1<<WGM02)  ; // prescaler 8 + mode 7
OCR0A=103;   // set TOP to generate ~20,000 kHz
OCR0B=52; // Choix du rapport cyclique ou durée d l'impulsion
DDRB|=(1<<DDB1) ;/// set PB1 PWN

while(1){
  
}
}

Je pense que le probleme a été mal posé

evidemment je ne vais pas repondre a la question

car:
le moteur d'aiguillage n'en est pas un ... (au sens rotatif du terme)
il suffit d'envoyer une tension pendant 0.8 s quand on veut basculer ou rien
envoyer une tension dans l'autre sens quand on veut rebasculer ou rien
il n'y a et je me repette pas besoin de pwm ! ce n'est pas parcequ'on commande un moteur rotatif en pwm avec un pont en h que tuas besoin de pwm ...

par contre le pont en h oui puisquon doit changer de sens (mais des relais ca marcherai aussi)

donc quand on doit basculer le l'aiguille dans un sens on envoie la tension dans le bon sens pendant 0.8 s
et pour basculer dans l'autre sens on envoie la tension pendant 0.8 s dans l'autre sens

On est d'accord. Merci bcp.


bonjour, tout fonctionne super bien.
Merci à tous.
Il me reste une question. Même avec 10v de tension le LGB 12010 fonctionne très bien. Je mets une impulsion de 110ms. Avec 12v le LGB 12010 chauffe un peu, même avec 2 ou 3 impulsions. Lorsque je baisse à 10v c'est beaucoup moins.
Or le manuel d'utilisateur prévoit un intervalle de tension entre 14-20VDC.
Du coup je suis un peu perdu. Si je vais au delà de 12v c'est clair que le 12010 va chauffer excessivement.
Le signal redressé à la base donne un courant de 17,9v pour un input de 18VAC avec une fréquence de 7kHz en moyenne.
Ensuite je le régule à 10v. Et tout fonctionne. J'ai testé mon schéma avec un arduino je n'ai pas encore reçu mon polulu 8876. Du coup je passe par un l298n.
Merci à tous en tous les cas.

Bonjour

sauf erreur sur le schéma une des diodes est court-circuitée par la ligne gnd ....

pour le reste une aiguille n'a pas besoin de basculer 10 fois en 10 s ... elle bascule puis plusieurs minutes plus tard elle rebascule donc ca a le temps de refroidir

Oui c'est exact pour le court-circuit. Dans mon circuit cette ligne enlevée.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.