Go Down

Topic: Registres PWM & timer ATmega 328 (Read 1 time) previous topic - next topic

RICOprod

Bonjour,
je souhaite connaitre les registres PWM de l'ATmega 328 pour obtenir une fréquence de découpage plus élevée qu'avec la fonction "analogWrite()" ( de l'orde de 10Khz ), les datasheets étant difficile à comprendre. Je pose la question car j'ai trouvé très peu d'informations sur la question ...
Merci d'avance

skizoh

salut, dans les projet fini tu peut trouver ça, http://arduino.cc/forum/index.php/topic,104058.0.html qui devrai largement répondre a ta question, tu a un code qui produit des PWM jusqu'à 8MHZ :)

Skizo !
Un tien vaux mieux que deux tu l'auras !

barbudor

Comme indiqué par Skywodd dans un autre post, il y a quelques articles sur le Wiki de Playground a ce sujet
Voici ce que j'ai réussi à retrouver (parce que franchement, trouver des trucs précis dans le Playground, ça doit être un métier à part entière ;))

http://arduino.cc/playground/Main/TimerPWMCheatsheet
http://arduino.cc/playground/Code/PwmFrequency
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

RICOprod

Merci beaucoup, parce que c'est vrai que trouver des infos précises sur le sujet est difficile  ... Je vais regarder tout ça

skywodd

Bonjour,

Si tu ne veut pas te casser la tête avec de l'anglais tu as aussi ce trés bonne article en français :
http://sen.enst.fr/node/222

Et aussi celui (en anglais) qui détaille tout les mode de PWM possible :
http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html
Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

RICOprod

merci pour les liens. je me suis penché sur la question et j'ai réussie a obtenir la fréquence de découpage voulue (10Khz) mais il y a plusieurs petites choses que je ne comprend pas:
j'ai utilisé le mode "fast pwm" du timer 2:               
  TCCR2A = 0x23;               
  TCCR2B = 0x0A;  ====> pré-diviseur a 8  :   16Mhz/8=2Mhz
  OCR2A = 200;     ====> registre pour la comparaison avant débordement:  2Mhz/200=10Khz
  OCR2B =100;      ====> rapport cyclique = 100/200=50%
Le problème est qu'il me faut 3 sorties pwm (à 10Khz de découpage) et qu'avec ce mode seul une sortie sur deux peux fonctionner
(par timer) car l'autre sert de comparaison (ici seul la broche 3(oc2b)fonctionne et pas la 11(oc2a) ) ...
Quelqu'un a-t-il une autre idée ?

RICOprod

j'ai enfin trouvé ce que je voulais mais a taton donc je ne serais pas trop expliquer pourquoi cette fréquence de 7.8khz:

void setup()
{
  TCCR2A = 0b10100011;
  TCCR2B = 0b00000010;     // mode fast pwm du timer 2 :: prediviseur 8 
 
  TCCR1A = 0b10100001;
  TCCR1B = 0b00001010;    // mode fast pwm du timer 1 :: prediviseur 8
   
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
 
  OCR1A = x;        // pin 9
  OCR1B = x;         // pin 10
  OCR2A = x;        // pin 11   
// x rapport cyclique de 0 à 255 ( je crois que c'est de la que viens la deuxième division par 255 par défaut cf datasheet: 16Mhz/8=2Mhz/255 =7.8khz)
}

voila si sa peux aider quelqu'un...


RICOprod

Re-bonjour tout le monde désolé de déterrer un peu le sujet mais c'est encore une question de registre que j'avais à poser:
Voila mon (nouveau) problème : je ne sais pas comment lire les valeurs sur un port entier.. je pensais qu'en écrivant:
int val;
val = PORTC;
cela marchais mais la valeur "val" obtenues prenait le valeur du portc mais rien ne ce passe,j'ai beau changer la valeur aux broches rien
j'ai aussi essayé:
int val;
val = PORTC & 0b11111111;
rien non plus.... comment faire ? le registre DDRC doit être à 0 ou à 1?

barbudor

PORTC c'est pour la sortie
PINC pour l'entrée
et DDRC pour la direction

Voir le Users Manual de l'ATmega dispo sur le site Atmel
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

RICOprod

merci de répondre aussi vite!

Donc si je veux prendre la valeur de 4 broches du portc je doit mettre le registre DDRC à 0 pour les broches dont je veux lire l'état et utilisé le registre PIN pour lire les broches les unes après les autres ? J'avais crue comprendre que le registre PORTx était accessible en écriture et en lecture...
donc
val = Pin(14) | (pin(15)<<2) | (pin(16)<<3) ;
devrait fonctionner?

SesechXP

Salut,

Dans la documentation indiquée par Barburdor :
Quote
13.2.4 Reading the Pin Value
Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register bit.


Donc pour lire la valeur du port C :
- on se fiche de sa direction (DDRC) ;
- on lit sa valeur en utilisant le registre PINC.

Donc
Code: [Select]
int val = PINC;

Il te reste juste à masquer PINC en fonction des broches dont tu veux lire la valeur.

RICOprod

A d'accord génial! Je viens de tester c'est ce que je voulais ...
je croyais que le registre PIN ne lisait que la valeur de la broche choisie comme avec la fonction digitalRead()

Il faudrait vraiment faire une synthèse précise des registres au moins pour l'ATmega328 parce que je sais pas si il y a que moi mais je trouve la doc difficile à lire et a comprendre...et les références arduino sont parfois trop légères
en tout cas merci pour tout !

SesechXP

Tu peux aussi lire les entrées une à une, du genre PINC0, PINC1, etc ;)

barbudor

PINC reflète toujours l'état des broches, que cet état soit imposé par l'extérieur si la broche est en entrée ou par l'intérieur si la broche est en sortie.
Donc non on ne se fiche pas de DDRC.

PORTC permet de positionner les pin en sortie à 1 ou 0 mais aussi d'activer on non la résistance de pull-up interne sur les broches d'entrées.

Donc pour lire en 1 seul fois les broches C.0, C.1, C.2 et C.3 :
DDRC &= ~0x0F; // met à 0 les 4 bits de poids faibles du registre de direction
byte val = PINC & 0x0F;
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

skywodd


Tu peux aussi lire les entrées une à une, du genre PINC0, PINC1, etc ;)

:smiley-eek: C'est cool ça !
Je savais pas que avr/io.h avait les déclarations qui vont bien pour accéder aux broches séparément ... du coup ça me donne des idées $)
Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Go Up