1. Introduction au PWM sur RK3566
Le PWM (Pulse Width Modulation) est une technique fondamentale pour le contrôle de puissance, comparable à l'ajustement continu du débit d'un robinet en alternant rapidement l'ouverture et la fermeture. Sur la puce RK3566, ce contrôleur offre quatre canaux indépendants, capables de fréquences allant jusqu'à 100 MHz. Cette fonctionnalité est souvent mise en œuvre pour des applications comme le rétroéclairage d'écrans LCD ou la régulation de vitesse de moteurs DC.
Pour commencer le développement, assurez-vous de disposer d'un hôte Linux avec des outils de compilation croisée, d'une carte RK3566 avec accès série, et des sources du noyau Linux récentes.
2. Configuration du Device Tree
2.1 Définition du nœud PWM
Le Device Tree est la carte de navigation pour le noyau. Voici un exemple de déclaration pour un contrôleur PWM, qui nécessite spécifiquement trois cellules (#pwm-cells = 3) pour définir la période, le rapport cyclique et la polarité.
pwm1: pwm@fdd70020 {
compatible = "rockchip,rk3568-pwm";
reg = <0x0 0xfdd70020 0x0 0x10>;
clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
clock-names = "pwm", "pclk";
pinctrl-names = "default";
pinctrl-0 = <&pwm1_pins>;
#pwm-cells = <3>;
status = "okay";
};
2.2 Multiplexage des broches
Les GPIO du RK3566 sont multifonctions. Pour utiliser une broche comme sortie PWM (par exemple GPIO1_A0), il faut définir son mode de fonction dans le nœud pinctrl.
pinctrl {
pwm1_pins: pwm1-pins {
rockchip,pins = <1 RK_PA0 1 &pcfg_pull_none>;
};
};
L'attribut 1 assigne la fonction PWM. Une erreur courante est de laisser la broche en mode GPIO, ce qui empêche toute sortie signal. Vérifiez l'état avec cat /sys/kernel/debug/pinctrl/pinctrl-ranges.
3. Compilation et chragement du pilote
3.1 Activation dans le noyau
Lors de la configuration du noyau via make menuconfig, activez les options suivantes pour garantir le support du matériel et l'accès par sysfs :
Device Drivers --->
PWM Support --->
[*] Rockchip PWM support
[*] Sysfs interface for PWM channels
Le support sysfs est essentiel pour la phase de test et de débogage.
3.2 Vérification du pilote
Après le flash du noyau, confirmez le chargement réussi du pilote avec :
dmesg | grep -i pwm
ls /sys/class/pwm/
La présence d'un répertoire comme pwmchip1 indique que le périphérique est reconnu.
4. Manipulation via Sysfs
4.1 Contrôle d'un canal
Les opérations PWM s'effectuent en écrivant dans des fichiers sysfs. Voici la séquence pour activer et paramétrer un canal (supposons le canal 0 sur pwmchip1) :
echo 0 > /sys/class/pwm/pwmchip1/export
echo 2000000 > /sys/class/pwm/pwmchip1/pwm0/period
echo 1000000 > /sys/class/pwm/pwmchip1/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip1/pwm0/enable
Cette séquence génère un signal à 500 Hz (période de 2 ms) avec un rapport cyclique de 50%. La valeur de période minimale est généralement de 20 ns.
4.2 Inversion de polarité
Pour inverser la polarité du signal, utile par exemple avec des LEDs à anode commune :
echo inversed > /sys/class/pwm/pwmchip1/pwm0/polarity
5. Résolution de problèmes courants
5.1 Absence de signal en sortie
Suivez ce processus de diagnostic :
- Vérifiez physiquement la connexion avec un multimètre.
- Consultez
/sys/kernel/debug/pwmpour confirmer l'enregistrement du canal. - Testez avec une fréquence très basse (ex. 1 kHz) pour éliminer les problèmes de timing.
- Vérifiez la carte des mémoires avec
cat /proc/iomem | grep pwm.
Un blocage fréquent est la désactivation de l'horloge PWM pendant la suspension. Ajoutez rockchip,enable-clock-in-suspend dans le nœud du contrôleur du Device Tree.
5.2 Déformation du signal
Pour améliorer la qualité du signal, notamment en présence de bruit :
- Ajustez le diviseur d'horloge dans le Device Tree, par exemple
rockchip,prescaler = <4>. - Évitez les conflits de multiplexage avec d'autres périphériques sur les mêmes broches.
- Stabilisez l'alimentatino avec des condensateurs de découplage.
6. Exemples d'application avancés
6.1 Contrôle de rétroéclairage
Pour créer une variation progressive de la luminosité d'un écran :
#!/bin/bash
CHIP_PATH="/sys/class/pwm/pwmchip1/pwm0"
echo 0 > $(dirname $CHIP_PATH)/export
echo 10000000 > $CHIP_PATH/period
for val in $(seq 0 10 100); do
# Conversion vers une courbe logarithmique pour une perception visuelle uniforme
duty=$(( (val * val * 100000) / 10000 ))
echo $duty > $CHIP_PATH/duty_cycle
usleep 50000
done
6.2 Système d'asservissement de moteur
Une boucle de contrôle PID peut réguler dynamiquement le rapport cyclique pour stabiliser la vitesse d'un moteur. Le principe est de calculer une correction proportionnelle à l'erreur, son intégrale et sa dérivée.
// Exemple de structure de contrôle PID
float compute_pid_correction(float setpoint, float measured, pid_state_t *state) {
float error = setpoint - measured;
state->integral += error * DT;
float derivative = (error - state->previous_error) / DT;
state->previous_error = error;
return (KP * error) + (KI * state->integral) + (KD * derivative);
}
L'ajustement précis des gains KP, KI et KD est critique pour obtenir une réponse rapide sans dépassement excessif.