Changer la frequence de l'arduino mega a 10khz et 1khz pour PWM

Salut a tous !

J'ai fait beaucoup de recherches et je n'ai pas trouve le moyen de changer la fréquence des PWM a 10khz et 1khz... En utilisant la division par prescaler on n'obtient pas ces valeurs... J'utilise un arduino mega 2560.

Mon projet me demande de faire 9 signaux PWM : 6 a 10hkz et 3 a 1khz

Timer 0 --> pin 4 and 13 ( valeur par défaut :980 hz)
Timer 1 --> pin 11 and 12 (490 hz)
Timer 2 --> pin 9 and 10 (490 hz)
Timer 3 --> pin 2, 3 and 4 (490 hz)
Timer 4 --> pin 6, 7 and 8 (490 hz)
Timer 5 --> pin 44, 45, and 46 (490 hz)

Je pense utiliser les timers 3,4 et 5. J'ai trouvé des méthodes sur ce site mais ça parle d'interruptions alors je ne sais pas si c'est possible...

16Mhz/prescaler/counter
16Mhz/128/124 --> 1khz
16Mhz/8/199 --> 10khz

Je suis débutant alors merci pour votre aide !!! :slight_smile: :slight_smile:

Salut,

Presqu'exactement ce que tu veux : Arduino Playground - TimerPWMCheatsheet

Oui j'ai vu ce topic mais avec ces divisions de prescaler je n'obtiens pas les bonnes fréquences.... :confused:

Il n'y a pas que le prescaler, il y a aussi la limite du compteur à régler

Si tu mets le prescaler à 1 et le compteur à 16 000 tu auras 1 khz.

Mais c'est quoi que tu veux exactement ? Du PWM ou juste des signaux carrés à une fréquence donnée ?

Ah d'accord ! c'est donc comme le lien que j'ai mis au dessus? On divise par un prescaler puis ensuite par un compteur?! ca serait parfait ^^ !
Je souhaite faire des signaux PWM. Mon sujet me donne une frequence pwm de base puis ensuite je dois pouvoir jouer avec le duty cycle... J'ai pris cette arduino ADK mega 2560 parce que j'ai besoin de 9 PWM et ce n'est pas un nombre très commun sur les cartes ! Et lui en propose 15 :slight_smile:

TCCR2A = bit (CS20) | bit (CS22) ; // prescaler of 128
OCR2A = 124; // count up to 125
This is an idea...

Pour simplifier :

Horloge/prescaler => vitesse à laquelle le compteur compte
"Butée" du compteur => jusqu'à combien il compte

