2017-10-14 7 views
0

J'ai du mal à trouver ce que je soupçonne d'être une erreur assez bête dans mon code. J'utilise un ATmega328. Ce dont j'ai besoin, c'est de générer un signal PWM dont le rapport cyclique varie entre 0% et 100%, mais entre deux autres valeurs. Ceci est pris en compte en définissant les macros duty_max et duty_min. Ce que je fais dans mon code est en train de lire l'ADC, qui a une résolution de 1024 valeurs, et la cartographie de la valeur lue à la gamme des valeurs acceptées:Comment limiter la plage des valeurs de duty-cycle PWM?

#define duty_max 239 
#define duty_min 50 

[...] 

//Reading the ADC 
ADMUX = 0b01000101; 
ADCSRA |= (1<<ADSC); 
while(!(ADCSRA & (1<<ADIF))); 
ADCSRA |= (1<<ADIF); 
//Setting the variable 'duty' to the value read by the ADC 
cli(); 
duty = ADC; 
sei(); 
//Mapping to the range of accepted values 
duty = round((duty*(duty_max-duty_min))/1023 + duty_min); 

//Generating the PWM signal 
OCR0B = duty; 
//Timer 0 
TCCR0A = 0b00100011; 
TCCR0B = 0b00000001; 

Le problème que je vais avoir est que le signal ne fonctionne pas comme il se doit. Lors du balayage de l'ADC de 0 à 1023 et de la mesure du signal de sortie à l'aide d'un oscilloscope, je souhaite que le signal passe du cycle de service minimum établi au maximum. Cependant, il va de 0 à 40% (environ) QUATRE fois. À savoir, lorsque la valeur de l'ADC augmente, à un certain moment, le cycle de service cesse d'augmenter et revient à 0, puis continue d'augmenter, jusqu'à atteindre 0 ... Quatre fois dans toute la plage ADC.

Si je remplace la formule de mappage par duty = round(duty/4);, cela fonctionne bien, mais le cycle de service se situe hors de la plage acceptée (puisqu'il passe de 0% à 100%).

Pourquoi cela se produit-il? L'erreur doit être dans la formule de cartographie, mais je ne peux pas le trouver et je l'ai déjà traité pendant un moment maintenant.

+0

Quel type est 'duty'? – flaviodesousa

+0

@flaviodesousa C'est 'unsigned int'. – Tendero

+0

Le commentaire "discussion approfondie" est toujours aussi pertinent que sur votre question précédente. Veuillez ne pas accepter de réponse à une question qui ne vous aide pas réellement. Utilisez une prime sur la question pour obtenir plus de vues. –

Répondre

0

J'ai pu presque reproduire vos symptômes en tronquant à 16 bits le résultat de

(duty*(duty_max-duty_min))/1023 

Lorsque le service est 347, la valeur de sortie passe de 114 (ce qui est d'environ 47% du maximum) à 50, qui est le cycle de service minimum. Cela se produit trois fois et un bit sur la plage d'entrée (pas quatre).

Pour éviter cela, vous pouvez essayer et, dans ce cas, diviser les deux chiffres par un diviseur commun: la différence de service, 189, est divisible par 3, et ainsi est 1023. Essayez d'écrire comme

duty = round((duty*63)/341) + duty_min; 

et de voir si cela change quelque chose.