rev 16/06/2025
Test Entrees Analogiques pour
parametrage Portail
avec BASE 18F27K42
1) Hardware
2) Config et mesures
analogique.
3) Reglage
PWM Lent (via EA0) et PWM Rapide (via EA1)
4)
Reglage durée en Butée via EA2
5) Reglage Alerte
INA221 via entree Ana EA3
1) Hardware
Prototype de test :
Pour ce test , j'utilise ma Base 18F27K42
Terminal YAT PC sur UART1 5C6 TXet RC7 RX , via un cordon
prolific LTTL/USB
Pickit4 pour programmer le PIC
MPLABX IDE + XC8 compilateur
Alimentation 5V
Base 18F27K42 + Breadboard + Shunt 0.01 avec INA226
+ IBT2 driver + LCD +3 potars
Entrées ANALOGIQUES : RA0,RA1,RA2,RA3
Sortie Led rouge : RA4
Sortie Marche IBT2 en RB6
INTB du MCP23017 sur ENtree RB0 ..non utilisée, uniquement
pour le test Interrupt MCP
Liaisons bus I2C1 RC3 (SCL) RC4 (SDA) vers INA226 et le LCD 4x20
.
Liaison sortie (Alarme) ALERTE INA226 -> entree RC0 du PIC18F (
Interrupt RC0!)
Liaison ICSP <-> Pickit4
Liaison UART TX RC6 et RX RC7 (Interrupt RX) via cordon
Prolific USB.TTL ... terminal PC YAT 115200bds
Alimentation du PIC et INA226 via converter DC/DC 9V---> 5V
La source de mesure de courant (Moteur ) vient d'une alim externe
DC ajustable de 5 à 12V
2)Configuration et et Acquisition des 4
Mesures Analogiques
sur RA0,RA1,RA2,RA3
schema partiel ;
![]() |
les resistances R4 et R5 pull up sur ma carte Base 18F27K42
sont absentes en mode entree analogique. (....utilisées
en mode OWS pour DS18B20) EA1 reliée au 0V |
ADC en mode 12bits .. 0 à 4096 Pts pour 0 à 5V
4 potentiometres permettent d'envoyer une consigne sur
respectivement :
RA0 consigne PWM vitesse Rapide
RA1 consigne PWM vitesse Lente
RA2 consigne Durée de blocage maxi x 0.1sec
RA3 consigne Courant Maxi en butée
mais je n'ai que 3 potars pour les tests :
Pot sur entree ANA RA0 consigne % pour PWM1 (mais pas PWM2 ..car
test sur 1 seul sens de rotation)
* RA1 entree ANA..au 0V ( car en l'air perturbe un peu !)
Pot sur entree Ana RA2 pour definir la tempo sur butee 0 à 255 ,
en divisant la mesure par 16 ou ne lisant que le MSB .de l'ADC
..( pour 0 à 25.5sec par pas de 0.1Sec)
Pot sur entree Ana RA3 pour definir le seuil d'alert de 0 à 1023
pour 0 à 0.6Amp dans le cas present
Rappel : ... à réactualiser plus tard, la calibration pour 0 à
8,192Amps au lieu de 0 à 0,6 actuellement ..
Nota : mes commandes de %PWM via le clavier YAT sont donc
ecrasées par les valeurs Potar .. (sauf PWM2 non concernée)
On peut donc inverser aussi le sens par une commande clavier de
PMW2 > PMW1
La cde clavier "Marche"qui armait RB6 a été passée sur
RB5 ..because probleme
avec Pickit4 ,plus reconnu (et RB6 en sortie!)
SOFTWARE :
Au lancement du programme :
Dans l'init Hardware
TRISA = 0b10001111 ;// declaration sens 0=Sortie
, sinon 1=entree
ANSELA = 0x0F; // declaration voies en analogique
unsigned int EA0,EA1,EA2,EA3;
L'init generale du mode d'acquisition voies ADC
void Init_Analog(void)
{
ADCON0=0;
//CONT=0 = ADC is cleared upon completion of each conversion
trigger
//CS: ADC Clock Selection bit=0 Clock supplied by FOSC, divided
according to ADCLK register
ADCON0bits.FM = 1; //right justify
ADCON0bits.CS = 1; //ADCRC Clock
//ADC instable avec ADCLK => FOSC/2
//ADCLK=0;//FOSC/2 15.6nS at 64MHz
ADCLK=7;//FOSC/16 250nS at 64MHz
//ADCLK=31;//2µs at 64MHz
ADCON1=0;
ADCON2=0; //Basic mode
ADPCH = 0x00; //RA0 is Analog channel
ADCON3=0; //no interrupt
TRISAbits.TRISA1 = 1; //Set RA0 to input
ANSELAbits.ANSELA1 = 1; //Set RA0 to analog
#ifdef With_ADC_REF4096
FVRCON=0;
FVRCONbits.EN=1;
FVRCONbits.ADFVR1=1; // 4.096V au lieu de Vdd=5V
FVRCONbits.ADFVR0=1;
#endif
ADCON0bits.ON = 1; //Turn ADC On
}DCON0bits.ON = 1; //Turn ADC On
}
L'acqusition des mesures ..codage lineaire
void Mesures_Analogiques()
{
uint16_t k;
ADCON0bits.ON = 1; //Turn ADC On
ADPCH=0;// choix de Channel
asm ("nop");asm ("nop"); // 2 Nop =delai
de stabilistation
ADCON0bits.GO = 1; //Start conversion
asm ("nop");
while (ADCON0bits.GO); //Wait for conversion done
k=(ADRESH <<8);
EA0=k+ADRESL;
ADPCH=1; asm ("nop");asm ("nop");
ADCON0bits.GO = 1; //Start conversion
asm ("nop");
while (ADCON0bits.GO); //Wait for conversion done
k=(ADRESH <<8);
EA1=k+ADRESL;
ADPCH=2; asm ("nop");asm ("nop");
ADCON0bits.GO = 1; //Start conversion
asm ("nop");
while (ADCON0bits.GO); //Wait for conversion done
k=(ADRESH <<8);
EA2=k+ADRESL;
ADPCH=3; asm ("nop");asm ("nop");
ADCON0bits.GO = 1; //Start conversion
asm ("nop");
while (ADCON0bits.GO); //Wait for conversion done
k=(ADRESH <<8);
EA3=k+ADRESL;
ADCON0bits.ADON=0;
};
dans le programme main :
CPrint(" Init
Mesures Analogiques\r\n"); Init_Analog(); Start_Chrono(); Mesures_Analogiques(); Stop_Chrono(1); sprintf(CRam1," EA0=%05d, EA1=%05d, EA2=%05d, EA3=%05d",EA0,EA1,EA2,EA3); Print(CRam1); CRLF1(); |
Init Mesures Analogiques SMT1 Nb Tics 158 uS EA0=01345, EA1=00000, EA2=02007, EA3=00294 |
chronometrage des 4 mesures Ana | sur terminal YAT .... 158 µSec |
puis dans la boucle principale :
3) Reglages Vitesse Lente et Rapide
En fait, on ne maitrise pas la vitesse ,mais la tension moyenne
du moteur !
La vitesse depend de U moteur , U=E- r*I avec r=resistance d'induit
et I courant en amperes.
A vide, on aura une linearité Vitesse=f(U) acceptable
.mais quid de la consommation moteur dependant de l'effort
mecanique
Avec une resistance de ligne complete : R du cable + R Induit
moteur => 6 Ohms
Au pire on peut avoir Vitesse Nulle avec E=28V et r*I = 6 ohms*4.6Amps....si
le moteur est bloqué mécaniquement.
Les PWM sont en mode 10 bits , donc 0 à 1023
pour 0 à 100%
* conditionné par la valeur de PR2 !,
car Nb de bits effectifs liée à la Frequence
Dans un premier temps on peut affecter arbitrairement 0 à 50% pour RA0 vitesse
Lente
et 50 à 100% pour PWM Vitesse Rapide
La mise à l'echelle Points ANA pour la vitesse Lente -> % PWM
de 0 à 512 est simple ..=>. 4096/8
EA0 0 à 4095 Pts ........PWM de 0 à 511 -> 0 à 51%
La mise à l'echelle Points ANA pour la vitesse Rapide -> %
PWM de 512 à 1023 = 512+ 4096/8
EA1 0 à 4095 Pts ........PWM de 512 à 1023 -> 51 à 100%
Mesures_Analogiques();
PWML=EA0>>3 ; // 4096 / 8 = > 51.2% PWM maxi vitesse
lente
PWMR=(EA1>>3)+512; => 100% maxima vitesse Rapide
Nota : pour mes tests j'ai laissé k1_PWM commande 0 à 100 % via
Potar sur EA0
et k2_PW1 (initialisé à 0% , donc non lié à EA1, mais
possibilité de commande via terminal YAT
4) Reglage Delai en butée
Avec une voie ANA sur 4096 points si on se contente de 127 points
et avec lusage de la base de temps generale de 0,1mS on
peut donc regler une duree de 0 à 12.7 sec
par comptage du nombre d'interrupt TimerX à 0,1sec
on pourrait aussi faire d'autres combinaisons ... 0 127
=> 0 à 12.7sec
NbTicks_Butee= EA2
>>5;
Exemple base de temps 100 mS pour
centrale clignotante :
void TMR6_Init_100ms(void)
{
PIE9bits.TMR6IE=0 ;
T6CLKCON = 0x05; // T2CS FOSC/4 ou 0x05 pour 500Khz soit T=2µS
T6HLT = 0x80; // synchro sur fosc/4
T6RST = 0x01; // restart by T6TMR Postscaled
//T6CON = 0x70 | 0x07 ; > ticks=2x1024=2048µS
T6CONbits.CKPS= 5; // Prescaler =5=>1/32
T6CONbits.OUTPS=6; //Poscaler=6=>1/7
T6PR=222; // 2µS * 32 * 7 * (223+1) =>100352 -> 100mS ou
222+1 -> 99 904µS
Flag_Timer6=0;
Drapeaux.Tmr6_Elapsed=0;
Cpt6=0;
PIR9bits.TMR6IF=0;//
PIE9bits.TMR6IE=1 ; // TMR6IE_bit=1;
TMR6ON = 1;
}
et interrupt associée
void __interrupt(irq(IRQ_TMR6),low_priority) TMR6_ISR(void)
{ //... evry 100mS ....
Cpt6++;
if (Cpt6 % 5==0) Bit500mS=!Bit500mS; // centrale clignotante pour led
Flag_Timer6=1;
T6PR=222; // pour 100mS
PIR9bits.TMR6IF=0;// clear the TMR6 interrupt flag
}
pour utiliser la duree de delay en
butée
En debut de programme :
TMR6_init();
// test reglage Duree butee
si #def ineTest_potar_Delay_Butee activé
test en boucle infinie,affiche la
due sous frome de . (chaque 100mS) en fonction du reglage Potar
sur EA2
resultat visuel sur YAT terminal :
5) Reglage Seuil de courant Alert INA via
EA3
Details
sur Mesure INA1 ici
En Résumé :
Module INA226 sur un shunt de 0.01 ohms (15Amps 150mV classe 0,5)
liaisons :
Shunt coté High End (point chaud alim du Moteur (12 ou 28V))..
alim module INA +5V et Gnd,
Bus I2C1 : RC3 SCL et RC4 SDA, PIC18F
sortie : ALERT sur inp RC0 , PIC18F
regsitres INA226 :
INA226_BUS_REG 0x02 //Bus Voltage Register
INA226_SHUNT_REG 0x01 //Shunt Voltage Registere
INA226_BUS_REG
INA226_CURRENT_REG
La valeur du seuil de courant est conditionné par
la relation
32768 points pour 81,92mV sur un shunt de 0,01 ohms ..soit 8,192Amps
pour un seuil d'ALERT à 6A => seuil = 32768 * 6.0 /8.192 .=>
24000 pour 6Amps
Le potar EA3 de 0 à100% delivre 0 à 4095 points
4096 * 6 => 24576 points => 6.144AmpsEn prenant 24576
points le coeff de mise à l'echelle est un entier =6
evite de manipuler des flottants 32 bits et calculs...
Usage de decalages logiques au lieu de Multiplication..
uint16_t k; // variable intermediare
k=(EA3<<1);// multiplie EA par 2
k=k+ (EA3<<2). // puis rajoute multiplie EA
par 4 ,... donc 6 fois
Mais il faut Informer l'INA226 de
cette modif ..
Nota : Auparavant, cette modif
pouvait AUSSI etre faite directement via le terminal YAT
..sans passe par la voie analogique.
Le meme traitement est appliqué
// Alert MASK_EN_REG register 07h <- 2400 pour 0.6 A
// 2400 pour 0.6Amps
// 24000 pour 6Amps
k contient la valeur du
seuil en point
tmp[0]=INA226_ALERT_LIMIT_REG;
tmp[1]=(k >> 8);
tmp[2]=(uint8_t)(k & 0x00FF);
Addr=INA226_ADDR;
p1=&tmp[0];
cx=3;
I2C1_WriteNBytes(Addr, p1, cx);
On relit le registre , à un autre moment dans la boucle
principale,
pour afficher la valeur en unites physiques : en Amperes ..sur
terminal ou LCD
Addr= INA226_ADDR;
tmp[0]=0;
tmp[1]=0;
p1=&tmp[0];
I2C1_ReadDataBlock(Addr, INA226_ALERT_LIMIT_REG,
p1,3);
k=(tmp[0]<<8) + tmp[1];
//Seuil_Alerte= 8.192 * (double)k / 32768.0;
Seuil_Alerte= (double)k / 4000.0; //
simplification de calcul
sprintf(CRam1," Seuil d'alerte %3.3f Amperes\r\n",Seuil_Alerte);
// pour affichage en Ampere
Print(CRam1);
CRLF1();
On pourrait donc regler "En live" l'alarme courant
ALERT ....
mais dans mon test je lance une commande YAT : SET INA1
ALERT via EA3 pour que la valeur de EA3
soit prise en compte... car dans l'application finale,il faudra
etre dans un certain Phase-Pas du programme
pour permettre ce changement.
Nota: pour le forçage en butée , le courant sera forcement
maximal !
=> ALERT générée ...mais devra etre inhibée pendant la
duree du temps reglé via potar EA2 Delay_Butee
sinon en "marche normale" ALERT => arrzet moteur
Capture terminal YAT :
derniere modif : inclusion en direct Live du reglage Alert(
Amperes)et reglage duree Butee ( x 100mS)
Terminal_pour_Test_portail_2025-0616.yacp
SOFTWARE :
Environnement MPLABX IDE + XC8 compilateur
Programmateur : Pickit4
18F27K42_PMW_INA226_MCP23017_2025-0618.X.zip
main_18F27K42_PMW_INA226_MCP23017_2025-0618.X.c
Dialogue_UART_MCP23017_2025-06.inc