Après la prog "en dur" sur Atmel je connais pas vraiment (sur MSP430 j'aurais été plus compétent) mais dans le principe c'est ça normalement

Il faut que tu étudies la datasheet du micro. Dedans tu trouveras des explications sur LES PWM.

J'ai bien écrit LES parce qu'il existe 3 types de PWM sur les AVR :

  • Fast PWM
  • Phase correct PWM
  • Phase and Frequency correct PWM.

Pour compliquer le tout chaque timer ne dispose pas de tous les types de PWM. En principe (je n'ai regardé que pour l'ATMega328p de la UNO) le seul type commun aux différents timers est la Fast PWM, c'est pour cela que les librairies Arduino ne gèrent que celle là.

La fréquence dépends des pré-diviseurs (prescaler) qui sont tous égaux à des puissance de 2.
A moins de changer le quartz de la carte ou d'utiliser une fréquence extérieure pour l'entrée du prescaler en lieu et place de la fréquence système du micro (16 MHz pour les cartes arduino) , je ne vois pas comment obtenir précisément du 1 kHz.

Pour cela seule la lecture de la datasheet peut donner le mode opératoire.

J'ai fait les calculs pour les différents PWM avec les formules de la datasheet... Par contre je ne suis pas sur de ma valeur TOP... Est-ce que je peux mettre ce que je veux ? ou est-elle limitée ? Dans mon tableau j'ai mis ce qui m'arrangeait....
Merci pour vos réponses en tout cas !

Il me semble que oui il y a des modes ou TOP peut être fixé par OCRAn mais, du moins avec un 328p, c'est très dépendant du timer. Je n'ai pas sous la main la datasheet du micro de la mega donc faut voir.
ATMega 328p
T0 = possible en mode 7 fast PWM
T1 = possible en mode 9 Phase et frequence correct et en mode 15 fast PWM
T2 = possible en mode en mode 5 Phase correct et en mode 7 Fast PWM

Si "SuperCinci" passe dans les parages peut-être pourra-t-il confirmer (ou infirmer) je sais qu'il s'est penché attentivement sur la question.

Reste la solution de faire des essais.

J'ai trouve ces formules dans la datasheet pour les Timer 1, 3. 4 et 5.... Je comptais utiliser les 3 derniers pour avoir mes neufs signaux! Je vais pouvoir faire des tests très prochainement.
Les timers 0 et 2 sont spécifiés PWM dans la datasheet c'est ce qui me fait un peu peur...
En effet si qqun qui a réfléchit au sujet peut m'aider en effet ça serait top ! Merci 68tjs

(Ci joint la datasheet du mega 2560: http://www.atmel.com/Images/doc2549.pdf)

D'accord super le changement de frequence fonctionne !
Par contre quand j'utilise la fonction analogWrite(numPin, dutycycle), pour une même valeur de duty cycle je n'observe pas le même sur l'oscillo. En clair : je mets 127 ce qui représente 50% du duty cycle et pour un signal a 1khz j'ai bien 50 mais pour un signal a 10khz j'ai 60. Est-ce que cela peut venir de la résolution dont tu parles?

Adiou,
Utilises tu le même mode de PWM que la fonction analogWrite() ?

Adishatz

J'utilise le mode Fast Pwm

+1

une fois parti dans le codage par registre, éviter de mélanger avec les fonction Arduino qui incluent souvent beaucoup de choses derrière, destinées à la base à simplifier l’expérience utilisateur

Je ne pense pas pouvoir faire ça car je dois faire une fonction qui passe en paramètre le duty cycle.... c'est l'utilisateur qui le choisira... Alors le code en dur dans les registres risque de poser pb.... non?

Adiou,

Non tu écris tes propres fonctions pour que l'utilisateur entre son choix.
Ce sera comme avec Arduino sauf que dans ce cas tu maîtrise tout et tu évitera les problèmes annoncés par @Batto :
"des fonction Arduino qui incluent souvent beaucoup de choses derrière, destinées à la base à simplifier l’expérience utilisateur".

Adishatz

Comme suggeré rien ne t'empêche de créer ta propre fonction :wink:

analogWriteMod(int pin, int Duty_Cycle, long PWM_Freq) {

// tu fais ta tambouille 

}

J'ai repris le modèle de analogWrite dans la librairie... Et je me suis dit que je pouvais peut être utiliser cette méthode : Arduino PWM - Mega 2560 pins, registers and changing the frequency and range
J'essaie de faire un exemple pour le timer 3 que je souhaite faire fonctionner a 10khz. Je me demande tout de meme si c'est ici que je dois faire les changement ... Ma fonction analogWrite ne prendrait tjrs que le duty cycle en paramètre. Les timers utilises seraient paramétrer directement a la fréquence désirée

Voici le code de la fonction analogWrite original puis modifie pour le timer 3A :

// ORIGINAL
#if defined(TCCR3A) && defined(COM3A1)
			case TIMER3A:
				// connect pwm to pin on timer 3, channel A
				sbi(TCCR3A, COM3A1);
				OCR3A = val; // set pwm duty
				break;
			#endif

// MODIFIE

#if defined(TCCR3A) && defined(COM3A1)
			case TIMER3A:
				// connect pwm to pin on timer 3, channel A
				sbi(TCCR3A, COM3A1);
                              
                               // prescaler choice (8)
                              cbi(TCCR4B, CS40); 
                             sbi(TCCR4B, CS41);	
                             cbi(TCCR4B, CS42);  

                              // mode Fast PWM (14)
                              sbi(TCCR4B, WGM43); 
                             sbi(TCCR4B, WGM42); 
                             sbi(TCCR4A, WGM41); 
                             cbi(TCCR4A, WGM40); 
                             
                              // counter
                              ICR3 = 199;

				OCR3A = val; // set pwm duty
				break;
			#endif

Autre possibilité : utiliser la librairie PWM qui a deja des fonctions comme SetFrequency(x)... SetTop(x), SetPrescaler(x) ?

Nan mais ne modifie pas le core directement, il te suffit juste de mettre ta fonction dans ton code. A la fin si tu veux faire plus clair, tu peux écrire une librairie.